对新索引数据的MYSQL查询异常缓慢
我有以下疑问:对新索引数据的MYSQL查询异常缓慢,mysql,sql,performance,Mysql,Sql,Performance,我有以下疑问: SELECT DISTINCT CONCAT(COALESCE(location.google_id, ''), '-', COALESCE(locationData.resolution, ''), '-', COALESCE(locationData.time_slice, '')) AS google_id FROM
SELECT DISTINCT
CONCAT(COALESCE(location.google_id, ''),
'-',
COALESCE(locationData.resolution, ''),
'-',
COALESCE(locationData.time_slice, '')) AS google_id
FROM
LocationData AS locationData
JOIN
Location AS location ON location.id = locationData.location_id
WHERE
location.company_google_id = 5679037876797440
AND location.google_id IN (4679055472328704, 6414382784315392, 5747093579759616)
AND locationData.resolution = 8
AND locationData.time_slice >= ((SELECT max(s.time_slice) FROM LocationData as s WHERE s.location_id = location.id ORDER BY s.time_slice ASC) - 255)
AND location.active = TRUE
ORDER BY location.google_id ASC , locationData.time_slice ASC
LIMIT 0 , 101
我在WHERE和ORDER BY子句中的所有列上都有索引,并且为LocationData.time\u切片、LocationData.location\u id添加了一个复合索引
运行explain会给这里的格式设置带来一些挑战,所以希望它能很好地显示出来:
id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra
1 | PRIMARY | location | range | PRIMARY,google_id_UNIQUE | google_id_UNIQUE | 8 | NULL | 3 | Using index condition; Using where; Using temporary; Using filesort
1 | PRIMARY | locationData | ref | max_time_slice_idx,max_time_slice_idx_desc | max_time_slice_idx | 5 | index2.location.id | 301 | Using where
2 | DEPENDENT SUBQUERY | s | ref | max_time_slice_idx,max_time_slice_idx_desc | max_time_slice_idx | 5 | index2.location.id | 301 | Using index
我知道依赖子查询的速度很慢,我愿意接受获得类似行为的建议,但我看到这个查询运行大约需要92秒,这与我在将新的复合索引添加到生产中之前运行的测试数据相差大约4个数量级
运行ALTER语句后是否会生成索引?是否有方法检查索引是否正确执行
两个表的行计数:
制作:
地点:6814
位置数据:13070888
测试数据:
地点:626
位置数据:594780
如有任何想法或建议,我们将不胜感激。提前谢谢 只是一个建议
可以使用内部联接避免子选择
SELECT DISTINCT
CONCAT(COALESCE(location.google_id, ''),
'-',
COALESCE(locationData.resolution, ''),
'-',
COALESCE(locationData.time_slice, '')) AS google_id
FROM LocationData AS locationData
INNER JOIN Location AS location ON location.id = locationData.location_id
INNER JOIN (
SELECT s.location_id, max(s.time_slice) -255 my_max_time_slice
FROM LocationData as s
GROUP BY s.location_id
) t on t.location_id = Location.id
WHERE
location.company_google_id = 5679037876797440
AND location.google_id IN (4679055472328704, 6414382784315392, 5747093579759616)
AND locationData.resolution = 8
AND locationData.time_slice >= t.my_max_time_slice
AND location.active = TRUE
ORDER BY location.google_id ASC , locationData.time_slice ASC
LIMIT 0 , 101
通过这种方式,您应该避免对每个id重复子查询,只使用一个查询为max_time_切片生成聚合结果
希望这是有用的添加到@scaisEdge的推荐中
WHERE l.company_google_id = 5679037876797440
AND l.google_id IN (4679055472328704, 6414382784315392, 5747093579759616)
AND ld.resolution = 8
AND ld.time_slice >= t.my_max_time_slice
AND l.active = TRUE
ORDER BY l.google_id ASC , ld.time_slice ASC
假设需要首先运行子查询,则最佳索引为。MySQL的旧版本就是这样
LocationData: (location_id, time_slice) -- in this order, for the subquery
locationData: (time_slice, resolution, location_id) -- for JOIN
如果id是location的主键,则不需要额外的索引
对于较新的版本,子查询可以具体化,并且可以构建合适的索引。在这种情况下,可能从位置开始:
没有办法通过优化ORDER,因为它会命中两个表,也没有办法避免排序
建议您添加所有这些索引,然后获取解释选择。。。如果你需要进一步讨论的话。显示创建表也很方便。假设innodb,您的innodb缓冲区池大小是多少,如果MyISAM,则关键缓冲区大小是多少?我的直觉告诉我你的尺寸太小了,而且100%的索引不适合缓冲区。@dossy我的设置是innodb_buffer_pool_size 10049552384好的,所以大约是10GB。索引有多大?从信息模式中选择表名称,roundsumindex长度/1024/1024,2。其中表名称在“LOCATION”、“LOCATIONDATA”组中按1@dossy你的脚本导致了1137.13。我想那是MB?是的,那是MB,所以你的索引是1.1GB,所以应该适合10GB。你的桌子行真的很长吗?每个表中有多少列?
location: (company_google_id, active, -- in either order
google_id) -- last
locationData: (location_id, time_slice) -- in this order (for subquery)
locationData: (location_id, resolution -- in either order (for JOIN)
time_slice) -- last