Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/60.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Mysql 如何确定最适合索引的列_Mysql_Sql_Indexing - Fatal编程技术网

Mysql 如何确定最适合索引的列

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

我读过很多关于识别列的文章,这些列可能是创建索引的最佳候选列。然而,大多数建议在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 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 from
c
连接到
a
。所以
a
是下一个。而
JOIN
使用
col1

接下来可以是
d
b
。看起来优化器可以按任意顺序进行优化,并且无论顺序如何,都会以相同的方式进行优化

d
Id
是如何到达它的

b
需要使用简单的
检查
上的
中的3项内容。因此,这3列的“复合”索引可以按任意顺序排列。(不,每列的“基数”并不重要,即使是在选择订单时也是如此。)

至于
b。。。IS NULL
WHERE
子句中进行测试——这些测试可能是测试
LEFT
是否未找到行。(通常只检查PK,所以我不知道您是否也在检查其他内容。)


再优化一次。。。有时,建立一个“覆盖”索引很有用。这是一个
索引
,它包含
选择
中提到的所有列(对于表)。这在这里似乎不实用,因为在这4种情况中,每种情况都会涉及很多列。

我假设这是MySQL,而不是SQL Server
ifnull
不是一个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