Какие индексы SQL я должен добавить для этого раздутого запроса? - PullRequest
3 голосов
/ 30 сентября 2011

Мне интересно, ускорят ли индексы этот запрос. Прошло 9 секунд, когда я последний раз проверял. Таблица трафика имеет около 300 тыс. Строк, списки и пользовательские 5 тыс. Строк. Я тоже открыт для насмешек / унижений, если это просто дерьмовый запрос. Я написал это давно.

Предполагается получить списки с наибольшим количеством просмотров страниц (трафик). Дайте мне знать, если объяснение отсутствует.

SELECT traffic_listingid AS listing_id, 
       COUNT(traffic_listingid) AS genuine_hits, 
       COUNT(DISTINCT traffic_ipaddress) AS distinct_ips, 
       users.username, 
       listings.listing_address,
       listings.datetime_created,
       DATEDIFF(NOW(), listings.datetime_created) AS listing_age_days 
FROM traffic 
  LEFT JOIN listings 
    ON traffic.traffic_listingid = listings.listing_id 
  LEFT JOIN users 
    ON users.id = listings.seller_id 
WHERE traffic_genuine = 1 
  AND listing_id IS NOT NULL 
  AND username IS NOT NULL 
  AND DATEDIFF(NOW(), traffic_timestamp) < 24 
GROUP BY traffic_listingid 
ORDER BY distinct_ips DESC
LIMIT 10

приписка

ENGINE=MyISAM /
MySQL Server 4.3

Ответы [ 2 ]

3 голосов
/ 30 сентября 2011

Sidenotes:

1.У вас есть

  LEFT JOIN listings 
    ON traffic.traffic_listingid = listings.listing_id 
  ...
WHERE ... 
  AND listing_id IS NOT NULL 

Это условие отменяет LEFT JOIN. Измените ваш запрос на:

  INNER JOIN listings 
    ON traffic.traffic_listingid = listings.listing_id 

и удалите listing_id IS NOT NULL из условий WHERE.

То же самое относится к LEFT JOIN user и username IS NOT NULL.


2. Проверка на traffic_timestamp:

      DATEDIFF(NOW(), traffic_timestamp) < 24

затрудняет использование индекса. Измените его на что-то вроде этого, которое может использовать индекс
проверьте , что моя версия эквивалентна, у меня могут быть ошибки):

      traffic_timestamp >= CURRENT_DATE() - INTERVAL 23 DAY

3. COUNT(non-nullable-column) эквивалентно COUNT(*). Измените:

   COUNT(traffic_listingid) AS genuine_hits, 

до:

   COUNT(*) AS genuine_hits, 

потому что это немного быстрее в MySQL (хотя я не уверен в этом для версии 4.3)


Для вопроса об индексе у вас должен быть хотя бы индекс для каждого столбца, который используется для объединения. Добавление еще одного для traffic_timestamp, вероятно, тоже поможет.

Если вы сообщите нам, в каких таблицах traffic_ipaddress и traffic_timestamp, и что показывает EXPLAIN EXTENDED, у кого-то может быть идея получше.

Повторно читая запрос, кажется, что на самом деле он GROUP BY только в таблице traffic, а две другие таблицы используются для получения справочных данных. Таким образом, запрос эквивалентен (группа трафика по) -join-list-join-user. Не уверен, поможет ли это в вашей старой версии MySQL, но может быть полезно иметь обе версии запроса и проверить, выполняется ли один запрос быстрее в вашей системе.

0 голосов
/ 30 сентября 2011

Индексы всегда должны помещаться в столбцы, которые вы используете в предложении where.

В этом случае листинг выглядит как хороший вариант, а также users.id, seller_id и traffic_timestamp.

Используйте EXPLAIN EXTENDED перед вашим запросом, чтобы увидеть, что MySQL рекомендует вам (показывает, сколько строк затронуто и какие индексы он использует)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...