Performance 加速使用WHERE-IN进行筛选的动态SQL查询
考虑以下数据表:Performance 加速使用WHERE-IN进行筛选的动态SQL查询,performance,tsql,join,Performance,Tsql,Join,考虑以下数据表: CREATE TABLE Person ( PersonId int PRIMARY KEY ) CREATE TABLE PersonData ( PersonId int, -- with foreign key to person table DateKey Date, Fact1 int, ) 我可以执行这样的查询,它将聚合Fact1,并按DateKey分组 SELECT DateKey, SUM(Fact1) FROM Pers
CREATE TABLE Person
(
PersonId int PRIMARY KEY
)
CREATE TABLE PersonData
(
PersonId int, -- with foreign key to person table
DateKey Date,
Fact1 int,
)
我可以执行这样的查询,它将聚合Fact1,并按DateKey分组
SELECT DateKey, SUM(Fact1)
FROM PersonData
GROUP BY DateKey
现在让我们假设我想按personId过滤并显示id为1、2和3的人员的数据。我可以这样做:
SELECT DateKey, SUM(Fact1)
FROM PersonData
WHERE PersonId IN (1, 2, 3)
GROUP BY DateKey
这是一个问题,如果我有大量的人形,我想过滤。i、 e.其中T2.PersonId在(1,2,3,4,5…1000+)
如果要筛选大量PersonId,如何提高性能
更新
虽然上面的例子是对我的数据结构的简化,但希望它是一个准确的类比
示例查询和时间影响,考虑到大约3200万行PersonData和2000个独特人物:
- 对单个PersonId进行过滤:100ms
- 完全没有过滤器:750毫秒
- 在1500个人身上过滤:2300 ms
declare @beginValue int = 1,
@endValue int = 87;
--Only work if you need a interval of numbers (example: 1 to 87, in Person table)
SELECT pdt.DateKey, SUM(pdt.Fact1)
FROM PersonData AS pdt
INNER JOIN Person AS per ON pdt.PersonId = per.PersonId
WHERE per.PersonId BETWEEN @beginValue AND @endValue
GROUP BY pdt.DateKey;
您可以尝试将所有PersonId加载到SQL中的表中。然后使用:
SELECT DateKey, SUM(Fact1)
FROM PersonData D
WHERE exists (SELECT 1 from PersonIDTable I where d.PersonID = I.PersonID)
GROUP BY DateKey
这通常会使查询运行得更快 是否大部分时间都花在了“groupby”子句中 请看一下执行计划
我想知道增加个人ID列表是否真的会导致DateKey排序成本线性增加。如果是这样,请在DateKey列上添加一个索引。我假设您不能将
T2.PersonId
-空间表示为某种查询?这意味着它必须是一个id
列表?假设Person->PersonData
是一对多,那么您所说的提高性能的Person
上的连接看起来是多余的。计划是什么样子的?您的表上有哪些索引?@jonnyGold-它不一定是一个ID列表,但是需要对应用程序进行大量重构才能将过滤器表示为连接,而不是一组ID。“我在这里寻找一个快速解决办法。”马丁史密斯说得对,这是一对多。不知道为什么它会提高性能。这个例子是我认为问题所在的一个粗略简化。希望它是有代表性的…@MartinSmith经过额外的测试,你是正确的。加入似乎没有什么不同。我已经从我的帖子中删除了这些信息。这很快,但没有用。通常情况下,这些值不会是顺序的,因为这会导致改进(1700ms),但不是一个很大的改进,并且我会失去插入的改进(然后是一些)。ID列表是动态的/由用户根据他们设置的过滤器选择的-因此我不能提前填充这样的表。