Почему один и тот же SQL-запрос с другим внешним ключом в предложении WHERE имеет разную производительность? - PullRequest
0 голосов
/ 31 января 2019

Почему эти два запроса, с той лишь разницей, что camp_id (внешний ключ к другой таблице) имеют разную производительность и разные результаты EXPLAIN?

Запрос 1 - Среднее время: 0,21 с

SELECT tx_time, campaign_id, tx_amount, tx_status FROM tx WHERE
 campaign_id=6963 ORDER BY tx_time DESC LIMIT 2500;

Запрос 2 - Среднее время: 0,29 с

 SELECT tx_time, campaign_id, tx_amount, tx_status FROM tx WHERE
 campaign_id=6946 ORDER BY tx_time DESC LIMIT 2500;

Запрос 1 против запроса 2 ОБЪЯСНЕНИЕ:

 id  select_type   table   partitions  type    possible_keys     key             key_len   ref   rows    filtered  Extra
 1   SIMPLE        tx      NULL        index   tx_campaign_id    tx_time         4         NULL  85591   2.92      Using where
 1   SIMPLE        tx      NULL        ref     tx_campaign_id    tx_campaign_id  4         const 106312  100       Using index condition; Using filesort

ОБНОВЛЕНИЕ: После добавления (tx_id,Индексы tx_time, campaign_id) и (tx_id, tx_time) и запущенный ANALYZE, Query 1 улучшен до 0,15 с, но Query 2 замедлен до 13 с.Обновленные объяснения:

 id  select_type   table   partitions  type    possible_keys     key             key_len   ref   rows    filtered  Extra
 1   SIMPLE        tx      NULL        index   tx_campaign_id    tx_time         4         NULL  75450   3.31      Using where
 1   SIMPLE        tx      NULL        ref     tx_campaign_id    tx_campaign_id  4         const 117400  100.00    Using index condition; Using filesort

Таблица tx:

CREATE TABLE tx (
tx_id bigint (20) без знака NOT NULL AUTO_INCREMENT,
tx_time отметка времени NOT NULL DEFAULT CURRENT_TIMESTAMP,
campaign_id int (10) без знака NOT NULL,
tx_amount десятичный (12,5) без знака NOT NULL,
tx_geo varchar (2) NOT NULL,
tx_langauge varchar (511) NOT NULL,
tx_ua varchar (511) NOT NULL,
tx_ip varchar (45) NOT NULL,
tx_status tinyint (255) ПО УМОЛЧАНИЮNULL,
ПЕРВИЧНЫЙ КЛЮЧ (tx_id),
КЛЮЧ tx_campaign_id (campaign_id),
КЛЮЧ tx_time (tx_time) ИСПОЛЬЗУЯ BTREE,
КЛЮЧ tx_amount (tx_amount) ИСПОЛЬЗОВАТЬ BTREE,
КЛЮЧ tx_time_campaign_id (tx_id, tx_time, campaign_id) ИСПОЛЬЗОВАТЬ BTREE,
КЛЮЧ tx_id_time (tx_id, tx_time) ИСПОЛЬЗОВАТЬ BTREE,
CONSTRAINT campaign_idcampaign_id ИНОСТРАННЫЙ КЛЮЧ (campaign_id) ССЫЛКИ campaign (campaign_id) ВКЛ УДАЛИТЬ НЕТ ДЕЙСТВИЙ ОБНОВЛЕНИЕ НЕТ ДЕЙСТВИЙ
) ДВИГАТЕЛЬ = InnoDB AUTO_INCREMENT = 10855433 CHARSET ПО УМОЛЧАНИЮ = utf8

Ответы [ 2 ]

0 голосов
/ 01 февраля 2019

Вам нужно INDEX(campaign_id, tx_time) со столбцами в указанном порядке.

Как правило, сначала ставьте столбец =, а именно campaign_id.В этом случае это касается всего предложения WHERE, поэтому вы можете перейти к ORDER BY.Затем добавьте все столбцы в ORDER BY, а именно tx_time.

После успешного создания индекса, который их обрабатывает, , а затем обработка может остановиться на строках LIMIT и избежатьa 'filesort'.

Указатель Поваренная книга

0 голосов
/ 31 января 2019

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

Я предполагаю, что у вас нет составного индекса(action_id, tx_time) для таблицы;если бы это было так, оптимизатор, вероятно, использовал бы это (и был бы быстрее).

Если вы думаете о том, как будет работать запрос, вы можете сначала найти все записи на основе идентификатора транзакции, а затем отсортировать их на основевовремя, или вы можете сортировать записи по времени и отбрасывать те, которые не принадлежат идентификатору транзакции, который вас интересует.

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

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

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