Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sqlite/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sqlite视图不对左联接查询使用索引_Sqlite_Indexing_View_Union - Fatal编程技术网

Sqlite视图不对左联接查询使用索引

Sqlite视图不对左联接查询使用索引,sqlite,indexing,view,union,Sqlite,Indexing,View,Union,在Sqlite中,我将视图定义为两个表的联合。当我使用该视图运行查询时,如果查询足够简单,就会使用索引。对于某些复杂的查询,它不会这样做,并最终运行完整的表扫描。有什么方法可以有效地使用视图吗 表/视图定义: 简单查询(使用索引): 解释查询计划: 复合查询 最左侧子查询 使用索引sqlite\u autoindex\u Table1\u 1(Id=?)将表1搜索为T1 联合所有 使用索引sqlite\u autoindex\u Table2\u 1(Id=?)将表2搜索为T2 左联接查询(不使

在Sqlite中,我将视图定义为两个表的联合。当我使用该视图运行查询时,如果查询足够简单,就会使用索引。对于某些复杂的查询,它不会这样做,并最终运行完整的表扫描。有什么方法可以有效地使用视图吗

表/视图定义: 简单查询(使用索引): 解释查询计划:
  • 复合查询
  • 最左侧子查询
  • 使用索引sqlite\u autoindex\u Table1\u 1(Id=?)将表1搜索为T1
  • 联合所有
  • 使用索引sqlite\u autoindex\u Table2\u 1(Id=?)将表2搜索为T2
  • 左联接查询(不使用索引): 解释查询计划
  • 具体化2
  • 复合查询
  • 最左侧子查询
  • 扫描表表1为T1
  • 联合所有
  • 扫描表表2为T2
  • 使用覆盖索引sqlite\u autoindex\u Table3\u 1(Id=?)将表3搜索为T3
  • 将子查询2扫描为T
  • 您的复杂查询会对
    Table1
    Table2
    进行完整的表扫描,因为您没有对
    UnionView
    进行任何筛选
    它确实使用了sqlite\u autoindex\u Table3\u 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
    • 复合查询
    • 最左侧子查询
    • 使用索引sqlite\u autoindex\u Table1\u 1(Id=?)将表1搜索为T1
    • 联合所有
    • 使用索引sqlite\u autoindex\u Table2\u 1(Id=?)将表2搜索为T2
    • 使用覆盖索引sqlite\u autoindex\u Table3\u 1(Id=?)将表3搜索为T3
    • 扫描子查询3

    如果左侧联接的右侧是一个表而不是一个视图,那么我们不需要RHS表的附加条件,对吗?因此,例如,此查询不需要对Table1进行显式筛选即可高效运行:
    SELECT T3.Id FROM Table3 T3 LEFT JOIN Table1 T1 on T3.Id=T1.Id,其中T3.Id='asdf'
    我相信我的困惑在于,因为在编写SELECT时我们可以将视图视为表,我不希望做一些不同的事情来高效地查询视图。@FernandoRodriguez不,这是不正确的。只有
    sqlite\u autoindex\u Table3\u 1
    将用于该查询,因为同样只有T3被过滤。@FernandoRodriguez查看演示:好的,也许这更像是sqlite优化的抱怨,但是sqlite不应该认为Id过滤器也应该应用于UnionView,而不是强迫我复制过滤器吗?您确实提到了where子句是在连接之后执行的,这有助于解释该行为。@FernandoRodriguez否,任何SQL查询中执行语句的顺序都会首先应用带有ON子句的连接,然后应用where子句中的条件。
    SELECT Id FROM [UnionView] WHERE Id = 'asdf'
    
    SELECT T3.Id FROM [Table3] T3 LEFT JOIN [UnionView] T ON T3.Id=T.Id  WHERE T3.Id = 'asdf'
    
    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'