Xen*_*nos 5 mysql explain sql-execution-plan
说我有这个查询:
EXPLAIN SELECT *
FROM (
SELECT "A" as a, i.n FROM (SELECT 1 AS n) AS i
UNION ALL SELECT "B" as a, i.n FROM (SELECT 1 AS n) AS i) AS t
WHERE a = "B";
Run Code Online (Sandbox Code Playgroud)
MySQL 说
id select_type table partitions type possible_keys key key_len ref rows filtered Extra
1 PRIMARY <derived2> \N ref <auto_key0> <auto_key0> 6 const 1 100.00 \N
2 DERIVED <derived3> \N system \N \N \N \N 1 100.00 \N
3 DERIVED \N \N \N \N \N \N \N \N \N No tables used
4 UNION <derived5> \N system \N \N \N \N 1 100.00 \N
5 DERIVED \N \N \N \N \N \N \N \N \N No tables used
Run Code Online (Sandbox Code Playgroud)
那么MySQL生成了一个中间索引<auto_key0>
,但是这个索引背后是什么?其中使用了哪些列?有没有办法可以手动设置这个索引,并强制 MySQL 使用某些列。
EXPLAIN FORMAT=JSON SELECT ...
会返回类似的东西
key: <auto_key0>, used_key_parts: ['a'], key_length: 6, ref: ['const']
Run Code Online (Sandbox Code Playgroud)
<auto_key0>
是优化器为派生表生成的索引。
(还有“优化器跟踪”;但可能没有这个特定信息。)
https://dev.mysql.com/doc/refman/8.0/en/driven-table-optimization.html说:
Run Code Online (Sandbox Code Playgroud)SELECT * FROM t1 JOIN (SELECT DISTINCT f1 FROM t2) AS derived_t2 ON t1.f1=derived_t2.f1;
如果这样做可以使用引用访问来实现最低成本的执行计划,则优化器会在衍生_t2 的列 f1 上构造索引。
我认为这意味着索引的列由连接表达式确定。MySQL 优化器知道哪些列对索引有用,因为它们在ON
连接子句中被引用。
我不知道有什么方法可以控制为派生表生成的索引。该指数是短暂的。它是在查询期间为临时表创建的,当查询结束时删除临时表时,它会自然删除。
如果您想要对索引进行更多控制,则必须创建自己的表(临时表或永久表)并为其定义索引。
您可能还想阅读由 MySQL 优化器负责人撰写的有关该主题的博客:https://mysqlserverteam.com/mysql-5-7-improved-performance-of-queries-with-衍生-tables/