需要帮助来提高一些 TSQL“不存在”的查询性能
Posted
技术标签:
【中文标题】需要帮助来提高一些 TSQL“不存在”的查询性能【英文标题】:Needing help to improve some TSQL "not exists" query performance 【发布时间】:2013-06-04 12:46:33 【问题描述】:我在对包含 750 000 个条目的表运行查询时遇到性能问题。执行需要 15 到 20 秒,在此期间阻止对数据库的访问并创建大量错误日志(当然还有愤怒的客户)。
这里是查询:
DECLARE @FROM_ID AS UNIQUEIDENTIFIER = 'XXX'
DECLARE @TO_ID AS UNIQUEIDENTIFIER = 'YYY'
update tbl_share
set user_id = @TO_ID
where user_id = @FROM_ID
and not exists (
select *
from tbl_share ts
where ts.file_id = file_id
and ts.user_id = @TO_ID
and ts.corr_id = corr_id
and ts.local_group_id = local_group_id
and ts.global_group_id = global_group_id
)
我现在有点卡住了,因为我的 TSQL 知识有限。 我想知道是否:
我应该创建一个临时表 我应该选择“*”以外的其他内容我没有太多机会运行测试,因为它是一个生产数据库,并且每天有 10-20 个客户永久连接。
感谢您的帮助!
【问题讨论】:
这个好像没用:and ts.corr_id = corr_id and ts.local_group_id = local_group_id and ts.global_group_id = global_group_id
@RBarryYoung 哦,谢谢,我会修改我的神话
另一种提高性能的方法可能是使用公用表表达式 (CTE)。 @Tim Schmelter:是的。
@sjkm:“是的,确实如此”的意思是,是的,它没用?整个条件没有意义,因为您需要使用第一个表,例如:where ts.file_id = tbl_share.file_id
而不是 ts.file_id = file_id
,这始终是正确的。
@BorisDelormas - 不,不是。它正在将子查询中的值与其自身进行比较。非限定列名从最近的范围向外解析。我之前发布的 SQL Fiddle 链接修复了该特定问题。
【参考方案1】:
重组你的代码逻辑怎么样?
DECLARE @FROM_ID AS UNIQUEIDENTIFIER = 'XXX'
DECLARE @TO_ID AS UNIQUEIDENTIFIER = 'YYY'
IF NOT EXISTS (select *
from tbl_share ts
where ts.user_id = @TO_ID)
BEGIN
update tbl_share
set user_id = @TO_ID
where user_id = @FROM_ID
END
因此,您事先进行了检查,仅在需要时才更新数据库。
HTH
【讨论】:
感谢您的方法,但我不能,因为我必须保持约束 ts.corr_id = corr_id and ts.local_group_id = local_group_id and ts.global_group_id = global_group_id跨度> 好的,我想你缺少一些索引,例如NOT EXISTS 语句中包含的所有列之一。创建非集群索引 [IX_TBL_SHARE_EXISTS] ON [TBL_SHARE](file_id, user_id, corr_id, local_group_id, global_group_id) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS , ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]【参考方案2】:让我们从优化选择开始。 检查查询计划。 如果那是PK那么它是碎片化的吗?
select *
from tbl_share
where user_id = @FROM_ID
and not exists (
select *
from tbl_share ts
where ts.file_id = file_id
and ts.user_id = @TO_ID
and ts.corr_id = corr_id
and ts.local_group_id = local_group_id
and ts.global_group_id = global_group_id
)
select tUpdate.*
from tbl_share as tUpdate
left outer join tbl_share as tExists
on tUpdate.user_id = @FROM_ID
and tExists.user_id = @TO_ID
and tExists.file_id = tUpdate.file_id
and tExists.corr_id = tUpdate.corr_id
and tExists.local_group_id = tUpdate.local_group_id
and tExists.global_group_id = tUpdate.global_group_id
where tExists.user_id is null
【讨论】:
以上是关于需要帮助来提高一些 TSQL“不存在”的查询性能的主要内容,如果未能解决你的问题,请参考以下文章