Удаление 50 строк в 3 таблицах с помощью IN () на SQL сервере так медленно - PullRequest
1 голос
/ 28 мая 2020

Я выполняю довольно простой запрос оператора удаления. У меня есть 50 файловых ключей, и я хочу их удалить. Схема нашей базы данных выглядит так:

  • File - UID (int) столбец является первичным ключом (с уникальным кластеризованным индексом)

  • Версия - File столбец является внешним ключом для File.UID, DataLockerToken столбец является внешним ключом для Cache.UID

  • Cache - UID (uniqueidentifier) ​​столбец является первичным ключом ( с уникальным некластеризованным индексом)

Версия должна была проиндексировать предложения из SQL, которые я применил:

CREATE NONCLUSTERED INDEX [nc_VersionFile_DataLockerToken] 
ON [dbo].[Version] ([File] ASC) INCLUDE([DataLockerToken])

CREATE NONCLUSTERED INDEX [nc_VersionFile_UID] 
ON [dbo].[Version] ([File] ASC) INCLUDE([UID]) 

Взаимосвязи: Файл 1: M к версии 1: 1 в кэш

Вот запрос, который я пытаюсь выполнить:

DELETE [Cache] 
FROM [Cache] c 
INNER JOIN Version v ON c.UID = v.DataLockerToken 
WHERE v.[File] IN ( 241647, ... 50 ids in total ..., 244038 );

DELETE Version 
WHERE [File] IN ( 241647, ... 50 ids in total ..., 244038 );

DELETE [File] 
WHERE UID IN ( 241647, ... 50 ids in total ..., 244038 );

Это занимает почти 1 минуту, и я ожидаю, что это будет практически мгновенно. Таблицы File и Version являются просто метаданными, тогда как таблица Cache фактически содержит двоичную информацию для файла.

Вот снимок экрана с планом выполнения:

enter image description here

ОБНОВЛЕНИЕ : это должно быть что-то с таблицей кэша или двоичной информацией внутри, потому что если я запускаю запрос в SQL Server Management Studio , как я уже сказал, это занимает ~ 1 минуту. Затем, если я снова запустил тот же самый запрос (те же ключи, поэтому, очевидно, их там нет) снова в Management Studio или даже в консольном приложении C#, запрос выполняется немедленно, поэтому, если нет какого-либо `` кеширования запросов '', которое я не думаю, что есть, это указывает на тот факт, что удаляемые данные - это проблема, а не проблема с запросом?

Имея эту минимальную информацию, кто-нибудь увидит явные проблемы в плане выполнения? Обычно я полагаюсь на SQL, чтобы дать мне подсказку по индексу, если это необходимо (и я знаю, что вы не всегда можете доверять SQL), но это не похоже на то, что эта схема db такая сложная.

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

Ответы [ 2 ]

1 голос
/ 28 мая 2020

SQL будет кэшировать планы запросов, поэтому во второй раз это будет намного быстрее. вы можете очистить буферы и повторно запустить запросы, чтобы увидеть разницу (DB CC FREEPROCCACHE)

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

сравнение удаления в таблице fre sh с удалением без результата на самом деле не является допустимым сравнением .

вы можете поместить 50 идентификаторов в кластеризованную таблицу. предложение IN не лучшее, и вы повторно используете один и тот же набор несколько раз. но я сомневаюсь, что это имеет большое значение. tbh

0 голосов
/ 28 мая 2020

С 50 записями я бы рекомендовал переключиться на временную таблицу и присоединиться к ней вместо использования большого предложения IN. Это сделает план выполнения c за запуск и выполнит гораздо более стабильную работу.

...