Mysql 使用2GB+;加速单个表上的SQL查询;

Mysql 使用2GB+;加速单个表上的SQL查询;,mysql,sql,performance,view,aggregate,Mysql,Sql,Performance,View,Aggregate,我正在MYSQL数据库中的一个非常大的表中查询广告收入。它包含许多维度,如设备类别、日期、广告客户、垂直、创意大小、位置等,以及一些指标,如交付印象、点击和收入 该表用于显示广告表现,因此通常按一个或两个维度分组,并按维度过滤 我将所有内容都放在一个表中,以避免连接并尽可能快地完成,但由于维度的数量,特别是广告客户,表很大,已经超过2.8Gb,并且还在增长 我尝试过索引和分区,但速度仍然很慢,所以我考虑创建一个更小的版本,将数据按更小的维度集分组,省去广告客户列,即 Select date, c

我正在MYSQL数据库中的一个非常大的表中查询广告收入。它包含许多维度,如设备类别、日期、广告客户、垂直、创意大小、位置等,以及一些指标,如交付印象、点击和收入

该表用于显示广告表现,因此通常按一个或两个维度分组,并按维度过滤

我将所有内容都放在一个表中,以避免连接并尽可能快地完成,但由于维度的数量,特别是广告客户,表很大,已经超过2.8Gb,并且还在增长

我尝试过索引和分区,但速度仍然很慢,所以我考虑创建一个更小的版本,将数据按更小的维度集分组,省去广告客户列,即

Select date, creative_size, device_class,ssp,billing_type, location,
       ad_impressions, clicks, revenue
  from ADS
 group by date,creative_size,device_class,ssp,billing_type,location
这将大大减少行数


我试图将其用作视图,但它不是永久存储的,因此需要更长的时间。如何创建这样一个表并根据另一个表使其保持最新?我需要写一个脚本还是可以使用一些内置的MySQL功能?这是可行的办法吗?当然,我对其他解决方案持开放态度:)

您是对的,MySQL的视图对象对查询性能没有帮助。用行业术语来说,它们不是“物化视图”

您还没有向我们透露您使用的实际查询或大表的实际布局。所以具体的建议是不可能的

您可以使用一些可能的方法来提高查询性能

  • 正如您所建议的,从明细表生成一些聚合表。如果您能够处理稍微陈旧的数据,您可以在一夜之间重新生成它们

  • 如果使用特定查询,请调查创建

  • 看看你问题中的问题。首先,我想它应该有一些总和项,就像这样。我还将您提到的
    date
    更改为
    date(date)
    ,以便在摘要中仅获取日期,而不是日期和时间。(也许这已经在你的桌子上完成了。如果是这样,不要再做了。)

    第二,这个没有任何
    WHERE
    子句。如果您添加了
    WHERE
    子句,您(几乎可以肯定)需要不同的复合覆盖索引。您可以在其他地方阅读如何使用包含
    WHERE
    子句的覆盖索引

    第三,这个查询可以通过一个特定的复合索引来加速:在
    groupby
    SELECT
    子句中提到的所有列上的索引。
    GROUP BY
    子句中的列在索引中应排在第一位,顺序通常与
    GROUP BY
    中的顺序相同。您可以创建这样一个索引

     CREATE INDEX summary_1 ON ADS 
                  (date, creative_size, device_class,ssp,billing_type, location,
                   ad_impressions, clicks, revenue);
    
    这很有帮助,因为MySQL的查询计划器可以按顺序读取索引以满足您的查询,而不必遵循指向表的指针

    第四,你能做到

    CREATE TABLE ad_summary AS
    Select date, creative_size, device_class,ssp,billing_type, location,
           SUM(ad_impressions), SUM(clicks), SUM(revenue)
      from ADS
     group by date,creative_size,device_class,ssp,billing_type,location;
    
    这是一个穷人的物化观点。(如果您使用Oracle,您可以使用他们的物化视图,我们称之为以前的富人物化视图。--以前是因为Oracle非常昂贵。)

    第五,您可以限制汇总表的日期(如果在应用程序中有效的话)。通过向查询中添加类似的内容来实现这一点

      WHERE date >= CURDATE() - INTERVAL 7 DAY
    
    这个特殊的
    WHERE
    子句可以使用相同的复合覆盖索引,因为它在
    date
    上进行范围扫描,并且该列位于索引的第一位

    这里有一些关于研磨非常大的表的一般性观察,供您考虑。< /P>
    • 像您这样的表上的许多单列索引通常对性能有害。MySQL不能很好地利用单个查询中单个表中的多个索引
    • SELECT*
      对性能肯定有害,尤其是当您有很多列时。相反,请枚举所需的列
    • 避免在大型查询中使用
      orderby
      子句,除非您知道需要它们
    • 这是一个很好的参考,使这个东西的工作

    如果您阅读本文,尤其是关于查询性能的部分,将有助于获得更好的答案。这个问题对于堆栈溢出格式来说过于宽泛。Ollie的很好,但是如果您需要更多帮助,我们确实需要
    SHOW CREATE TABLE
    和实际查询。还要检查innodb\u buffer\u pool\u size对于如此小的RAM来说大约是600米。在汇总表上。
      WHERE date >= CURDATE() - INTERVAL 7 DAY