explain select * from users u join wallet w on w.userId=u.uuid where w.userId='8319611142598331610'; //Index is taken
explain select * from users u join wallet w on w.userId=u.uuid where w.currencyId=8; //index is not taken
如上所述,索引userididx用于后一种情况,但不用于前一种情况。
以下是两个表的架构-
CREATE TABLE `users` (
`uuid` varchar(600) DEFAULT NULL,
KEY `uuidIdx` (`uuid`),
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
CREATE TABLE `wallet` (
`Id` int(11) NOT NULL AUTO_INCREMENT,
`userId` varchar(200) NOT NULL DEFAULT '',
`currencyId` int(11) NOT NULL,
PRIMARY KEY (`Id`),
KEY `userIdIdx` (`userId`),
KEY `currencyIdIdx` (`currencyId`)
) ENGINE=InnoDB AUTO_INCREMENT=279668 DEFAULT CHARSET=latin1;
如何强制mysql考虑 userIdIdx
或者 uuidIdx
索引?
2条答案
按热度按时间mv1qrgav1#
这两个查询都在尽最大努力处理您提供给它们的内容。
如果表中只有一行(例如
users
),优化器采用不同的路径。第一个查询似乎就是这样。否则,两个查询都将以
wallet
因为正在进行过滤。中的每个辅助键wallet
对于其中一个查询很方便。更好的是第一列用于
WHERE
; 另外两列使索引“覆盖”,这样就不需要在索引和数据之间跳转。(天哪,那些表的列太少了。)
过滤后
w
,它将转到u
和用途INDEX(uuid)
. 因为那是表中唯一的一列,(没有名字??),所以它可以是“using index”,也就是“covering”。唯一的原因是
u
验证是否存在值匹配的用户w.userId
. 既然你可能一直都这样,为什么JOIN
至users
在所有的查询中??whhtz7ly2#
有两种方法可以改进这一点。
方法1:
添加多列索引
wallet(userId, currencyId)
这两个查询看起来都更好。请参见演示https://www.db-fiddle.com/f/aesnyevezwopmxrnqjrpos/0
方法2
重写查询。
这适用于当前的表结构。
查询
请参见演示https://www.db-fiddle.com/f/aesnyevezwopmxrnqjrpos/3
p、 我也建议你也加上
Id int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY
当您使用innodb作为表引擎时,可以将其添加到users表。我的帖子解释了原因https://dba.stackexchange.com/a/48184/27070