Jos*_*dan 4 performance sql-server-2008 sql-server query-performance
在适当排序的索引覆盖的单个范围内执行 MIN() 或 MAX() 时,SQL Server 执行 TOP() 并因此在仅获取一行后返回值。当搜索条件包含多个范围时,SQL Server 会从两个范围中获取所有索引值并进行流聚合,这比对每个子值执行 TOP() 慢得多。
例如,假设每个客户有大量订单,如下所示:
CREATE TABLE orders
(
customer_id int,
quantity int
)
Run Code Online (Sandbox Code Playgroud)
运行此查询:
SELECT MAX(quantity)
FROM orders
WHERE customer_id IN (1,2)
Run Code Online (Sandbox Code Playgroud)
将导致查询所需的时间是仅指定一个客户 ID 时的数倍。
执行上述查询的最有效方法是什么?相关地,如果需要单独的结果(即 GROUP BY customer_id),最好的方法是什么?
SQL小提琴:http ://sqlfiddle.com/#!3/ef0c6/1
这是一个使用 的解决方案CROSS APPLY,它对TOP每个执行相同的查询customer_id:
SELECT MAX(b.MaxQuantity) AS quantity
FROM
(
SELECT 1 AS customer_id UNION ALL
SELECT 2
) a
CROSS APPLY
(
SELECT TOP 1
quantity AS MaxQuantity
FROM orders o
WHERE o.customer_id = a.customer_id
ORDER BY quantity DESC
) b;
Run Code Online (Sandbox Code Playgroud)
这与UNION ALL您在 Fiddle 中编写的基于 -based 的查询的工作相同;不同之处在于customer_id输入是从查询的主体中抽象出来的,因此可以轻松转换为使用表变量或表值参数,这将导致静态查询计划,这一点很重要。这种方法适用于少量customer_id值,并且简单地移除外部MAX值将为每个客户返回最大值。我不相信有一种方法可以customer_id使用这些数据结构针对少量s进一步优化此查询(假设customer_ids 是随机的,而不是范围)。
对于大量的customer_idS,它可能是更便宜做索引扫描和流合计比许多寻求。为了加快速度,您必须转向某种非规范化的数据结构。MAX索引视图中不支持,因此在应用程序逻辑或触发器中滚动您自己的机制是唯一的方法。根据此表上的读/写比率,这可能比上述方法快也可能不快:您必须在您的确切场景中对其进行测试。
| 归档时间: |
|
| 查看次数: |
2064 次 |
| 最近记录: |