MySQL: оптимизировать запрос с помощью DISTINCT - PullRequest
1 голос
/ 04 сентября 2011

В моем Java-приложении обнаружена небольшая проблема с производительностью, вызванная таким простым запросом:

 SELECT DISTINCT a 
   FROM table 
  WHERE checked = 0 
  LIMIT 10000

У меня есть индекс в столбце checked.

В начале запрос выполняется очень быстро (т. Е. Там, где почти все строки имеют checked = 0).Но поскольку я отмечаю все больше и больше строк, как проверено, запрос становится очень неэффективным (до нескольких минут).

Как повысить производительность этого запроса?Должен ли я добавить комплексный индекс

  • a, проверено

или, скорее,

  • проверено, a?

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

Ответы [ 5 ]

2 голосов
/ 04 сентября 2011

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

Вы также можете использовать переписанный запрос как (на тот случай, если оптимизатор не поймет, что он эквивалентен):

  SELECT a 
    FROM table 
   WHERE checked = 0 
GROUP BY a
   LIMIT 10000
1 голос
/ 04 сентября 2011

В моей таблице много миллионов строк <...>, где почти все строки имеют проверено = 0

В этом случае кажется, что лучшим индексом будет простой (a).

UPDATE:

Не было ясно, сколько строк проверено. Из вашего комментария ниже вопрос:

В начале 0 в 100% строк, но в конце дня это будет стать 0%

Это все меняет. Так что у @Ben правильный ответ.

1 голос
/ 04 сентября 2011

Добавить составной индекс в столбце DISTINCT (a в этом случае).MySQL может использовать этот индекс для DISTINCT.

MySQL также может получить прибыль от составного индекса на (a, checked) ( порядок имеет значение , столбец DISTINCT должен быть вначало индекса).Попробуйте оба и сравните результаты с вашими данными и вашими запросами.

(После добавления этого индекса вы должны увидеть Using index for group-by в выводе EXPLAIN.)

См. Оптимизация GROUP BY в руководстве.(A DISTINCT очень похож на GROUP BY.)

Наиболее эффективный способ обработки GROUP BY - это использование индекса для непосредственного извлечения столбцов группировки.С этим методом доступа MySQL использует свойство некоторых типов индексов, которые упорядочивают ключи (например, BTREE).Это свойство позволяет использовать группы поиска в индексе без необходимости учитывать все ключи в индексе, которые удовлетворяют всем условиям WHERE.>

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

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

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

Я нашел совершенно другое решение, которое бы сработало. Я просто создам новую таблицу со всеми возможными уникальными значениями "a". Это позволит мне избежать DISTINCT

...