按索引使用排序

时间:2013-02-08 12:18:01

标签: mysql sql-order-by sugarcrm

我正在通过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);
    
  • 使用表连接执行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使用filesort而查询1能够使用索引。我是否有可能遇到本文档中描述的以下限制?

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

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

1 个答案:

答案 0 :(得分:0)

您已正确识别第二个查询未使用索引的原因。

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

我认为您的查询无法在功能上保持相同但使用test2的索引...但是如果您要将联接类型从left join更改为{{ 1}},它应该使用索引。