Справка по производительности MYSQL Triple Join, копирование в таблицу Tmp - PullRequest
1 голос
/ 17 июня 2011

Я работаю над запросом для новостного сайта, который найдет FeaturedContent для отображения на главной домашней странице. Контент, помеченный таким образом, помечается как «FeaturedContent» и упорядочивается в избранной таблице по «домашней странице». В настоящее время у меня есть желаемый результат, но запрос выполняется в течение 3 секунд, которые мне нужно сократить. Как оптимизировать запрос, подобный следующему?

РЕДАКТИРОВАТЬ: материализовал представление каждую минуту, как предложено, до 0,4 секунды:

SELECT f.position, s.item_id, s.item_type, s.title, s.caption, s.date
FROM live.search_all s 
INNER JOIN live.tags t 
ON s.item_id = t.item_id AND s.item_type = t.item_type AND t.tag = 'FeaturedContent' 
LEFT OUTER JOIN live.featured f 
ON s.item_id = f.item_id AND s.item_type = f.item_type AND f.feature_type = 'homepage'
ORDER BY position IS NULL, position ASC, date

Возвращает все функции домашней страницы по порядку, за ними следует другое рекомендуемое содержимое, упорядоченное по дате.
Объяснение выглядит так:

|-id---|-select_type-|-table-|-type---|-possible_keys---------|-key--------|-key_len-|-ref---------------------------------------|-rows--|-Extra-------------------------------------------------------------|
|-1----|-SIMPLE------|-t2----|-ref----|-PRIMARY,tag_index-----|-tag_index--|-303-----|-const-------------------------------------|-2-----|-Using where; Using index; Using temporary; Using filesort;--------|
|-1----|-SIMPLE------|-t-----|-ref----|-PRIMARY---------------|-PRIMARY----|-4-------|-newswires.t2.id---------------------------|-1974--|-Using index-------------------------------------------------------|
|-1----|-SIMPLE------|-s-----|-eq_ref-|-PRIMARY, search_index-|-PRIMARY----|-124-----|-newswires.t.item_id,newswires.t.item_type-|-1-----|-------------------------------------------------------------------|
|-1----|-SIMPLE------|-f-----|-index--|-NULL------------------|-PRIMARY----|-190-----|-NULL--------------------------------------|-13----|-Using index-------------------------------------------------------|

А профиль выглядит следующим образом:

|-Status---------------|-Time-----|
|-starting-------------|-0.000091-|
|-Opening tables-------|-0.000756-|
|-System lock----------|-0.000005-|
|-Table lock-----------|-0.000008-|
|-init-----------------|-0.000004-|
|-checking permissions-|-0.000001-|
|-checking permissions-|-0.000001-|
|-checking permissions-|-0.000043-|
|-optimizing-----------|-0.000019-|
|-statistics-----------|-0.000127-|
|-preparing------------|-0.000023-|
|-Creating tmp table---|-0.001802-|
|-executing------------|-0.000001-|
|-Copying to tmp table-|-0.311445-|
|-Sorting result-------|-0.014819-|
|-Sending data---------|-0.000227-|
|-end------------------|-0.000002-|
|-removing tmp table---|-0.002010-|
|-end------------------|-0.000005-|
|-query end------------|-0.000001-|
|-freeing items--------|-0.000296-|
|-logging slow query---|-0.000001-|
|-cleaning up----------|-0.000007-|

Я новичок в чтении вывода EXPLAIN, поэтому я не уверен, есть ли у меня более удобный порядок или что-нибудь более простое, что можно было бы сделать, чтобы ускорить их.

Таблица search_all является материализованной таблицей представлений, которая периодически обновляется, а теги и избранные таблицы являются представлениями. Эти представления не являются обязательными, и их нельзя обойти.

Представление тегов объединяет теги и реляционную таблицу для получения списка тегов в соответствии с item_type и item_id, но все остальные представления являются простыми представлениями одной таблицы.

РЕДАКТИРОВАТЬ: С материализованным представлением самым большим узким местом кажется шаг «Копирование в временную таблицу». Без упорядочения выходных данных это займет 0,0025 секунды (намного лучше!), Но конечный вывод требует упорядочивания Есть ли способ повысить производительность этого шага или обойти его?

Извините, если форматирование трудно читать, я новичок и не уверен, как это регулярно делается.
Спасибо за вашу помощь! Если что-то еще нужно, пожалуйста, дайте мне знать!

РЕДАКТИРОВАТЬ: Размеры таблицы, для справки:
Отношения тегов: 197,411
Теги: 16 897
Истории: 51 801
Изображения: 28 383
Видео: 2,408
Рекомендуемые: 13

1 Ответ

1 голос
/ 17 июня 2011

Я думаю, что оптимизация вашего запроса не будет очень полезной. Первые мысли о том, что присоединение к подзапросу, самому созданному из UNIONs, является лишь двойным узким местом для производительности.

Если у вас есть возможность изменить структуру базы данных, я бы предложил объединить 3 таблицы stories, images и videos в одну, если они, как кажется, очень похожи (добавляя их type ENUM('story', 'image', 'video')) для разграничения записей; это удалит и подзапрос, и объединение.

Кроме того, похоже, что ваши представления по stories и videos не используют индексированное поле для фильтрации содержимого. Вы запрашиваете индексированный столбец?

Это довольно сложная проблема, не зная вашей полной структуры таблицы и перераспределения ваших данных!

Другой вариант, который не предполагает внесения изменений в существующую базу данных (особенно если она уже находится в работе), заключается в том, чтобы «кэшировать» эту информацию в другой таблице, которая будет периодически обновляться заданием cron.

Кэширование может выполняться на разных уровнях, либо на полном запросе, либо на его части (независимые представления или 3 объединения, объединенные в одну таблицу кеша и т. Д.)

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

...