Как запретить MySQL выбирать один индекс, если доступен лучший? - PullRequest
0 голосов
/ 22 октября 2011

У меня есть таблица с 30000 строками (и растущая), к которой я присоединяюсь с другой таблицей. Несколько страниц, мне нужно выполнить более 100 таких запросов, и все идет медленно. Если я EXPLAIN запрос, я заметил, что одна таблица использует первичный ключ и является быстрым, а другая таблица использует один из ее индексов, который не является лучшим. Вот краткий обзор:

SIMPLE | acc_entries | ref | ledger,date,type,status,status_ledger_date_type | type | 1 | const | 15359 | Using where

Это пример запроса:

SELECT SUM(usd) AS total FROM acc_entries
LEFT JOIN acc_ledgers ON acc_entries.ledger = acc_ledgers.id
WHERE acc_entries.status = 1 AND 
acc_ledgers.account = 3004 AND 
date >= '2011-01-01' AND 
date <= '2011-08-30' AND 
type = 'credit'

Как видите, я использую в своем WHERE поля status, ledger (это поле, которое соединяется с acc_ledgers.account), date и type. Все эти поля имеют индексы. Тем не менее, есть также определенный индекс, который используется для всех них, в том же порядке. Он называется status_ledger_data_type, и, как вы можете видеть, это один из индексов, которые MySQL рассматривает как использование. Однако в конце MySQL выбирает type в качестве индекса. У этого есть приблизительно 15 000 возможных строк (половина таблицы), тогда как другой объединенный индекс показывает только часть этого. Поэтому у меня возникает вопрос: почему MySQL выбирает этот индекс, когда доступен лучший, и как я могу предотвратить это?

Ответы [ 2 ]

1 голос
/ 22 октября 2011

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

Документы MySql для подсказок по указателю

Индекс битвы между силами и оптимизатор запросов

7 способовубедить MySQL использовать правильный индекс

0 голосов
/ 22 октября 2011

На самом деле, вы хотите, чтобы ваш индекс основывался на меньшей гранулярности.Главная книга из вашей таблицы Acc_Entries присоединится к вашей таблице ACC_Ledgers по первичному индексу ITS идентификатора ITS, поэтому Acc_Ledgers на самом деле не использует часть Ledger для предложения WHERE.Ваш индекс должен максимально соответствовать предложению WHERE ваших общих запросов.В этом случае у меня будет индекс на

(Учетная запись, Статус, Тип, Дата)

Причина, по которой Учетная запись - первая, меньший набор результатов.Вы можете иметь 5000 записей.Из них 300 записей для одной учетной записи, так что вы уже удалили огромное количество данных для прохождения.Затем, статус ... из 300, вы можете иметь 100 @ статус 1, 100 @ статус 2, 100 @ статус 3, так что теперь вы уменьшили набор еще больше и т. Д. По другим критериям типа и даты.

В противном случае ваш запрос вполне подойдет ... просто личный стиль написания. Я стараюсь писать свои запросы с условиями WHERE, также точно совпадающими с индексом в той же последовательности, так что сначала я бы просто предложил предложение Account.затем Status, Type и Date ... но опять же, это личный стиль написания запросов.

...