在join on子句中提到字段时,未获取Mysql索引
如上所述,索引userIdIdx用于后一种情况,但不用于前一种情况 以下是两个表的模式:在join on子句中提到字段时,未获取Mysql索引,mysql,indexing,Mysql,Indexing,如上所述,索引userIdIdx用于后一种情况,但不用于前一种情况 以下是两个表的模式: explain select * from users u join wallet w on w.userId=u.uuid where w.currencyId=8; //index is not taken < >我如何强迫MySQL考虑 USEIDIDX 或 uudidx index?< /p> < p>有两种方法来改进这一点。 方法1: 添加多列索引wallet(userId,currencyId
explain select * from users u join wallet w on w.userId=u.uuid where w.currencyId=8; //index is not taken
< >我如何强迫MySQL考虑<代码> USEIDIDX 或<代码> uudidx index?< /p> < p>有两种方法来改进这一点。 方法1: 添加多列索引
wallet(userId,currencyId)
似乎对这两个查询都更有利
见演示
方法2
重写查询这适用于当前的表结构 查询
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;
见演示
p、 我还建议您在使用InnoDB作为表引擎时,也将Id int(11)NOT NULL AUTO_INCREMENT主键添加到users表中。
我的这篇帖子解释了为什么这两个查询都在尽可能地利用您提供的内容
SELECT
*
FROM (
SELECT
wallet.userId
FROM
wallet
WHERE
wallet.currencyId = 8
) AS wallet
INNER JOIN
users
ON
wallet.userId = users.uuid
如果表中只有一行(例如用户
),优化器将采用不同的路径。第一个查询似乎就是这样
否则,两个查询都将以wallet
开头,因为正在进行筛选。钱包
中的每一个辅助键都便于进行其中一项查询。那就更好了
select *
from users u
join wallet w ON w.userId=u.uuid
where w.userId='8319611142598331610';
select *
from users u
join wallet w ON w.userId=u.uuid
where w.currencyId=8;
第一列用于中,其中
;其他两列使索引“覆盖”,因此它不需要在索引和数据之间跳转
(天哪,那些表的列太少了。)
在w
中进行过滤后,它将转到u
,并使用索引(uuid)
。因为这是表中唯一的一列(没有名字??),所以它可以是“使用索引”,即“覆盖”
进入u
的唯一原因是验证是否存在值与w.userId
匹配的用户。既然您可能总是这样,那么为什么在查询中加入JOIN
到users
?为什么单列索引不起作用?@SandePanath“您能解释一下为什么方法1中的多列索引起作用吗?为什么单列索引不起作用?”检查并查看MySQL优化器如何处理您的第二个查询atfer重写和优化。注意重写是join test.wallet w,其中((test.w.currencyId=8)和(test.w.userId=test.u.uuid))
,并检查此项。。你现在明白了吗?那么我无法解释这个。这些表中还有其他列吗?为什么uuid
在users
中没有主键
?在users
中是否只有一行??
select *
from users u
join wallet w ON w.userId=u.uuid
where w.userId='8319611142598331610';
select *
from users u
join wallet w ON w.userId=u.uuid
where w.currencyId=8;
INDEX(userId, currencyId, id) -- for first query
INDEX(currencyId, userId, id) -- for second query