我注意到有关SQLite's query optimizer的在线页面保证,如果索引的最左侧列为SELECT MAX(colA) FROM TABLE
,则可以优化colA
格式的查询。
但是,我不太清楚当使用索引根据WHERE
子句中的相等性来缩小表时会发生什么,这样索引中的下一列就是I&# 39; m开始MAX
。根据索引的结构,最大值应该可以快速访问,作为满足WHERE
子句的索引子集中的最后一行。例如,给定colA
和colB
的索引,应该可以找到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
但不同的ProductID
。 EXPLAIN QUERY PLAN
告诉我,我的查询使用了为复合主键自动构建的索引,但无论是扫描还是二进制搜索使用索引找到的行的子集,都是如此:
EXPLAIN QUERY PLAN SELECT MAX(ProductID) FROM Product
WHERE ProductTypeID = ?;
=>
SEARCH TABLE Product USING COVERING INDEX sqlite_autoindex_Product_1(ProductTypeID=?)
答案 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行)之后中止。