为什么要使用IS DISTINCT FROM - Postgres

时间:2015-11-20 13:48:55

标签: sql postgresql

Postgres IS DISTINCT FROM中此功能的最佳用途是什么,试听使用COALESCE获得了相同的结果,但在更短的时间内,在测试后:

SELECT COUNT(P.id)

FROM produto P
  INNER JOIN cliente CL ON P.id_cliente = CL.id_cliente

WHERE 
  COALESCE(CL.tp_pessoa,'') <> 'JURIDICA' -- test with COALESCE, average 610 ms

  (CL.tp_pessoa <> 'JURIDICA' OR CL.tp_pessoa IS NULL) -- test with OR, average 668 ms

  CL.tp_pessoa IS DISTINCT FROM 'JURIDICA' -- test with IS DISTINCT FROM, average 667 ms

  OUTRO TESTE:

  COALESCE(CL.tp_pessoa,'') <> COALESCE(P.observacao,'') -- test with IS DISTINCT FROM, average 940 ms

  CL.tp_pessoa IS DISTINCT FROM P.observacao -- test with ```IS DISTINCT FROM```, average 930 ms, a little beter here

它具有较低的性能,并且是SQL Server等其他数据库中找不到的功能,这是不使用它的另一个原因。

进行另一项测试,其中两个条件都可以NULLIS DISTINCT FROM略有优势,这将是它的用途,还有更多适用的标准?

编辑:

就像@hvd所说的那样,它是ANSI SQL的一部分,COALESCE(CL.tp_pessoa,'') <> COALESCE(P.observacao,'')的结果与CL.tp_pessoa IS DISTINCT FROM P.observacao的结果不同。

4 个答案:

答案 0 :(得分:4)

COALESCE()的问题在于它使该子句成为非SARGable。这会影响性能,因为无法使用索引。

(CL.tp_pessoa <> 'JURIDICA' OR CL.tp_pessoa IS NULL)的问题在于它很冗长,特别是当您正在考虑比较两个可能都为NULL的字段时:

(CL.tp_pessoa <> CL2.tp_pessoa 
    OR (CL.tp_pessoa IS NOT NULL AND CL2.tp_pessoa IS NULL) 
    OR (CL.tp_pessoa IS NULL AND CL2.tp_pessoa IS NOT NULL))

如果您正在进行UPDATE以将临时表与基表合并,并且它们共享30个字段,并且您只想在至少有一个字段不同时更新,并且29个非关键字段中的任何一个都可以NULL ...你可以理解编写查询会有多痛苦。

答案 1 :(得分:2)

首先,很方便。其次,您需要对大量数据运行测试。在一秒钟内,数据库服务器上可能会发生很多事情,因此百分之一秒的小变化不一定表示整体性能。

从积极的方面来说,我认为Postgres会使用is distinct from的索引。我不认为索引必然会用于所有替代方案。

答案 2 :(得分:2)

您看到的性能差异很小。注重正确性。

你举个例子

COALESCE(CL.tp_pessoa,'') <> COALESCE(P.observacao,'')

CL.tp_pessoa IS DISTINCT FROM P.observacao

如果CL.tp_pessoaNULL,而P.observacao'',则第一次比较将它们视为相等,而第二次比较将它们视为不相等。

因此,如果要将它们相等,请使用第一个版本;如果要将它们比较为不相等,则使用第二个版本。

答案 3 :(得分:1)

如果column1上有一个索引,如CREATE INDEX "index_name" ON table1 USING btree (column1);,那么在IS DISTINCT FROM sql引擎的情况下,可以使用该索引。使用COALESCE时,它不能。