分析查询效率应该依赖explain命令吗?

Should rely on explain command when analyzing query efficiency?

explain  SELECT * FROM house JOIN street s on house.STREET_ID = s.ID WHERE s.type<>'out_of' AND street.DISTRICT_ID=4 ORDER BY house.num;
explain SELECT * FROM house JOIN street s on house.STREET_ID = s.ID WHERE s.type<>'out_of' AND house.DISTRICT_ID=4 ORDER BY house.num;

Type 和 district_id 是在 Street table 中编入​​索引的化合物 district_id 在众议院 table

中编入​​索引
  1. 说明与street.DISTRICT_ID=4,街道table相连
<data>
<row>
 <id>1</id>
 <select_type>SIMPLE</select_type>
 <table>street</table>
 <type>ref</type>
 <possible_keys>PRIMARY,FK_STREET_DISTRICT,IDX_STREET_DISTRICT_ID_STREET_TYPE</possible_keys>
 <key>IDX_STREET_DISTRICT_ID_STREET_TYPE</key>
 <key_len>8</key_len>
 <ref>const</ref>
 <rows>16</rows>
 <Extra>Using index condition; Using temporary; Using filesort</Extra>
</row>
<row>
 <id>1</id>
 <select_type>SIMPLE</select_type>
 <table>house</table>
 <type>ref</type>
 <possible_keys>FK_HO_ST,idx_or_st_entity</possible_keys>
 <key>FK_HO_ST</key>
 <key_len>8</key_len>
 <ref>street.ID</ref>
 <rows>70695</rows>
 <Extra></Extra>
</row>
</data>

  1. 用house.DISTRICT_ID=4
  2. 解释
<data>
<row>
  <id>1</id>
  <select_type>SIMPLE</select_type>
  <table>house</table>
  <type>ALL</type>
  <possible_keys>FK_ST_HO,FK_ST_DISTRICT,idx_or_st_entity,IDX_HO_DISTRICT_NUM</possible_keys>
  <key>null</key>
  <key_len>null</key_len>
  <ref>null</ref>
  <rows>989734</rows>
  <Extra>Using where; Using filesort</Extra>
</row>
<row>
  <id>1</id>
  <select_type>SIMPLE</select_type>
  <table>street</table>
  <type>eq_ref</type>
  <possible_keys>PRIMARY</possible_keys>
  <key>PRIMARY</key>
  <key_len>8</key_len>
  <ref>house.STREET_ID</ref>
  <rows>1</rows>
  <Extra>Using where</Extra>
</row>
</data>

DISTRICT_ID 对于 house 和 street 是相同的,但是接收到的估计行有很大的不同。这是否意味着使用连接 DISTRICT_ID 的查询效率更高,估计行数 = 70695?

第一个查询实际上正在检查估计的 1,131,120 行。对于 JOIN 查询,您应该查看联接的 table 之间的 rows 字段的乘积。在您的情况下,它估计它将检查 street 中的 16 行,并且对于这些行中的每一行,它估计它将检查连接的 table house 中的 70,695 行。 16*70695 = 1131120.

而第二个 table 估计它将检查 house 中的 989,734 行(作为 table-scan,由 type: ALL 表示),以及每个匹配的行, 它将通过主键(由 type: eq_ref 表示)在连接的 table street 中查找 1 行。

对数字持保留态度。它们只是估计值,可能会相差很多。最好不要将它们视为精确的数字,而应视为数量级。我会认为它们都是低效的,除非你期望查询的最终结果有数十万行。

没有看到您的 table,很难猜出更好的索引策略。通常关于 query-optimization 的问题应该包括 link 到 dbfiddle,或者查询中每个 table 的 SHOW CREATE TABLE 的输出。

根据您的查询,我猜 table 都有一个 DISTRICT_ID 列。这是多余的,还是可以用来优化连接条件?例如:

... 
FROM house h JOIN street s 
ON h.STREET_ID = s.ID AND h.DISTRICT_ID = s.DISTRICT_ID
...

我的想法是,如果这可以用来缩小检查的行数,那么将它添加到索引中是值得的。但鉴于您提供的关于这些 table 的有限信息,我无法确定。