Как повысить производительность записи в базу данных?

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

Так что либо

  • Придумываем способ его оптимизировать
  • Уберите эту функцию или
  • Сделайте что-нибудь совершенно другое при регистрации этих значений.
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
0
913
10
Перейти к ответу Данный вопрос помечен как решенный

Ответы 10

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

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

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


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

Я обновил свои вопросы, индекс НЕ на ПК, спасибо за быстрый ответ.

RyanKeeter 23.09.2008 00:03

первичные ключи всегда имеют связанный уникальный индекс. Нам нужна дополнительная информация. Какой DDL вы использовали для создания таблицы? Какие DML используют для поиска? Используете ли вы предложение "нравится"?

David Medinets 23.09.2008 00:22
Ответ принят как подходящий

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

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

Индексированный поиск в таблице из 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.

Danimal 23.09.2008 00:03

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

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

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

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

Вы также можете изучить:

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

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

David Medinets 23.09.2008 00:19

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

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

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

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

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

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

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

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

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

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

Вам нужны операторы обновления и вставки на основе наборов.

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

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

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

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

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

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

Другие вопросы по теме