MySql多列索引的工作原理

Ram*_*ams 1 mysql sql indexing

我们有一个表MySql,以下是架构

CREATE TABLE campaigns (
  domain varchar(50) ,
  campaign_id bigint(12) ,
  log_time datetime ,
  log_type int,
  node_id bigint(12) 
)
Run Code Online (Sandbox Code Playgroud)

关于表格的简要信息

一个域可以有多个广告系列,一个广告系列可以有多个节点

表有1.5亿行.独特的域名是40k.

我想在此表上创建一个综合索引,以获取有关广告系列级和节点级的报告

假设我创建了如下的复合索引

KEY campid_domain_nodeid_logtime (`campaign_id`,`domain`,`node_id`,`log_time`)
Run Code Online (Sandbox Code Playgroud)

它是否完全满足以下查询,这意味着在广告系列级别和节点级别上

广告系列级报告

select count(*) from campaigns 
where domain = 'aaa' and campaign_id = '1235' 
and log_time between '2016-01-01 00:00:00' and '2016-02-02 00:00:00' 
Run Code Online (Sandbox Code Playgroud)

节点级别报告

select count(*) from campaigns
       where domain = 'aaa' and campaign_id = '1235' and node_id = '2345' and  log_time between '2016-01-01 00:00:00' and '2016-02-02 00:00:00
Run Code Online (Sandbox Code Playgroud)

谢谢

Mei*_*ier 10

您可以将索引视为具有快速查找的订单列表.如果你有一个带有字段A,B,C,D的复合索引,那么列表将在A上排序,然后对于与B相同的行,而不是C,而不是C.

A1 | B1 | C1 | D1 | -> pointer to row
A1 | B1 | C1 | D2 | -> pointer to row
A1 | B1 | C2 | D1 | -> pointer to row
A1 | B1 | C2 | D2 | -> pointer to row
A1 | B2 | C1 | D1 | -> pointer to row
...
A2 | B1 | C1 | D1 | -> pointer to row
A2 | B1 | C1 | D2 | -> pointer to row
Run Code Online (Sandbox Code Playgroud)

查询优化器将检查您的查询.如果您的查询要求A,B,C,D,一切都很好.对于一个好的数据库,查询的顺序无关紧要,因此您也可以编写查询 where D and C and B and A.

如果你的查询只询问A,那么一切都很好,因为具有相同A的所有行都是一个接一个.

如果您的查询仅询问D,则索引无用.具有相同D但不同A的行分布在整个列表中.

如果您的查询要求A,B,D,就像您的广告系列级报告一样,则索引会有所帮助.它可以用于加速A和B的查找,但是它需要迭代所有数据,因为C缺失.

您可以定义多个索引.缺点当然是每个附加索引使写入速度变慢并且需要硬盘驱动器上的一些空间.