我正在运行一个非常直接的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模式并不是那么复杂。
让我知道是否有一个更好的平台来问这个问题,如果这不是正确的地方。
2条答案
按热度按时间csbfibhn1#
sql将缓存查询计划,因此第二次缓存速度会快得多。您可以清理缓冲区并重新运行查询以查看差异(dbcc freeproccache)
还要注意删除本身的查询开销。你不必再这样做了。根据你的查询,你几乎得不到任何信息。例如,select count(*)的结果要快得多,因为count比删除行更简单
比较一个新表上的delete和一个没有结果的delete并不是一个真正有效的比较。
你可以把50个id放在一个集群表中。in子句不是最好的子句,而且您多次使用同一个集合。但我怀疑这有什么不同
qvsjd97n2#
对于50条记录,我建议切换到一个temp表,并加入它,而不是使用一个大in子句。这将使每次运行的执行计划都是静态的,并且执行起来更加一致。