Sql 空值时的查询性能
我想知道空值如何影响SQLServer2005中的查询性能 我有一张类似的表格(简化): 我正在对它进行如下查询:Sql 空值时的查询性能,sql,sql-server,database,performance,Sql,Sql Server,Database,Performance,我想知道空值如何影响SQLServer2005中的查询性能 我有一张类似的表格(简化): 我正在对它进行如下查询: SELECT * FROM MyTable WHERE QuickPickOrder IS NOT NULL ORDER BY QuickPickOrder 因此QuickPickOrder基本上是一个列,用于从较大的列表中挑出一些常用的项。它还提供了它们向用户显示的顺序。空值表示它不显示在快速拾取列表中 我一直被告知,数据库中的空值在某种程度上是有害的,至少从
SELECT *
FROM MyTable
WHERE QuickPickOrder IS NOT NULL
ORDER BY QuickPickOrder
因此QuickPickOrder基本上是一个列,用于从较大的列表中挑出一些常用的项。它还提供了它们向用户显示的顺序。空值表示它不显示在快速拾取列表中
我一直被告知,数据库中的空值在某种程度上是有害的,至少从规范化的角度来看是如此,但在WHERE约束中过滤掉不需要的行是一种可以接受的方式吗
使用特定的数值(如-1或0)来表示不需要的项目是否更好?还有其他选择吗
编辑:
该示例无法准确表示实值与空值的比率。更好的示例可能会显示每个非NULL至少10个NULL。表格大小可能为100到200行。这是一个参考表,所以很少有更新。
NULL
在我看来,这很好。性能可能与使用非空列和常量值时基本相同,或者甚至更好地过滤掉所有null
s。它们不会对数据库造成负面性能影响。请记住,NULL更像是一种状态而不是一个值。检查NOTNULL与将该值设置为-1没有区别,除了-1可能会破坏您的数据完整性,依我看。SQL Server
索引NULL
值,因此这很可能只是在QuickPickOrder
上的索引上使用索引搜索
,用于筛选和排序。另一种方法是使用外键将QuickPickOrder规范化为一个表,然后执行内部联接以筛选空值(或使用where子句进行左联接以筛选非空值)。空值对我来说也很好。SQL Server有多种索引可供选择。我忘了是哪一个这样做了,但有些只是在给定范围内的索引值。如果测试列上有这种索引,空值记录将不在索引中,索引扫描将很快。另一种选择是两个表:
MyTable:
ID | ImportantData
------------------
1 | 'Some Text'
2 | 'Other Text'
3 | 'abcdefg'
4 | 'whatever'
5 | 'it is'
6 | 'technically'
7 | 'a varchar'
8 | 'of course'
9 | 'but that'
10 | 'is not'
11 | 'important'
QuickPicks:
MyTableID | QuickPickOrder
--------------------------
2 | 3
4 | 4
5 | 2
8 | 1
11 | 5
SELECT MyTable.*
FROM MyTable JOIN QuickPicks ON QuickPickOrder.MyTableID = MyTable.ID
ORDER BY QuickPickOrder
这将允许在不锁定MyTable中的任何内容或记录该表的整行事务的情况下更新QuickPickOrder。因此,根据MyTable的大小以及更新QuickPickOrder的频率,可能存在可伸缩性优势
另外,拥有一个单独的表将允许您在QuickPickOrder上添加一个唯一的索引,以确保没有重复,并且可以更容易地在以后进行缩放,以允许不同类型的快速选取,使它们特定于特定的上下文或用户等。在一个列中有大量空值,该列上有索引(或从索引开始)通常对这种查询是有益的 索引中不输入NULL值,这意味着插入/更新其中包含NULL的行不会受到必须更新另一个辅助索引的性能影响。比如说,如果该列中只有0.001%的行具有非null值,那么IS NOT null查询将变得非常有效,因为它只扫描相对较小的索引
当然,所有这些都是相对的,如果您的表很小,则不会产生明显的差异。在数据库中使用空值可能会影响SQL Server的性能。这有几个原因 首先,出现在固定长度列(CHAR)中的空值占据整个列的大小。因此,如果列的宽度为25个字符,并且其中存储了空值,那么SQL Server必须存储25个字符来表示空值。增加的空间增加了数据库的大小,这反过来意味着查找所需数据需要更多的I/O开销。当然,解决这个问题的一种方法是使用可变长度字段。将空值添加到可变长度列时,空间不会像固定长度列那样被不必要地浪费 其次,在WHERE子句中使用IS NULL子句意味着索引不能用于查询,将执行表扫描。这会大大降低性能 第三个,使用空值可能会导致复杂的Transact-SQL代码,这可能意味着代码无法高效运行或存在缺陷 理想情况下,SQL Server数据库中应该避免空值 在数据库中使用与此类似的编码方案,而不是使用空值:
- NA:不适用
- 尼恩:还不知道
- 谭:真的不知道
这种方案提供了使用null的好处,但没有缺点。如果表的列为50%null(类似于给定的示例数据),我认为它可能倾向于使用索引scan@KM:为什么在这里进行索引扫描?它可能会执行表扫描/聚集索引扫描以避免RID查找/键查找,但我们这里有一个范围条件,因此索引查找总是优于此条件。它不会忽略索引和扫描,因为大多数值都是相同的(null)?@KM:它可以这样做,但它不会是索引扫描,而是表扫描或聚集索引扫描(与群集表的表扫描相同).Index Scan意味着在QuickPickOrder上遍历整个索引,过滤掉错误的值,然后使用键查找/RID查找与表连接,以获取SELECT子句请求的*值。Index Seek执行相同的操作,但从第一个非空值开始,因此空值只是剩余值。筛选的索引设计指南显示,您可以如果您有一个使用筛选索引的列的值大部分为空,则索引将具有更好的性能。
MyTable:
ID | ImportantData
------------------
1 | 'Some Text'
2 | 'Other Text'
3 | 'abcdefg'
4 | 'whatever'
5 | 'it is'
6 | 'technically'
7 | 'a varchar'
8 | 'of course'
9 | 'but that'
10 | 'is not'
11 | 'important'
QuickPicks:
MyTableID | QuickPickOrder
--------------------------
2 | 3
4 | 4
5 | 2
8 | 1
11 | 5
SELECT MyTable.*
FROM MyTable JOIN QuickPicks ON QuickPickOrder.MyTableID = MyTable.ID
ORDER BY QuickPickOrder