组合查询
select a, b from A where a > 5 and b in (select b from B where c = "some")
花费比固定查询长30倍的时间
select a, b from A where a > 5 and b in (1, 2, 3)
尽管
select b from B where c = "some"
产生与固定查询(1, 2, 3)
select b from B where c = "some"
仅需0.01秒即可执行select a, b from A where a > 5
的执行时间为0.3s。在A的(a,b)上有一个索引。
分析组合查询:
analyze select a, b from A where a > 5 and b in (select b from B)
*************************** 1. row ***************************
id: 1
select_type: PRIMARY
table: A
type: range
possible_keys: idx_a_b
key: idx_a_b
key_len: 8
ref: NULL
rows: 126459
r_rows: 66181.00
filtered: 100.00
r_filtered: 100.00
Extra: Using index condition; Using temporary; Using filesort
*************************** 2. row ***************************
id: 1
select_type: PRIMARY
table: B
type: eq_ref
possible_keys: PRIMARY
key: PRIMARY
key_len: 2
ref: A.b
rows: 1
r_rows: 1.00
filtered: 100.00
r_filtered: 0.09
Extra: Using where
请注意,r_rows = 66181与select a, b from A where a > 5
相匹配。
好像MariaDB仅使用索引的a部分,而忽略了b应该在第一步中从子查询中获取的b。说明扩展显示MariaDB用
替换了我的查询select b, a from B join A where ((B.b = A.b) and (A.a > 5) and (B.c = "some"))
如果给定的是固定值(1、2、3)(由子查询返回),而不是子查询本身,那么奇怪的是,MariaDB确实确实同时使用了索引的a和b通过分析固定查询来观察:
analyze select a, b from A where a > 5 and y in (1, 2, 3)
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: A
type: range
possible_keys: idx_a_b
key: idx_a_b
key_len: 10
ref: NULL
rows: 126459
r_rows: 59.00
filtered: 100.00
r_filtered: 100.00
Extra: Using index condition; Using temporary; Using filesort
r_rows = 59匹配两个查询(组合查询和固定查询)的结果集大小。
如何通过使用A的索引中的a和子查询b来使MariaDB使用与固定查询中相同的查询计划?
答案 0 :(得分:1)
有时,查询的优化方式有所不同。当您拥有固定的值列表时,查询计划者会更多地了解您在做什么。
如果b
中没有重复项,那么join
通常会制定出良好的执行计划:
select a.a, a.b
from a join
b
on a.b = b.b
where a.a > 5;
我还建议改为尝试exists
:
select a, b
from A
where a > 5 and
exists (select 1 from B where b.b = a.b) ;
并确保您在b(b)
上有一个索引:
create index idx_b_b on b(b);
答案 1 :(得分:0)
我的大脑变得笨拙,试图处理B vs b和A vs a,所以我更改了表名。
select Y.b, Y.a
from X
join Y
where ((X.b = Y.b)
and (Y.a > 5)
and (X.c = "some")
)
该查询需要
X: INDEX(c, b)
Y: INDEX(a, b), INDEX(b, a)
这样,无论优化器以哪个表开头,它都可以高效运行。优化器将根据a
和c
的统计信息选择更好的表作为开始。但是,除非您打开“直方图”(MariaDB 10.0-10.3;默认为10.4启用),否则优化器可能没有完整的故事。