【问题标题】:SQL Replace Join With Something Faster [closed]SQL用更快的东西替换连接[关闭]
【发布时间】:2019-05-14 08:54:43
【问题描述】:

我在 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 秒多一点。感谢那些帮助过的人!

【问题讨论】:

  • 一种肯定会加快速度的方法是不使用视图,它对 MySQL 中底层索引的访问非常有限,因此几乎没有用。
  • 我很想从中创建一个查询而不是使用视图,但我不太擅长 SQL,这帮助我使逻辑比一个非常大的单个查询简单得多,这当然会是更好的解决方案。我还听说过使用索引以及如何使查询更快,但我又不是很擅长 SQL,也不知道如何使用它们。

标签: mysql sql join subquery mysql-workbench


【解决方案1】:

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

与最后的 order by 一样,您计算 Price 和 BTC,但不要在 priceTarget 视图中使用它们(您使用 PriceView1 中已经可用的值)。我认为您将其留在那里是为了拥有唯一的日期/符号,您可以使用选择 DISTINCT 来实现相同的结果。

我不知道这是否是故意的,但 BTC 和价格是根据价格视图 1 中的平均值计算得出的,它们不在价格视图 2 中。

这是我对 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'

我对视图的理解是,它们可以与其他语言中的宏相媲美:更像是代码替换而不是预计算。

因此,当您在 priceTarget avg(pv1.Price) 中执行时,考虑到 pv1.Price 被定义为 avg(Price),您是在平均一个平均值。

除了我上面建议的更改之外,我还更改了 PriceView2 以计算新价格和 BTC 平均值,因此 priceTarget 视图不必

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

【讨论】:

  • 感谢您的回复!将第二个视图更改为此将查询时间从 17.25 秒缩短到 12.95 秒。当我写这个问题时,我在想问题是加入,我想改变它,但似乎这不是问题。我认为用子查询或变量替换某些逻辑会更快,但听起来不值得这样做
  • @Ricky 祝你好运,只剩下 12.9 秒了!只是给你一些指示(我只在 Sybase 上工作过)查询优化需要一个真实的数据集,这样你就可以测试、分析查询计划并检查在 MySQL 中似乎称为 EXPLAIN 的 IO。如果您可以创建额外的表格,则每天早上您都可以填写 PriceTarget 表格(这不是一个完美的解决方案,因为您可能需要在当天刷新它)..
  • 感谢指点!我想我可以创建一个已过滤数据的新表,而不是让两个视图都使用整个数据集,然后对其进行过滤。 12.95 查询现在需要 3.25,这似乎更合理(尽管 0.05 查询会很恶心)。我喜欢创建额外表的想法,但是每小时都会有新数据出现,我认为这可能会变得复杂。感谢你的建议!在 MySQL 中使用“配置文件”似乎效果很好,但我会进一步解释,谢谢!
【解决方案2】:

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

【讨论】:

  • 虽然我认为这些都是非常有效的观点,但我不相信这是一个答案,也许应该作为评论留下
猜你喜欢
  • 1970-01-01
  • 2021-06-23
  • 1970-01-01
  • 1970-01-01
  • 2017-01-29
  • 1970-01-01
  • 2013-04-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多