1

我正在研究我在使用 SugarCRM 时遇到的问题的特殊顺序,我认为以下测试用例描述了该问题:

  • 给定以下两个表:

      CREATE TABLE test1 (
      id int(11) NOT NULL AUTO_INCREMENT,
      name char(20),
      PRIMARY KEY (id)
      );
    
    CREATE TABLE test2 (
    id int(11) NOT NULL AUTO_INCREMENT,
     name char(20),
     name2 varchar(10),
     PRIMARY KEY (id)
    );
    
  • 将随机数据插入表 test1:

     delimiter $$  
     create procedure randomizer()
     begin
     declare i int Default 0 ;
     declare random char(20) ;
     declare random2 char(10) ;
     myloop: loop
     set random=conv(floor(rand() * 99999999999999), 20, 36) ;
     insert into test1 (id, name) VALUES (i+1,random) ;
     set i=i+1;
     if i=1000 then
      leave myloop;
    

    万一; 结束循环 myloop; 结束 $$ 分隔符;

  • 将随机数据插入表 test2:

     delimiter $$  
     create procedure randomizer()
     begin
     declare i int Default 0 ;
     declare random char(20) ;
     declare random2 char(10) ;
     myloop: loop
     set random=conv(floor(rand() * 99999999999999), 20, 36) ;
     set random2=conv(floor(rand() * 999999), 10, 36) ;
     insert into test2 (id, name, name2) VALUES (i+1,random, random2) ;
     set i=i+1;
     if i=1000 then
     leave myloop;
    

    万一; 结束循环 myloop; 结束 $$ 分隔符;

  • 添加二级索引:

         alter table test1 add index(name);
    
         alter table test2 add index(name);
    
  • 在连接中的第一个表上使用带有 order by 的表连接执行 QEP:

    explain select test1.name, test2.name from test1 left join test2 on test1.id=test2.id order by test1.name
    
    +----+-------------+-------+--------+---------------+---------+---------+---------------+------+-------------+
    | id | select_type | table |  type  | possible_keys |   key   | key_len |      ref      | rows |    Extra    |
    +----+-------------+-------+--------+---------------+---------+---------+---------------+------+-------------+
    |  1 | SIMPLE      | test1 | index  | NULL          | name    |      21 | NULL          |  981 | Using index |
    |  1 | SIMPLE      | test2 | eq_ref | PRIMARY       | PRIMARY |       4 | test.test1.id |    1 |             |
    +----+-------------+-------+--------+---------------+---------+---------+---------------+------+-------------+
    
  • 再一次,但在连接中的第二个表上排序:

    explain select test1.name, test2.name from test1 left join test2 on test1.id=test2.id order by test2.name
    
    +----+-------------+-------+--------+---------------+---------+---------+---------------+------+----------------------------------------------+
    | id | select_type | table |  type  | possible_keys |   key   | key_len |      ref      | rows |                    Extra                     |
    +----+-------------+-------+--------+---------------+---------+---------+---------------+------+----------------------------------------------+
    |  1 | SIMPLE      | test1 | index  | NULL          | name    |      21 | NULL          |  981 | Using index; Using temporary; Using filesort |
    |  1 | SIMPLE      | test2 | eq_ref | PRIMARY       | PRIMARY |       4 | test.test1.id |    1 |                                              |
    +----+-------------+-------+--------+---------------+---------+---------+---------------+------+----------------------------------------------+
    

我不明白为什么查询 2 使用文件排序,而查询 1 能够使用索引。我是否可能遇到本文档中描述的以下限制?

http://dev.mysql.com/doc/refman/5.0/en/order-by-optimization.html

“您正在连接许多表,并且 ORDER BY 中的列并非全部来自用于检索行的第一个非常量表。(这是 EXPLAIN 输出中第一个没有 const 连接类型的表。)”

4

1 回答 1

0

您已经正确确定了为什么您的第二个查询没有使用索引。

由于您执行了LEFT JOINfrom test1to test2test1是第一个用于检索 rows 的非常量表test2,因此无法使用索引对 from 的列进行排序。

我认为没有办法让您的查询在功能上保持相同,但使用索引 for test2... 但如果您要将连接类型从left jointo更改inner join,则它应该使用索引。

于 2013-02-08T16:05:08.813 回答