在没有“where”的连接上使用索引

时间:2015-01-12 10:08:31

标签: mysql sql database database-administration

我试图了解如果在第一个表上没有限制的位置,是否可以在连接上使用索引。

注意:这不是一个逐行的实际用法,只是我为了理解目的而共同起草的内容。不要指出显而易见的“你试图通过这种模式获得什么?”,“你应该使用UNSIGNED”或类似因素,因为这不是问题。

注意2:此MySQL JOINS without where clause以某种方式相关但不相同

架构:

CREATE TABLE posts (
         id_post INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
         text VARCHAR(100)
       );

CREATE TABLE related (
         id_relation INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
         id_post1 INT NOT NULL,
         id_post2 INT NOT NULL
       );

CREATE INDEX related_join_index ON related(id_post1) using BTREE;

查询:

EXPLAIN SELECT * FROM posts FORCE INDEX FOR JOIN(PRIMARY) INNER JOIN related ON id_post=id_post1 LIMIT 0,10;

SQL小提琴:http://sqlfiddle.com/#!2/84597/3

正如您所看到的,索引正在第二个表上使用,但引擎正在对第一个表进行全表扫描(FORCE INDEX只是为了突出显示一般问题)。

我想了解是否可以在左侧获得“参考”。

谢谢!

更新:如果第一个表的记录明显多于第二个表,则事物交换:引擎使用第一个索引,第二个http://sqlfiddle.com/#!2/3a3bb/1使用全表扫描仍然无法在两者上使用索引。

2 个答案:

答案 0 :(得分:3)

DBMS有一个优化器来确定执行查询的最佳计划。由优化器决定是使用索引还是直接读取表。

当DBMS期望从表中读取的记录很少时(例如,仅占所有行的1%),索引才有意义。但是一旦它期望读取许多记录(比如所有行的99%),就不会使用索引。阈值可以低至5%(即< = 5% - >指数;> 5%表扫描)。

有例外。一种是索引包含所需的所有列。然后根本不必阅读表本身。另一个可能是优化器认为尽管必须读取许多行,索引访问可能会更快。优化器也总是可能猜错了。

答案 1 :(得分:1)

MySQL文档中有关于此主题的page

关于从查询中获得第一个表ref的可能性,简短答案为NO

原因很明显:因为没有WHERE子句 ALL ,所以分析了表posts中的行,因为它们可以包含在结果集中。没有理由使用索引,全表扫描更好,因为它获取所有行;并且因为顺序无关紧要,所以访问(或多或少)是顺序的。使用索引需要从存储中读取更多信息(索引和数据)。

如果index子句中出现的所有列都存在于索引中,MySQL将使用连接类型SELECT。在这种情况下,MySQL将执行full index scan(连接类型index)而不是full table scan(连接类型ALL),因为它需要从存储中读取更少的信息(索引)通常小于整个表数据。)