未将 innodb_buffer_pool_size 设置为 5GB 的 MySQL I/O 绑定(bind) InnoDB 查询优化问题

标签 mysql database database-design

我陷入了 MySQL 设计可扩展性问题。任何帮助将不胜感激。

要求:

在他们的社交图中存储用户关于每个用户的 SOCIAL_GRAPH 和 USER_INFO。每秒发生许多并发读取和写入。脏读可接受。

当前设计:

我们有 2 个(相关的)表。两者都是 InnoDB 进行行锁定,而不是表锁定。

  1. USER_SOCIAL_GRAPH 表,将登录 (user_id) 映射到另一个 (related_user_id)。主键复合 user_id 和 related_user_id。

  2. USER_INFO 表,其中包含有关每个相关用户的信息。主键是 (related_user_id)。

注 1:没有定义关系。

注2:现在每个表的大小约为1GB,分别有800万条和200万条记录。

简化表 SQL 创建:

CREATE TABLE `user_social_graph` (
  `user_id` int(10) unsigned NOT NULL,
  `related_user_id` int(11) NOT NULL,
  PRIMARY KEY (`user_id`,`related_user_id`),
  KEY `user_idx` (`user_id`)
) ENGINE=InnoDB;

CREATE TABLE `user_info` (
  `related_user_id` int(10) unsigned NOT NULL,
  `screen_name` varchar(20) CHARACTER SET latin1 DEFAULT NULL,
  [... and many other non-indexed fields irrelevant]
  `last_updated` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (`related_user_id`),
  KEY `last_updated_idx` (`last_updated`)
) ENGINE=InnoDB;

MY.CFG 值集:

innodb_buffer_pool_size = 256M
key_buffer_size         = 320M

注3:可用内存1GB,这2张表2GB,其他innoDB表3GB。

问题:

以下示例 SQL 语句需要访问找到的所有记录,执行需要 15 秒 (!!) 并且 num_results = 220,000:

SELECT SQL_NO_CACHE COUNT(u.related_user_id) 
FROM user_info u LEFT JOIN user_socialgraph u2 ON u.related_user_id = u2.related_user_id 
WHERE u2.user_id = '1' 
AND u.related_user_id = u2.related_user_id 
AND (NOT (u.related_user_id IS NULL));

对于计数为 30,000 的 user_id,大约需要 3 秒(!)。

EXPLAIN EXTENDED 用于 220,000 计数用户。它使用索引:

+----+-------------+-------+--------+------------------------+----------+---------+--------------------+--------+----------+--------------------------+
| id | select_type | table | type   | possible_keys          | key      | key_len | ref                | rows   | filtered | Extra                    |
+----+-------------+-------+--------+------------------------+----------+---------+--------------------+--------+----------+--------------------------+
|  1 | SIMPLE      | u2    | ref    | user_user_idx,user_idx | user_idx | 4       | const              | 157320 |   100.00 | Using where              |
|  1 | SIMPLE      | u     | eq_ref | PRIMARY                | PRIMARY  | 4       | u2.related_user_id |      1 |   100.00 | Using where; Using index |
+----+-------------+-------+--------+------------------------+----------+---------+--------------------+--------+----------+--------------------------+

我们如何在不将 innodb_buffer_pool_size 设置为 5GB 的情况下加快这些速度?

谢谢!

最佳答案

user_social_graph 表没有正确索引!!!

你有:

创建表 user_social_graph
(user_id int(10) unsigned NOT NULL,
related_user_id int(11) NOT NULL,
主键 (user_id,related_user_id),
KEY user_idx (user_id))
引擎=InnoDB;

第二个索引是多余的,因为第一列是 user_id。您正在尝试将 related_user_id 列连接到 user_info 表。该列需要编入索引。

按如下方式更改 user_social_graphs:

创建表 user_social_graph
(user_id int(10) unsigned NOT NULL,
related_user_id int(11) NOT NULL,
主键 (user_id,related_user_id),
唯一键 related_user_idx (related_user_id,user_id))
引擎=InnoDB;

这应该会改变 EXPLAIN PLAN。请记住,索引顺序很重要,具体取决于您查询列的方式。

试一试!!!

关于未将 innodb_buffer_pool_size 设置为 5GB 的 MySQL I/O 绑定(bind) InnoDB 查询优化问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5613281/

相关文章:

database - 我可以使用优雅的配对功能作为数据库中的主键吗?

mysql - ER_NON_UNIQ_ERROR以及如何正确设计表

sql - 如何查看列中数据的来源?

mysql - 如何引用mysql中同一行的值?

Mysql select on word(复数,单数)

php - 使用连接表更新

mysql - mysql中select语句存储过程

mysql - 拆分字符串并循环遍历 MySQL 存储过程中的值

MongoDB固定大小数组实现

python - 根据另一个字段的值在 Django 模型上添加约束