默认情况下,某些T-SQL开发人员使用0表示如果(例如)用户处于活动状态,而当用户处于被动状态时,它的值为1.以下代码(在我的示例中)显示当前活动用户:
SELECT * FROM USERS WHERE ISACTIVE = 0
我的问题是,此查询处理速度是否比以下更快? =>
SELECT * FROM USERS WHERE ISACTIVE = 1
答案 0 :(得分:5)
在最简单的情况下,没有区别。与任何性能问题一样,关键是测试,因此我设置了下表,其中包含1,000,000个随机分布的行(每个行为500,000,分别为1和0)。
CREATE TABLE #T (ID INT IDENTITY PRIMARY KEY, Filler CHAR(1000), Active BIT NOT NULL);
INSERT #T (Active)
SELECT Active
FROM ( SELECT TOP 500000 Active = 1
FROM sys.all_objects AS a
CROSS JOIN sys.all_objects AS b
UNION ALL
SELECT TOP 500000 Active = 0
FROM sys.all_objects AS a
CROSS JOIN sys.all_objects AS b
) AS t
ORDER BY NEWID();
下一步是对聚集索引扫描对每个扫描进行多长时间的简单测试:
SET STATISTICS TIME ON;
SET STATISTICS IO ON;
SELECT COUNT(Filler) FROM #T WHERE Active = 1;
SELECT COUNT(Filler) FROM #T WHERE Active = 0;
两者的执行计划完全相同:
与IO一样:
扫描计数5,逻辑读取143089,物理读取0,预读读取0,lob逻辑读取0,lob物理读取0,lob预读读取0。
然后查看经过的时间,超过10次(不够,但图片相当清晰)经过的时间是(以毫秒为单位)
Active = 1 Active = 0
---------------------------
125 132
86 86
89 61
83 89
88 89
63 64
85 93
126 125
100 117
66 68
--------------------------
91.1 92.4 (Mean)
因此平均差异大约为1ms,这不足以被视为物质。所以在你的情况下没有,没有区别。
然后我可能会对列上的排序索引产生影响,因此添加了一个:
CREATE INDEX IX_T__Active ON #T (Active) INCLUDE (Filler);
结果再次显示没有(相关)差异:
Active = 1 Active = 0
--------------------------
57 55
42 48
56 57
58 55
44 42
46 41
41 42
42 52
43 43
52 59
--------------------------
48.1 49.4
总之,它不会产生重大差异,我很确定这是Donald Knuth was referring too的过早优化。
答案 1 :(得分:1)
您可以在tempdb上快速测试。
create table #tmp
(
id int, flag bit default(0)
);
DECLARE @max AS INT, @rc AS INT;
SET @max = 200000;
SET @rc = 1;
INSERT INTO #tmp VALUES(1, 0);
WHILE @rc * 2 <= @max
BEGIN
INSERT INTO #tmp SELECT id + @rc, 0 as flag FROM #tmp;
SET @rc = @rc * 2;
END
INSERT INTO #tmp
SELECT id + @rc, 1 as flag FROM #tmp WHERE id + @rc <= @max;
GO
set statistics time on
Go
select * from #tmp where flag = 1
set statistics time off
Go
set statistics time on
Go
select * from #tmp where flag = 0
set statistics time off
Go
尝试创建索引,您将看到更多的差异,即如果索引具有不同的值,位列的工作方式。
答案 2 :(得分:0)
我不认为这个设计因为性能而存在,因为您的两个查询都会生成相同的执行计划。更重要的方面是,如果您在此列上有索引。
为什么要标记值为1
的非活动用户还有其他多种原因。
为什么我会这样做的一些原因:
1)0
的默认值为int
和bool
在某些ORM中(例如,EF6),您不必为状态列指定任何值,并且它将设置为0.因此,默认情况下,用户将处于活动状态。
在大多数系统中,大多数用户都是active
。如果用户是inactive
,则需要涵盖特殊情况。不是全部。
2)未来价值考虑因素
此列可能在将来包含不同的值,表示用户已被暂停,删除等。
拥有
没有多大意义0-inactive, 1-active, 2-suspended, etc.
而不是
0-active, 1-inactive, 2-suspended, etc.
这样就可以通过简单的表达式status > 0
来查询有问题的用户。