CREATE TABLE tbl (
column1 TEXT NOT NULL,
column2 TEXT NOT NULL,
val INTEGER NOT NULL,
PRIMARY KEY (column1, column2)
);
-- Uncomment to make the final SELECT fast
-- CREATE INDEX column2_ix ON tbl (column2);
EXPLAIN QUERY PLAN SELECT val FROM tbl WHERE column1 = 'column1' AND column2 = 'column2';
EXPLAIN QUERY PLAN SELECT val FROM tbl WHERE column1 = 'column1';
EXPLAIN QUERY PLAN SELECT val FROM tbl WHERE column2 = 'column2';
QUERY PLAN
`--SEARCH tbl USING INDEX sqlite_autoindex_tbl_1 (column1=? AND column2=?)
QUERY PLAN
`--SEARCH tbl USING INDEX sqlite_autoindex_tbl_1 (column1=?)
QUERY PLAN
`--SCAN tbl
因此,前两个查询,即SELECT on (column1, column2)和(column1),将使用索引来执行搜索。 请注意,最后一个查询SELECT on (column2)有不同的输出。它说它将访问SCAN表--也就是说,逐个遍历每一行。这将大大降低性能。 如果我们在上面的脚本中取消注解CREATE INDEX会发生什么?
QUERY PLAN
`--SEARCH tbl USING INDEX sqlite_autoindex_tbl_1 (column1=? AND column2=?)
QUERY PLAN
`--SEARCH tbl USING INDEX sqlite_autoindex_tbl_1 (column1=?)
QUERY PLAN
`--SEARCH tbl USING INDEX column2_ix (column2=?)
3条答案
按热度按时间bakd9h0s1#
这可能不会带来性能上的好处,因为针对
col1=xxx and col2=yyy
的查询将使用与col1=zzz
等查询相同的索引,但没有提到col2。但我的经验仅限于Oracle、SQL Server、Ingres和MySQL。我不确定。1dkrff032#
您当然不希望在列1上添加一个唯一索引,就像您刚才所说的那样:
column1和column2本身都不是唯一的。
如果第一列在前,那么在大多数数据库中,它将是多列索引中的第一列,因此它很可能会被使用。第二列可能不会使用索引。除非你发现问题,否则我不会在第二列上添加索引。同样,我会根据你上面写的评论添加一个索引,而不是唯一索引。
但是SQLlite必须有某种方式来查看它正在使用的数据,就像大多数其他数据库一样,对吗?设置Pk,看看只使用column1的查询是否正在使用它。
cnh2zyt33#
我在研究这个问题的时候偶然发现了这个问题,所以我想我应该分享一下我的发现。注意,下面的所有内容都是在SQLite 3.39.4上测试的。我不保证它在旧的/未来的版本上会如何运行。也就是说,SQLite并不完全以随机地彻底改变行为而闻名。
要具体给予SQLite的具体答案:
column1
上的索引将不提供任何益处,但是column2
上的索引将提供益处。让我们看一个简单的SQL脚本:
EXPLAIN QUERY PLAN
是SQLite的一种方法,它允许您检查其查询计划器实际要做什么。您可以通过以下方式执行脚本:
这给出了输出
因此,前两个查询,即
SELECT
on(column1, column2)
和(column1)
,将使用索引来执行搜索。请注意,最后一个查询
SELECT
on(column2)
有不同的输出。它说它将访问SCAN
表--也就是说,逐个遍历每一行。这将大大降低性能。如果我们在上面的脚本中取消注解
CREATE INDEX
会发生什么?现在,
column2
上的查询也将使用索引,并且性能应该与其他查询一样。