我在SQLite中使用下面的SQL代码来获取包含交易的表中的交易列表,然后将其与当天的总投资组合值相结合,从具有一组工具的头寸和价格数据的持股表中
馆藏表有大约150000条记录,交易表大约有1700条
SELECT t.*, (SELECT p.adjclose FROM prices AS p
WHERE t.instrument = p.instrument
AND p.date = "2013-02-28 00:00:00") as close,
su.mv as mv
FROM trades AS t
left outer join
(SELECT h.date, SUM(h.price * h.position) as mv FROM holdings AS h
WHERE h.portfolio = "usequity"
AND h.date >= "2013-01-11 00:00:00"
AND h.date <= "2013-02-2"
GROUP BY h.date) as su
ON t.date = su.date
WHERE t.portname = "usequity"
AND t.date >= "2013-01-11 00:00:00"
AND t.date <= "2013-02-28 00:00:00";
运行SQL代码返回
[2014-12-01 19:21:00] 123 row(s) retrieved starting from 1 in 572/627 ms
对于小型数据集来说,这看起来真的很慢。两个表都按仪器和日期编制索引。
我不知道如何动态索引表su
,所以我不知道如何改进这段代码。非常感谢任何帮助。
解释查询计划显示
selectid,order,from,detail
1,0,0,"SEARCH TABLE holdings AS h USING AUTOMATIC COVERING INDEX (portfolio=?) (~7 rows)"
1,0,0,"USE TEMP B-TREE FOR GROUP BY"
0,0,0,"SCAN TABLE trades AS t (~11111 rows)"
0,1,1,"SEARCH SUBQUERY 1 AS su USING AUTOMATIC COVERING INDEX (date=?) (~3 rows)"
0,0,0,"EXECUTE CORRELATED SCALAR SUBQUERY 2"
2,0,0,"SEARCH TABLE prices AS p USING INDEX p1 (instrument=? AND date=?) (~9 rows)"
答案 0 :(得分:1)
prices
上的查询速度很快(它使用两列的索引)。
您可以为su
子查询创建临时表并为其添加索引,但AUTOMATIC INDEX
表示数据库已在执行此操作。
holdings
上的查找是使用临时索引完成的;你应该为它创建一个显式索引。 (portfolio
和date
上的索引会更有效率。)
您可以通过动态查找holdings
的值来避免需要临时表,就像您已经在收盘价一样(但如果有很多交易,这可能不会有所改善)同一天):
SELECT t.*,
(SELECT p.adjclose
FROM prices AS p
WHERE p.instrument = t.instrument
AND p.date = '2013-02-28 00:00:00'
) AS close,
(SELECT SUM(h.price * h.position)
FROM holdings AS h
WHERE h.portfolio = 'usequity'
AND h.date = t.date
) AS mv
FROM trades AS t
WHERE t.portname = 'usequity'
AND t.date BETWEEN '2013-01-11 00:00:00'
AND '2013-02-28 00:00:00';