我们有一个大型的统计表,每天记录每件产品的点击量。
date | datetime
productid | int
hits | int
channel | enum约200米rows+
我们有两种查询此日期的方法--它总是在WHERE (或多个productid )中有productid,然后也可以选择指定日期。大多数查询都有。
我们允许用户查询通常的日期‘桶’,如今天/昨天/最后7天/上个月/最后3个月/今年/去年。他们也可以选择任意的日期。
因此,我在日期分区与productid之间进行切换。我的想法是,如果我们同时查询多个产品if (使用IN()),那么这可能意味着跨越多个分区。但是,由于大多数查询将在一年内进行,按日期进行分区将是最好的吗?
由于大多数查询的时间都很短(如天/周),也许我们有如下内容:
最后三个月,最后3-6个月,6-12个月,然后每年的桶。
我们的数据可以追溯到2005年。
谢谢你的建议。
发布于 2020-11-29 18:56:08
首先要确保数据类型尽可能小。会有10亿个产品吗?INT是4个字节。MEDIUMINT UNSIGNED是3个字节,允许值在0到1600万之间。等。
你有这些的组合吗?
AND productid = 123 (or, equivalently, productid IN (123)) -- (1)
AND productid IN (234,345,456) -- (2)
AND date >= '2020...'
AND date < '2020...' + INTERVAL 7 DAY -- (3)您的“上个月”速记可以很容易地转换成一个日期范围与开始日期和那个+ INTERVAL 1 MONTH。
For和子句(1)或(1和3)或(2):即使没有分区,PRIMARY KEY(productid, date)也是最优的。如果那对是唯一的,那就去做。(听起来是这样。)
( 3 )和(2和3)比较棘手。
(3)需要INDEX(date)
你需要删除“旧”的统计数据吗?如果是这样,那么强烈建议使用PARTITION BY RANGE(date)。它允许您DROP PARTITION (非常快)而不是DELETE。请参阅http://mysql.rjweb.org/doc.php/partitionmaint
通过分区,您可以获得(2和3)的一些二维帮助。或者优化器可能足够聪明,可以在表中跳过我推荐的PK。
我会在2020年之前每年建一次桶,然后从2020年1月开始每月一次。将来我也不会把每月合并成每年一次,因为这样做“太多了”。分区:
1 pre-2005 (empty) (see link for reason)
15 2005..2019 (Thanks for providing the '2005')
11(so far) 2020, jan..nov
1 "future" (see link)
(28 currently, but growing)并在需要之前,每晚尝试创建一个新的“月”分区。(不要预先构建许多分区。)
(注意: years+months分区是一个一次性任务。所有未来的分区都是“月份”,我避免将几个月合并成几年。在计算机或项目的生命周期内,您将不会对分区设置任何限制。)
他们从来不测试channel吗?他们从来不做SUM(hits) .. GROUP BY吗?这将导致更多的讨论。
“参考地点”..。
数据可能占用10 The?你有多少内存?innodb_buffer_pool_size的设置是什么?用户通常读“最近的”数据吗?答案交互预测需要多少I/O,因此查询运行得有多快。
上面我推荐的索引和分区的目标是
如果所有查询都用于“最近”data.
您可能已经注意到,我主要集中在productid上。影响如下:
partitioning.
。
11个月的数据可能还不到1GB?同样,对于所有“最近”的查询,这很可能会留在buffer_pool中。(参考地点;“分区剪枝”)。
https://stackoverflow.com/questions/65038912
复制相似问题