如何在mysql的范围查询中使用复合索引

Mr *_*ain 2 mysql performance index query-performance

我有一张桌子?

create table test (
   field1 bigint,
   field2 bigint
);

alter table test 
add index field1_field2 (field1, field2)
Run Code Online (Sandbox Code Playgroud)

这是一个sql:

select * 
from test 
    force index(field1_field2)
where field1 > 100 
  and field2 = 2 
limit 200 ;
Run Code Online (Sandbox Code Playgroud)

它运行得不是很好。我解释了一下,发现只有field1索引查询使用的条件,field2条件被忽略了。

我想知道为什么,我需要一个完美的答案。

有很多数据field1 > 100和很多数据field2 = 2

ype*_*eᵀᴹ 7

您需要在列上建立一个复合索引(它们不是字段!),但顺序相反,在(field2, field1)此查询上。

当条件具有相等检查 ( =) 和范围/不等式检查 ( >, >=, <, <=, IN) 时,相等检查中涉及的列应首先在索引中,然后是不等式列。

alter table test 
    add index ix_field2_field1 
    (field2, field1) ;
Run Code Online (Sandbox Code Playgroud)

补充说明:

  • LIMIT和没有的查询ORDER BY将产生不确定的结果。除非您不关心每次执行是否会得到不同的结果ORDER BYLIMIT否则请始终使用with :

    select * 
    from test  
                              -- no need to force anything
    where field2 = 2          -- the order here doesn't matter
      and field1 > 100        -- but is useful for developers
    order by field2, field1
    limit 200 ;
    
    Run Code Online (Sandbox Code Playgroud)
  • 真的,为列选择一些适当的名称,而不是“field1”、“field2”等。

  • 您的表没有PRIMARY KEY定义。从理论和实践的角度来看,这都不好。假设表使用 InnoDB 引擎,那么通过不定义主键,InnoDB 添加了一个 6 字节的隐藏列作为聚集索引。这也意味着所有索引都附加了这个 6 字节的列,使它们更宽。我建议您PRIMARY KEY在所有表格中都有一个 - 最好是狭窄的。