Sql 当存在NULL时,选择与另一个表中的项不匹配的行的性能
相关问题: 我试图使用此方法选择行,但无法使其在SQLite中工作。经过一番争论,我突然想到,原因可能是某些字段中存在空值。果然,我是对的,当我在下面的查询中将Sql 当存在NULL时,选择与另一个表中的项不匹配的行的性能,sql,sqlite,Sql,Sqlite,相关问题: 我试图使用此方法选择行,但无法使其在SQLite中工作。经过一番争论,我突然想到,原因可能是某些字段中存在空值。果然,我是对的,当我在下面的查询中将=更改为IS时,事情开始按预期运行: CREATE TEMP TABLE newEvent(id INTEGER,t INTEGER,name,extra,extra2,extra3); INSERT INTO newEvent(id,t,name,extra,extra2,extra3) VALUES
=
更改为IS
时,事情开始按预期运行:
CREATE TEMP TABLE newEvent(id INTEGER,t INTEGER,name,extra,extra2,extra3);
INSERT INTO newEvent(id,t,name,extra,extra2,extra3) VALUES
(0, 1376351146, 'TEST', NULL, NULL, NULL),
(0, 1376348867, 'OLD', NULL, NULL,NULL);
SELECT n.id,n.t,n.name,n.extra,n.extra2,n.extra3 FROM newEvent n
LEFT JOIN event E ON n.t = E.t AND n.name IS E.name
AND n.extra IS E.extra;
AND n.extra2 IS E.extra2;
AND n.extra3 IS E.extra3
WHERE E.id IS NULL;
DROP TABLE newEvent;
在上面的示例中,表event
中有一条记录,其name='OLD'
。newEvent
表的定义与原始event
表相同
然而,我注意到一个大问题:我的查询现在运行几乎需要30秒!如果我只将n.name IS E.name
更改为n.name=E.name
,但保留所有其他IS
的原样,那么查询只需要大约400毫秒。(表event
中约有300万条记录)
为什么性能有这么大的差异?事实证明,对于名称
比较,我实际上可以使用=
而不是IS
,因为它从来都不是空的,但如果它曾经是空的,它似乎会中断。相反,我担心在某个时候查询可能会开始运行缓慢,因为我不明白是什么让平等查询运行得如此之快。我的猜测是,也许SQLite不知何故知道额外字段中有空值,并且能够进行优化,但我希望有比胡乱猜测更坚定的东西
据我所知,
IS
只是=
,还有一个附加条件,即它将把空比较视为空字符串(假设没有实际的空字符串进行比较)。那么,为什么在名称字段上使用=
的速度要快75倍,但对额外字段的性能没有影响呢?在连接中,SQLite可以通过索引查找优化=
,但不能优化is
。
此外,在单个查询中,每个表不可能使用多个索引
因此,要么您没有同时包含name
和extra
*的多列索引,要么额外列的选择性不够高
您可以使用以下命令尝试完全不同的查询:
但是,这不允许您获得未比较的列(如
id
)。为什么不比较id
列?要匹配的行是否会有所不同?@Andriy name和其他字段都是非类型化的(类型对SQLite来说更像是“建议”)。Name始终是一个字符串,而extra则是string、number和NULL。它确实有区别,因为SQLite不会将“200”匹配为等于200,例如。@CL我不匹配该行,因为它是自动的,在插入之前我不知道它。我基本上是在试图防止同一条记录被插入两次(在我使用的体系结构中,在极少数情况下是可能的)。其他字段足以唯一标识记录。谢谢,我不知道非类型化列的事情,这是SQLite的一个奇怪方面。(并删除我特别吵闹的第一条评论。)奇怪的是,名字上没有索引,也没有额外的字段。。。然而,在t字段上有一个。
SELECT t, name, extra, extra2, extra3 FROM newEvent
EXCEPT
SELECT t, name, extra, extra2, extra3 FROM event