我有一个查询需要4秒钟才能完成:
SELECT MAX(Date), Bond_Id, Sell_Price FROM Quotes GROUP BY Bond_Id;
该表有大约31K条记录:
CREATE TABLE Quotes (
_id INTEGER PRIMARY KEY AUTOINCREMENT,
Bond_Id INTEGER NOT NULL,
Date TEXT NOT NULL,
Buy_Yield REAL NOT NULL,
Sell_Yield REAL NOT NULL,
Buy_Price REAL NOT NULL,
Sell_Price REAL NOT NULL,
Base_Price REAL NOT NULL,
FOREIGN KEY (Bond_Id) REFERENCES Bonds(_id));
CREATE INDEX QuotesNdx ON Quotes(Bond_Id);
我设法将查询时间从7秒减少到4秒,这仍然是不可接受的。我尝试了ANALYZE
、附加的复合索引和删除外键。EXPLAIN
输出:
0 Trace 0 0 0 explain select max(date),bond_id,sell_price from quotes group by bond_id; 00
1 Noop 0 0 0 00
2 Integer 0 6 0 00
3 Integer 0 5 0 00
4 Goto 0 20 0 00
5 Integer 1 6 0 00
6 Return 0 0 0 00
7 IfPos 5 9 0 00
8 Return 0 0 0 00
9 AggFinal 1 1 0 max(1) 00
10 SCopy 1 9 0 00
11 SCopy 2 10 0 00
12 SCopy 3 11 0 00
13 ResultRow 9 3 0 00
14 Return 0 0 0 00
15 Null 0 2 0 00
16 Null 0 3 0 00
17 Null 0 4 0 00
18 Null 0 1 0 00
19 Return 0 0 0 00
20 Gosub 0 15 0 00
21 Goto 0 48 0 00
22 SetNumColumns 0 7 0 00
23 OpenRead 0 6 0 00
24 SetNumColumns 0 2 0 00
25 OpenRead 2 7 0 keyinfo(1,BINARY) 00
26 Rewind 2 44 13 0 00
27 Noop 2 -7 13 0 01
28 IdxRowid 2 16 0 00
29 MoveGe 0 0 16 00
30 Column 2 0 8 00
31 Eq 7 36 8 collseq(BINARY) 10
32 Move 8 7 0 00
33 Gosub 0 7 0 00
34 IfPos 6 47 0 00
35 Gosub 0 15 0 00
36 Column 0 2 17 00
37 CollSeq 0 0 0 collseq(BINARY) 00
38 AggStep 0 17 1 max(1) 01
39 SCopy 7 2 0 00
40 Column 0 6 3 00
41 RealAffinity 3 0 0 00
42 Integer 1 5 0 00
43 Next 2 27 0 00
44 Close 0 0 0 00
45 Close 2 0 0 00
46 Gosub 0 7 0 00
47 Halt 0 0 0 00
48 Transaction 0 0 0 00
49 VerifyCookie 0 9 0 00
50 TableLock 0 6 0 Quotes 00
51 Goto 0 22 0 00
3条答案
按热度按时间ffscu2ro1#
可以通过创建覆盖索引来优化此特定查询;列必须按照它们用于查找的顺序排列:
ioekq8ef2#
感谢你们所有人的回答。事实上,在我的查询中,违规者是“group by”。我设法通过阅读关于SQLite的SELECT的这篇文章找到了解决方案(http://sqlite.org/lang_select.html)文档:
“如果SELECT语句是具有GROUP BY子句的聚合查询,则将为数据集的每一行计算指定为GROUP BY子句一部分的每个表达式。然后,根据结果将每一行分配到一个“组”;将计算GROUP BY表达式的结果相同的行分配到同一组。为了对行进行分组,NULL值被视为相等。在计算GROUP BY子句中的表达式时,适用于选择用于比较文本值的排序规则序列的常见规则。GROUP BY子句中的表达式不必是出现在结果中的表达式。GROUP BY子句中的表达式不能是聚合表达式。
因此,解决方案是创建一个包含(Date,Bond_ID)的复合索引,并将我的查询替换为如下内容:
现在这个查询只用了不到1秒的时间就完成了,这太棒了!
qyuhtwio3#
您的问题:
从按Bond_ID分组的报价中选择Max(Date)、Bond_ID、Sell_Price;
第一:您的查询有误。不应使用保留字作为字段名称。在您的示例中是一个“Date”字段
如果您在GROUP BY中使用任何字段,还应将SELECT中的所有其他字段与任何分组函数(MIN/MAX/COUNT/等)一起使用。
对应查询应为:
按Bond_ID从报价分组中选择Max(Date)、Bond_ID;
或
按“Date”=Max(“Date”)的Bond_ID从报价分组中选择Bond_ID,Max(Sell_Price);
第二个:
您需要为MIN/MAX/...中使用的每个字段创建索引...并在分组依据中