Mysql ove还不错。)问题是“很多”分区会带来不同的低效率;“太少”分区会导致“何必麻烦”
请注意,几乎总是分区表的最佳PK不同于等效的非分区表 请注意,我不同意在Mysql ove还不错。)问题是“很多”分区会带来不同的低效率;“太少”分区会导致“何必麻烦”,mysql,performance,query-optimization,Mysql,Performance,Query Optimization,请注意,几乎总是分区表的最佳PK不同于等效的非分区表 请注意,我不同意在vention\u id上进行分区,因为很容易将该列放在PK的开头 分析 假设您搜索一个场馆id并使用我建议的分区和主键,下面是选择的执行方式: 根据日期范围进行筛选。这可能会将活动限制为单个分区 钻取该分区的数据树,以查找该分区的场馆id 从那里跳转数据,降落在所需的区域ID 对于每个,根据日期进一步筛选 我相信MySQL通常一次只能利用一个索引,所以将字段单独索引可能不是最好的选择;我建议尝试在(场馆id,日纪元)或(场
vention\u id
上进行分区,因为很容易将该列放在PK的开头
分析
假设您搜索一个场馆id
并使用我建议的分区和主键,下面是选择
的执行方式:
场馆id
区域ID
我相信MySQL通常一次只能利用一个索引,所以将字段单独索引可能不是最好的选择;我建议尝试在
(场馆id,日纪元)
或(场馆id,分区id,日纪元)
上创建一个综合索引。。。此外,在问题中包含表的创建也不会有任何影响。groupby
通常用于聚合,你想在未分组的字段中选择一个半随机值吗?@uuerdo上面的查询不是整个查询我有一个外部选择,它需要groupby
,但我没有费心显示,因为这不是问题所在,内部查询(显示)正在减慢速度。我将尝试创建该复合索引。如果GROUPBY用于外部查询,则不需要将其包含在您发布的内容中;原始查询应该有一个)
将您发布的内容与分组依据之前的外部部分分隔开来。@uuerdo包含分组依据的原因是,这可能会减慢查询速度。我知道你不知道它为什么会在那里,我现在已经解释过了。我认为问题是由于我所做的编辑。我目前正在添加索引,但我有太多的数据,需要一段时间:)我尝试使用此索引,等待了大约5分钟,但出现了500个错误。是的。。。检查服务器是否仍在执行该查询。既然你说你的表已经分区了,你可以简化这个新索引,只需要有两列addindex complex\u idx('day\u epoch','zone\u id')
。但在这种情况下,我认为您不应该强制使用此索引,而是应该允许服务器优化器分析查询。我刚刚检查了,失败的查询不再运行。那么现在最好不要强制指数?您认为这可能是SQL配置吗?我们使用的AWS RDS服务器具有30GB RAM和8个vCPU,我怀疑服务器规格是否存在问题。是的,我同意服务器硬件看起来不错。只需再尝试一次创建索引,但更简单的索引没有vention\u id
,因为它已经分区了。关于分区的另一个问题。您是否有办法从场馆id
检测分区id?如果是,我们可以将分区强制添加到查询中,这是有意义的。我尝试了一下,但不幸的是,它没有提高查询速度。我只是觉得奇怪,通过在日期范围内增加一天,它会从0.7秒变为13秒。你会在两个日期之间相遇吗?不,有道理。意味着日期筛选器将大量“返回”到下一个条件。这可能是您的服务器/资源的提示点:)是的,例如,当我在第5次和第9次之间查询时,需要0.7秒,但当我在第5次和第10次之间查询时,需要13秒。因此,仅仅一点点额外的数据就会产生巨大的影响。这可能与MySQL配置有关吗?正如旁注一样,每天返回大约20k条记录,因此,如果再添加一天,就不会有超过100k条记录,因此我认为查询速度不会受到太大影响。@Martijn-优化器可以并且将重新排列WHERE
子句项。手动重新排列它们没有好处。另一方面,复合索引中列的顺序可能非常重要。@Lukerayner-很可能优化器选择了不同的索引来使用,但它弊大于利。为这两种情况提供EXPLAIN选择…
(如果可能)。
SELECT device_uuid,
day_epoch,
is_repeat
FROM tracking_daily_stats_zone_unique_device_uuids_per_hour
WHERE day_epoch >= 1552435200
AND day_epoch < 1553040000
AND venue_id = 46
AND zone_id IN (102,105,108,110,111,113,116,117,118,121,287)
CREATE TABLE `tracking_daily_stats_zone_unique_device_uuids_per_hour` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`day_epoch` int(10) NOT NULL,
`day_of_week` tinyint(1) NOT NULL COMMENT 'day of week, monday = 1',
`hour` int(2) NOT NULL,
`venue_id` int(5) NOT NULL,
`zone_id` int(5) NOT NULL,
`device_uuid` binary(16) NOT NULL COMMENT 'binary representation of the device_uuid, unique for a single day',
`device_vendor_id` int(5) unsigned NOT NULL DEFAULT '0' COMMENT 'id of the device vendor',
`first_seen` int(10) unsigned NOT NULL DEFAULT '0',
`last_seen` int(10) unsigned NOT NULL DEFAULT '0',
`is_repeat` tinyint(1) NOT NULL COMMENT 'is the device a repeat for this day?',
`prev_last_seen` int(10) NOT NULL DEFAULT '0' COMMENT 'previous last seen ts',
PRIMARY KEY (`id`,`venue_id`) USING BTREE,
KEY `venue_id` (`venue_id`),
KEY `zone_id` (`zone_id`),
KEY `day_of_week` (`day_of_week`),
KEY `day_epoch` (`day_epoch`),
KEY `hour` (`hour`),
KEY `device_uuid` (`device_uuid`),
KEY `is_repeat` (`is_repeat`),
KEY `device_vendor_id` (`device_vendor_id`)
) ENGINE=InnoDB AUTO_INCREMENT=450967720 DEFAULT CHARSET=utf8
/*!50100 PARTITION BY HASH (venue_id)
PARTITIONS 100 */
ALTER TABLE tracking_daily_stats_zone_unique_device_uuids_per_hour
ADD INDEX complex_idx (`venue_id`, `day_epoch`, `zone_id`)
SELECT device_uuid,
day_epoch,
is_repeat
FROM tracking_daily_stats_zone_unique_device_uuids_per_hour
USE INDEX (complex_idx)
WHERE day_epoch >= 1552435200
AND day_epoch < 1553040000
AND venue_id = 46
AND zone_id IN (102,105,108,110,111,113,116,117,118,121,287)
SELECT device_uuid,
day_epoch,
is_repeat
FROM tracking_daily_stats_zone_unique_device_uuids_per_hour
PARTITION (`p46`)
WHERE day_epoch >= 1552435200
AND day_epoch < 1553040000
AND zone_id IN (102,105,108,110,111,113,116,117,118,121,287)
INDEX(venue_id, zone_id, day_epoch)
PRIMARY KEY(venue_id, zone_id, day_epoch, -- this order, as discussed above;
id) -- to make sure that the entire PK is unique.
INDEX(id) -- to keep AUTO_INCREMENT happy
PARTITION BY RANGE(day_epoch) -- see note below
PRIMARY KEY(venue_id, zone_id, id)