我已经谷歌搜索过,并找到了很多类似问题的答案,但找不到真正好的答案,这满足了我的问题。
我正在考虑具有大量数据的大型表的查询性能,以及根据某些条件从该表中进行选择。
我想知道,在查询中最好使用什么来按数值(例如, select * from myTable where myNumericColumn ...
(进行选择。这里更好的是:为 null、不为 null 或 =value。我的意思是:
select * from myTable where myNumericColumn is null
select * from myTable where myNumericColumn is not null
select * from myTable where myNumericColumn != 0
select * from myTable where myNumericColumn = 0
我读到SQL Server索引NULL 值,因此使用它更有效。但这是真实的答案还是只是某些用户的意见?
我需要了解SQL Server和Oracle(在我的问题领域(。
提前谢谢。
编辑!对不起,我犯了错误。我的意思是优化数据表的结构,以便在查询时达到最佳查询性能。我应该使用某个值而不是 NULL 值来达到更好的执行速度,还是需要使用 NULL,或者我只需要以正确的方式索引表。我知道它是基于意见的,但我需要专业人士的回答,他们致力于数据库的结构开发、优化和查询性能
我想知道真正的问题是什么,因为您正在尝试比较不同的查询,除非表格根据测试进行相应准备。对于性能,有一些东西可以产生不同的答案,比如行数,每个值之间的比率。
通常,您编写查询的方式甚至无关紧要,因为查询优化器将重新排列查询以获得与表上的数据和索引一致的最佳结果。
所以最好的方法是测试并检查QUERY PLAN
但是你必须比较类似的东西
创建一个具有相同NULL
数且不NULL
的表,您可以比较前两个查询。
然后创建一个具有相同0
数的表,并<>0
并比较性能。
我有一个包含~200万个用户帐户的表,用于测试数据。我添加了两列,COL1 和 COL2。
- COL1 要么为 NULL,要么具有"1"。有 ~75k "1" 值。
- COL2 是"0"或"1"。有 ~75k "1" 值。
这是我的设置方式:
ALTER TABLE Profile.UserAccount ADD COL1 INT NULL
ALTER TABLE Profile.UserAccount ADD COL2 INT NOT NULL DEFAULT (0)
UPDATE Profile.UserAccount -- Update ~75k rows
SET COL1 = 1,
COL2 = 1
WHERE PasswordIsExpired = 'Y'
CREATE INDEX DELETE_ME1 ON Profile.UserAccount (COL1)
CREATE INDEX DELETE_ME2 ON Profile.UserAccount (COL2)
然后,我将以下查询放入 SSMS 并运行它们,输出查询计划。这将以百分比形式提供"相对于批处理的查询成本"。如果它们都返回为 25%,这意味着它们的成本都相等(4 个查询 x 25% = 批次的 100%(。
我在每个语句旁边添加了查询成本。开销越低,查询相对于其他查询的效率就越高:
-- Query Cost: 50%
SELECT COUNT(*) FROM Profile.UserAccount WHERE COL1 IS NULL
/*
SQL Server Execution Times:
CPU time = 0 ms, elapsed time = 0 ms.
SQL Server parse and compile time:
CPU time = 12 ms, elapsed time = 12 ms.
Table 'UserAccount'. Scan count 1, logical reads 2634, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
SQL Server Execution Times:
CPU time = 250 ms, elapsed time = 481 ms.
*/
-- Query Cost: 3%
SELECT COUNT(*) FROM Profile.UserAccount WHERE COL1 IS NOT NULL
/*
SQL Server Execution Times:
CPU time = 0 ms, elapsed time = 0 ms.
Table 'UserAccount'. Scan count 1, logical reads 136, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
SQL Server Execution Times:
CPU time = 16 ms, elapsed time = 35 ms.
*/
-- Query Cost: 45%
SELECT COUNT(*) FROM Profile.UserAccount WHERE COL2 = 0
/*
SQL Server Execution Times:
CPU time = 0 ms, elapsed time = 0 ms.
SQL Server parse and compile time:
CPU time = 0 ms, elapsed time = 0 ms.
Table 'UserAccount'. Scan count 1, logical reads 2068, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
SQL Server Execution Times:
CPU time = 250 ms, elapsed time = 441 ms.
*/
-- Query Cost: 2%
SELECT COUNT(*) FROM Profile.UserAccount WHERE COL2 != 0
/*
SQL Server Execution Times:
CPU time = 0 ms, elapsed time = 0 ms.
SQL Server parse and compile time:
CPU time = 0 ms, elapsed time = 0 ms.
Table 'UserAccount'. Scan count 2, logical reads 113, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
SQL Server Execution Times:
CPU time = 31 ms, elapsed time = 159 ms.
*/