所以这是我的表:
create table page_relation (
relationid int primary key,
userid int,
pageid int,
registryid int
);
让我们想象一下,我想要了解用户每一页的所有注册表的数量。 以下是我将要运行的查询:
select count(*) as register_count
from page_relation
where userid = 10
group by pageid;
我需要帮助找出加速这一查询的最佳索引是什么。
到目前为止,我尝试使用复合索引超过(userid, pageid)
,希望MySQL将该索引用于分组,但不幸的是,当我使用EXPLAIN时,额外的信息不包含任何“使用索引进行分组”信息,只说我使用索引,我在哪里使用。这是否意味着我的索引没有被用于排序?
理论上如果它是聚集的,这个索引不会起作用吗?我认为B-Tree,聚集和稀疏索引可以很好地完成这项工作......说实话,我期待它甚至可以作为覆盖索引,但我无法确定它是否存在。
这是我的解释声明:
# id, select_type, table, type, possible_keys, key, key_len, ref, rows, Extra
1, SIMPLE, page_relation, ref, idx_count, idx_count, 4, const, 60, Using where; Using index
仅用于执行此查询的最佳索引是什么?
感谢您的时间。
答案 0 :(得分:0)
使用下面提到的两种方法可以满足要求:
查询:
select userid,pageid,count(*) as register_count
from page_relation
where userid = 10
group by userid,pageid;
查询:查询将保持与问题中提到的相同。
注意:对于复合键,MySQL按声明顺序使用索引。例如,组合键(userid,pageid)必须使用字段userid
进行过滤或分组,否则将忽略索引。
第一种方法的好处是它只能引用一个索引。数字索引越少,写入效率越高。考虑到空间和时间的复杂性,我建议您1st approach
进行BTREE
索引。
假设:pageid
字段不是唯一的。
注意:如果索引未在任何版本的MySQL中使用,请在group by
中保留select clause
个字段。
答案 1 :(得分:0)
INDEX(userid, pageid)
是唯一合理的索引。
当指示是否使用或忽略索引(在这种情况下为EXPLAIN
)时, pageid
非常蹩脚。您可以尝试EXPLAIN FORMAT=JSON SELECT ...
查看是否澄清了问题。
INDEX(userid), INDEX(pageid)
不太有用。它会使用一个或另一个,但不是两个。它可能会使用(userid),但这实际上并不比复合索引更好,可能更糟。
查询本身令人费解。你有多排吗?如果没有,请摆脱GROUP BY
。如果是,您是否应该将pageid
添加到SELECT
列表?
其中大部分内容都在我的Index Cookbook中。
另一个难题......这是一个'关系'表;你是说userids和pageids之间的“多对多”映射?或者是其他东西。在很多:很多表中,通常你想要两个方向,从而需要两个方向的索引。代理id
也没用,因为PRIMARY KEY (userid, pageid)
是有保证的。 (见我的食谱。)
我将此升级到PRIMARY KEY
,可以提高效率。
我越来越深入“if ifs”;解决我的一些问题;然后我会进一步漫步。