SQL用更快的速度替换联接

时间:2018-12-13 07:17:27

标签: mysql sql join subquery mysql-workbench

我在SQL中有一个使用联接的视图,并且花费的时间比我想要的长得多。我认为如果将其转换为子查询,它将运行得更快,但是我遇到了麻烦。

基本上,我想创建一个“目标”列,以计算资产价格24%的变化。现在,我要解决的方法是创建一个第一个视图,该视图是普通表,然后创建一个第二个视图,该视图是第一个表的副本,但具有date + 1,然后我可以用它来计算24小时目标。下面是我的SQL代码。我正在使用MySQL。

create view PricesView1 as
select Date,Symbol, avg(Price) as 'Price', avg(BTC_Dominance) as 'BTC_Dominance', 
    pkdummy,pkey from Prices group by Date,pkdummy,pkey, Symbol 
    having right(pkdummy,2)=22 and Date > '2018-11-22';

create view PricesView2 as
select sq.Date, sq.oldDate, sq.Symbol, sq.Price, newP.Price as 'NewPrice',
    newP.BTC_Dominance as 'NewBTCdominance', newP.pkdummy from (
    select date_add(Date, INTERVAL 1 DAY) as 'Date', Date as 'oldDate',Symbol,avg(Price) as 'Price', 
        avg(BTC_Dominance) as 'BTC_Dominance',  pkdummy,pkey from Prices 
        group by Date,date_add(Date, INTERVAL 1 DAY),pkdummy,pkey, Symbol having right(pkdummy,2)=22)sq
    join Prices newP on newP.Date=sq.Date and newP.Symbol=sq.Symbol 
    where right(newP.pkdummy,2)=22 and sq.Date > '2018-11-22' order by datetime desc;

#Use other two views to calculate target
create view priceTarget as
select pv1.Date, pv1.Symbol, avg(pv1.Price) as 'Initial Price', avg(pv2.NewPrice) as 'Price24hLater',
    avg(((pv2.NewPrice-pv1.Price)/pv1.Price)*100) as 'Target24hChange',
    avg(((pv2.NewBTCdominance-pv1.BTC_Dominance)/pv1.BTC_Dominance)*100) as 'BTCdominance24hChange',
    pv1.pkey from PricesView1 pv1 
    join PricesView2 pv2 on pv1.Date=pv2.oldDate and pv1.Symbol=pv2.Symbol
    group by pv1.Date, pv1.Symbol;

Here is a screenshot of the output of the query:
SELECT * FROM priceTarget WHERE symbol = 'btc' ORDER BY date desc;

是否有关于如何通过避免使用联接的更快查询来实现相同结果的想法?

任何帮助将不胜感激!


编辑:我想这只能归结为我只是加载了很多数据的事实。我创建了一个新的第一个视图来提前过滤我的数据,并将加载时间从大约32秒减少到刚刚超过10秒。感谢那些帮助过的人!

2 个答案:

答案 0 :(得分:1)

在创建PriceView2时,似乎有一些不必要的代码

类似于最后的订单,您可以计算价格和BTC,但不要在priceTarget视图中使用它们(您可以使用PriceView1中已经可用的值)。我想您将它留在那里有唯一的日期/符号,可以使用select DISTINCT来达到相同的结果。

我不知道这是否是故意的,但BTC和价格是根据PriceView1中的平均值计算出来的,而不是由PriceView2中的平均值计算得出的。

这是我对PriceView2的建议:

create view PricesView2 as
select
    sq.Date,
    newP.Date,
    sq.Symbol,
    newP.Price as 'NewPrice',
    newP.BTC_Dominance as 'NewBTCdominance',
    newP.pkdummy
from (
        select distinct
            Date as 'oldDate',
            Symbol,
            pkdummy,
            pkey
        from Prices 
        having right(pkdummy,2)=22) sq
    join Prices newP on
        newP.Date=date_add(sq.oldDate, INTERVAL 1 DAY)
        and newP.Symbol=sq.Symbol 
where right(newP.pkdummy,2)=22
and   sq.Date > '2018-11-22'

我对视图的理解是,它们与其他语言中的宏具有可比性:更像是代码替换,而不是预先计算。

因此,当您考虑到pv1.Price被定义为avg(Price)时,在priceTarget avg(pv1.Price)中进行平均时,就会得出平均值。

除了我上面建议的更改之外,我还将更改pricesview2以计算新的价格和BTC平均值,从而不必使用priceTarget视图

最后在priceTarget视图中,除了pv1.Date和pv1.symbol外,您还应该按pv1.pkey分组。

答案 1 :(得分:0)

首先,我将对查询本身进行一些分析,以找出导致瓶颈的原因,即如何调用表,每个表返回多少行,正在使用哪些索引等。 FROM子句中的表可以帮助提高性能。您的查询可能缺少一两个可以大大提高性能的索引。