我有一个非常小的,简单的MYSQL表来保存预先计算的财务数据。该表看起来像: refDate | instrtument | rate | startDate | maturityDate | carry1 | carry2 | carry3
将3个索引定义为:
唯一unique_ID(refDate,instrument)
refDate(refDate)
仪器(仪器)
现在行大约有1000万行,但对于每个refDate,现在只有大约5000种不同的工具
我有一个自我加入此表的查询,以生成如下输出: refDate | rate instrument = X |率工具= Y | rate instrument = Z | ....
基本上返回时间序列数据,然后我可以自己进行分析。
问题出在这里:我的原始查询如下:
Select distinct AUDSpot1yFq.refDate,AUDSpot1yFq.rate as 'AUDSpot1yFq',
AUD1y1yFq.rate as AUD1y1yFq
from audratedb AUDSpot1yFq inner join audratedb AUD1y1yFq on
AUDSpot1yFq.refDate=AUD1y1yFq.refDate
where AUDSpot1yFq.instrument = 'AUDSpot1yFq' and
AUD1y1yFq.instrument = 'AUD1y1yFq'
order by AUDSpot1yFq.refDate
请注意,在下面这个特定的时间查询中,我实际上得到了10种不同的工具,这意味着查询的时间要长得多,但遵循相同的命名,内连接和where语句模式。
这很慢,在工作台上我将它计时为7-8秒(但是接近0个获取时间,因为我在运行服务器的机器上有工作台)。当我剥离了明显的,持续时间下降到0.25-0.5秒(更易于管理),当我剥离&#34;顺序时,#34;它变得更快(<0.1秒,此时我不在乎)。但是我的Fetchtime爆炸了大约7秒钟。所以总的来说,我什么也得不到,但它已成为一个获取时间问题。当我从将要进行提升和工作的python脚本运行此查询时,无论是否包含distinct,我都会得到大致相同的时间。
当我在我的减少查询(具有可怕的获取时间)上运行解释时,我得到:
1 SIMPLE AUDSpot1yFq ref unique_ID,refDate,instrument instrument 39 const 1432 100.00 Using where
1 SIMPLE AUD1y1yFq ref unique_ID,refDate,instrument unique_ID 42 historicalratesdb.AUDSpot1yFq.refDate,const 1 100.00 Using where
1 SIMPLE AUD2y1yFq ref unique_ID,refDate,instrument unique_ID 42 historicalratesdb.AUDSpot1yFq.refDate,const 1 100.00 Using where
1 SIMPLE AUD3y1yFq ref unique_ID,refDate,instrument unique_ID 42 historicalratesdb.AUDSpot1yFq.refDate,const 1 100.00 Using where
1 SIMPLE AUD4y1yFq ref unique_ID,refDate,instrument unique_ID 42 historicalratesdb.AUDSpot1yFq.refDate,const 1 100.00 Using where
1 SIMPLE AUD5y1yFq ref unique_ID,refDate,instrument unique_ID 42 historicalratesdb.AUDSpot1yFq.refDate,const 1 100.00 Using where
1 SIMPLE AUD6y1yFq ref unique_ID,refDate,instrument unique_ID 42 historicalratesdb.AUDSpot1yFq.refDate,const 1 100.00 Using where
1 SIMPLE AUD7y1yFq ref unique_ID,refDate,instrument unique_ID 42 historicalratesdb.AUDSpot1yFq.refDate,const 1 100.00 Using where
1 SIMPLE AUD8y1yFq ref unique_ID,refDate,instrument unique_ID 42 historicalratesdb.AUDSpot1yFq.refDate,const 1 100.00 Using where
1 SIMPLE AUD9y1yFq ref unique_ID,refDate,instrument unique_ID 42 historicalratesdb.AUDSpot1yFq.refDate,const 1 100.00 Using where
我现在意识到distinct不是必需的,当我将输出输出到数据帧时,order by是我可以丢弃并在pandas中排序的东西。那样太好了。但我不知道如何让Fetch时间缩短。我不打算在这个网站上赢得任何能力竞赛,但我已经尽可能多地搜索,无法找到解决这个问题的方法。非常感谢任何帮助。
〜可可
答案 0 :(得分:0)
问题没有提及现有索引,或者显示EXPLAIN
对任何查询的输出。
提高性能的快速答案是添加索引:
... ON audratedb (instrument,refdate,rate)
为了回答我们为什么要添加该索引,我们需要了解MySQL如何处理SQL语句,可能的操作以及需要哪些操作。要查看MySQL实际处理语句的方式,您需要使用EXPLAIN
查看查询计划。
答案 1 :(得分:0)
(我必须简化表别名以便阅读它:)
Select distinct
s.refDate,
s.rate as AUDSpot1yFq,
y.rate as AUD1y1yFq
from audratedb AS s
join audratedb AS y on s.refDate = y.refDate
where s.instrument = 'AUDSpot1yFq'
and y.instrument = 'AUD1y1yFq'
order by s.refDate
需要索引:
INDEX(instrument, refDate) -- To filter and sort, or
INDEX(instrument, refDate, rate) -- to also "cover" the query.
假定查询并不比你说的复杂。我看到EXPLAIN
已经有更多的表了。请提供SHOW CREATE TABLE audratedb
和整个SELECT
。
回到你的问题......
DISTINCT
有以下两种方式之一:(1)对表进行排序,然后进行重复数据删除,或(2)在内存中的哈希中进行重复数据删除。请记住,您正在扣除所有3列(refDate,s.rate,y.rate)。
ORDER BY
是一种排序。但是,使用建议的索引(不是您拥有的索引),不需要排序,因为索引将按所需顺序获取行。
但是...... DISTINCT
和ORDER BY
的可能会使优化程序混淆到它做某事的地步......
您说(refDate,instrument)
是UNIQUE
,但您没有提到PRIMARY KEY
,也没有提到您正在使用的引擎。如果您使用InnoDB,那么PRIMARY KEY(instrument, refDate)
,按此顺序,将进一步加快速度,并避免需要任何新索引。
此外,拥有(a,b)
和(a)
也是多余的。也就是说,您当前的架构不需要INDEX(refDate)
,但通过更改PK,您将不需要INDEX(instrument)
。
底线:仅
PRIMARY KEY(instrument, refDate),
INDEX(refDate)
并且没有其他索引(除非您可以显示一些需要它的查询)。
有关EXPLAIN
的更多信息。注意Rows
列如何表示1432,1,1,......这意味着它扫描了第一个表的估计1432行。由于缺乏适当的指数,这可能远远超过必要。然后它需要在每个其他表中只查看一行。 (不能比那更好。)
SELECT
中没有 DISTINCT
或ORDER BY
的行数是多少?这告诉你在提取和JOINing
之后需要做多少工作。我怀疑它只是少数几个。 A&#34;少数&#34; DISTINCT
和ORDER BY
非常便宜;因此我觉得你正在吠叫错误的树。甚至1432行的处理速度也非常快。
至于buffer_pool ...桌子有多大?做SHOW TABLE STATUS
。我怀疑该表超过1GB,因此它无法容纳在buffer_pool中。因此,提高缓存大小将使查询在RAM中运行,而不是访问磁盘(至少在缓存之后)。请记住,在冷缓存上运行查询会有很多I / O.随着缓存预热,查询将运行得更快。但如果缓存太小,您将继续需要I / O. I / O是处理过程中最慢的部分。
我希望你有至少6GB的内存;否则,2G可能会非常危险。交换对性能来说真的很糟糕。