Mysql 如何确定最适合索引的列
我读过很多关于识别列的文章,这些列可能是创建索引的最佳候选列。然而,大多数建议在JOIN或WHERE子句中使用的列上创建索引 尽管如此,我还是不能确定下面这样的复杂查询Mysql 如何确定最适合索引的列,mysql,sql,indexing,Mysql,Sql,Indexing,我读过很多关于识别列的文章,这些列可能是创建索引的最佳候选列。然而,大多数建议在JOIN或WHERE子句中使用的列上创建索引 尽管如此,我还是不能确定下面这样的复杂查询 select b.col1 ,a.col1 ,a.selectionId ,a.table2Id ,a.selectionName ,b.UserId,b.ParantId , a.teamType ,d.Name,b.isBack,b.SelectionId,b.Admin AS admin, b.Master AS mast
select b.col1 ,a.col1 ,a.selectionId ,a.table2Id ,a.selectionName ,b.UserId,b.ParantId ,
a.teamType ,d.Name,b.isBack,b.SelectionId,b.Admin AS admin,
b.Master AS master,c.MstDate AS MstDate, c.col2
from tblselection a
join table1 c on c.col1 = a.col1
join table2 d on d.Id = a.table2Id
left join tabletest b on b.SelectionId = a.selectionId and a.table2Id = b.table2Id and b.IsMatched = 1
where ((ifnull(c.active,0) = 1) and isnull(b.Result) and isnull(b.ResultID))
在此查询的所有4个表中,哪些列是索引的最佳候选列
我应该在这里创建复合索引还是单独索引 使用前面的
EXPLAIN
关键字运行查询(EXPLAIN SELECT b.cl1,a.col1…
)。MySQL会给你一个东西是如何连接在一起的分类,以及它扫描多少行来找出答案
通常,您需要在被引用的列上建立索引,特别是当它需要查看大量行或使用“表扫描”连接它们时。你想让它说“使用主”或“使用索引”
下面是我的一个数据库的输出示例。您可以看到这个查询连接了3个表,但最终很快找到了它需要的内容,即使这些表相当大。每个子零件只需要引用一行:
+----+-------------+-------+------------+--------+---------------------+---------+---------+-------------------------------+------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+--------+---------------------+---------+---------+-------------------------------+------+----------+-------------+
| 1 | SIMPLE | sa | NULL | ref | choice_id,user_id | user_id | 5 | const | 1 | 100.00 | Using where |
| 1 | SIMPLE | qc | NULL | eq_ref | PRIMARY,question_id | PRIMARY | 4 | sa.choice_id | 1 | 100.00 | Using where |
| 1 | SIMPLE | q | NULL | eq_ref | PRIMARY | PRIMARY | 4 | qc.question_id | 1 | 100.00 | NULL |
+----+-------------+-------+------------+--------+---------------------+---------+---------+-------------------------------+------+----------+-------------+
基本上,您希望从
where
子句中的可索引列开始。您没有(因为函数调用)。因此,请从join
列开始:
from tblselection a join
table1 c
on c.col1 = a.col1 join
table2 d
on d.Id = a.table2Id left join
tabletest
on b.SelectionId = a.selectionId and a.table2Id = b.table2Id and b.IsMatched = 1
我将从table1(col1)
,table2(id)
和tabletest(SelectionId,table2Id,IsMatched)
开始,首先,更改
where ((ifnull(c.active,0) = 1)
and isnull(b.Result)
and isnull(b.ResultID))
到
我怀疑优化器是否能很好地处理IFNULL()
请提供SHOW CREATE TABLE
和EXPLAIN SELECT…
您现在可能会看到c
是EXPLAIN
中的第一个表。让我们通过提供
c: INDEX(active, col1) -- in that order
此后,
a: INDEX(col1)
d: INDEX(Id) -- unless it is already PRIMARY KEY(Id)
b: INDEX(IsMatched, table2Id, SelectionId) -- in any order
在处理JOIN
时,您需要确定表的查看顺序。不要相信EXPLAIN,因为它(最初)不知道您要添加什么索引
在您的情况下,WHERE
引用了c
和b
。但是b
是一个左连接
,所以我们不能使用它。剩下的是c
。要索引的唯一有用列是活动列
(重新格式化后)。但这听起来像是一个简单的、低基数的、优化器将回避的“标志”。我在索引中添加了一些东西,希望优化器会上当受骗使用它
那么,“下一个”表是什么?将
get fromc
连接到a
。所以a
是下一个。而JOIN
使用col1
接下来可以是d
或b
。看起来优化器可以按任意顺序进行优化,并且无论顺序如何,都会以相同的方式进行优化
d
:Id
是如何到达它的
b
需要使用简单的和检查上的中的3项内容。因此,这3列的“复合”索引可以按任意顺序排列。(不,每列的“基数”并不重要,即使是在选择订单时也是如此。)
至于b。。。IS NULL
在WHERE
子句中进行测试——这些测试可能是测试LEFT
是否未找到行。(通常只检查PK,所以我不知道您是否也在检查其他内容。)
再优化一次。。。有时,建立一个“覆盖”索引很有用。这是一个索引
,它包含选择
中提到的所有列(对于表)。这在这里似乎不实用,因为在这4种情况中,每种情况都会涉及很多列。我假设这是MySQL,而不是SQL Serverifnull
不是一个t-SQL函数。@Larnu:是的,它是MySQL。tblselection(selectionId,table2Id)不是索引的好候选对象吗?
a: INDEX(col1)
d: INDEX(Id) -- unless it is already PRIMARY KEY(Id)
b: INDEX(IsMatched, table2Id, SelectionId) -- in any order