Как улучшить производительность записи в базу данных? - PullRequest
0 голосов
/ 22 сентября 2008

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

Так что либо

  • Мы придумываем способ его оптимизации
  • Удалите эту функцию или
  • Делайте что-то совершенно другое, регистрируя эти значения.

Ответы [ 10 ]

2 голосов
/ 22 сентября 2008

Просто чтобы прояснить, индекс находится в поле (предположительно, varchar или nvarchar) в таблице, верно? Не ПК?

хорошо, после редактирования: выполняется индексированный поиск в большом (n) текстовом поле varchar. Даже с индексом, который может быть довольно медленным - вы по-прежнему делаете 2 больших сравнения строк. Я не могу придумать отличный способ сделать это, но некоторые начальные SWAGS:

  • вычисляет хэш текста, который нужно зарегистрировать, и сохраняет его в базе данных для последующих поисков
  • , как предложил другой автор, сохраняет все строки и отфильтровывает дубликаты в запрос (или с ночной партией, независимо от того, что
  • не проверяет дубликаты. Поймать исключение может все еще дешевле, чем поиск *
  • нанять человека с действительно хорошей памятью, который быстро мыши. Когда сообщение будет зарегистрировано, высветите его на экран с приглашением принять / отклонить. Если запись обманчива, нажмите «Отклонить»


* Да, я знаю, что меня это унизит, но иногда прагматизм просто работает.

1 голос
/ 23 сентября 2008

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

Во-вторых. Посмотрите на физическое расположение вашего сервера. У вас есть что-то вроде журналов и данных на одном диске?

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

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

Если у вас нет столбцов BLOB-объектов, 350 тыс. Строк намного ниже порога, в котором разделение должно иметь значение. Эта таблица размеров должна полностью помещаться в кеше.

1 голос
/ 23 сентября 2008

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

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

Вы также можете посмотреть:

  1. индексирование лучше, при условии, что есть место для улучшения
  2. Изменение физического макета базы данных для улучшения ввода-вывода
  3. Увеличение объема памяти, доступной для SQL Server
1 голос
/ 23 сентября 2008

Не видя ваших реальных запросов, я могу только обобщить. Тем не менее, я бы предложил следующие идеи / советы:

1) Вы убедились, что ваш индекс действительно используется для поискового запроса? Если бы это был индекс с высокой кардинальностью, он должен быть намного быстрее.

2) Вы можете объединить 2 операции в одну хранимую процедуру, которая сначала ищет строку, а затем выполняет вставку, если необходимо .... что-то вроде:

IF EXISTS (SELECT ID FROM YourTable WHERE ID = @ID_to_look_for)
      @ID_exists = 1
ELSE
      @ID_exists = 0

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

1 голос
/ 22 сентября 2008

Требуется 1 секунда, чтобы выполнить индексированный поиск в таблице из 350 тыс. Строк? Это звучит довольно медленно для меня .. Вы уверены, что нет ничего плохого?

1 голос
/ 22 сентября 2008

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

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

0 голосов
/ 24 сентября 2008
  1. Исключите проблемы с подключением и драйвером - убедитесь, что другие операции в той же базе данных, выполняемые таким же образом, выполняются достаточно быстро

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

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

  4. Проверьте, является ли поиск более дорогим (99%) или дорогая запись на диск - хотя 10 секунд слишком высоки даже для медленного диска. Сделайте это ради полноты.

  5. Проверьте, используется ли ваш индекс в запросе - может происходить сканирование таблицы.

  6. Если столбцы, используемые для индекса, являются текстовым полем, проверьте, не является ли текстовая индексация корнем проблемы, выполнив поиск по нетекстовому столбцу с индексом. Если это так, попробуйте изменить логику для использования PK или использовать хеш вместо текста.

0 голосов
/ 23 сентября 2008

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

Требуются операторы обновления и вставки на основе набора.

0 голосов
/ 23 сентября 2008

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

Мы привыкли называть это операцией "upsert".

try:
    UPDATE log SET blah blah blah WHERE key = key;
except Missing Key:
    INSERT INTO log(...) VALUES(...);

Мы никогда не делали собственный запрос, чтобы выяснить, существует ли ключ, так как это работа оператора UPDATE.

0 голосов
/ 23 сентября 2008

Я не уверен, что у меня достаточно информации, чтобы ответить на этот вопрос, но вот некоторые мысли:

  1. Если вы этого еще не сделали, возможно, вы сможете выполнить вставку и проверку в одном SQL (вставить в таблицу (значения) (выберите последующее внешнее соединение с таблицей, где id равен нулю)
  2. Используете ли вы слой DAL или хранимые процедуры для этого? Контролируете ли вы SQL, используемый для выбора / вставки? Если вы этого не сделаете, вы можете захотеть, чтобы пользователь SQL Profiler проверил, что отправляется в БД, если его формат делает индекс недействительным.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...