我正在尝试决定在我正在设计的数据库中采用哪种方法。
我将在表格中添加ProcessedDate datetime null
列。当记录未被处理时,它将是可空的。
那么,是否值得拥有Processed bit not null default 0
列?
使用以下查询:
select * from tablename where ProcessedDate is null
和
select * from tablename where Processed = 0
所有条件相同*,两个版本之间的性能差异是什么?
*:在每个版本的表中应用适当的索引。我不是在寻找建立什么指数的建议。我只想要应用于单行的有关过滤器性能的信息。如果需要扫描表格中的所有行,或者搜索完成与手头的问题无关。
我知道可以做出一个论点,即Processed标志更明确,因此更具可读性,但它也会引起有关保持列同步的问题(可以通过使用计算列来处理)。无论如何,我想把这个问题的范围限制在表现方面。
答案 0 :(得分:3)
就我可以用相同的数据集而言,它们完全相同。您可以在下面运行我的示例并查看要检查的执行计划。您将看到它测试谓词的过滤器元素在每个中占用相同的时间比例。即使添加了索引,它也不会比另一个更有效,因为它们基本上都在做同样的事情。
WITH Test (MyInt, MyNull)
AS
(
SELECT 1 AS MyInt, Null AS MyNull
UNION ALL
SELECT
MyInt + 1,
CASE
WHEN MyInt % 2 = 0 THEN Null
ELSE MyInt
END
FROM Test
WHERE MyInt < 10000
)
SELECT * FROM Test
WHERE MyNull IS NULL
OPTION (MAXRECURSION 32767);
WITH Test (MyInt, MyBit)
AS
(
SELECT 1 AS MyInt, 0 AS MyBit
UNION ALL
SELECT
MyInt + 1,
CASE
WHEN MyInt % 2 = 0 THEN 0
ELSE 1
END
FROM Test
WHERE MyInt < 10000
)
SELECT * FROM Test
WHERE MyBit = 0
OPTION (MAXRECURSION 32767);
我知道我的例子是人为的,但它使用相同数量的空值和0。即使您将每个示例的CTE重新写入表变量,您也应该看到相同的性能。
答案 1 :(得分:2)
你不应该同时拥有两者。
选择与您的域名模型最匹配的那个。
使用正确的索引,任何性能差异都可以忽略不计(假设'处理'到'未处理'的相对分布意味着优化器将首先选择一个索引。)
答案 2 :(得分:2)
与大多数SQL性能问题一样,答案将由表模式驱动,而不是由SQL文本驱动。就像现在一样,两个版本都需要全表扫描,所以它们都差不多。
ProcessedDate上的非聚集索引可能对第一个版本有帮助,但由于您在投影中要求*
,索引引爆点可能会启动并仍然会进行完整扫描。
另一方面,最左边的密钥Processed的聚簇索引将始终有效,并且这样的聚簇索引结构在队列处理中很常见(并且具有'ProcessedDate'列可以清楚地表明您的表用作队列)。
但是,对于聚簇索引,ProcessedDate上最左边的列也可以像Processed位一样工作。
带回家的教训:不是查询,是架构。总是
答案 3 :(得分:1)
ProcessedDate is null
谓词的一个优点是你不会冒被(显式或隐式)参数化的风险。
如果您使用Processed = 0
,SQL服务器可能会在内部将此参数化为Processed = @p
,并根据@p = 0的假设生成查询计划。但是,如果您在某处执行相同操作查询但where Processed = 1
,您可能会得到@p = 1的计划,并且由于数据可能会有所偏差,因此计划可能不会相同。