1

我有一个非常简单的查询,大约需要 4 秒才能完成:

SELECT MAX(Date), Bond_Id, Sell_Price FROM Quotes GROUP BY Bond_Id;

该表也很简单,只有大约 31K 条记录。这是架构:

创建表行情(
    _id 整数主键自动增量,
    Bond_Id 整数非空,
    日期文本不为空,
    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);

我研究了 SQLite 文档,并设法将查询时间从 7s 减少到 4s,这仍然是不可接受的。这几天我一直在绞尽脑汁,没有运气。我已经尝试过 ANALYZE,一些额外的复合索引,并且还尝试删除外键。没有什么。

这是解释输出:

0 Trace 0 0 0 解释 select max(date),bond_id,sell_price 从报价组按bond_id;00
1 午饭 0 0 0 00
2 整数 0 6 0 00
3 整数 0 5 0 00
4 转到 0 20 0 00
5 整数 1 6 0 00
6 返回 0 0 0 00
7 IfPos 5 9 0 00
8 返回 0 0 0 00
9 AggFinal 1 1 0 最大(1) 00
10 复印 1 9 0 00
11 复制 2 10 0 00
12 复印 3 11 0 00
13 结果行 9 3 0 00
14 返回 0 0 0 00
15 空 0 2 0 00
16 空 0 3 0 00
17 空 0 4 0 00
18 空 0 1 0 00
19 返回 0 0 0 00
20 戈苏 0 15 0 00
21 转到 0 48 0 00
22 组数列 0 7 0 00
23 打开读取 0 6 0 00
24 组数列 0 2 0 00
25 打开读取 2 7 0 密钥信息(1,二进制) 00
26 倒带 2 44 13 0 00
27 午饭 2 -7 13 0 01
28 IdxRowid 2 16 0 00
29 移动锗 0 0 16 00
30 列 2 0 8 00
31 等式 7 36 8 collseq(BINARY) 10
32 移动 8 7 0 00
33 戈苏 0 7 0 00
34 IfPos 6 47 0 00
35 戈苏 0 15 0 00
36 列 0 2 17 00
37 CollSeq 0 0 0 collseq(BINARY) 00
38 AggStep 0 17 1 最大(1) 01
39 复印 7 2 0 00
40 列 0 6 3 00
41 真实亲和 3 0 0 00
42 整数 1 5 0 00
43 下一个 2 27 0 00
44 关闭 0 0 0 00
45 关闭 2 0 0 00
46 戈苏 0 7 0 00
47 暂停 0 0 0 00
48 交易 0 0 0 00
49 验证Cookie 0 9 0 00
50 表锁 0 6 0 行情 00
51 转到 0 22 0 00

有小费吗?

4

3 回答 3

3

这个特定的查询可以通过创建一个覆盖索引来优化;列必须按照它们用于查找的顺序排列:

CREATE INDEX whatever ON Quotes(Bond_ID, Date, Sell_Price);
于 2013-09-19T16:21:33.953 回答
0

谢谢大家的答案。实际上,我的查询中的违规者是“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) 的复合索引,并将我的查询替换为:

SELECT Date, Bond_Id, Sell_Price FROM Quotes
   WHERE Bond_Id=Bonds._id
   AND Date=(SELECT MAX(Date) FROM Quotes);

现在这个查询只需要不到 1 秒的时间就可以完成,这太棒了!

于 2013-09-24T11:10:01.200 回答
-1

您的查询

SELECT MAX(Date), Bond_Id, Sell_Price FROM Quotes GROUP BY Bond_Id;

第一:您的查询不正确。您不应使用保留字作为字段名称。在您的情况下是“日期”字段

如果您使用 GROUP BY 中的任何字段,您还应该将 SELECT 中的所有其他字段与任何分组函数(MIN/MAX/COUNT/etc..)一起使用

正确的查询应该是:

SELECT MAX(Date), Bond_Id FROM Quotes GROUP BY Bond_Id;

或者

SELECT Bond_Id, MAX(Sell_Price) FROM GROUP BY Bond_Id HAVING "Date" = MAX("Date");

第二

您需要为 MIN/MAX/... 和 GROUP BY 中使用的每个字段创建索引

于 2013-09-19T12:51:37.363 回答