Индексирование и Альтернативы для столбцов с низкой селективностью

какой диапазон тактик доступен для выбора записей в Столбцах с низкой селективностью?

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

похожие вопросы по индексации
MySQL: низкая мощность/селективность столбцов = как индексировать?
индексы сосут в SQL?
что такое индексы и как их использовать для оптимизации запросов в моей базе данных?
определение индексов: какие столбцы, и производительность Удар?
и многие другие родственники.

подходы, о которых я читал (в stackoverflow и в других местах), включают

  • используйте растровый индекс
  • используйте частичный индекс (create index x on t(c2) where c1='a')
  • использовать кластеризованный индекс?
  • не индексируйте столбцы с низкой селективностью, используйте последовательное чтение
  • разделите данные (например, на несколько таблиц с идентичной схемой)
  • использовать дополнительную таблицу (например,active_customers(customer_id)

моя текущая СУБД не поддерживает первые три варианта, перечисленные выше, а остальные кажутся проблематичными - есть ли другие часто используемые подходы?

обновление: я видел - индексируйте столбец с низкой селективностью, но всегда выбирайте только для значений с высокой селективностью.

3 ответов


Я согласен с неразумия это филиала. Но есть кое-что, что нужно знать об этом деле.

Это называется косой и косой убивает. Это идеальное использование для частичного индекса, где вы исключаете 95% оплаченных счетов-фактур и индексируете только более интересную и выборочную статистику. Но у тебя его нет. Вы можете горизонтально разбить все строки на отдельные таблицы/разделы, но затем вам нужно учитывать миграцию строк (перемещение из одного состояния в другое) и это дорого. СУБД должна выполнить обновление, удаление и вставку для изменения состояния. Если вы система с большим объемом, это будет больно.

забудьте, что вы сказали о том, следует ли индексировать на основе избирательности, потому что размещение индекса на быстро меняющемся столбце также обычно является плохой идеей. Ваш индекс будет иметь горячие блоки, где все шаги 1 удаляются, а другой, где все шаги 2 вставляются и Oh кстати, некоторые шаги 2 удаляются на то же время в Шаг 3. Это не будет хорошо масштабироваться.

Я бы рекомендовал вертикально разбить ваш статус на отдельную таблицу(ы).

ваша таблица счетов будет иметь ПК и все столбцы, кроме статуса.

ваш статус вы можете обрабатывать двумя способами. Эта таблица будет иметь значение PK как FK обратно в таблицу накладных, статус и отметку времени для ввода этого статуса. Лучше всего-горизонтально секционированная таблица состояния. У вас будет раздел для каждого статуса возможно. Таким образом, поиск всех или одного "помещенного" статуса будет разделять чернослив и читать только тот раздел, который ему нужен - это очень небольшое количество блоков. Поскольку строка настолько узкая, вы можете получить 400 статусов счетов-фактур в одном блоке. Поиск этого статуса любого счета-фактуры легко, так как на ПК есть глобальный индекс.

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

у вас есть другой выбор Вы можете писать платные статусы или нет. Если это секционированная таблица, можно просто удалить накладную из таблицы состояние накладной при ее перемещении в оплаченную. (Конечно, вы напишете оплаченная запись в таблицу истории, указанную в Бонусном материале). Затем вы сделаете внешнее соединение с таблицей состояния, и nulls будет означать paid. Если вы почти никогда не запрашиваете платный статус, Нет причин делать это быстрым запросом.

Бонусы

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


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

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

индекс можно использовать для

  • index lookups-проверьте указатель индекса, получить запись, повторите
  • index scans-сканирование индекса и получение значений непосредственно из индекс

в противном случае это не очень полезно.

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

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

, я не уверен, что вы понимаете, что в вашем примере вы не имеют низкую селективность. Как вы говорите, большинство записей будет оплачено, и очень мало записей будет выделено. Эти (выделенные) записи будут иметь высокая селективность. Особенно если есть дополнительные условия и если существует составной индекс, содержащий эти дополнительные условия.

Итак, вы, возможно, стучать головой не проблема.

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


разделение-это подход, который хранит же таблица в отдельных областях на основе данных-разработчикам SQL не нужно обращаться к отдельным таблицам.

Я думаю, что это идеально подходит для описанной проблемы - вы можете найти больше об этом на Informix здесь: http://www.dbmag.intelligententerprise.com/blog/main/archives/2008/09/data_partitioni.html