Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/batch-file/6.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连接类型古怪(使用“ALL”而不是“eq_ref”)_Mysql_Join_Optimization - Fatal编程技术网

MySql连接类型古怪(使用“ALL”而不是“eq_ref”)

MySql连接类型古怪(使用“ALL”而不是“eq_ref”),mysql,join,optimization,Mysql,Join,Optimization,我正在为一些数据构建一个扁平化查询,我得到了这个外键,它导致查询突然从0.031秒运行到2.460秒运行。我分析了查询,并将连接作为一个ALL连接进行,另外使用where;使用联接缓冲块嵌套循环而不是eq_ref联接 为了弄清楚到底发生了什么,我复制了两张桌子,把它们精简到最低限度。表格定义如下: CREATE TABLE `zz_submission` ( `id` int(11) NOT NULL AUTO_INCREMENT, `rcId` int(11) DEFAULT NULL

我正在为一些数据构建一个扁平化查询,我得到了这个外键,它导致查询突然从0.031秒运行到2.460秒运行。我分析了查询,并将连接作为一个ALL连接进行,另外使用where;使用联接缓冲块嵌套循环而不是eq_ref联接

为了弄清楚到底发生了什么,我复制了两张桌子,把它们精简到最低限度。表格定义如下:

CREATE TABLE `zz_submission` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `rcId` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `idx_rcId` (`rcId`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE `zz_rc` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(255) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
zz_rc有5行名称。zz_提交文件有5行,带有来自RC的有效id

运行此查询时,表r的类型为all:

运行此查询时,表r的类型为eq\u ref:

为什么在联接表中选择ID vs Name列会影响联接类型?我在最初的查询中测试了它,它再次切换回0.031s运行


我该怎么做才能让查询在这里使用eq\u ref连接?

您的查询似乎读取了整个s表,然后读取了大部分或全部r表,对吗

使用联接缓冲区意味着它将所需的数据从r加载到缓冲区中。在您的情况下,这可以通过快速扫描索引PK来完成。然后,可以在RAM中进行查找,而无需进一步点击r

第一次选择需要id和名称;第二个只需要id。基于数据类型,并且我或优化器不知道VARCHAR的庞大性,有人会猜测[id,name]会比[id]大很多

连接缓冲区的大小有限-显示“连接缓冲区大小”之类的变量;。因此,它可能容纳所有的[id],但不足以容纳[id,name]

你真的有255个字符长的名字吗?你的例子可能很好地解释了为什么255不应该是每个人的默认值

eq_ref意味着它将在r中进行合理有效的查找。但这可能比使用联接缓冲区慢

块嵌套循环的大致意思是:通过s循环,每行到达r


每个连接可能会分配一个连接缓冲区,因此不要使其大于RAM的1%。

您的查询似乎读取整个s表,然后读取大部分或全部r表,对吗

使用联接缓冲区意味着它将所需的数据从r加载到缓冲区中。在您的情况下,这可以通过快速扫描索引PK来完成。然后,可以在RAM中进行查找,而无需进一步点击r

第一次选择需要id和名称;第二个只需要id。基于数据类型,并且我或优化器不知道VARCHAR的庞大性,有人会猜测[id,name]会比[id]大很多

连接缓冲区的大小有限-显示“连接缓冲区大小”之类的变量;。因此,它可能容纳所有的[id],但不足以容纳[id,name]

你真的有255个字符长的名字吗?你的例子可能很好地解释了为什么255不应该是每个人的默认值

eq_ref意味着它将在r中进行合理有效的查找。但这可能比使用联接缓冲区慢

块嵌套循环的大致意思是:通过s循环,每行到达r


每个连接可能会分配一个连接缓冲区,因此不要使其大于RAM的1%。

您没有显示解释输出、总行数。你的问题不够详细,你把它们说得太过分了。对于5行,扫描表比使用任何索引都要快。很抱歉,我添加了解释输出。您没有显示解释输出,总行数。你的问题不够详细,你把它们说得太过分了。对于5行,扫描表比使用任何索引都要快。很抱歉,我添加了解释输出。正确。S是我的主表,我从中获取所有行。我从R加入FK是为了得到一个状态名。我不明白为什么仅仅根据我从联接表中选择的列,联接类型和执行时间会有如此大的变化。正确。S是我的主表,我从中获取所有行。我从R加入FK是为了得到一个状态名。我不明白为什么仅仅根据我从联接表中选择的列,联接类型和执行时间会有如此大的变化。
explain SELECT
    s.ID,
    r.name
FROM zz_submission s
    LEFT JOIN zz_rc r ON s.rcId = r.id
;
explain SELECT
    s.ID,
    r.id
FROM zz_submission s
    LEFT JOIN zz_rc r ON s.rcId = r.id
;