2014-11-12 10 views
0

У меня есть следующие таблицы.Как эффективно масштабировать данные геоинформации из хранилища данных MySQL

CREATE TABLE `media_scores` (
    `media_id` int(10) unsigned NOT NULL, 
    `sorting_score` float unsigned NOT NULL DEFAULT '0', 
    `date_added` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', 
    `date_updated` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP, 
    PRIMARY KEY (`media_id`), 
) ENGINE=InnoDB DEFAULT CHARSET=latin1; 

CREATE TABLE `media_restrict` (
    `media_id` int(11) NOT NULL, 
    `restrict_type` enum('exclude','include') NOT NULL, 
    `country_code` char(2) NOT NULL, 
    PRIMARY KEY (`media_id`,`restrict_type`,`countryCode`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8; 

Стол media_scores имеет 1,8 млн записей. Стол media_restrict имеет равные или более записи.

Вот некоторые примеры данных внутри: media_scores

+----------+---------------+-------------+--------------+ 
| media_id | sorting_score | date_added | date_updated | 
+----------+---------------+-------------+--------------+ 
|  1 |   25 | 2014-11-05 | 0000-00-00 | 
|  2 |   16 | 2014-11-05 | 0000-00-00 | 
|  3 |   33 | 2014-11-05 | 0000-00-00 | 
|  4 |   11 | 2014-11-04 | 0000-00-00 | 
+----------+---------------+-------------+--------------+ 

media_restrict

+----------+---------------+--------------+ 
| media_id | restrict_type | country_code | 
+----------+---------------+--------------+ 
|  1 | exclude  | US   | 
|  1 | exclude  | UK   | 
|  2 | include  | US   | 
|  2 | include  | CA   | 
|  3 | include  | CN   | 
+----------+---------------+--------------+ 

Я бегу следующий запрос:

SELECT ms.* 
FROM media_scores as ms 
LEFT OUTER JOIN media_restrict AS mr 
ON ms.media_id = mr.media_id and mr.restrict_type = 'exclude' and mr.country_code = 'CA' 
LEFT OUTER JOIN media_restrict AS mr2 
ON ms.media_id = mr2.media_id AND mr2.restrict_type = 'include' AND mr2.country_code = 'CA' 
LEFT OUTER JOIN media_restrict AS mr3 
ON ms.media_id = mr3.media_id AND mr3.restrict_type = 'include' AND mr3.country_code != 'CA' 
WHERE mr.media_id IS NULL AND 
(CASE mr2.media_id WHEN ms.media_id THEN NULL ELSE mr3.media_id END) IS NULL; 

для достижения этой цели:

+----------+---------------+------------+--------------+ 
| media_id | sorting_score | date_added | date_updated | 
+----------+---------------+------------+--------------+ 
|  1 |   25 | 2014-11-05 | 0000-00-00 | 
|  2 |   16 | 2014-11-05 | 0000-00-00 | 
|  4 |   11 | 2014-11-04 | 0000-00-00 | 
+----------+---------------+------------+--------------+ 

В небольшом подмножестве - запрос выполняется нормально. На 1.8M Im имеет проблемы с масштабируемостью.

В конечном итоге я хочу добиться того, чтобы предметы внутри media_scores отображались только в странах, которые разрешены только.

Я очень гибкий с точки зрения инфраструктуры, поэтому MySQL не может быть решением, но это все, что я могу обернуть вокруг.

Набор данных будет расти, поскольку я заполняю больше данных и больше ограничений для стран.

Как я могу ограничить свои данные по странам эффективно в более крупном масштабе. Как любые службы проверяют ограничения контента (например, Youtube, которые не могут отображать контент в зависимости от стран).

Есть две вещи, которые необходимо учитывать: скорость и точность. Текущий контрольный показатель составляет около 13 секунд, и если я загружу это как набор данных, а затем я должен манипулировать им - его слишком много. Точность означает, что я должен обеспечить, чтобы я получил правильный результат, который мне нужен. В настоящее время упомянутый запрос является правильным.

Примечание: данные обновляются часто, но не до минуты (я бы сказал, что каждый час или около того может быть больше) - поэтому Vertica может предложить большой набор данных для эффективного запроса, но поскольку Vertica не поддерживает обновления или удаление красиво - он это нарушает.

ответ

1

В вашем вопросе есть небольшая двусмысленность - для любых данных media_id вы могли бы включить и исключенные страны? Похоже, что если вы включите страны, естественное предположение будет исключено из всех других стран и наоборот (если вы исключаете страны, все остальные будут включены) - это правда? Если это так, то для данного media_id у вас будет только включение или исключение, но не оба.

И если я правильно интерпретировать запрос, что бы упростить ее, позволяя не беспокоиться об этой части:

LEFT OUTER JOIN media_restrict AS mr3 
ON ms.media_id = mr3.media_id AND mr3.restrict_type = 'include' AND mr3.country_code != 'CA' 
WHERE mr.media_id IS NULL AND 
(CASE mr2.media_id WHEN ms.media_id THEN NULL ELSE mr3.media_id END) IS NULL; 

Есть другие большие улучшения, которые вы можете сделать, но они зависят от вашего ответьте на мой вопрос выше, поэтому я позволю вам ответить первым.

+0

Это правильно - вы можете быть включены или исключены только для обоих носителей media_id. ОДНАКО Мне нужна последняя часть для «global» media_id. Если вы посмотрите на ожидаемый результат: необходимо показать media_id 4 - который не включен или не исключен, потому что он не ограничен какой-либо страной. – azngunit81

-1

Got it.Структура данных для media_restrict не идеальна для выполнения всего этого в базе данных, поэтому, поскольку ваша инфраструктура является гибкой, кажется, что она будет более читаемой и эффективной, если вы явно кодируете эту логику на другом языке за пределами базы данных. Псевдокод будет что-то вроде:

$countrycode = 'CA'; 
$includearray = getMySQLresult('select media_id from media_restrict where restrict_type = 'include' and country_code = $countrycode;') 
$excludearray = getMySQLresult('select media_id from media_restrict where restrict_type = 'exclude' and country_code = $countrycode;') 

if (count($includearray) >= 1) 
    {$media_scores_result = getMySQLresult('select * from media_scores where media_id in $includearray;'} else 
if (count($excludearray) >= 1) 
    {$media_scores_result = getMySQLresult('select * from media_scores where media_id in $excludearray;'} 
else 
    {$media_scores_result = getMySQLresult('select * from media_scores;'} 

А если добавить индекс только (restrict_type, countryCode) на media_retrict, запросы, которые населяют $ includearray и $ исключить должны идти гораздо быстрее.

+0

Извините, но ответ, который вы мне даете, не говорит мне, что его более высокая производительность, а псевдо-код не переводится в сравнимое масштабируемое значение. – azngunit81

+0

Извините, приятель, не время быть настолько основательным в вашей проблеме. Просто дайте предложение. Удачи. – albielin

Смежные вопросы