我正在比较SQL Server 2012中的两个查询。目标是在选择最佳查询时使用查询优化器中所有可用的相关信息。这两个查询产生相同的结果。所有客户的最大订单编号。
在使用FREEPROCCACHE和DROPCLEANBUFFERS执行每个查询之前,已清除缓冲池
使用下面提供的信息,哪个查询是更好的选择?
-- Query 1 - return the maximum order id for a customer
SELECT orderid, custid
FROM Sales.Orders AS O1
WHERE orderid = (SELECT MAX(O2.orderid)
FROM Sales.Orders AS O2
WHERE O2.custid = O1.custid);
-- Query 2 - return the maximum order id for a customer
SELECT MAX(orderid), custid
FROM Sales.Orders AS O1
group by custid
order by custid
统计时间
查询1 STATISTICS TIME:CPU时间= 0ms,已用时间= 24 ms
查询2 STATISTICS TIME:CPU时间= 0 ms,经过的时间= 23 ms
统计IO
查询1统计IO:表“订单”。扫描计数1,逻辑读取5,物理读取2,预读读取0,lob逻辑读取0,lob物理读取0,lob预读取0。
查询2统计IO:表“订单”。扫描计数1,逻辑读4,物理读1,预读8,lob逻辑读0,lob物理读0,lob预读0。
执行计划
SELECT属性查询1
SELECT属性查询2
结论:
查询1
- 批次成本48%
- 逻辑读物5
- 物理读物2
- 预读:0
- CPU时间:0ms
- 经过时间24ms
- 估计的子树成本:0.0050276
- 编译CPU:2
- 编译内存:384
- 编译时间:2
查询2
- 批处理成本52%
- 逻辑读4
- 物理读物1
- 预读:8
- CPU时间0
- 经过时间23ms
- 估计的子树成本:0.0054782
- 编译CPU:0
- 编译内存:192
- 编译时间:0
就个人而言,尽管根据图形化计划,查询2的批处理成本更高,但我认为它比查询1更为有效。这是因为查询2所需的逻辑读取次数较少,经过时间略短,因此compilecpu,compilememory和compiletime值是降低。预读读取对于查询2是8,对于查询1是0。
更新12:03
聚集索引定义
ALTER TABLE [Sales].[Orders] ADD CONSTRAINT [PK_Orders] PRIMARY KEY CLUSTERED
(
[orderid] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO
非聚集索引idx_nc_custid
CREATE NONCLUSTERED INDEX [idx_nc_custid] ON [Sales].[Orders]
(
[custid] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO