使用NULL查询性能

时间:2009-07-01 17:19:11

标签: sql sql-server database performance

我想知道NULL值如何影响SQL Server 2005中的查询性能。

我有一张类似于此的表(简化):

ID | ImportantData | QuickPickOrder
--------------------------
1  | 'Some Text'   | NULL
2  | 'Other Text'  | 3
3  | 'abcdefg'     | NULL
4  | 'whatever'    | 4
5  | 'it is'       | 2
6  | 'technically' | NULL
7  | 'a varchar'   | NULL
8  | 'of course'   | 1
9  | 'but that'    | NULL
10 | 'is not'      | NULL
11 | 'important'   | 5

我正在对此进行查询:

SELECT   *
FROM     MyTable
WHERE    QuickPickOrder IS NOT NULL
ORDER BY QuickPickOrder

因此,QuickPickOrder基本上是一个用于从较大列表中挑选出一些常用项目的列。它还提供了它们对用户显示的顺序。 NULL值表示它不会显示在快速选择列表中。

我总是被告知数据库中的NULL值在某种程度上是邪恶的,至少从标准化的角度来看,但是它是否可以在WHERE约束中过滤掉不需要的行?

使用特定的数字值(如-1或0)来表示不需要的项目会更好吗?还有其他选择吗?

修改 该示例并不准确地表示实际值与NULL的比率。更好的示例可能会为每个非NULL显示至少10个NULL。表大小可能是100到200行。它是一个参考表,所以更新很少见。

8 个答案:

答案 0 :(得分:5)

SQL Server索引NULL值,因此这很可能仅使用Index Seek而不是QuickPickOrder上的索引,用于过滤和排序。

答案 1 :(得分:3)

另一种选择是两个表:

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

这样可以更新QuickPickOrder,而无需锁定MyTable中的任何内容或记录该表的完整行事务。因此,根据MyTable的大小以及更新QuickPickOrder的频率,可能会有可扩展性优势。

此外,拥有一个单独的表将允许您在QuickPickOrder上添加唯一索引以确保不会重复,并且可以在以后更容易扩展以允许不同类型的QuickPicks,使它们特定于某些上下文或用户等。< / p>

答案 2 :(得分:2)

他们没有对数据库造成负面影响。请记住,NULL更多的是状态而不是值。检查NOT NULL与将该值设置为-1没有区别,除了-1可能会破坏您的数据完整性,imo。

答案 3 :(得分:1)

对于这个目的,

NULL对我来说很好。性能可能与非空列和常量值基本相同,或者甚至可能更好地过滤掉所有NULL

答案 4 :(得分:1)

另一种方法是将QuickPickOrder规范化为具有外键的表,然后执行内部联接以过滤掉空值(或使用where子句的左连接来过滤掉非空值)。

答案 5 :(得分:1)

在数据库中使用NULLS可能会影响SQL Server的性能。这有几个原因。

首先,出现在固定长度列(CHAR)中的NULLS占用了列的整个大小。因此,如果您有一个25个字符宽的列,并且其中存储了NULL,则SQL Server必须存储25个字符来表示NULL值。这个增加的空间增加了数据库的大小,这反过来意味着它需要更多的I / O开销来查找您正在寻找的数据。当然,解决此问题的一种方法是使用可变长度字段。当NULL被添加到可变长度列时,空间不会被浪费,因为它具有固定长度的列。

第二,在WHERE子句中使用IS NULL子句意味着索引不能用于查询,并且将执行表扫描。这可能会大大降低性能。

第三次,使用NULLS会导致错综复杂的Transact-SQL代码,这可能意味着代码无法有效运行或有错误。

理想情况下,应在SQL Server数据库中避免使用NULL。

不使用NULL,而是在数据库中使用与此类似的编码方案:

  • NA:不适用
  • NYN:尚未知晓
  • TUN:真的不为人知

这样的方案提供了使用NULL的好处,但没有缺点。

答案 6 :(得分:0)

NULL对我来说也很好看。 SQL Server有多种索引可供选择。我忘记了哪些人这样做,但有些只是给定范围内的索引值。如果您正在测试的列上有这种索引,则NULL值记录将不在索引中,并且索引扫描会很快。

答案 7 :(得分:0)

在列中有很多NULL,其上有一个索引(或从它开始)通常有利于这种查询。

未在索引中输入NULL值,这意味着在其中插入/更新具有NULL的行不会影响必须更新另一个二级索引的性能。例如,如果只有0.001%的行在该列中具有非空值,则IS NOT NULL查询变得非常有效,因为它只扫描相对较小的索引。

当然所有这些都是相对的,如果你的桌子很小,它没有任何明显的区别。