在此SQLite模式中是否有冗余索引?

时间:2019-02-08 14:56:23

标签: sql sqlite

我创建了一个SQLlite模式,如下所示:

CREATE TABLE tab1 (
        year INTEGER,
        tar_id TEXT,
        content BLOB,
        UNIQUE (year, tar_id) ON CONFLICT REPLACE);
CREATE INDEX tab1_ix1 ON bcas (year, tar_id);

然后,我查看了一个查询计划:

sqlite> explain query plan select * from tab1 where tar_id = 1 and year = (select max(year) from tab1 where year < 2019 and tar_id = 1);
QUERY PLAN
|--SEARCH TABLE tab1 USING COVERING INDEX sqlite_autoindex_tab1_1 (year=? AND tar_id=?)
`--SCALAR SUBQUERY
   `--SEARCH TABLE tab1 USING COVERING INDEX tab1_ix1 (year<?)

在我看来,只有一个索引足以完成此操作,但是它同时使用了我的显式tab1_ix1和自动生成的sqlite_autoindex_tab1_1

其中之一是多余的吗?如果是这样,我如何摆脱其中之一并获得相同的行为?

2 个答案:

答案 0 :(得分:2)

是的,您有一个冗余索引。 unique约束自动生成索引。您无需以相同的顺序为相同的列创建另一个显式索引。

请注意,(tar_id, year)上的索引将是不同的索引,因为索引中键的顺序很重要。

答案 1 :(得分:0)

尽管两个接缝都是多余的,但仍有一些细节需要重点关注。在查询的第一部分中使用“ *”,因此自动创建的候选项最适合,因为它链接了所有其他列以进行检索。在第二部分的“ max”子句中,仅考虑了两列(年份,tar_id),它们均以所需的顺序出现在手动创建的“较小”索引“ tab1_ix1”中,并且引擎认为较小的效率高,因此这次使用了tab1_ix1

因此,如果可以承受轻微的性能下降,并且第二个较小的tab1_ix1似乎负担较重,那么引擎将使用默认的自动创建索引。