sql-server - 在 WHERE 子句中带有分支的 SELECT 查询的性能
问题描述
我有以下旧版 SP:
CREATE PROCEDURE dbo.get_orders_history
(
@FirstDt DATETIME2(6),
@LastDt DATETIME2(6),
@Class VARCHAR(12),
@PeriodType SMALLINT
)
AS
SET NOCOUNT ON
CREATE TABLE #BufferTable (OrderId INT)
INSERT INTO #BufferTable
SELECT DISTINCT
O.OrderId
FROM
BaseOrders O JOIN Classes C ON O.ClassId = C.ClassId
WHERE
(O.Changed = 0) AND
(C.ClassCode = @ClassCode) AND
(
(@PeriodType = 1 AND O.LastActionDateTime >= @FirstDt AND O.OrderDateTime < @LastDt) OR
(@PeriodType = 2 AND O.OrderDateTime >= @FirstDt AND O.OrderDateTime <= @LastDt)
)
OPTION(RECOMPILE);
SELECT A.Column,
C.Column,
OB.Column1,
...
OB.Column10,
O.Column1,
...
O.Column100,
FROM BaseOrders OB
JOIN #BufferTable IDL ON (OB.OrderId = IDL.OrderId)
JOIN Orders O ON (O.OrderId = IDL.OrderId)
JOIN Classes C ON (O.ClassId = C.ClassId)
ORDER BY
O.OrderId
DROP TABLE #BufferTable
GO
现在要添加参数“PeriodType” ,我怀疑这种制作分支的方式(WHERE 子句中的条件)是否有效。
SP 很少被调用但返回很多行(100K+),所以我认为 OPTION RECOMPILE for SELECT 在这种情况下是合理的解决方案。
任何 SQL 专家都可以提出更有效的方法来实现这样的分支吗?
- 编辑:我将澄清 SP 的当前 prod 版本没有参数“期间类型”,并且 WHERE 如下:
WHERE
(O.Changed = 0) AND
(C.ClassCode = @ClassCode) AND
(O.LastActionDateTime >= @FirstDt AND O.OrderDateTime < @LastDt)
我的目标是在当前 SP 中实现两种类型的日期范围类型,而没有或只有最小的性能损失。
解决方案
您是否尝试从初始插入中删除 OR 并随后使用否定删除?这是一个代码片段。
CREATE TABLE #BufferTable (OrderId INT, LastActionDateTime datetime, OrderDateTime datetime)
INSERT INTO #BufferTable
SELECT DISTINCT
o.OrderId
, o.LastActionDateTime
, o.OrderDateTime
FROM
BaseOrders O JOIN Classes C ON O.ClassId = C.ClassId
WHERE
(O.Changed = 0) AND
(C.ClassCode = @ClassCode);
delete p
from #BufferTable p
where not
(
(@PeriodType = 1 AND p.LastActionDateTime >= @FirstDt AND p.OrderDateTime < @LastDt) OR
(@PeriodType = 2 AND p.OrderDateTime >= @FirstDt AND p.OrderDateTime <= @LastDt)
)
推荐阅读
- sql - 获取 last_value MariaDB SQL
- stm32 - 多次写入外部 eeprom 会损坏以前的数据
- node.js - MongooseError:操作 `urls.find()` 缓冲在 10000 毫秒后超时
- java - 在调试 JavaFX 时,OpenJDK 平台二进制文件已停止在 Eclipse 中工作
- javascript - 无需提交即可填写表单数据 (PHP/JS)
- excel - 使用 VBA 将目录中的 csv 文件上传到文件夹
- java - 如何在 Android API 级别 29 (>= 29) 及以上以编程方式断开和忘记 Wi-fi 网络
- java - 如何处理 Maven 中生成的源的依赖关系?
- android - 从标签布局中的片段访问父活动视图?
- html - Flex-basis 对 IE11 的百分比支持?