Запрос SELECT COUNT, соответствующий 100 миллионам строк из таблицы с 1 миллиардом строк, занимает 30 секунд даже с индексом - PullRequest
2 голосов
/ 22 апреля 2020

Я пытаюсь понять индексы в MySQL и как они работают и насколько они улучшают скорость. Я создал таблицу с 1 миллиардом строк, в которой есть столбец index_this, содержащий 10 возможных строковых значений, примерно равномерно распределенных (поэтому каждое значение находится примерно в 100 миллионах строк). Вот запрос, который я выполняю.

SELECT COUNT(*) FROM mydatabase.mytable WHERE mytable.index_this = ‘A1ndxstring’;

Выполнение этого запроса занимает 30 секунд с индексом BTREE для столбца index_this. Я проверил, использует ли оптимизатор запросов индекс.

EXPLAIN SELECT COUNT(*) FROM mydatabase.mytable WHERE mytable.index_this = ‘A1ndxstring’;

возвращает

id              1
select_type     SIMPLE
table           mytable
type            ref
possible_keys   index_this
key             index_this
key_len         43
ref             const
rows            188130384
Extra           Using where; Using index

Вот как я создал свой индекс.

CREATE INDEX myindex ON mydatabase.mytable (index_this);

Я не указал длину префикса, но ранее я пытался это с длиной префикса 2, и это просто сделало запрос почти в 100 раз длиннее. Целесообразно ли 30 секунд для этого размера таблицы и этого запроса, даже с индексом? Я ищу любой совет о том, как я могу улучшить скорость. Заранее спасибо.

1 Ответ

1 голос
/ 27 апреля 2020

Префикс индекса редко помогает; часто это больно.

Using index говорит, что индекс «покрывает» и использовался. То есть не нужно трогать данные. И, учитывая запрос, ничего лучше сделать нельзя.

Итак, почему это заняло так много времени? Просто. Он должен был пройти через ~ 188 миллионов «строк» ​​в индексе. Это может быть миллион блоков индекса. Каждый блок 16 КБ. Сколько времени занимает ваш диск, чтобы пройти через несколько ГБ? Вероятно, 30 секунд, которые вы испытали, это реалист c. Даже если все эти блоки кэшируются в buffer_pool, их просмотр займет некоторое время.

Если бы было 1000 различных значений, оптимизатор все равно выбрал бы тот же план запроса («Использование индекса»). ) и работать в 100 раз быстрее. Время пропорционально количеству затронутых строк индекса.

По сути, есть два способа выполнения запроса: использование индекса по сравнению со сканированием таблицы. Он выбрал «правильный». Никакая статистика, анализ и т. Д. c не могут помочь.

Если вы хотите описать цель real , возможно, вам поможет другой метод - например, «сводные таблицы». Есть несколько способов обновить статистику. Триггер, отдельное обновление, SP, ночной накопительный пакет и т. Д. c - выбор зависит от производительности, ограничений, потребности в значениях с точностью до секунды и т. Д. c. (Начните новый Вопрос, если вы хотите копать глубже.)

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

«Бросить аппаратное обеспечение в него» вряд ли поможет.

  • Скорость ЦП - примерно до 2000 года, ЦП становились все быстрее и быстрее. Но с тех пор изменений было очень мало.
  • Количество ядер - MySQL не использует более одного ядра для одного запроса. (8.0.17 (?) Имеет очень несколько случаев, когда он делает вещи параллельно. Я не думаю, что ваш запрос среди них.)
  • Скорость оперативной памяти - Кроме того, не ускоряется очень быстро.
  • Размер оперативной памяти - если индекс кэшируется в пуле буферов, а не читается с диска, ускорение заметно. (Я подозреваю, что у вас сейчас достаточно оперативной памяти.)
  • Скорость диска - единственное значительное увеличение скорости чтения с диска за последние несколько десятилетий было с HDD на SSD. Но мой ответ предполагал, что вы используете SSD.
...