Select SQLite选择时间非常慢

Select SQLite选择时间非常慢,select,sqlite,inner-join,Select,Sqlite,Inner Join,我的程序有一些奇怪的行为,也许你能给它带来一些启示 今天我开始测试一些代码,并意识到一个特定的查询非常慢(大约需要2分钟) 在此处选择: select distinct table1.someName from table1 INNER JOIN table2 ON table2.id = table1.t2_id INNER JOIN table3 ON table1.id = table3.t1_id INNER JOIN table4 ON Table3.id = table4.t3_id

我的程序有一些奇怪的行为,也许你能给它带来一些启示

今天我开始测试一些代码,并意识到一个特定的查询非常慢(大约需要2分钟)

在此处选择:

select distinct table1.someName
from table1
INNER JOIN table2 ON table2.id = table1.t2_id
INNER JOIN table3 ON table1.id = table3.t1_id
INNER JOIN table4 ON Table3.id = table4.t3_id 
INNER JOIN table5 ON table5.id = table4.t5_id 
INNER JOIN table6 ON table4.id = table6.t4_id 
where t4_name = 'whatever'
and t2_name = 'moarWhatever'

and timestamp_till is null 

order by someName
所以问题是,结果是大约120条记录。
内部连接
s将
timestamp\u的检查量减少到每个记录上约20条记录,直到为空

最让我头疼的是,我已经测试过将整个表
table6
插入到新创建的表中,并将
timestamp\u-till
重命名为
ende
。在该表上,选择大约在0.1秒内完成

时间戳是SQLite3的某种保留名称吗?这可能是SQLite引擎中的错误吗?是我的错吗?哦

编辑:添加
解释查询计划
输出

当使用
进行查询时,timestamp\u till为空
他给出:

0|0|4|SEARCH TABLE table5 USING COVERING INDEX sqlite_autoindex_table5 (t4_name=?) (~1 rows)
0|1|3|SEARCH TABLE table4 USING INDEX table4.fk_table4_1_idx (t5_id=?) (~10 rows)
0|2|2|SEARCH TABLE table3 USING INTEGER PRIMARY KEY (rowid=?) (~1 rows)
0|3|0|SEARCH TABLE table1 USING INTEGER PRIMARY KEY (rowid=?) (~1rows)
0|4|1|SEARCH TABLE table2 USING INTEGER PRIMARY KEY (rowid=?) (~1 rows)
0|5|5|SEARCH TABLE table6 USING INDEX table6.fk_table6_ts_till (timestamp_till=?) (~2 rows)
0|0|0|USE TEMP B-TREE FOR GROUP BY
0|0|0|USE TEMP B-TREE FOR DISTINCT
最快的是:

   select distinct table1.someName
    from table1
    INNER JOIN table2 ON table2.id = table1.t2_id
    INNER JOIN table3 ON table1.id = table3.t1_id
    INNER JOIN table4 ON Table3.id = table4.t3_id 
    INNER JOIN table5 ON table5.id = table4.t5_id 
    INNER JOIN table6 ON table4.id = table6.t4_id 
    where t4_name = 'whatever'
    and t2_name = 'moarWhatever'    
    order by someName
其结果是:

0|0|4|SEARCH TABLE table5 USING COVERING INDEX sqlite_autoindex_table5_1 (t4name=?) (~1 rows)
0|1|3|SEARCH TABLE table4 USING INDEX table4.fk_table4_1_idx (t5_id=?) (~10 rows)
0|2|2|SEARCH TABLE table3 USING INTEGER PRIMARY KEY (rowid=?) (~1 rows)
0|3|0|SEARCH TABLE table1 USING INTEGER PRIMARY KEY (rowid=?) (~1rows)
0|4|1|SEARCH TABLE table2 USING INTEGER PRIMARY KEY (rowid=?) (~1 rows)
0|5|5|SEARCH TABLE table6 USING COVERING INDEX sqlite_autoindex_table6_1 (id=?) (~10 rows)
0|0|0|USE TEMP B-TREE FOR GROUP BY
0|0|0|USE TEMP B-TREE FOR DISTINCT
使用作为表6副本的测试表

