我有一个带有四个表的内部联接的SQL查询,使用当前索引和查询结构需要超过30秒。我想尽快做到;至少快于5秒。
我首先考虑了非规范化,但是阅读here通常应该可以通过正确的索引等进行优化。在这种情况下,我无法弄清楚。当前查询计划包含最小表上的索引扫描和其中一个内连接上的“无连接谓词”警告。
我们有以下表格(显示行数和相关字段):
TableName Rows Fields ------------------- ----- ---------------------------------------------- ProjectType 150 ProjectTypeID, ProjectTypeName Employee 200 EmployeeID, RefDepartmentID Project 0.2M ProjectID, RefProjectTypeID ProjectTransaction 3.5M Hours, RefEmployeeID, RefProjectID, Date, Type
查询应该总结给定部门的小时数,日期范围等。目前我尝试:
SELECT E.RefDepartmentID, SUM(PTran.Hours)
FROM Employee E
JOIN ProjectTransaction PTran
ON E.EmployeeID = PTran.RefEmployeeID
JOIN Project P
ON PTran.RefProjectID = P.ProjectID
JOIN ProjectType PType
ON P.RefProjectTypeID = PType.ProjectTypeID
WHERE E.RefDepartmentID = @departmentID
AND @from <= PTran.Date AND PTran.Date <= @to
AND PTran.Type = 0
AND PType.ProjectTypeName NOT IN (N'1', N'2', N'3')
GROUP BY E.RefDepartmentID
感谢所有快速解答。 (我已经在'{1}}子句中有'外键'和标准的索引。)我重新排序查询,先得到两个小表,然后是中等大小,最后是大表。瞧瞧大约一秒钟:
WHERE
答案 0 :(得分:9)
它并不总是有效,但请尝试:
使用子查询代替ProjectTransaction
表:
JOIN (SELECT RefEmployeeID,RefProjectID FROM ProjectTransaction WHERE @from&lt; = PTran.Date AND PTran.Date&lt; = @to AND PTran.Type = 0)AS trans
答案 1 :(得分:1)
确保外键列上有索引。
答案 2 :(得分:1)
假设P.ProjectID
和PType.ProjectTypeID
为PRIMARY KEY
,请创建此索引:
CREATE INDEX ix_ptran_emloyee_type_date ON ProjectTransaction(RefEmployeeID, Type, Date)
,摆脱GROUP BY
:
SELECT @departmentID, SUM(PTran.Hours)
FROM Employee E
JOIN ProjectTransaction PTran
ON PTran.RefEmployeeID = E.EmployeeID
JOIN Project P
ON P.ProjectID = PTran.RefProjectID
JOIN ProjectType PType
ON PType.ProjectTypeID = P.RefProjectTypeID
WHERE E.RefDepartmentID = @departmentID
AND PTran.Date BETWEEN @from AND @to
AND PTran.Type = 0
AND PType.ProjectTypeName NOT IN (N'1', N'2', N'3')
答案 3 :(得分:1)
所有外键的索引。
ProjectTransaction也是你唯一真正的大表,你在Where子句中对它进行了大量的过滤。我会为您要过滤的所有列添加索引:
ProjectTransaction.Date
ProjectTransaction.Type
编辑:由于您有一个包含350万行的表,您可能需要考虑的另一种优化“技术”是升级SQL Server上的硬件。一些额外的内存或一些额外的处理器有时比花费在优化上的开发时间更具成本效益(取决于开发成本和您正在进行的优化程度,显然)......见Hardware is Cheap, Programmers are Expensive。
答案 4 :(得分:0)
您的查询计划是什么意思?如果在同一个表上有两个索引扫描,然后在它们的结果之间进行散列连接(或类似),则使用两个索引扫描中的字段创建一个复合索引 - 然后DB可以执行单个索引查找在复合指数中。
确保您拥有最新的统计信息。当提供这些数据库时,数据库可以更好地进行优化。
答案 5 :(得分:0)
Database Engine Tuning Advisor会告诉您是否只是问它。
答案 6 :(得分:0)
到目前为止,所有的建议都是合理的,但如果你想要专家(即SQL Server)的观点,你可能会比使用Database Engine Tuning Advisor更糟糕。即使您没有广泛的实际数据,顾问也可以根据一小组测试数据提出一些合理的建议。