Ran*_*dle 40 mysql performance query-performance
我们有一个社交网站,会员可以在其中相互评价兼容性或匹配度。该user_match_ratings表包含超过 2.2 亿行(9 演出数据或近 20 演出索引)。针对此表的查询通常显示在 slow.log(阈值 > 2 秒)中,并且是系统中记录最频繁的慢查询:
Query_time: 3 Lock_time: 0 Rows_sent: 3 Rows_examined: 1051
"select rating, count(*) as tally from user_match_ratings where rated_user_id = 395357 group by rating;"
Query_time: 4 Lock_time: 0 Rows_sent: 3 Rows_examined: 1294
"select rating, count(*) as tally from user_match_ratings where rated_user_id = 4182969 group by rating;"
Query_time: 3 Lock_time: 0 Rows_sent: 3 Rows_examined: 446
"select rating, count(*) as tally from user_match_ratings where rated_user_id = 630148 group by rating;"
Query_time: 5 Lock_time: 0 Rows_sent: 3 Rows_examined: 3788
"select rating, count(*) as tally from user_match_ratings where rated_user_id = 1835698 group by rating;"
Query_time: 17 Lock_time: 0 Rows_sent: 3 Rows_examined: 4311
"select rating, count(*) as tally from user_match_ratings where rated_user_id = 1269322 group by rating;"
Run Code Online (Sandbox Code Playgroud)
SHOW COLUMNS FROM user_match_ratings;
Run Code Online (Sandbox Code Playgroud)
给出:
???????????????????????????????????????????????????????????????????
? id ? int(11) ? NO ? PRI ? NULL ? auto_increment ?
? rater_user_id ? int(11) ? NO ? MUL ? NULL ? ?
? rated_user_id ? int(11) ? NO ? MUL ? NULL ? ?
? rating ? varchar(1) ? NO ? ? NULL ? ?
? created_at ? datetime ? NO ? ? NULL ? ?
???????????????????????????????????????????????????????????????????
Run Code Online (Sandbox Code Playgroud)
select * from mutual_match_ratings where id=221673540;
Run Code Online (Sandbox Code Playgroud)
给出:
?????????????????????????????????????????????????????????????????????????????
? id ? rater_user_id ? rated_user_id ? rating ? created_at ?
?????????????????????????????????????????????????????????????????????????????
? 221673540 ? 5699713 ? 3890950 ? N ? 2013-04-09 13:00:38 ?
?????????????????????????????????????????????????????????????????????????????
Run Code Online (Sandbox Code Playgroud)
该表设置了 3 个索引:
rated_user_id rater_user_id和created_at rated_user_id和rater_user_id显示来自 user_match_ratings 的索引;
给出:
??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
? Table ? Non_unique ? Key_name ? Seq_in_index ? Column_name ? Collation ? Cardinality ? Sub_part ? Packed ? Null ? Index_type ? Comment ?
??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
? user_match_ratings ? 0 ? PRIMARY ? 1 ? id ? A ? 220781193 ? NULL ? NULL ? BTREE ? ? ?
? user_match_ratings ? 1 ? user_match_ratings_index1 ? 1 ? rater_user_id ? A ? 11039059 ? NULL ? NULL ? BTREE ? ? ?
? user_match_ratings ? 1 ? user_match_ratings_index1 ? 2 ? created_at ? A ? 220781193 ? NULL ? NULL ? BTREE ? ? ?
? user_match_ratings ? 1 ? user_match_ratings_index2 ? 1 ? rated_user_id ? A ? 4014203 ? NULL ? NULL ? BTREE ? ? ?
? user_match_ratings ? 1 ? user_match_ratings_index2 ? 2 ? rater_user_id ? A ? 220781193 ? NULL ? NULL ? BTREE ? ? ?
? user_match_ratings ? 1 ? user_match_ratings_index3 ? 1 ? rated_user_id ? A ? 2480687 ? NULL ? NULL ? BTREE ? ? ?
??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
Run Code Online (Sandbox Code Playgroud)
即使有索引,这些查询也很慢。
是否将此表/数据分离到服务器上的另一个数据库,该服务器有足够的内存来将此数据存储在内存中,这会加速这些查询吗?无论如何,我们可以改进表/索引的设置以加快这些查询的速度吗?
目前我们有 16GB 的内存;但是,我们正在考虑将现有机器升级到 32GB 或添加一台至少有那么多容量的新机器,也许还有固态驱动器。
ype*_*eᵀᴹ 36
关于这个问题的想法,以随机顺序抛出:
此查询的明显索引是:(rated_user_id, rating)。一个只为百万用户中的一个获取数据并且需要 17 秒的查询做错了:从(rated_user_id, rater_user_id)索引读取然后从表中读取列的(数百到数千)值rating,因为rating在任何索引中都没有。因此,查询必须读取位于许多不同磁盘位置的表中的许多行。
在开始在表中添加大量索引之前,尝试分析整个数据库、整个慢查询集的性能,再次检查数据类型的选择、您使用的引擎和配置设置。
考虑迁移到较新版本的 MySQL、5.1、5.5 甚至 5.6(还有:Percona 和 MariaDB 版本)。由于错误已得到纠正,优化器得到改进,您可以将慢查询的低阈值设置为小于 1 秒,从而带来一些好处(比如 10 毫秒)。这将为您提供关于慢查询的更好信息。
数据类型的选择rating很奇怪。VARCHAR(1)? 为什么不CHAR(1)呢?为什么不TINYINT呢?这将为您节省一些空间,无论是在表中还是在(将)包含该列的索引中。varchar(1) 列需要比 char(1) 多一个字节,如果它们是 utf8,则 (var)char 列将需要 3(或 4)个字节,而不是 1(tinyint)。
| 归档时间: |
|
| 查看次数: |
197542 次 |
| 最近记录: |