在SQLServer中使用in()删除3个表中的50行太慢了

plicqrtu  于 2021-08-13  发布在  Java
关注(0)|答案(2)|浏览(536)

我正在运行一个非常直接的delete语句查询。我有50个'文件'键,我想删除它们。我们的数据库架构如下所示:
文件- UID (int)列是主键(具有唯一聚集索引)
版本- File 列是的外键 File.UID , DataLockerToken 列是cache.uid的外键
缓存- 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 表实际上保存文件的二进制信息。
以下是执行计划的屏幕截图:

更新:它必须是缓存表或二进制信息中的东西,因为如果我在SQLServerManagementStudio中运行查询,就像我说的,需要大约1分钟。然后,如果我在management studio甚至是c控制台应用程序中再次运行完全相同的查询(相同的键,显然它们不在那里),那么查询是即时的,所以除非存在某种我认为不存在的“查询缓存”,否则这就说明了一个事实,即被删除的数据是问题,而不是查询的问题?
有没有人能在执行计划中看到一些明显的问题?如果需要的话,我通常依赖sql来给我一个索引提示(我知道你不能总是相信sql),但是这个db模式并不是那么复杂。
让我知道是否有一个更好的平台来问这个问题,如果这不是正确的地方。

csbfibhn

csbfibhn1#

sql将缓存查询计划,因此第二次缓存速度会快得多。您可以清理缓冲区并重新运行查询以查看差异(dbcc freeproccache)
还要注意删除本身的查询开销。你不必再这样做了。根据你的查询,你几乎得不到任何信息。例如,select count(*)的结果要快得多,因为count比删除行更简单
比较一个新表上的delete和一个没有结果的delete并不是一个真正有效的比较。
你可以把50个id放在一个集群表中。in子句不是最好的子句,而且您多次使用同一个集合。但我怀疑这有什么不同

qvsjd97n

qvsjd97n2#

对于50条记录,我建议切换到一个temp表,并加入它,而不是使用一个大in子句。这将使每次运行的执行计划都是静态的,并且执行起来更加一致。

相关问题