Sqlite View 不使用索引进行左连接查询
Sqlite View does not use index for left join queries
在 Sqlite 中,我将视图定义为两个 table 的联合。当我 运行 使用该视图进行查询时,如果查询足够简单,则会使用索引。对于某些复杂的查询,它不会并最终 运行ning 完整 table 扫描。有没有办法解决这个问题,以便我可以高效地使用视图?
Table/View 定义:
CREATE TABLE 'Table1' (Id varchar (18) PRIMARY KEY UNIQUE ON CONFLICT ROLLBACK, Name varchar (255) )
CREATE TABLE 'Table2' (Id varchar (18) PRIMARY KEY UNIQUE ON CONFLICT ROLLBACK, Name varchar (255) )
CREATE TABLE 'Table3' (Id varchar (18) PRIMARY KEY UNIQUE ON CONFLICT ROLLBACK, Name varchar (255) )
CREATE VIEW [UnionView] AS SELECT 'T1' tid, T1.rowid, T1.* FROM [Table1] T1 UNION ALL SELECT 'T2' tid, T2.rowid, T2.* FROM [Table2] T2
简单查询(使用索引):
SELECT Id FROM [UnionView] WHERE Id = 'asdf'
解释查询计划:
- 复合查询
- 最左子查询
- SEARCH TABLE Table1 AS T1 USING INDEX sqlite_autoindex_Table1_1 (Id=?)
- 联合所有
- SEARCH TABLE Table2 AS T2 USING INDEX sqlite_autoindex_Table2_1 (Id=?)
LEFT JOIN 查询(未使用索引):
SELECT T3.Id FROM [Table3] T3 LEFT JOIN [UnionView] T ON T3.Id=T.Id WHERE T3.Id = 'asdf'
解释查询计划
- 实体化 2
- 复合查询
- 最左子查询
- 扫描 TABLE Table1 AS T1
- 联合所有
- 扫描TABLE Table2 AS T2
- SEARCH TABLE Table3 AS T3 USING COVERING INDEX sqlite_autoindex_Table3_1 (Id=?)
- 扫描子查询 2 为 T
您的 复杂 查询对 Table1
和 Table2
进行了完整 table 扫描,因为您没有对 UnionView
进行任何过滤].
它确实使用 sqlite_autoindex_Table3_1
.
此外,WHERE
子句在连接后应用。
如果您在连接之前过滤 UnionView
,则将使用索引:
EXPLAIN QUERY PLAN
SELECT T3.Id
FROM [Table3] T3
LEFT JOIN (SELECT Id FROM [UnionView] WHERE Id = 'asdf') T
ON T3.Id=T.Id
WHERE T3.Id = 'asdf'
结果:
- 实体化 3
- 复合查询
- 最左子查询
- SEARCH TABLE Table1 AS T1 USING INDEX sqlite_autoindex_Table1_1 (Id=?)
- 联合所有
- SEARCH TABLE Table2 AS T2 USING INDEX sqlite_autoindex_Table2_1 (Id=?)
- SEARCH TABLE Table3 AS T3 USING COVERING INDEX sqlite_autoindex_Table3_1 (Id=?)
- 扫描子查询 3
在 Sqlite 中,我将视图定义为两个 table 的联合。当我 运行 使用该视图进行查询时,如果查询足够简单,则会使用索引。对于某些复杂的查询,它不会并最终 运行ning 完整 table 扫描。有没有办法解决这个问题,以便我可以高效地使用视图?
Table/View 定义:
CREATE TABLE 'Table1' (Id varchar (18) PRIMARY KEY UNIQUE ON CONFLICT ROLLBACK, Name varchar (255) )
CREATE TABLE 'Table2' (Id varchar (18) PRIMARY KEY UNIQUE ON CONFLICT ROLLBACK, Name varchar (255) )
CREATE TABLE 'Table3' (Id varchar (18) PRIMARY KEY UNIQUE ON CONFLICT ROLLBACK, Name varchar (255) )
CREATE VIEW [UnionView] AS SELECT 'T1' tid, T1.rowid, T1.* FROM [Table1] T1 UNION ALL SELECT 'T2' tid, T2.rowid, T2.* FROM [Table2] T2
简单查询(使用索引):
SELECT Id FROM [UnionView] WHERE Id = 'asdf'
解释查询计划:
- 复合查询
- 最左子查询
- SEARCH TABLE Table1 AS T1 USING INDEX sqlite_autoindex_Table1_1 (Id=?)
- 联合所有
- SEARCH TABLE Table2 AS T2 USING INDEX sqlite_autoindex_Table2_1 (Id=?)
LEFT JOIN 查询(未使用索引):
SELECT T3.Id FROM [Table3] T3 LEFT JOIN [UnionView] T ON T3.Id=T.Id WHERE T3.Id = 'asdf'
解释查询计划
- 实体化 2
- 复合查询
- 最左子查询
- 扫描 TABLE Table1 AS T1
- 联合所有
- 扫描TABLE Table2 AS T2
- SEARCH TABLE Table3 AS T3 USING COVERING INDEX sqlite_autoindex_Table3_1 (Id=?)
- 扫描子查询 2 为 T
您的 复杂 查询对 Table1
和 Table2
进行了完整 table 扫描,因为您没有对 UnionView
进行任何过滤].
它确实使用 sqlite_autoindex_Table3_1
.
此外,WHERE
子句在连接后应用。
如果您在连接之前过滤 UnionView
,则将使用索引:
EXPLAIN QUERY PLAN
SELECT T3.Id
FROM [Table3] T3
LEFT JOIN (SELECT Id FROM [UnionView] WHERE Id = 'asdf') T
ON T3.Id=T.Id
WHERE T3.Id = 'asdf'
结果:
- 实体化 3
- 复合查询
- 最左子查询
- SEARCH TABLE Table1 AS T1 USING INDEX sqlite_autoindex_Table1_1 (Id=?)
- 联合所有
- SEARCH TABLE Table2 AS T2 USING INDEX sqlite_autoindex_Table2_1 (Id=?)
- SEARCH TABLE Table3 AS T3 USING COVERING INDEX sqlite_autoindex_Table3_1 (Id=?)
- 扫描子查询 3