Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/heroku/2.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_Performance_Database Indexes - Fatal编程技术网

Mysql索引的使用

Mysql索引的使用,mysql,sql,performance,database-indexes,Mysql,Sql,Performance,Database Indexes,我有两个带有公共字段的表。在一个表上,公共字段有一个索引 而在另一方面,则不是。按以下方式运行查询: SELECT * FROM table_with_index LEFT JOIN table_without_index ON table_with_index.comcol = table_without_index.comcol WHERE 1 与运行相反的查询相比,查询的性能要差得多: SELECT * FROM table_without_index LEFT JOIN tabl

我有两个带有公共字段的表。在一个表上,公共字段有一个索引 而在另一方面,则不是。按以下方式运行查询:

SELECT * 
FROM table_with_index
LEFT JOIN table_without_index ON table_with_index.comcol = table_without_index.comcol
WHERE 1
与运行相反的查询相比,查询的性能要差得多:

SELECT * 
FROM table_without_index 
LEFT JOIN table_with_indexON table_without_index.comcol = table_with_index.comcol 
WHERE 1

任何人都可以向我解释为什么以及在这种情况下使用索引背后的逻辑

要检查MySQL查询优化器的运行情况,请显示这两个查询的解释计划。是这样的:

EXPLAIN 
SELECT * FROM table_with_index
LEFT JOIN table_without_index ON table_with_index.comcol =       table_without_index.comcol
WHERE 1


您可以使用EXPLAIN在查询前加上前缀,以了解MySQL将如何使用索引以及它将以何种顺序加入表

查看的文档以了解如何解释结果

由于存在左联接,因此无法更改表的顺序。MySQL需要在最终结果集中包含左表中的所有行,无论它们在右表中是否匹配

在内部联接上,MySQL通常交换表,并将行数较少的表放在第一位,因为这样它要分析的行数较少

让我们以这个查询为例,它是对表使用较短名称的查询:

SELECT *
FROM a
  LEFT JOIN b ON a.col = b.col
WHERE 1
MySQL如何运行此查询:

它从表a中获取与查询条件匹配的第一行。如果WHERE或join子句中存在仅使用表a字段和常量值的条件,则使用包含部分或全部这些字段的索引仅筛选与条件匹配的行

选择表a中的一行后,它将转到执行计划中的下一个表,这是查询中的表b。它必须选择与WHERE条件和联接条件匹配的所有行。更具体地说,从表b中选择的行必须匹配条件b.col=X,其中X是步骤1中当前从表a中选择的行的列col的值。它找到第一个匹配的行,然后转到下一个表。由于此查询中没有下一个表,它将把a和b中的一对行放入结果集中,然后放弃b中的行并搜索下一个,重复此步骤,直到在步骤1中找到与当前从a中选择的行匹配的b中的所有行

如果在第2步中无法从b中找到与当前从a中选择的行匹配的任何行,则左侧联接将强制MySQL组成一行,其中b的列全部为null,并与a中的当前行一起创建一行,将其放入结果集中

处理完b中的所有匹配行后,MySQL将丢弃a中的当前行,从a中选择与WHERE和join条件匹配的下一行,并从b步骤2中选择匹配行开始

此过程将循环,直到处理中的所有行

备注:

步骤1第一行的含义取决于许多因素。例如,如果表a上有一个包含查询中指定的表a的所有列的索引,那么MySQL将不会读取表数据,而是使用该索引。在本例中,行的顺序由索引给出。在其他情况下,行是从表数据中读取的,其顺序由存储在存储介质上的顺序提供

这个简单查询没有任何WHERE条件,其中1始终为TRUE,并且JOIN子句中也没有只包含a中的列的条件。表a中的所有行都包含在结果集中,如果可能的话,这将导致索引或索引扫描

在第2步中,如果表b在列col上有一个索引,那么MySQL使用该索引从b中查找列col上有值X的行。这是一个快速操作。如果表b在列col上没有索引,那么MySQL需要执行表b的索引。这意味着它必须读取表b中的所有行,才能找到列col上具有值X的行。这是一个非常缓慢且消耗资源的操作

因为表a的行没有条件,所以MySQL不能使用表a的索引来过滤它选择的行。另一方面,当它需要在步骤2中从表b中选择行时,它有一个匹配b.col=X的条件,并且它可以使用索引来加速选择,因为表b上存在这样的索引

这解释了两个查询之间性能的巨大差异。此外,由于左连接,您的两个查询不相等,它们产生不同的结果

免责声明:请注意,上面列出的步骤过于简化,说明了查询的执行过程。它试图用简单的话来表达,并跳过幕后发生的许多技术方面


有关如何加快查询运行速度的提示,请参见MySQL文档,第节

无差异。优化器应该选择执行查询的最快方式,无论您以何种方式指定联接条件。您正在从表中选择所有行,因此索引表将更快。无论它是否是内部JO
在内部联接上没有区别。在左边,优化器无法交换表。@很抱歉,axiac没有仔细阅读。
SELECT *
FROM a
  LEFT JOIN b ON a.col = b.col
WHERE 1