0|0|4|SEARCH TABLE table5 USING COVERING INDEX sqlite_autoindex_table5_1 (name=?) (~1 rows)
0|1|3|SEARCH TABLE table4 USING INDEX table4.fk_t5_idx (t5_id=?) (~10 rows)
0|2|2|SEARCH TABLE table3 USING INTEGER PRIMARY KEY (rowid=?) (~1 rows)
0|3|0|SEARCH TABLE table1 USING INTEGER PRIMARY KEY (rowid=?) (~1rows)
0|4|1|SEARCH TABLE table2 USING INTEGER PRIMARY KEY (rowid=?) (~1 rows)
0|5|5|SEARCH TABLE test USING INDEX test.fk_test__idx (id=?) (~2 rows)
0|0|0|USE TEMP B-TREE FOR GROUP BY
0|0|0|USE TEMP B-TREE FOR DISTINCT

为测试创建脚本

CREATE TABLE "test"(
  "id" INTEGER NOT NULL,
  "t12_id" INTEGER NOT NULL,
  "value" DECIMAL NOT NULL,
  "anfang" INTEGER NOT NULL,
  "ende" INTEGER DEFAULT NULL,
  PRIMARY KEY("id","t12_id","anfang"),
  CONSTRAINT "fk_test_t12_id"
    FOREIGN KEY("t12_id")
    REFERENCES "table12"("id"),
  CONSTRAINT "fk_test_id"
    FOREIGN KEY("id")
    REFERENCES "id_col"("id"),
  CONSTRAINT "fk_test_anfang"
    FOREIGN KEY("anfang")
    REFERENCES "ts_col"("id"),
  CONSTRAINT "fk_test_ende"
    FOREIGN KEY("ende")
    REFERENCES "ts_col"("id")
);
CREATE INDEX "test.fk_test_idx_t12_id" ON "test"("t12_id");
CREATE INDEX "test.fk_test_idx_id" ON "test"("id");
CREATE INDEX "test.fk_test_anfang" ON "test"("anfang");
CREATE INDEX "test.fk_test_ende" ON "test"("ende");

soo long zai

第一个注意事项:SQLite将在其查询中仅使用1个索引。永远不会更多(使用当前版本)

因此,SQLite正在做的是:

  • 慢速查询:使用
    时间戳上的索引直到
  • 快速查询(无时间戳):使用
    table6.id
    上的(自动)索引
我看到两个解决办法

您可以使用子查询:

select distinct SomeName FROM
(
   select table1.someName as "SomeName", timestamp_till
   from table1
   INNER JOIN table2 ON table2.id = table1.t2_id
   INNER JOIN table3 ON table1.id = table3.t1_id
   INNER JOIN table4 ON Table3.id = table4.t3_id 
   INNER JOIN table5 ON table5.id = table4.t5_id 
   INNER JOIN table6 ON table4.id = table6.t4_id 
   where t4_name = 'whatever'
   and t2_name = 'moarWhatever'
) Q
where timestamp_till is null 
order by SomeName;
或者,如果您在其他地方不需要索引,也可以将索引放在
时间戳上直到


通过重新排列连接顺序,也可能会获得一些速度提升。通常情况下,最小的表首先会更快,但这可能会有很大差异。

两个查询的输出是什么?连接两个表将需要一些时间,这取决于它们都有多少个条目,而不是最终结果。加入6个表将花费更多的时间。确保所有外键都已索引,这应该会有所帮助。@CL.添加到问题@MPelletier是的,我知道,但是相同的查询
timestamp\u-till为null
需要1-2分钟,甚至不需要一秒钟……你能详细说明一下
timestamp\u-till
someName
在哪个表中吗?添加了快速查询和
timesamp\u-till
来自哪里。这看起来很酷,但它如何解释呢,对于
timestamp\u till
的1:1副本,使用其他名称的“慢速查询”可以非常快,并且在原始表上不是吗?@Zaiborg您的其他名称也被索引了吗?是的,我从重命名的create创建了整个测试script@Zaiborg我开始怀疑“1指数”规则。我看不到您的查询中,
timestamp\u-till
有另一个名称。查询是一样的,我只是复制了表并将
timestamp\u-till
重命名为
ende
成为舒尔,这不会是名称冲突。。。今天,“慢查询”是第一次尝试,就像“快速查询”(即时结果)一样,在一些运行之后,像往常一样慢。。。