Мы регистрируем значения, и мы записываем их в таблицу только один раз. Когда мы добавляем значения в таблицу, мы должны каждый раз искать, чтобы увидеть, нужно ли вставить значение или просто получить идентификатор. У нас есть индекс для таблицы (не по первичному ключу), но там около 350 000 строк (так что на выполнение 10 из этих значений уходит 10 секунд).
Так что либо





Чтобы было ясно, индекс находится в поле (предположительно varchar или nvarchar) в таблице, правильно? Не ПК?
хорошо, после редактирования: вы выполняете индексированный поиск в большом (n) текстовом поле varchar. Даже с индексом, который может быть довольно медленным - вы все равно делаете 2 больших сравнения строк. Я не могу найти отличного способа сделать это, но некоторые начальные SWAGS:
* да, я знаю, что буду понижать мод для этого, но иногда прагматизм просто работает.
первичные ключи всегда имеют связанный уникальный индекс. Нам нужна дополнительная информация. Какой DDL вы использовали для создания таблицы? Какие DML используют для поиска? Используете ли вы предложение "нравится"?
Как часто вы пишете в таблицу или читаете из нее. Если у вас есть частые записи и случайные чтения, подумайте о том, чтобы просто всегда выполнять вставки, а затем обрабатывать сворачивание значений при выполнении выбора.
Если вы пытаетесь поместить все в одну таблицу, подумайте о том, чтобы разбить их на отдельные таблицы, чтобы уменьшить размер, или запретите использование разделов в таблице.
Индексированный поиск в таблице из 350 тыс. Строк занимает 1 секунду? Для меня это звучит излишне медленно ... Вы уверены, что что-то еще не так?
Не видя ваших реальных вопросов, я могу только обобщить. Однако я бы предложил следующие идеи / советы:
1) Вы проверили, действительно ли ваш индекс используется для поискового запроса? Если бы это был индекс с высокой мощностью, он должен был быть намного быстрее.
2) Вы можете объединить 2 операции в одну хранимую процедуру, которая сначала искала строку, а затем при необходимости выполняла вставку .... что-то вроде:
IF EXISTS (SELECT ID FROM YourTable WHERE ID = @ID_to_look_for)
@ID_exists = 1
ELSE
@ID_exists = 0
Если вы опубликуете, как выглядят точные запросы, возможно, я смогу предложить более подробный ответ.
Я предполагаю, что он просматривает записанный текст, а не идентификаторы. То есть выберите @id = id из mytable, где log_text = @text.
Не уверен, что у меня достаточно информации, чтобы ответить на этот вопрос, но, тем не менее, вот несколько мыслей:
Вместо поиска просто попробуйте вставить значение. Если таблица предназначена для отказа от повторяющихся записей, то есть у нее есть первичный ключ или уникальный индекс, то при вставке произойдет ошибка. Просто перехватите ошибку вставки и, если она получена, возьмите идентификатор, как обычно.
Я согласен с тем, что поиск не должен занимать так много времени, но зачем заставлять движок анализировать запрос, отображать путь, выполнять поиск, а затем отправлять вам результаты до того, как вы вставите, если он может делать и то, и другое одновременно.
Вы также можете изучить:
С уникальным индексом база данных всегда будет делать собственный выбор, чтобы определить, существует ли уже запись. Следовательно, вам определенно не следует выполнять тот же выбор внутри приложения перед вставкой - если только производительность не важна и вам нужно избегать исключений для управления сообщениями.
«Когда мы добавляем значения в таблицу, мы должны каждый раз искать, чтобы увидеть, нужно ли вставить значение или просто получить идентификатор».
Мы привыкли называть это операцией «upsert».
try:
UPDATE log SET blah blah blah WHERE key = key;
except Missing Key:
INSERT INTO log(...) VALUES(...);
Мы никогда не выполняли собственный запрос, чтобы узнать, существует ли ключ, поскольку это задача оператора UPDATE.
Прежде всего, посмотрите на план запроса, чтобы понять, что он делает. Это скажет вам, использует ли он index. Одна секунда для теста / вставки одной строки - это слишком медленно. Для 350 тыс. Строк этого достаточно, чтобы он мог сканировать таблицу по кэшированной таблице.
Второй. Посмотрите на физическое расположение вашего сервера. У вас есть что-то вроде журналов и данных, совместно использующих один и тот же диск?
В-третьих, убедитесь, что столбцы индекса в вашем уникальном ключе находятся в том же порядке, что и предикат в запросе выбора. Различия в порядке могут запутать оптимизатор запросов.
В-четвертых, рассмотрим кластеризованный индекс по уникальному ключу. Если это ваш основной режим поиска строки, это уменьшит количество обращений к диску, поскольку данные таблицы физически хранятся с кластеризованными индексами. Информацию о кластерных индексах см. В Этот. Установите стол с большим коэффициентом заполнения.
Если у вас нет столбцов BLOB-объектов, 350 тыс. Строк намного ниже порога, при котором разделение должно иметь значение. Эта таблица размеров должна полностью помещаться в кеш.
Вы случайно используете курсор? На таком маленьком столе не должно пройти десять секунд, чтобы сделать то, что вы сказали.
Вам нужны операторы обновления и вставки на основе наборов.
Исключите проблемы с подключением и драйверами - убедитесь, что другие операции с той же базой данных, выполняемые таким же образом, выполняются достаточно быстро
Убедитесь, что вы измеряете эту операцию независимо от других операций, которые могут выполняться в рамках той же транзакции.
Убедитесь, что у вас нет сценариев блокировки - остановите все остальное и просто выполните последовательность поиска и обновления из своего инструмента управления.
Проверьте, является ли поиск более затратным (99%) или дорогостоящей записью на диск - хотя 10 секунд - это слишком много даже для медленного диска. Сделайте это для полноты картины.
Проверьте, используется ли ваш индекс запросом - возможно, выполняется сканирование таблиц.
Если столбцы, используемые для индекса, представляют собой текстовое поле, проверьте, является ли индексирование текста корнем проблемы, выполнив поиск в нетекстовом столбце, который имеет индекс. В таком случае попробуйте изменить логику, чтобы использовать PK или использовать хэш вместо текста.
Я обновил свои вопросы, индекс НЕ на ПК, спасибо за быстрый ответ.