Mysql: оптимальный способ выполнения операции count (*) для столбца с низкой мощностью - PullRequest
0 голосов
/ 18 марта 2019

Справочная информация:

У меня есть схема Mysql со следующей структурой

@Data
public class DBQueryEvaluation {
    //primary key
    private final Long id;

    //The combination of a 'query' and an 'evaluationId' will always be unique.
    private final Long evaluationId;
    private final String query;

    private final Date createdAt;
    private final Date updatedAt;
}

1012 * Constraint *:

Комбинация ' запроса ' и 'valuationId ' всегда будет уникальной.

Для данного оценочного идентификатора может быть довольно много запросов. Всего в таблице 5 миллионов записей. (~ 50 000 запросов на каждый оценочный идентификатор, 100 таких оценок = 5 миллионов записей).

Цель:

Хотите сделать подсчет (записи) для данного оценочного идентификатора.

Вопросы:

Принимая во внимание, что кардинальность оценкиId довольно низкая (тот же оценочный идентификатор повторяется для ~ 50k записей) :

  1. Индексирование'valuationId 'рекомендуется делать здесь. Ожидая, что реализация BTree должна быть в состоянии обеспечить счет в порядке миллисекунд. (<10 мс) </li>
  2. Какие могут быть возможные недостатки, если таковые имеются, для индексации такого атрибута с низкой мощностью?
  3. Каковы другие наилучшие подходы для подсчета (*).

=== Обновление ===

  • Я ожидаю полностью последовательного представления. Нет приближений.
  • Обновления могут быть применены поверх существующих строк.

1 Ответ

2 голосов
/ 18 марта 2019
  1. Индексация'valuationId 'рекомендуется делать здесь.Ожидая, что реализация BTree должна быть в состоянии обеспечить счет в порядке миллисекунд.(<10 мс) </li>

Да, без индекса движок должен выполнить полное сканирование таблицы.Однако при использовании индекса ему не нужно будет получать доступ к записям данных, но он может получить счет только из индекса.Для этого ему нужно прочитать количество записей индекса, которое намного меньше числа записей данных, поскольку:

  • Листовые блоки индекса имеют несколько указателей записей, которые читаются в чанках блоков.
  • Количество дополнительных операций чтения блоков, необходимых для выделения конечных блоков, которые относятся к идентификатору оценки, является логарифмическим по отношению к общему количеству блоков.

Например, если размер блока равен 10, а 50 000 записей имеют идентификатор оценки, то необходимо прочитать около 5555 блоков.Сравните это как минимум с 500 000 блоков, которые нужно прочитать при сканировании таблицы.Очевидно, что в базах данных есть методы оптимизации, которые затрудняют справедливое сравнение, и поэтому имеет смысл просто попробовать.

Какие могут быть возможные недостатки, если таковые имеются для индексации такого атрибута с низкой мощностью?

Роль мощности зависит от того, сколько записей данных помещается в один блок (т. Е. <=размер записи / размер блока).Если это число приблизится к количеству элементов, то преимущество индекса исчезнет. </p>

Каковы другие наилучшие подходы для получения счетчика (*).

Вы можете переоценить, насколько важно иметь точный счет, когда такойколичество составляет порядка 50 000, и, зная, что через секунду после того, как вы получите счет, возможно, уже были новые вставки / удаления.Имеет ли значение, действительно ли это 49 756, а не 49 695?

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

Чтобы повысить точность, вы можете объединить приведенную выше таблицу «count» с триггером вставки / удаления в таблицу данных, который бы вставил эффект этогоизменить (как значение +1 или -1) в таблицу журнала.Тогда запрос количества записей будет использовать таблицу «count» в качестве отправной точки и изменить результат на основе этих значений + 1 / -1 в таблице журнала.Приведенное выше задание очищает журнал при каждом запуске.

...