我有一个 MariaDB 10.5.10 数据库,其中有一个由 150,000 行组成的表activity
。它拥有:
- 字段
id
(整数、主键) - 一个
tenant
。大约有 85,000 行,租户 = 12 - an
activity_type
(整数,充当另一个表的键activity_type
)
另一个表 ,activity_type
有 6 行,带有id
(主键,整数)
这个查询是从 ORB 生成的(我几乎无法修改),需要大约 4-5 秒来执行,我想让它运行得更快:
select count(activity.id) from activity
left join activity_type on activity.type = activity_type.id
where tenant = 12 ;
当我删除该left join
行时,它运行得更快,大约 0.7 秒。
使用explain
,我可以看到没有left join
,该extra
列提到using index
(实际上是该列上的索引tenant
):
explain select SQL_NO_CACHE count(activity.id) from activity
where tenant = 12;
但left join
该extra
列为空:
explain select SQL_NO_CACHE count(activity.id) from activity
left join activity_type on activity.type = activity_type.id
where tenant = 12;
并且使用left join
but NOwhere
子句,它还显示Using index
:
explain select SQL_NO_CACHE count(activity.id) from activity
left join activity_type on activity.type = activity_type.id;
LEFT JOIN
当和WHERE
语句都存在时,您能帮助我提高性能吗?
请注意:
- 不会
LEFT JOIN
向结果添加任何行,因为每个活动只有一行activity_type
(我也尝试UNIQUE
在 上添加索引activity_type.id
,但它不会改变任何性能) - 但是我需要该
LEFT JOIN
语句,因为在某些情况下,用户可能希望添加where
与表中字段相关的更多条件(在子句中)activity_type
。
非常感谢!
将以下索引添加到
activity
表中请参阅复合(综合)索引
不,你不知道。根据用户提供的条件构建所需的查询。看来这
AND activity_type = '...'
是唯一LEFT JOIN
需要该条款的情况。其他提示:
COUNT(*)
而不是COUNT(x)
除非您需要检查x IS NOT NULL
.SHOW CREATE TABLE
以便我们准确了解表中的索引、数据类型等。LEFT JOIN
不需要的东西。解释:
(tenent, id)
type
。PRIMARY KEY(id)
”作为数据的“索引”。因此,这种情况下的“使用索引”意味着“表扫描”。使困惑?我不怪你。
我会使用一个短字符串来表示“类型”,并将其作为列包含在
activity
. 这将消除JOIN
(除非“类型”表中有其他感兴趣的内容)。但是,您可能需要INDEX(tenant, type)
,特别是对于原始查询的简化版本。