0

对于 SQL 查询性能,处理空列的最佳方法是什么?

假设我有一些数据对象 Person 和 Employer。一个人可以有一个雇主的引用,但他们也可以是失业的,这通过有一个空引用来表示。

对可以为空的 EmployerId 字段进行左外连接,还是对“空”雇主进行内连接,然后在数据检索代码中将该“空”雇主变为实际空值,对数据库性能是否更好?

(我知道这是一个微不足道的例子,但假设我有数万行外部连接开始显着影响性能)

可空列的外部联接

表人员(PersonId、Name、EmployerId)(EmployerId 可以为空)

(1, 'John Doe', 1)  
(2, 'Joe Smith', NULL)  
(3, 'Jane Doe', 2)  

表雇主(EmployerId,姓名)

(1, 'Microsoft')  
(2, 'google')  

询问

SELECT * FROM Person LEFT OUTER JOIN Employers ON Person.EmployerId = Employers.EmployerId

(1, 'John Doe', 1, 'Microsoft')  
(2, 'Joe Smith', NULL, NULL)  
(3, 'Jane Doe', 2, 'google')  

除了读取数据库之外,代码不需要做任何事情。

“空”行的内连接

表人员(PersonId、Name、EmployerId)(EmployerId 不可为空)

(1, 'John Doe', 1)  
(2, 'Joe Smith', 0)  
(3, 'Jane Doe', 2)  

表雇主(EmployerId,姓名)

(0, '{NULL}')  
(1, 'Microsoft')  
(2, 'google')  

询问

SELECT * FROM Person INNER JOIN Employers ON Person.EmployerId = Employers.EmployerId

(1, 'John Doe', 1, 'Microsoft')  
(2, 'Joe Smith', 0, '{NULL}')  
(3, 'Jane Doe', 2, 'google') 

代码必须进行数据库读取,然后检测“{NULL}”并转换为空引用。

4

1 回答 1

3

第二个版本在我看来很奇怪。 NULL意思更像是“缺少值”,而不是“以 NULL 作为索引的相应记录”。如果您打算使用第二个版本,请使用其他值而不是NULL.

通常,当数据库引擎支持外连接时,该算法与内连接算法惊人地相似。如果数据库支持嵌套循环内连接、索引查找内连接、基于散列的内连接或边缘排序内连接,那么它支持外连接的相同算法。由于外部连接的结果集更大,性能差异会更大。

顺便说一句,在您现在修改的第二个示例中,效果与内部连接相同。查询是:

SELECT *
FROM Person INNER JOIN
     Employers
     ON Person.EmployerId = Employers.EmployerId

join一个或两个EmployerIds 为时,条件失败NULLNULL失败所有比较,除了is null. 因此,第二个示例不会获取雇主记录NULL

您可以更改on条件来解决此问题。这里有两种方法:

     on (Person.EmployerId = Employers.EmployerId) or
        (Person.EmployerId is NULL and  Employers.EmployerId is null)

     on coalesce(Person.EmployerId, -1) = coalesce(Emlpoyers.EmployerId, -1)

然后在这两种情况下连接不再相同。而且,这些连接的执行可能与第一种情况完全不同。特别是,or列上的条件和函数会阻碍使用索引进行连接。

于 2013-06-03T16:20:51.933 回答