【问题标题】:single column indexing vs multiple column indexing单列索引与多列索引
【发布时间】:2018-07-27 06:37:13
【问题描述】:

我必须在一个包含大约 2000 万行的非常大的表上运行 2 个简单查询。

表格列是id|user_id|earned_amount|created_at

查询一:

select user_id, sum(earned_amount) as total_earning 
from earning_history 
where user_id=XX;

查询2:

SELECT date(created_at) date, sum(earned_amount) as earning, count(id) as total_entry 
FROM `earning_history` 
where user_id=xx 
GROUP by date

我必须比第一个查询更多地运行第二个查询。所以我正在考虑索引user_idcreated_at 列;

没有索引,执行第二个查询大约需要 6-7 秒。 我的问题是,

  1. 我应该只索引 user_id 列吗?还是应该同时索引user_idcreated_at 列?

  2. 我应该使用像 => ALTER TABLE earning_history ADD INDEX (user_id, created_at); 这样的多列索引吗?

【问题讨论】:

  • 也许你可以运行一些测试,比较没有索引的时间,user_id 上的一个索引,user_id 和 created_ad 上的两个索引,但我不确定索引对于按字段分组是否真的有用:@ 987654321@

标签: mysql mariadb


【解决方案1】:

您可以使用复合索引来快速访问并减少对数据检索值的访问。您可以使用 where (user_id) 中的列和 select 中使用的列 ..

但对于函数或计算列中使用的列,通常使用索引

anyqwey 你应该有一些使用和索引的好处

create index my_index  on my_table ( user_id, id, created_at, earned_amount)

create index my_index  on my_table ( user_id,  created_at,id, earned_amount)

【讨论】:

    【解决方案2】:

    除非id 可以是NULL,否则说COUNT(*) 而不是id。那么两个查询的最佳索引是这个顺序

    INDEX(user_id, earned_amount, created_at)
    

    两个查询都将其用作“覆盖”索引。两者都需要user_id 成为第一——以满足WHERE。第一个查询将仅使用前两列,由于未使用第三列,因此开销很小。第二个查询不关心第 2 列和第 3 列的顺序,我选择这个顺序是为了使单个 INDEX 对两者都有效。

    两个单独的单列索引不会那么有效。 MySQL 可能只使用一个索引,它是(user_id)。然后它必须在包含索引的 BTree 和包含所有列的 BTree 之间反弹——为了至少获得earned_amount。 “覆盖”避免了这种反弹。

    【讨论】:

      猜你喜欢
      • 2020-05-06
      • 1970-01-01
      • 2011-11-07
      • 2010-09-15
      • 1970-01-01
      • 2021-09-01
      • 2016-05-17
      • 2019-03-22
      相关资源
      最近更新 更多