Значительно ли замедляет вставка индекса по битовому столбцу?

11

У меня есть таблица с записями от 1 до 5 миллионов. Небольшая часть этих записей имеет один из битовых столбцов, установленный в «TRUE». Нужно быстро найти эти записи. Я думаю, что индекс может ускорить поиск по этому столбцу, но я боюсь насчет INSERT. Отсюда и мой вопрос.

База данных работает как хранилище данных, поэтому существует множество SELECT и небольших (до 10-20 в день), но довольно больших INSERT (до 200 тысяч записей одновременно). Я боюсь более длительного времени этого импорта в базу данных.

marioosh
источник
5
Какая версия SQL Server? Если 2008+ звучит как отфильтрованный индекс, может быть то, что вам нужно.
Мартин Смит
SQL Server 2005
marioosh
1
Вы можете разделить таблицу (добавить новую таблицу только с одним столбцом, PK таблицы, которая будет заполнена только теми строками, для которых битовый столбец имеет значение true - в конце концов, вы даже можете удалить битовый столбец.) Индексированный view будет работать, как и в 2005 году, с отсутствием частичных индексов.
ypercubeᵀᴹ
Будьте внимательны с индексированным представлением, так как вы упомянули, что у вас есть 10-20 больших вставок в день, обслуживание индексированного представления может превзойти выигрыш в производительности. Я не думаю, что какая-либо «готовая к использованию» функция SQL 2005 вы можете использовать для улучшения ситуации. но если вы перечислите текущую структуру таблицы и существующий индекс, мы можем найти альтернативный дизайн.
Ануп Шах

Ответы:

8

Битовый индекс на 1 миллион записей бесполезен. Оптимизатор никогда не будет его использовать, вы просто заплатите за его поддержку. Гораздо лучшая альтернатива - добавить этот бит как самый левый ключ в кластеризованном индексе.

Но я сделаю слепой выстрел в темноте и угадаю, что у вас есть шаблон очереди: записи сбрасываются в таблицу с битом, установленным в «ИСТИНА» (т. Е. «Needsprocessing = true»), и затем фоновый процесс выглядит для этих записей выполняет некоторую обработку и обновляет бит до FALSE. Это вездесущий паттерн, также известный как «шаблон рецепта катастрофы производительности». Я бы порекомендовал поместить записи в таблицу и одновременно поместить уведомление (может быть таким же простым, как только что вставленный идентификатор записи) в очередь . См. Использование таблиц в качестве очередей .

Ремус Русану
источник
1
Я не вижу смысла размещать битовый столбец слева, поскольку мы не знаем других столбцов фильтра с высокой степенью кардинальности, которые может иметь пользователь. до сих пор я видел столбец BIT - последний выбор в кластерном индексе. но да, +1 за хорошую ссылку "Использование таблицы в качестве очередей".
Ануп Шах
2
На самом деле я провел тест, и да, он будет использовать индекс. Создайте таблицу (идентификатор Id, бит myBit), добавьте 100 строк, где бит равен 0, и 2000000, где бит равен 1. Убедитесь, что статистика обновлена ​​(при необходимости), и выполните запрос для myBit = 0, и индекс будет использоваться.
Кеннет Фишер
@KennethFisher за исключением того, что в типичном высокоскоростном паттерне вставки TRUE / update to FALSE статистика всегда будет устаревшей. Если вы предпочитаете играть в русскую рулетку с оптимизатором, а не делать четкий дизайн, вы получите то, что заслуживаете ...
Ремус Русану
«никогда не будет его использовать», это утверждение верно для 99% случаев, но мы не знаем, в каком случае находится OP. Я успешно проиндексировал бит. Варианты использования существуют.
USR
вопрос - является ли здесь неправильный ответ , в частности> "Когда вы индексируете битовое поле (или некоторый узкий диапазон), вы уменьшаете рабочий набор только на количество строк, соответствующих этому значению. Если у вас есть небольшое количество строк, соответствующих ему значительно уменьшит ваш рабочий набор . Для большого количества строк с распределением 50/50 это может принести вам очень небольшой прирост производительности по сравнению с обновлением индекса ». В каком случае индекс для бита, который соответствует 1% записей, избавит от необходимости сканировать 99% из 1 миллиона для значительного увеличения?
drzaus
2

Как сказал @MartinSmith, если вы когда-нибудь обновитесь до SQL 2008, тогда фильтрованный индекс будет идеальным решением. Однако в то же время в общем случае ЛЮБОЙ добавленный индекс увеличит ваше время загрузки. Маленькие индексы меньше, чем большие.

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

Следующая вещь, на которую стоит обратить внимание: «У меня уже есть много индексов?» Не существует жесткого и быстрого правила относительно того, что такое «много», но я обычно придерживаюсь правила из 10 индексов - это предел, если мне ДЕЙСТВИТЕЛЬНО не нужен новый.

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

Только вы действительно можете решить, что является «значительным». У меня есть машины, где добавление 5 минут к времени загрузки является «значительным», а другие, где я смело могу увидеть увеличение на пару часов.

РЕДАКТИРОВАТЬ:

Другой вариант - разделить ваш стол. Возможно, вам придется использовать многораздельное представление, если вы не используете Enterprise Edition, но даже в этом случае это должно помочь. Вы помещаете свой бит 0 в один раздел, а свой бит 1 в другой. Предполагая, что вы вставляете только одну версию или другую, вы можете даже ускорить вставку.

Кеннет Фишер
источник