Почему индекс используется только когда принудительно, но не по умолчанию? - PullRequest
1 голос
/ 25 октября 2019

В моей таблице около 420 миллионов записей. В столбце colC из user_table есть только индекс. Ниже запрос возвращает около 1,5 миллиона записей на основе colC. Но индекс как-то не используется и возвращает записи через 20-25 минут

select colA ,ColB , count(*) as count 
from user_table 
where colC >='2019-09-01 00:00:00' 
      and colC<'2019-09-30 23:59:59' 
      and colA in ("some static value") 
      and ColB in (17) 
group by colA ,ColB;

Но когда я делаю принудительный индекс, он начинает привыкать и возвращает запись только через 2 минуты. Мой вопрос, почему MYSQL не использует индекс по умолчанию, когда время выборки намного меньше с индексом? Я воссоздал индекс вместе с восстановлением, но по умолчанию ничего не работает, чтобы использовать его.

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

Обновление За подробностями обращайтесь к Evert

CREATE TABLE USER_TABLE ( id bigint(20) unsigned NOT NULL AUTO_INCREMENT, COLA varchar(10) DEFAULT NULL, COLB int(11) DEFAULT NULL, COLC datetime DEFAULT NULL, .... PRIMARY KEY (id), KEY colA ( COLA ), KEY colB ( COLB ), KEY colC ( COLC ) ) ENGINE=MyISAM AUTO_INCREMENT=2328036072 DEFAULT CHARSET=latin1 |

Ответы [ 2 ]

1 голос
/ 25 октября 2019

для повышения производительности вы можете попробовать использовать составной индекс .. на основе столбца, включенного в ваше предложение where
и попытаться изменить предложение IN во внутреннем объединении
, предполагая, что содержимое предложения IN является набором фиксированныхзначения, которые вы могли бы использовать union (или новую таблицу с нужным вам значением)

например, используя union (вы можете сделать нечто похожее, если предложение IN является подзапросом)

select user_table.colA ,ColB , count(*) as count 
from user_table 
INNER JOIN  ( 
  select 'FIXED1' colA
  union
  select 'FIXED2'
  ....
  union 
  select 'FIXEDX'
  )  t on t.colA = user_table.colA  
where colC >='2019-09-01 00:00:00' 
      and ColB = 17  
group by colA ,ColB;

youмог бы также добавить составной индекс к таблице user_table для столбцов

   colA, colB, colC

для того, что относится к элементу, используемому оптимизатором запросов mysql, для определения индекса, чтобы использовать там несколько аспектов, и для всех них оптимизатор запросов назначает цену
Любое, что вы должны принять во внимание

  • столбец, включенный в условие Where
  • Размер таблиц (а не только размер таблиц в соединении)
  • Оценка количества строк, которые будут выбраны (чтобы решить, использовать ли индекс или просто отсканировать таблицу)
  • , если данныеpes совпадают или не совпадают между столбцами в jion и where:
  • Использование функции или преобразования типов данных, включая неправильное сопоставление
  • Размер индекса
  • Количество элементовindex

и для всех этих опций оценивается стоимость, и это приводит к выбору индекса

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

Также для этого я предложил составной индекс с крайним левым столбцом, связанным с не преобразованными значениями

0 голосов
/ 25 октября 2019

Индексы стараются привыкнуть как можно лучше. Я не могу гарантировать, но это звучит так, как будто движок строит временный индекс на основе A & B для определения статических значений в вашем запросе. Для 420 с лишним миллионов это как раз время для создания такого временного индекса. Если вы заставляете индекс помогать оптимизировать время, то иначе.

Теперь, если вы (и другие) не совсем понимаете индексы, это способ предварительной группировки данных, чтобы помочь оптимизатору. Если у вас есть условия GROUP BY, эти компоненты, где это целесообразно, должны быть частью индекса, а TYPICALLY будет частью критериев, которые есть в вашем запросе.

select colA ,ColB , count(*) as count 
from user_table 
where colC >='2019-09-01 00:00:00' 
      and colC<'2019-09-30 23:59:59' 
      and colA in ("some static value") 
      and ColB in (17) 
group by colA ,ColB;

Теперь давайте посмотрим на вашиндекс, и доступно только на основе ColC. Предположим, что все записи основаны на дне для целей сценария. Сделайте вид, что каждый ИНДЕКС (одиночный или составной) хранится в отдельной комнате. У вас есть индекс только по столбцу даты C. В этой комнате у вас есть 30 коробок (от 1 сентября до 30 сентября), не считая всех других коробок для других дней. Теперь вы должны проходить каждый блок в день и искать все записи, которые имеют значения ColA и ColB, которые вы хотите. Материал в коробке не отсортирован, поэтому вы должны смотреть на каждую запись. Теперь сделайте это за все 30 дней сентября.

Теперь имитируйте СЛЕДУЮЩИЙ индекс, ящики, хранящиеся в другой комнате. Эта комната является составным индексом на основе (и в этом порядке, чтобы помочь оптимизировать ваш запрос) столбцов A, B и C. Итак, теперь вы можете иметь 100 записей для «A». Вы заботитесь только о ColA = "некоторое статическое значение", поэтому вы берете эту одну коробку.

Теперь вы открываете эту коробку и видите кучу меньших коробок ... О .. Это все отдельные "Колонка Б »записи. В верхней части каждого окна представлены все отдельные записи «B», поэтому вы найдете 1 поле со значением 17.

Наконец, теперь вы открываете Box B и смотрите в сторону. Ух ты ... все они приятно отсортированы по дате. Итак, теперь вы быстро прокрутите список, чтобы найти 1 сентября, и потяните все записи до 30 сентября.

Быстрый переход к источнику по оптимизированному индексу поможет вам в долгосрочной перспективе. Наличие индекса

(colA, colB, colC)

значительно повысит производительность вашего запроса.

Последнее замечание. Поскольку вы запрашиваете только одно значение «A» и одно значение «B», вы получите только одну строку назад и не будете нуждаться в выражении group by (в данном случае).

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

Еще одно преимущество индекса из нескольких столбцов. Например, в этом случае, когда все столбцы являются частью индекса, базе данных не нужно переходить на страницы необработанных данных для подтверждения других столбцов. Это означает, что вы смотрите только на значения A, B и C. Все эти поля являются частью индекса. Ему не нужно возвращаться к страницам необработанных данных, где хранятся фактические данные, чтобы подтвердить возвращение их квалификации.

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

Второй индекс уже имеет«A», «B» и предварительно отсортированный диапазон дат «C». Совершено без необходимости перехода на страницы необработанных данных.

...