MySql查询速度很慢

时间:2011-08-09 14:03:23

标签: mysql sql query-optimization

我在我的数据库上运行以下查询:

SELECT e.id_dernier_fichier
FROM Enfants e JOIN FichiersEnfants f
ON e.id_dernier_fichier = f.id_fichier_enfant

查询运行正常。如果我修改这样的查询:

SELECT e.codega
FROM Enfants e JOIN FichiersEnfants f
ON e.id_dernier_fichier = f.id_fichier_enfant

查询变得非常慢!问题是我想在表e和f中选择许多列,查询最多可能需要1分钟!我尝试了不同的修改但没有任何作用我在e.codega上也有关于id_ *的索引。 Enfants有9000行,FichiersEnfants有20000行。有什么建议吗?

以下是要求的信息(抱歉没有从头开始显示):

Table FichiersEnfants Table Enfants Index Enfants Explain Query 1 Explain Query 2

1 个答案:

答案 0 :(得分:2)

性能差异可能是,因为e.id_dernier_fichier位于用于JOIN的索引中,但e.codega不在 index。

如果没有对两个表及其所有索引的完整定义,则无法确定。此外,包括两个查询的两个EXPLAIN PLAN将有所帮助。


但是现在,我可以详细说明一些事情......

如果INDEX是CLUSTERED(这也适用于PRIMARY KEY),则数据实际上是按INDEX的顺序物理存储的。这意味着您知道在INDEX中想要 位置x 也意味着您需要在TABLE中 位置x

但是,如果INDEX不是群集,则INDEX只是为您提供查找。在INDEX中有效地说 位置x 对应于表中的 位置y

此处的重要性在于访问未在INDEX中指定的字段。这样做意味着您必须实际转到TABLE以获取数据。在CLUSTERED INDEX的情况下,你已经在那里,找到该字段的开销非常低。但是,如果INDEX不是聚类的,那么您必须将TABLE加入INDEX,然后找到您感兴趣的字段。


请注意;在(id_dernier_fichier, codega)上建立综合索引与仅在(id_dernier_fichier)上设置一个索引和在(codega)上设置单独索引非常不同。


对于您的查询,我认为您根本不需要更改代码。但是可能从更改索引中受益。

您提到要访问许多字段。将所有这些字段放在复合索引中可能不是最佳解决方案。相反,您可能希望在(id_dernier_fichier)上创建CLUSTERED INDEX。这意味着一旦定位了* id_dernier_fichier *,您就已经在正确的位置获得所有其他字段。


编辑 Note About MySQL and CLUSTERED INDEXes

13.2.10.1。集群和二级指数

每个InnoDB表都有一个特殊的索引,称为聚簇索引,其中存储了行的数据:

  • 如果在表上定义PRIMARY KEY,InnoDB会将其用作聚簇索引。
  • 如果没有为表定义PRIMARY KEY,MySQL会选择第一个只有NOT NULL列作为主键的UNIQUE索引,而InnoDB将它用作聚簇索引。
  • 如果表没有PRIMARY KEY或合适的UNIQUE索引,InnoDB会在包含行ID值的合成列内部生成隐藏的聚簇索引。行按InnoDB分配给此类表中的行的ID排序。行ID是一个6字节的字段,随着新行的插入而单调增加。因此,由行ID排序的行在物理上处于插入顺序。