Оптимизация MySQL Query - PullRequest
       9

Оптимизация MySQL Query

0 голосов
/ 07 мая 2009

Я сейчас работаю над веб-сайтом, который нуждается в некоторой оптимизации ... так как загрузка главной страницы занимает около 15-20 секунд, я подумал, что некоторая оптимизация будет хорошей.

Вот один запрос, который появился в журнале медленных запросов MySQL:

SELECT a.user,a.id
FROM `profil_perso` pp
INNER JOIN `acces` a ON pp.parrain = a.id
INNER JOIN `acces` ap ON ap.id = pp.id
WHERE pp.parrain_visibilite = '1'
  AND a.actif = 1
GROUP BY a.id
ORDER BY ap.depuis DESC LIMIT 15;

На profil_perso (~ 207K строк - содержит электронные письма и профили) есть perso_id, который является первичным ключом, также есть id (внешний ключ) + parrain (реферер) + parrain_visibilite (реферер показан), которые являются индексами.

На acces есть id, который является первичным ключом, также есть depuis (дата регистрации), который проиндексирован

Тест показывает это на самом деле:

Первый раз: 1.94532990456
Последний раз: 1.94532990456
Среднее время: 0.0389438009262

Я пытался выразиться так:

SELECT DISTINCT a.id, a.user
FROM `profil_perso` pp
LEFT JOIN `acces` a ON pp.parrain = a.id
WHERE pp.parrain_visibilite = 1
  AND a.actif = 1
  AND pp.id != 0
ORDER BY pp.id DESC LIMIT 15;

Тем не менее тест показывают это:

Первый раз: 1.96376991272
В прошлый раз: 1.96376991272
Среднее время: 0.0393264245987

Есть ли подсказка, чтобы уменьшить время запроса?

Вот полные индексы:

доступ:

id (primary)
derniere_visite -- last visit
pays_id -- country_id
depuis -- registration time
perso_id -- foreign key to profil_perso primary key
actif -- account status
compte_premium -- if account is premium

profil_perso:

perso_id (primary)
id -- foreign key to acces primary key
genre -- gender
parrain_visibilite -- visibility of referer
parrain -- referer
parrain_contexte
telephone
orientation
naissance -- birthdate
photo -- if it has a picture

Ответы [ 4 ]

3 голосов
/ 07 мая 2009

Пробег EXPLAIN SELECT DISTINCT a.id .....;

Это поможет показать вам, где могут отсутствовать индексы и т. Д.

0 голосов
/ 07 мая 2009

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

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

Тем не менее, я думаю, что большой удар по производительности может заключаться в том, что вы сортируете 207 тыс. Записей для извлечения последних 15 вставленных - можете ли вы достичь того же по-другому?

0 голосов
/ 07 мая 2009

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

Но мы могли бы начать с первого разреза со схемой задействованных таблиц, а также с результатами текущего EXPLAIN (выполнение по кругу, второе и первое результаты).

0 голосов
/ 07 мая 2009

Почему у вас два JOIN здесь?

Создать составной индекс для acces (actif, depuis):

CREATE INDEX ix_acces_actif_depuis ON acces (actif, depuis)

, создайте составной индекс для profil_perso (parrain, parrain_visibilite):

CREATE INDEX ix_profilperso_parrain_parrainvisibilite ON profil_perso (parrain, parrain_visibilite)

и попробуйте это:

SELECT  a.user, a.id
FROM    acces a
JOIN    profil_perso p
ON      pp.parrain = a.id
        AND pp.parrain_visibilite = 1
WHERE   a.actif = 1
ORDER BY
        a.actif DESC, a.depuis DESC
LIMIT 15

Этот запрос будет использовать индекс на actif, чтобы избежать сортировки, и индекс на profil_perso, чтобы найти и отфильтровать невидимые parrain.

Поскольку у вас есть LIMIT 15 здесь, этот запрос должен быть мгновенным.

Это также поможет узнать, насколько избирательным является ваше поле actif.

Чтобы понять это, пожалуйста, запустите:

SELECT COUNT(DISTINCT actif) / COUNT(*)
FROM   acces
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...