性能优化 Row_Number() 通过分区:
我一直在尝试优化表(Table1)和子查询之间存在左连接的存储过程的性能。当部门表中的记录增加时,速度会变慢;我认为,这是由于 ROW_NUMBER 函数造成的。它适用于部门表中记录数量较少的情况。 Table1 和存储过程末尾的子查询之间有一个左联接。
下面是示例表 Table1
、Employee
和 Department
,涉及运行缓慢的查询。
CREATE TABLE [Table1]
(
[ID] [int] NOT NULL PRIMARY KEY,
[Name] VARCHAR(250) NOT NULL,
[DepartmentID] int
) ON [PRIMARY]
INSERT [Table1] ([ID], [Name], [DepartmentID])
VALUES (1, N'A', 1), (2, N'D', 2),
(3, N'C', 3), (4, N'E', 4),
(5, N'D', 5), (6, N'A', 6),
(7, N'B', 7)
GO
CREATE TABLE [Department]
(
[DepartmentID] [int] NOT NULL PRIMARY KEY,
[Name] VARCHAR(250) NOT NULL,
) ON [PRIMARY]
INSERT [Department] ([DepartmentID], [Name])
VALUES (1, N'Engineering'), (2, N'Administration'),
(3, N'Sales'), (4, N'Marketing'),
(5, N'Finance')
GO
CREATE TABLE [Employee]
(
[EmployeeID] [int] NOT NULL PRIMARY KEY,
[FirstName] VARCHAR(250) NOT NULL,
[LastName] VARCHAR(250) NOT NULL,
[DepartmentID] [int] NOT NULL
REFERENCES [Department](DepartmentID),
) ON [PRIMARY]
GO
INSERT [Employee] ([EmployeeID], [FirstName], [LastName], [DepartmentID])
VALUES (1, N'Orlando', N'Gee', 1), (2, N'Keith', N'Harris', 2),
(3, N'Donna', N'Carreras', 3), (4, N'Janet', N'Gates', 3)
运行缓慢的示例查询。
SELECT
*
FROM
Table1 AS t
LEFT JOIN
(SELECT
D.Name,
E.DepartmentID,
ROW_NUMBER() OVER (PARTITION BY E.DepartmentID
ORDER BY D.DepartmentID ASC,
CASE WHEN D.Name IS NULL THEN 1 ELSE 0 END ASC, D.Name ASC) AS ord_index
FROM
Department AS D
INNER JOIN
Employee AS E ON D.DepartmentID = E.DepartmentID) AS x ON x.DepartmentID = t.DepartmentID
WHERE
x.ord_index = 1 OR x.ord_index IS NULL
我尝试根据调整顾问的建议添加索引,但它并没有提高性能。我也尝试使用 APPLY,但由于 ROW_NUMBER
函数而无法弄清楚。不过,我一直在尝试浏览平台上的相关标题。
我很感谢任何优化此类查询的指南。
I have been trying to optimize performance of a stored procedure that has left join between a table (Table1) and a subquery. It gets slow when the records in the department table increase; I think, it is due to the ROW_NUMBER function. It works fine with lower number of records in the Department table. There is a left join between Table1 and a subquery at the end of the stored procedure.
Below is sample tables Table1
, Employee
and Department
, involved in the query that is running slow.
CREATE TABLE [Table1]
(
[ID] [int] NOT NULL PRIMARY KEY,
[Name] VARCHAR(250) NOT NULL,
[DepartmentID] int
) ON [PRIMARY]
INSERT [Table1] ([ID], [Name], [DepartmentID])
VALUES (1, N'A', 1), (2, N'D', 2),
(3, N'C', 3), (4, N'E', 4),
(5, N'D', 5), (6, N'A', 6),
(7, N'B', 7)
GO
CREATE TABLE [Department]
(
[DepartmentID] [int] NOT NULL PRIMARY KEY,
[Name] VARCHAR(250) NOT NULL,
) ON [PRIMARY]
INSERT [Department] ([DepartmentID], [Name])
VALUES (1, N'Engineering'), (2, N'Administration'),
(3, N'Sales'), (4, N'Marketing'),
(5, N'Finance')
GO
CREATE TABLE [Employee]
(
[EmployeeID] [int] NOT NULL PRIMARY KEY,
[FirstName] VARCHAR(250) NOT NULL,
[LastName] VARCHAR(250) NOT NULL,
[DepartmentID] [int] NOT NULL
REFERENCES [Department](DepartmentID),
) ON [PRIMARY]
GO
INSERT [Employee] ([EmployeeID], [FirstName], [LastName], [DepartmentID])
VALUES (1, N'Orlando', N'Gee', 1), (2, N'Keith', N'Harris', 2),
(3, N'Donna', N'Carreras', 3), (4, N'Janet', N'Gates', 3)
Sample query that is running slow.
SELECT
*
FROM
Table1 AS t
LEFT JOIN
(SELECT
D.Name,
E.DepartmentID,
ROW_NUMBER() OVER (PARTITION BY E.DepartmentID
ORDER BY D.DepartmentID ASC,
CASE WHEN D.Name IS NULL THEN 1 ELSE 0 END ASC, D.Name ASC) AS ord_index
FROM
Department AS D
INNER JOIN
Employee AS E ON D.DepartmentID = E.DepartmentID) AS x ON x.DepartmentID = t.DepartmentID
WHERE
x.ord_index = 1 OR x.ord_index IS NULL
I tried adding indexes per the suggestion of tuning advisor, but it doesn't improve the performance. I was also trying to use APPLY, but couldn't get it clear due to the ROW_NUMBER
function. I have been trying to go through the related titles on the platform though.
I appreciate any guide in optimizing such query.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您可以重构查询以使用
外部应用
,这可能会产生更好的执行计划(取决于支持的索引),例如:请参阅DB<>Fiddle 显示更好的计划
You could refactor the query to use an
outer apply
which may result in a better execution plan (depending on the supporting indexes) such as :See DB<>Fiddle showing better plan
在查询中,难以索引的部分是
CASE WHEN D.Name IS NULL THEN 1 ELSE 0 END
。但是,如果您愿意在Department
表中添加额外的生成列,则可以对其建立索引。例如:有了新列和索引,查询可以改写为:
In the query, the section that is difficult to index is
CASE WHEN D.Name IS NULL THEN 1 ELSE 0 END
. This can, however, be indexed if you are willing to add an extra generated column in theDepartment
table. For example:With the the new column in place and the index, the query can be rephrased as: