Как я могу ускорить запросы с `GROUP BY` в них? - PullRequest
0 голосов
/ 19 февраля 2019

Подробности:

  • MariaDB: Версия сервера: 10.2.10-MariaDB Сервер MariaDB
  • В таблице БД trans_tbl используется ядро ​​Aria DB
  • Таблица несколько большая: 126 006 123 строки
  • Сервер совсем не большой: AWS t3 micro с подключенным 30 ГБ EBS

Я применил индексы к этой таблице БД следующим образом:

  • Первичный ключ: evt_id
  • Еще один индекс в столбце, который я хочу сгруппировать, по: transaction_type

3 Вопросы, связанные с этим:

  1. Почему индекс transaction_type игнорируется, когда я выполняю следующее?

    SELECT COUNT(evt_id), transaction_type FROM trans_tbl GROUP BY transaction_type
    

    Если я смотрю на вывод из EXPLAIN, я вижу:

    MariaDB [my_db]> EXPLAIN SELECT COUNT(evt_id), transaction_type FROM trans_tbl GROUP BY transaction_type;
    +------+-------------+-----------+------+---------------+------+---------+------+-----------+---------------------------------+
    | id   | select_type | table     | type | possible_keys | key  | key_len | ref  | rows      | Extra                           |
    +------+-------------+-----------+------+---------------+------+---------+------+-----------+---------------------------------+
    |    1 | SIMPLE      | trans_tbl | ALL  | NULL          | NULL | NULL    | NULL | 126006123 | Using temporary; Using filesort |
    +------+-------------+-----------+------+---------------+------+---------+------+-----------+---------------------------------+
    

    Что меня смущает, так это то, что оба элементов в запросе проиндексированы.Так не следует ли использовать индекс (ы)?

  2. Почему является индексом transaction_type, используемым в следующем случае, где всеГотово переключается с COUNT(evt_id) - первичный ключ - на COUNT(1).(Столбец transaction_type, сгенерированный из него индекс называется TransType.)

    MariaDB [my_db]> EXPLAIN SELECT COUNT(1), transaction_type FROM trans_tbl GROUP BY transaction_type;
    +------+-------------+-----------+-------+---------------+-----------+---------+------+-----------+-------------+
    | id   | select_type | table     | type  | possible_keys | key       | key_len | ref  | rows      | Extra       |
    +------+-------------+-----------+-------+---------------+-----------+---------+------+-----------+-------------+
    |    1 | SIMPLE      | trans_tbl | index | NULL          | TransType | 35      | NULL | 126006123 | Using index |
    +------+-------------+-----------+-------+---------------+-----------+---------+------+-----------+-------------+
    
  3. Первый запрос (с COUNT(evt_id)) занимает 2 минуты и 40 секунд,Поскольку это не использование индексов, это имеет смысл.Но второй запрос (с COUNT(1)) занимает 50 секунд.Это не имеет смысла для меня.Разве это не должно занять по существу 0 секунд?Разве он не может просто посмотреть на первое и последнее значение индекса каждой группы, вычесть их и подсчитать?Мне кажется, что это действительно на самом деле считается.Какой смысл в индексе?

    • Наверное, мой более важный вопрос: Как мне настроить мои индексы, чтобы позволить группировке по этому индексу возвращать результаты почти мгновенно, как я хотел быожидаете?

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

1 Ответ

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

COUNT(x) проверяет x на наличие NOT NULL перед подсчетом строки.

COUNT(*) - это обычный шаблон для подсчета строк.

Итак ...

SELECT COUNT(evt_id), transaction_t is just `SELECT FIND_IN_SET(17, '8,12,17,90');`ype
    FROM trans_tbl GROUP BY transaction_type;

решил сделать сканирование таблицы, затем отсортировать и сгруппировать.

SELECT COUNT(*), transaction_type
    FROM trans_tbl GROUP BY transaction_type;

увидел INDEX(transaction_type) и сказал: "Хорошо, я могу просто отсканировать этот индекс без необходимости сортировки".Примечание: он все еще должен сканировать, чтобы считать.Но INDEX меньше таблицы, поэтому это можно сделать быстрее.Это также называется «покрывающим» индексом, поскольку все столбцы, необходимые в SELECT, находятся в том, что один INDEX.

COUNT(1) может обрабатываться так же, как COUNT(*), я не знаю.

INDEX(transaction_type) по сути идентично INDEX(transaction_type, evt_id).Это потому, что PRIMARY KEY незаметно прикреплен к любому вторичному ключу в InnoDB.

Я не знаю, почему INDEX(transaction_type, evt_id) не использовался.Итог: используйте COUNT(*).

Почему бы не 0 секунд?Подсчеты нигде не сохраняются.В любом случае, могут быть другие запросы, изменяющие количество при запуске SELECT.Улучшение произошло благодаря сканированию 126M строк с двумя столбцами вместо 126M строк с несколькими столбцами.

...