40W条数据查找超时,联合唯一索引

MySql 码拜 8年前 (2016-02-13) 1102次浏览
游戏服务器的数据库有个表account_role是用来绑定账号与角色(一个账号对应一个角色)之间的关系,表结构如下

+--+--+--+--+--+--+
| Field            | Type             | Null | Key | Default | Extra          |
+--+--+--+--+--+--+
| role_id          | int(10) unsigned | NO   | PRI | NULL    | auto_increment |
| server_id        | tinyint(4)       | YES  | MUL | NULL    |                |
| account_id       | bigint(20)       | YES  |     | NULL    |                |
| account_name     | varchar(32)      | YES  |     | NULL    |                |
+--+--+--+--+--+--+

字段分别是:角色ID,账号库id,账号id,账号
DDL

CREATE TABLE `account_role` (
  `role_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `server_id` tinyint(4) DEFAULT NULL,
  `account_id` bigint(20) DEFAULT NULL,
  `account_name` varchar(32) DEFAULT NULL,
  PRIMARY KEY (`role_id`),
  UNIQUE KEY `index_account` (`server_id`,`account_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

由于可以用多种账号库登陆,例如可以用网易账号和百度账号登录,由客户端选择,两个账号库的账号ID可能相同,所以有个账号库字段
server_id和account_id有个联合唯一索引
现在有大约20-30个线程用于登录检查绑定关系,假如没有绑定角色,则插入一条记录,否则读取role_id获取角色信息
大致是这样的

select role_id from account_role where server_id=1 and account_id=1000000;

假如没找到则插入

insert into account_role values(0, 1, 1000000, "asdfghj");

假如insert成功,则查询刚才插入的role_id

select last_insert_id();

这个server_id和account_id联合唯一索引的目的是多线程insert同一个玩家时(例如玩家点击了多次登录,在不同的线程同时处理,要做线程同步),保证只有一个insert成功,也就是利用数据库的唯一索引来同步线程
现在的问题是数据库中有约40W条数据,当新玩家进来时,insert这句经常会超时(100多秒)?

解决方案

15

这里的账户表不能够拆成多个表么?
多个线程同时查询多个表,当有一个查询出结果,通知其他线程停止搜索。
当然,前提该数据必须有唯一设定,假如可以查出多条数据的话不在我们的讨论范围。

15

LZ你好
这样的数据库系统应该将读写分开,并且应用cache缓存等技术,才能明显的提高性能

10

select role_id from account_role where server_id=1 and account_id=1000000;
看下这个sql的执行计划
最好索引创建的时候是UNIQUE KEY `index_account` (`account_id`,`server_id`)

CodeBye 版权所有丨如未注明 , 均为原创丨本网站采用BY-NC-SA协议进行授权 , 转载请注明40W条数据查找超时,联合唯一索引
喜欢 (0)
[1034331897@qq.com]
分享 (0)