Eth*_*aul 3 sql-server execution-plan sorting cross-apply top
我正在尝试优化查询以更快地运行。查询如下:
SELECT grp_fk_obj_id, grp_name
FROM tbl_groups as g1
CROSS APPLY (SELECT TOP 1 grp_id as gid
FROM tbl_groups as g2
WHERE g1.grp_fk_obj_id = g2.grp_fk_obj_id
ORDER BY g2.date_from DESC, ISNULL(date_to, '4000-01-01') DESC) as a
WHERE g1.grp_id = gid
Run Code Online (Sandbox Code Playgroud)
grp_id 是主键。grp_fk_obj_id 是另一个对象的外键。这两列都有索引(我猜它是默认的)。
完成大约需要半秒钟,但我需要它来加快工作速度。我查看了执行计划,它显示“Top N 排序”的成本超过 90%。另外,我注意到,如果我删除了交叉应用中的 where 子句,那么它的运行速度至少要快 5 倍,但我需要以一种或另一种方式使用 where 子句。
您是否认为有可能提高此查询的性能?
编辑:表创建 DDL:
create table tbl_groups
(
grp_id bigint identity
constraint PK_tbl_groups
primary key,
grp_fk_obj_id bigint not null
constraint FK_grp_fk_obj_id
references tbl_other,
grp_name varchar(30) not null,
date_from date not null,
date_to date
)
go
create index IDX_grp_fk_obj_id
on tbl_groups (grp_fk_obj_id)
go
create index IDX_grp_name
on tbl_groups (grp_name)
go
Run Code Online (Sandbox Code Playgroud)
您需要更好的索引和一些重写。
因为您只使用一个表,所以您可以在子查询中使用 ROW_NUMBER(),然后从每个分区中获取第一行。
SELECT grp_fk_obj_id, grp_name, grp_id
FROM (
SELECT grp_fk_obj_id, grp_name, grp_id, ROW_NUMBER() OVER (PARTITION BY grp_fk_obj_id ORDER BY date_from DESC, ISNULL(date_to, '4000-01-01') DESC) AS rownum
FROM tbl_groups
) g
WHERE g.rownum = 1;
Run Code Online (Sandbox Code Playgroud)
而且,修复您的ORDER BY
子句,因为它会强制它进行排序。因为您对表达式进行排序,所以无法有效地对其进行索引。如果你可以强制 date_to 有一个值 order by date_from desc, date_to desc
,那么索引(grp_fk_obj_id, date_from, date_to) include (grp_name)
就会真正有帮助。它甚至会使您的原始查询运行得更快。
归档时间: |
|
查看次数: |
893 次 |
最近记录: |