我在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功能?这是一种可行的方法吗?我当然愿意接受其他解决方案:)
答案 0 :(得分:3)
MySQL的VIEW对象无法帮助查询性能,这是正确的。用行业的术语来说,它们不是“物化观点”。
您尚未向我们透露您使用的实际查询或大表的实际布局。所以具体的建议是不可能的。
您可以采用一些方法来提高查询效果。
如您所知,从详细信息表中生成一些聚合表。如果您能够使用稍微陈旧的数据,则可以在一夜之间重新生成它们。
如果您使用特定查询,请调查创建compound covering indexes to accelerate those queries。
查看问题中的查询。首先,我想它应该有一些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 BY
和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
上进行范围扫描,并且该列在索引中是第一个。
以下是关于研磨超大表的一般观察结果供您考虑。
SELECT *
肯定会对性能有害,尤其是当您有很多列时。相反,枚举所需的列。ORDER BY
子句。