索引上非最左列的MAX查询的Sqlite优化

时间:2017-07-16 03:16:20

标签: database sqlite optimization indexing

我注意到有关SQLite's query optimizer的在线页面保证,如果索引的最左侧列为SELECT MAX(colA) FROM TABLE,则可以优化colA格式的查询。

但是,我不太清楚当使用索引根据WHERE子句中的相等性来缩小表时会发生什么,这样索引中的下一列就是I&# 39; m开始MAX。根据索引的结构,最大值应该可以快速访问,作为满足WHERE子句的索引子集中的最后一行。例如,给定colAcolB的索引,应该可以找到SELECT MAX(colB) FROM SillyTable WHERE colA = 1而不扫描与colA = 1关联的所有6行:

Index of SillyTable on colA, colB:
colA    colB    rowid
1       1       4
1       2       5
1       4       2
1       5       8
1       6       3     # This is the one
2       1       1
2       5       6
2       8       7

SQLite是否实际上优化了这样的查询,还是会扫描满足WHERE子句的所有行?如果进行扫描,如何更改查询以使其运行得更快?

我的具体用例类似于SillyTable示例。我创建了下表:

CREATE TABLE Product(
  ProductTypeID      INTEGER NOT NULL,
  ProductID          INTEGER NOT NULL,
  PRIMARY KEY(ProductTypeID, ProductID),
  FOREIGN KEY(ProductTypeID)
    REFERENCES ProductType(ProductTypeID)
);

ProductTypeID对表格没有特别的选择性;我可能有许多行具有相同的ProductTypeID但不同的ProductIDEXPLAIN QUERY PLAN告诉我,我的查询使用了为复合主键自动构建的索引,但无论是扫描还是二进制搜索使用索引找到的行的子集,都是如此:

EXPLAIN QUERY PLAN SELECT MAX(ProductID) FROM Product
  WHERE ProductTypeID = ?;

=>

SEARCH TABLE Product USING COVERING INDEX sqlite_autoindex_Product_1(ProductTypeID=?)

1 个答案:

答案 0 :(得分:0)

这在EXPLAIN输出中显示:

sqlite> EXPLAIN SELECT MAX(ProductID) FROM Product WHERE ProductTypeID = ?;
addr  opcode         p1    p2    p3    p4             p5  comment      
----  -------------  ----  ----  ----  -------------  --  -------------
0     Init           0     17    0                    00  Start at 17  
1     Null           0     1     2                    00  r[1..2]=NULL 
2     OpenRead       1     3     0     k(2,,)         02  root=3 iDb=0; sqlite_autoindex_Product_1
3     Variable       1     3     0                    00  r[3]=parameter(1,)
4     IsNull         3     13    0                    00  if r[3]==NULL goto 13
5     Affinity       3     1     0     D              00  affinity(r[3])
6     SeekLE         1     13    3     1              00  key=r[3]     
7       IdxLT          1     13    3     1              00  key=r[3]     
8       Column         1     1     4                    00  r[4]=Product.ProductID
9       CollSeq        0     0     0     (BINARY)       00               
10      AggStep0       0     4     1     max(1)         01  accum=r[1] step(r[4])
11      Goto           0     13    0                    00  max() by index
12    Prev           1     7     0                    00               
13    AggFinal       1     1     0     max(1)         00  accum=r[1] N=1
14    Copy           1     5     0                    00  r[5]=r[1]    
15    ResultRow      5     1     0                    00  output=r[5]  
16    Halt           0     0     0                    00               
17    Transaction    0     0     1     0              01  usesStmtJournal=0
18    Goto           0     1     0                    00               

为了使代码生成器更简单,SQLite总是为聚合创建一个循环(第6到12行)。但是,对于//Action With Parameter public ActionResult ClosedEvents(string searchBy, string search, int page = 1, int pageSize = 20, bool falsPositive = false) { } //And your routing should be : routes.MapRoute( "history", // Route name "{controller}/{action}/{searchBy}/{search}/{page}/{pageSize}/{falsPositive}", // URL with parameters new { controller = "Teum", action = "ClosedEvents", searchBy = "", search = "",page="",pageSize="",falsPositive="" } // Parameter defaults ); ,此循环在第一个成功步骤(第11行)之后中止。