使用2GB +

时间:2017-04-27 10:22:47

标签: mysql sql performance view aggregate

我在MYSQL数据库中的一个非常大的表中运行广告收入查询。它包含许多维度,例如设备类,日期,广告客户,纵向,creative_size,位置等,以及一些指标,如已投放的展示次数,点击次数和收入。

该表用于显示广告效果,因此通常按一维或二维分组并按维度过滤。

我已将所有内容放在一个表中以避免连接并使其尽可能快,但由于维度的数量,尤其是广告客户,表格很大,已经超过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功能?这是一种可行的方法吗?我当然愿意接受其他解决方案:)

1 个答案:

答案 0 :(得分:3)

MySQL的VIEW对象无法帮助查询性能,这是正确的。用行业的术语来说,它们不是“物化观点”。

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

您可以采用一些方法来提高查询效果。

  1. 如您所知,从详细信息表中生成一些聚合表。如果您能够使用稍微陈旧的数据,则可以在一夜之间重新生成它们。

  2. 如果您使用特定查询,请调查创建compound covering indexes to accelerate those queries

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

    Select DATE(date), creative_size, device_class,ssp,billing_type, location,
           SUM(ad_impressions), SUM(clicks), SUM(revenue)
      from ADS
     group by DATE(date),creative_size,device_class,ssp,billing_type,location
    

    其次,这个没有任何WHERE条款。如果添加WHERE子句,则(几乎可以肯定)需要不同的复合覆盖索引。您可以阅读有关如何在其他地方使用WHERE子句覆盖索引的信息。

    第三,此查询可以通过特定的复合索引加速:GROUP BYSELECT子句中提到的所有列的索引。 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上进行范围扫描,并且该列在索引中是第一个。

    以下是关于研磨超大表的一般观察结果供您考虑。

    • 像您这样的表上的大量单列索引通常会对性能产生影响。如果有的话,MySQL不会在单个查询中很好地利用单个表中的多个索引。
    • SELECT * 肯定会对性能有害,尤其是当您有很多列时。相反,枚举所需的列。
    • 除非您知道需要,否则请避免在大型查询中使用ORDER BY子句。
    • http://use-the-index-luke.com/是让这些东西运作良好的绝佳参考。