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

0

У меня есть большая таблица MySQL, которая может содержать 100 миллионов записей. Схема таблицы - это что-то вроде this-

Id varchar(36), --guid,  primary key
IsDirty bit(1),
CreatedOn(Date),
Info varchar(500)

Я создал раздел в поле CreateOn, который создает раздел для ежемесячных данных. Некоторые из строк в таблице обновляются и isDirty устанавливается в 1. При макс, только 10% строк будут иметь значение IsDirty = 1. Существует процесс, который запускается каждую ночь и удаляет данные, которые составляют 6 месяцев со значением IsDirty = 0.

Есть ли увеличение производительности, если я создаю индекс в поле IsDirty? Из того, что я читал, создание индексов в битовом поле может не принести большого значения производительности, но переиндексация после удаления записей может понизить производительность из-за индекса.

Правильно ли я понимаю? Есть ли лучший способ достичь желаемой функциональности?

Теги:
performance
rds

2 ответа

1
Лучший ответ

Существует правило, в котором говорится, что лучше всего индексировать столбцы с высокой мощностью. Численность - это оценочное число различных значений в столбце. Когда вы show indexes from your_table; вы увидите, что ваша колонка IsDirty имеет мощность 2. Очень плохо.

Однако это не учитывает распределение данных. Когда только 10% имеют IsDirty = 1, запросы, такие как select * from your_table where IsDirty = 1 будут полезны из индекса. С другой стороны, ваше задание на удаление, которое проверяет IsDirty = 0 было бы IsDirty = 0, так как дешевле просто выполнить полное сканирование таблицы, поскольку использование вторичного индекса означает, что из индекса считывается первичный ключ (в каждом вторичном индексе первичный ключ сохраняется, поэтому всегда полезно сделать как можно меньше первичного ключа), чтобы идентифицировать строку, которую нужно прочитать.

В руководстве указано следующее, когда предпочитается полное сканирование таблицы:

Каждый индекс таблицы запрашивается, и лучший индекс используется, если оптимизатор не считает, что эффективнее использовать сканирование таблицы. В свое время сканирование использовалось на основании того, что лучший индекс охватывает более 30% таблицы, но фиксированный процент больше не определяет выбор между использованием индекса или проверки. Оптимизатор теперь более сложный и основывает свою оценку на дополнительных факторах, таких как размер таблицы, количество строк и размер блока ввода-вывода.

Также обратите внимание, что тип данных бит не идеален для хранения значений 0 или 1. Существует тип данных bool (который внутренне реализуется как tinyint (1). Я думаю, что я где-то читал причину этого, но я забыл об этом).

  • 0
    Большое спасибо, это помогло.
  • 0
    Это решает поставленный вопрос. (Не беспокойтесь о добавлении INDEX(IsDirty) .) Но INDEX(IsDirty) что делать дальше.
0

Не беспокойтесь о разделении, это вряд ли поможет производительности. Во всяком случае, вам нужно будет увеличивать количество разделов и использовать PARTITION BY RANGE(to_days(..)). Вы не сможете использовать DROP PARTITION, что сделает удаление очень быстрым.

Я осторожно заберу это. Это может сработать и может позволить DROP PARTITION, но я сбив с толку относительно синтаксиса.

PARTITION BY RANGE(TO_DAYS(CreatedOn))
SUBPARTITION BY LINEAR KEY(IsDirty)
SUBPARTITIONS 2

Если вы каждый день получаете большой DELETE, то либо

  • Делайте это ежечасно (или постоянно), чтобы удаление не было большим
  • Как это обсуждается здесь

Также есть

INDEX(IsDirty, CreatedOn) -- in this order.

(Примечание: если подразделение можно заставить работать, этот индекс не нужен.)

Другие советы:

  • Используйте InnoDB.
  • Установите innodb_buffer_pool_size примерно на 70% от объема оперативной памяти.
  • UUID ужасны для больших таблиц из-за случайности доступа - отсюда и высокие значения ввода-вывода.
  • Id varchar(36), --guid, primary key - Id varchar(36), --guid, primary key его в BINARY(16). (Дайте мне знать, если вам нужна помощь.) Сохранение пространства → сокращение стола → сокращение от ввода-вывода.
  • Из-за огромности uuids разбиение может помочь избежать большого количества операций ввода-вывода - это потому, что все вставки этого месяца будут входить в один раздел. То есть, "рабочий набор", поэтому размер buffer_pool может быть меньше.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню