[官方] mysql 性能优化文档(中英文自译)

大家好,我是烤鸭

根据官方文档翻译并精简部分内容。建议有时间的朋友下载原版查看,全文106页pdf,快的话1-2天就能看完。自己翻译的有些地方可能不完整,欢迎指正。
官方pdf下载,需登录:
https://www.mysql.com/cn/why-mysql/presentations/tune-mysql-queries-performance/
csdn下载地址:
https://download.csdn.net/download/angry_mills/10953302
简化版地址:
https://blog.csdn.net/Angry_Mills/article/details/88081834

[官方] mysql 性能优化文档(中英文自译)

  • How to Analyze and Tune MySQL Queries for Better Performance `如何分析和调整MySQL查询以获得更好的性能`
  • Program Agenda `目录`
    • Cost-based query optimization in MySQL `MySQL中基于成本的查询优化`
    • Tools for monitoring, analyzing, and tuning queries `用于监视,分析和调整查询的工具 `
    • Data access and index selection `数据访问和索引选择`
    • Join optimizer `连接优化器`
    • Subqueries `子查询`
    • Sorting `排序`
    • Influencing the optimizer `影响优化器`

How to Analyze and Tune MySQL Queries for Better Performance 如何分析和调整MySQL查询以获得更好的性能

Program Agenda 目录

Cost-based query optimization in MySQL MySQL中基于成本的查询优化

MySQL Optimizer mysql优化器
[官方] mysql 性能优化文档(中英文自译)_第1张图片
通常的想法:

  1. Assign cost to operations 将成本分配到操作
  2. Assign cost to partial or alternative plans 将成本分配到部分或替代计划
  3. Search for plan with lowest cost 搜索成本最低的计划
  4. Cost-based optimizations 基于成本的优化
  5. Access method 访问方式Subquery strategy 子查询策略Join order 连接顺序

mysql优化的特点

  • Produce the query plan that uses least resources IO and CPU
    尽量减少CPU和I/O操作
  • Optimizes a single query No inter-query optimizations
    使用简单的查询,尽量少用嵌套的查询
  • Produces left-deep linear query execution plan
    生成以左连接为主的线性查询执行计划

Optimizer Cost Model 优化器成本模型

图 Optimizer Cost Mode
[官方] mysql 性能优化文档(中英文自译)_第2张图片

Cost Estimates 成本估算

  • Cost unit:
    “read a random data page from disk” 随机从硬盘获取"一页"的数据
    Main cost factors:
  • IO cost:
    pages read from table:默认 1.0
    pages read from index:默认 1.0
  • CPU cost:
    Evaluating query conditions:默认 0.2
    Comparing keys/records :默认 0.1,mysql 5.7以后可配置

图 Cost Estimates
[官方] mysql 性能优化文档(中英文自译)_第3张图片

Cost Model Example 成本模型实例

  • Table scan:全表扫描
    • IO-cost: #pages in table * IO_BLOCK_READ_COST
      IO成本:表中的pages * IO阻塞读取成本
    • CPU cost: #rows * ROW_EVALUATE_COST
      CPU成本: 行 * 行计算成本
  • Range scan (on secondary index): 范围扫描(第二索引)
    • IO-cost: #rows_in_range * IO_BLOCK_READ_COST
      IO成本:范围中的行 * IO阻塞读取成本
    • CPU cost: #rows_in_range * ROW_EVALUATE_COST
      IO成本:范围中的行 * 行计算成本

图 Cost Model Example
[官方] mysql 性能优化文档(中英文自译)_第4张图片

图 Cost Model Example: Optimizer Trace
[官方] mysql 性能优化文档(中英文自译)_第5张图片

图 Cost Model vs Real World
[官方] mysql 性能优化文档(中英文自译)_第6张图片

图 Cost Model Performance Schema
[官方] mysql 性能优化文档(中英文自译)_第7张图片

Tools for monitoring, analyzing, and tuning queries 用于监视,分析和调整查询的工具

  • Useful tools
    • MySQL Enterprise Monitor (MEM), Query Analyzer Commercial
      product 付费产品
    • Performance schema, MySQL sys schema
      执行计划,MySQL 系统计划
  • EXPLAIN
    • Tabular EXPLAIN 表格式EXPLAIN
    • Structured EXPLAIN (FORMAT=JSON)结构式EXPLAIN 图*2 [官方] mysql 性能优化文档(中英文自译)_第8张图片
      [官方] mysql 性能优化文档(中英文自译)_第9张图片
    • Visual EXPLAIN (MySQL Workbench)可视化EXPLAIN
      [官方] mysql 性能优化文档(中英文自译)_第10张图片
    • Optimizer trace 优化器跟踪
    • Slow log 日志
    • Status variables (SHOW STATUS LIKE ‘Sort%’) 状态变量

MEM 图形化界面,收费的,暂时不考虑了,看下面的例图

图 Query Analyzer[官方] mysql 性能优化文档(中英文自译)_第11张图片

图 Query Analyzer Query Details
[官方] mysql 性能优化文档(中英文自译)_第12张图片

Performance schema 执行计划
一些有用的表:

  • events_statements_history,events_statements_history_long Most
    recent statements executed

    大部分最近执行的statement
    
  • events_statements_summary_by_digest Summary for similar statements
    (same statement digest)

     总结相似操作(相同的statement合并)
    
  • file_summary_by_event_name

  • Interesting event: wait/io/file/innodb/innodb_data_file

  • table_io_waits_summary_by_table

  • table_io_waits_summary_by_index_usage

  • Statistics on storage engine access per table and index

     统计存储引擎的每个表和索引
    

Statement events

  • Tables:(Current statement for each thread)
    每个线程当前执行的statement

  • events_statements_history (10 most recent statements per thread)
    每个线程最近执行的最多10条statement

  • events_statements_history_long (10000 most recent statements)
    最近执行的最多10000statement

  • Statement digest statement合并

  • Normalization of queries to group statements that are similar to be
    grouped and summarized:

    规范化的按statement分组的查询,类似于分组和汇总、如下:

SELECT * FROM orders WHERE o_custkey=10 AND o_totalprice>20
SELECT * FROM orders WHERE o_custkey = 20 AND o_totalprice > 100
SELECT * FROM orders WHERE o_custkey = ? AND o_totalprice > ?

events_statements_summary_by_digest
MySQL sys Schema 系统计划

  • A collection of views, procedures and functions, designed to make
    reading raw Performance Schema data easier
    一组视图,过程和函数,旨在简化读取原始性能模式数据
  • Implements many common DBA and Developer use cases
    实现许多常见的DBA和Developer用例
    • File IO usage per user 每个用户的文件IO使用
    • Which indexes is never used? 哪个索引从未被使用
    • Which queries use full table scans? 哪些查询是全表扫描
  • Examples of very useful functions: 非常有用的函数示例
    • format_time() , format_bytes(), format_statement()
  • Included with MySQL 5.7 包含mysql 5.7
  • Bundled with MySQL Workbench 与MySQL Workbench捆绑在一起

MySQL sys Schema MySQL 系统计划

  • statement_analysis :Lists a normalized statement view with aggregated
    statistics, ordered by the total execution time per normalized
    statement (SELECT * FROM sys.statement_analysis LIMIT 1\G
    列出带聚合的规范化语句视图统计信息,按每个规范化语句的总执行时间排序

EXPLAIN Understand the query plan

图 EXPLAIN[官方] mysql 性能优化文档(中英文自译)_第13张图片

Structured EXPLAIN (EXPLAIN FORMAT=JSON SELECT …

图 Structured EXPLAIN[官方] mysql 性能优化文档(中英文自译)_第14张图片

Contains more information:

  • Used index parts
    • Pushed index conditions 触发索引的条件
    • Cost Estimates 成本估算
    • Data estimates 数据估算

图 Structured EXPLAIN[官方] mysql 性能优化文档(中英文自译)_第15张图片

图 MySQL sys Schema Example
[官方] mysql 性能优化文档(中英文自译)_第16张图片

Visual EXPLAIN 可视化EXPLAIN

图 Visual EXPLAIN
[官方] mysql 性能优化文档(中英文自译)_第17张图片

Optimizer Trace: Query Plan Debugging 优化程序跟踪:查询计划调试

  • EXPLAIN shows the selected plan EXPLAIN 展示了选择的计划
  • Optimizer trace shows WHY the plan was selected
    优化跟踪展示了为什么选这个计划
    	SELECT * FROM t1,t2 WHERE f1=1 AND f1=f2 AND f2>0;
    	SELECT trace FROM information_schema.optimizer_trace INTO OUTFILE  LINES TERMINATED BY '';```
    	SET optimizer_trace="enabled=off";
    	
    
    

图 Optimizer Trace Debugging[官方] mysql 性能优化文档(中英文自译)_第18张图片

Data access and index selection 数据访问和索引选择

  • Finding the optimal method to read data from storage engine
    找到最合适的方式从储存引擎读取数据
  • For each table, find the best access method: 对于每个表,找到最佳访问方法
    • Check if the access method is useful 检查访问方法是否有用
    • Estimate cost of using access method 估算使用访问方法的成本
    • Select the cheapest to be used 选择最便宜的使用
  • Choice of access method is cost based 访问方法的选择是基于成本的
  • Ref Access 参考访问
  • Single Table Queries 单表查询

图 Ref Access Single Table Queries
[官方] mysql 性能优化文档(中英文自译)_第19张图片

Join Queries 连接查询
[官方] mysql 性能优化文档(中英文自译)_第20张图片

图 Ref Access Single Join Queries
[官方] mysql 性能优化文档(中英文自译)_第21张图片

Join Queries, continued 未命中的索引的连接查询

图 Ref Access Join Queries continued
[官方] mysql 性能优化文档(中英文自译)_第22张图片

  • Range Optimizer 范围优化器
    • Goal: find the “minimal” ranges for each index that needs to be read
      目的: 找到需要读取索引的"最小"变化
      Example:
    	SELECT * FROM t1 WHERE (key1 > 10 AND key1 < 20) AND key2 > 30
    
    

图 Ref Access Range Optimizer
[官方] mysql 性能优化文档(中英文自译)_第23张图片

  • Range Optimizer, cont 范围优化器,常量
    • Range optimizer selects the “useful” parts of the WHERE condition:
      范围优化器选择WHERE条件"有用的"部分
      • Conditions comparing a column value with a constant: 条件是一列和常量比较的数据
      • Nested AND/OR conditions are supported 嵌套的AND/OR 是支持的
    • Result: list of disjoint ranges that need to be read from index:结果: 没有交集的范围从索引读取
  • Cost estimate based on number of records in each range: 成本估算基于每个范围的记录数量
    • Record estimate is found by asking the Storage Engine (“index dives”)
      记录估算通过询问存储引擎("指数潜水")获取

Optimizer Trace show ranges 优化程序跟踪显示范围

图 Optimizer Trace show ranges
[官方] mysql 性能优化文档(中英文自译)_第24张图片

Range Optimizer: Case Study 范围优化:案例学习

  1. Why table scan? 为什么全表扫描?
SELECT * FROM orders WHERE YEAR(o_orderdate) = 1997 AND MONTH(o_orderdate) = 5
AND o_clerk = 'Clerk#000001866';

图 Range Optimizer Case Study1
possible keys NULL 未使用索引[官方] mysql 性能优化文档(中英文自译)_第25张图片

  1. Some Reasons Why Index can not be Used 一些未使用索引的原因
    • ndexed column is used as argument to function 索引列使用函数计算

      YEAR(o_orderdate) = 1997
      
    • Looking for a suffix 寻找前缀

      name LIKE '%son'
      
    • First column(s) of compound index NOT used 符合索引的前置列未被使用

      b = 10 when index defined over (a, b) 当复合索引(a,b),但是查询条件是b = 10

    • Type mismatch 类型不匹配

      my_string = 10
      
    • Character set / collation mismatch 字符集/排序规则不匹配

      t1 LEFT JOIN t2 ON t1.utf8_string = t2. latin1_string
      

案例学习:

  1. Rewrite query to avoid functions on indexed columns 重写查询以避免索引列上的函数
    例如:
    SELECT * FROM orders WHERE o_orderdate BETWEEN '1997-05-01' AND '1997-05-31' AND o_clerk = 'Clerk#000001866';
    
    i_o_orderdate 命中索引

图 Case Optimizer Case Study2
[官方] mysql 性能优化文档(中英文自译)_第26张图片

  1. Adding another index 添加另一个索引
    mysql> CREATE INDEX i_o_clerk ON orders(o_clerk); 就上面的例子,添加 o_clerk 索引
    

图 Range Optimizer Case Study3
[官方] mysql 性能优化文档(中英文自译)_第27张图片

  • Range Access for Multi-Column Indexes 多列索引的范围访问

  • Example table with multi-part index 具有多部分索引的示例表 有索引abc ,index(a,b,c)

  • Logical storage layout of index: 索引的逻辑存储布局:

图 Range Access for Multi-Column Indexes
[官方] mysql 性能优化文档(中英文自译)_第28张图片

Range Access for Multi-Column Indexes, cont 多列索引的范围访问,常量

  • Equality on 1st index column?第一个索引列上的平等?

  • Can add condition on 2nd index column to range
    condition?可以在第二个索引列上添加条件到范围条件?

    例如:

    	SELECT * from t1 WHERE a IN (10,11,13) AND (b=2 OR b=4)
    

Resulting range scan 结果范围扫描:

图 Range Access for Multi-Column Indexes, cont
[官方] mysql 性能优化文档(中英文自译)_第29张图片

  • Non-Equality on 1st index column? 第一个索引列上不平等?

  • Can NOT add condition on 2nd index column to range
    condition?可以不在第二个索引列上添加条件到范围条件?

    例如:

    	SELECT * from t1 WHERE a > 10 AND a < 13 AND (b=2 OR b=4)
    

Resulting range scan 结果范围扫描:

图 Range Access for Multi-Column Indexes, cont+
[官方] mysql 性能优化文档(中英文自译)_第30张图片

案例学习:

  • Create multi-column index 创建多列索引
    CREATE INDEX i_o_clerk_date ON orders(o_clerk, o_orderdate); 
    

图 Range Optimizer Case Study4
[官方] mysql 性能优化文档(中英文自译)_第31张图片

Performance Schema: Query History 执行计划:查询历史
mysql5.7 默认enabled的。

	UPDATE performance_schema.setup_consumers SET enabled='YES' WHERE name = 'events_statements_history'; 

	SELECT sql_text, (timer_wait)/1000000000.0 "t (ms)", rows_examined rows
	FROM performance_schema.events_statements_history ORDER BY timer_start;

图 Performance Schema: Query History
[官方] mysql 性能优化文档(中英文自译)_第32张图片

Index Merge 索引合并

  • Uses multiple indexes on the same table 同一张表使用多重索引
  • Implemented index merge strategies 实施索引合并策略
    • Index Merge Union 索引合并并集
      • OR-ed conditions between different indexes 不同的索引之间使用OR条件
    • Index Merge Intersection 索引合并交集
      • AND conditions between different indexes 不同的索引之间的情况
  • Index Merge Sort-Union 索引合并排序并集
  • OR-ed conditions where condition is a range WHERE范围条件使用OR

Index Merge Union 索引合并并集

  • Single index cannot handle ORed conditions on different columns 单一索引不能处理不同列使用OR的情况
    例如:
	SELECT * FROM t1 WHERE a=10 OR b=10
INDEX(a) a = 10  INDEX(b) b = 10
Result: a= 10 OR b = 10

图 Index Merge Union
[官方] mysql 性能优化文档(中英文自译)_第33张图片

Index Merge Intersection 索引合并交集

  • Combine several indexes to reduce number of (or avoid) accesses to base table for ANDed conditions
    在AND条件下组合多个索引以减少(或避免)对基表访问次数
    例如:
	SELECT * FROM t1 WHERE a=10 AND b=10
INDEX(a) a = 10  INDEX(b) b = 10
Result: a= 10 AND b = 10

图 Index Merge Intersection
[官方] mysql 性能优化文档(中英文自译)_第34张图片

Example1:

图 Index Merge Intersection Example 1
[官方] mysql 性能优化文档(中英文自译)_第35张图片

Example2:
Beware of low-selectivity indexes! 注意低选择性索引!

图 Index Merge Intersection Example 2
[官方] mysql 性能优化文档(中英文自译)_第36张图片

Example3:
Handler status variables 处理程序状态变量

图 Index Merge Intersection Example 2+
[官方] mysql 性能优化文档(中英文自译)_第37张图片

Join optimizer 连接优化器

”Greedy search strategy” 贪婪的搜索策略
目的: Given a JOIN of N tables, find the best JOIN ordering N张表中找到最好的连接排序

  • Strategy: 策略:
    • Start with all 1-table plans (Sorted based on size and key dependency)
      从所有1表计划开始(根据大小和密钥依赖性排序)
    • Expand each plan with remaining tables 用剩余的表扩展每个计划
      • Depth-first 深度优先
    • If “cost of partial plan” > “cost of best plan”: 如果"部分计划成本" > "最好的计划成本"
      • “prune” plan 精简计划
  • Heuristic pruning: 探索式精简
    • Prune less promising partial plans 精简没什么用的部分计划
    • May in rare cases miss most optimal plan (turn off with set optimizer_prune_level = 0)
      可能在极少数情况下错过最佳计划 (关闭并设置 optimizer_prune_level = 0)

JOIN Optimizer Illustrated 连接优化器插图

图 Join Optimizer
[官方] mysql 性能优化文档(中英文自译)_第38张图片

Change join order with STRAIGHT_JOIN 使用STRAIGHT_JOIN更改连接顺序

图 Join Optimizer+
[官方] mysql 性能优化文档(中英文自译)_第39张图片

Join Order 连接顺序

图 Join Order
[官方] mysql 性能优化文档(中英文自译)_第40张图片

Join Order Hints 连接顺序提示
MySQL 8.0 Optimizer Labs Release MySQL 8.0优化工具实验室发布

  • Alternatives with same effect for this query: 对此查询具有相同效果的替代方案
	JOIN_PREFIX(customer) JOIN_SUFFIX(orders) JOIN_FIXED_ORDER()

图 Join Order Hints
[官方] mysql 性能优化文档(中英文自译)_第41张图片

National Market Share Query 全国市场份额查询

	SELECT o_year, SUM(CASE WHEN nation = 'FRANCE' THEN volume ELSE 0 END) / SUM(volume) AS mkt_share
	FROM (
	SELECT EXTRACT(YEAR FROM o_orderdate) AS o_year, l_extendedprice * (1 - l_discount) AS volume, n2.n_name AS nation
	FROM part
	JOIN nation n2 ON s_nationkey = n2.n_nationkey JOIN region ON n1.n_regionkey = r_regionkey JOIN nation n1 ON c_nationkey = n1.n_nationkey JOIN customer ON o_custkey = c_custkey JOIN orders ON l_orderkey = o_orderkey JOIN supplier ON s_suppkey = l_suppkey JOIN lineitem ON p_partkey = l_partkey WHERE r_name = 'EUROPE' AND o_orderdate BETWEEN '1995-01-01' AND '1996-12-31' AND p_type = 'PROMO BRUSHED STEEL'
	) AS all_nations GROUP BY o_year ORDER BY o_year;

MySQL Workbench Visual EXPLAIN MySQL Workbench 可视化 EXPLAIN

图 MySQL Workbench: Visual EXPLAIN
[官方] mysql 性能优化文档(中英文自译)_第42张图片

Force early processing of high selectivity conditions 强制早期处理高选择性条件

图 Force early processing of high selectivity conditions
[官方] mysql 性能优化文档(中英文自译)_第43张图片

Improved join order 优化连接顺序

图 Improved join order
[官方] mysql 性能优化文档(中英文自译)_第44张图片

  • Improvements to Query 8 in MySQL 5.7: mysql 5.7 对Query8的优化
  • Filtering on non-indexed columns are taken into account 考虑对非索引列进行过滤
  • No need for hint to force part table to be processed early 部分表强制提前处理无需提示
  • Merge derived tables into outer query 将派生表合并到外部查询中
  • No temporary table 无临时表

Subqueries 子查询

Overview of Subquery Optimizations 子查询优化概述

Subquery category: 子查询分类 Strategy:策略
IN (SELECT …) Semi-join 半连接Materialization 实体化
NOT IN (SELECT …) IN ➜ EXISTS
FROM (SELECT …) Merged 合并 Materialized 实体化
ALL/ANY (SELECT …) MAX/MIN re-write 最大/最小化 重写
EXISTS/other Execute subquery 执行子查询

图 Subquery category
[官方] mysql 性能优化文档(中英文自译)_第45张图片

  • Traditional Optimization of IN Subqueries IN子查询的传统优化
    • IN -> EXISTS transformation IN 转化为 EXISTS
  • Convert IN subquery to EXISTS subquery by “push-down” IN-equality to
    subquery 从IN子查询转化为EXISTS子查询通过"向下"的同等子查询
     SELECT title FROM film WHERE film_id IN (SELECT film_id FROM actor WHERE name=“Bullock”)
    
    优化为 =>
    SELECT title FROM filmWHERE EXISTS (SELECT 1 FROM actor WHERE name=“Bullock” AND film.film_id = actor.film_id)
    
  • Benefit: subquery will evaluate fewer records 优点:子查询将计算更少的记录
  • Note: Special handling if pushed down expressions can be NULL 注意:如果"向下"表达式为NULL,则可特殊处理

Semi-join 半连接

  • Convert subquery to inner join, BUT Need some way to remove duplicates
    将子查询转换为内连接 但需要一些方法去重

  • Different strategies for duplicate removal: 去重的不同策略

    • FirstMatch (equivalent to IN→EXISTS execution) 匹配优先(等价于IN—>EXISTS的方式)
    • LooseScan (index scan, skip duplicates) 懒扫描(索引扫描,跳过重复)
    • Materialization: MatLookup (like subquery materialization), MatScan
      (materialized table is first in join order)
      实体化:MatLookup(像子查询实体化),MatScan(实体化表在连接顺序的第一位)
    • Duplicate WeedOut (insert result rows of semi-join query into
      temporary table with unique index; duplicate rows will be rejected.
      Any join order.) 去重(用唯一索引将半连接的行插入临时表;重复列将会被拒绝。无论连接顺序)
  • If duplicate removal is not necessary: 如果去重是非必须的话

    • Table pull-out 表将删掉

Main advantage : 主要优势:

  • Opens up for more optimal ”join orders” 有更多优化"连接顺序"的选择
    例如:
    	SELECT o_orderdate, o_totalprice FROM orders WHERE o_orderkey IN (SELECT l_orderkey FROM lineitem WHERE l_shipDate='1996-09-30');
    
    • Will process less rows if starting with lineitem instead of orders 使用行代替排序会经过较少的行
  • Restriction: 限制:
    • Cannot use semi-join if subquery contains union or aggregation
      如果子查询包含union(并集)或者aggregation(聚合)不能使用半连接

MySQL 5.6: Semi-join: Example mysql5.6 半拦截的例子:

图 MySQL 5.6: Semi-join: Example
[官方] mysql 性能优化文档(中英文自译)_第46张图片

MySQL 5.7: Hint Example: SEMIJOIN 提示示例: 半连接

  • No hint, optimizer chooses semi-join algorithm LooseScan: 没有提示,优化器选择半连接算法LooseScan
  • Disable semi-join with hint: 使用提示禁用半连接:

图 Hint Example: SEMIJOIN
[官方] mysql 性能优化文档(中英文自译)_第47张图片

  • Subquery Materialization 子查询实体化
    • Execute subquery once and store result in a temporary table 执行一次子查询并在临时表中存结果
    • Table has unique index for quick look-up and duplicate removal 表有唯一索引可以快速查找并去重
  • Execute outer query and check for matches in temporary table 执行外部查询并检查临时表中的匹配项

图 Subquery Materialization
比较子查询实现和IN➜EXISTS 比较IN —> EXISTS的实现
[官方] mysql 性能优化文档(中英文自译)_第48张图片

图 Comparing Subquery Materialization
[官方] mysql 性能优化文档(中英文自译)_第49张图片

图 Subquery Materialization+
[官方] mysql 性能优化文档(中英文自译)_第50张图片

Derived Tables 派生表

  • Subquery in FROM clause FROM子句中的子查询
    SELECT AVG(o_totalprice) FROM ( SELECT * FROM orders ORDER BY o_totalprice DESC LIMIT 100000 ) td; 
    
  • MySQL 5.6 and earlier: Executed separately and result stored in a
    temporary table (materialization) MySQL 5.6及更早版本:单独执行并将结果存储在临时表中(实现)
  • MySQL 5.7: Treat derived tables like views: May be merged with outer
    query block MySQL 5.7:处理类似于视图的派生表:可以与外部查询块合并

图 Index on Materialized Derived Table
[官方] mysql 性能优化文档(中英文自译)_第51张图片

图 Materialization of Derived Tables EXPLAIN
[官方] mysql 性能优化文档(中英文自译)_第52张图片

  • Merge Derived Table with Outer Query 用外部连接合并派生表
    • Derived tables based on GROUP BY, DISTINCT, LIMIT, or aggregate
      functions will not be merged 基于GROUP BY,DISTINCT,LIMIT或聚合函数的派生表将不会合并

图 Merge Derived Table with Outer Query
[官方] mysql 性能优化文档(中英文自译)_第53张图片

Hint: Merge/Materialize Derived Table or View 暗示:合并/实现派生表或视图

  • MySQL 8.0.0 optimizer labs release MySQL 8.0.0优化器实验室发布
    • Derived tables/views are, if possible, merged into outer query 如果可能,派生表/视图将合并到外部查询中

    • NO_MERGE hint can be used to override default behavior: NO_MERGE提示可用于覆盖默认行为

      • SELECT /*+ NO_MERGE(dt) */ * FROM t1 JOIN (SELECT x, y FROM t2) dt ON t1.x = dt.x;
    • MERGE hint will force a merge MERGE提示将强制合并

      • SELECT /*+ MERGE(dt) */ * FROM t1 JOIN (SELECT x, y FROM t2) dt ON t1.x = dt.x;
    • Can also use MERGE/NO_MERGE hints for views 也可以使用MERGE / NO_MERGE提示查看视图

      • SELECT /*+ NO_MERGE(v) */ * FROM t1 JOIN v ON t1.x = v.x;

Sorting 排序

ORDER BY Optimizations 排序优化

  • General solution; “Filesort”: 通常的解决方案;"文件排序"
    • Store query result in temporary table before sorting 在排序之前将查询结果存储在临时表中
    • If data volume is large, may need to sort in several passes with intermediate storage on disk.
      如果数据量很大,可能需要在磁盘上使用中间存储进行多次传递排序
  • Optimizations : 优化
    • Take advantage of index to generate query result in sorted order 利用索引按排序顺序生成查询结果
    • For ”LIMIT n” queries, maintain priority queue of n top items in
      memory instead of filesort. (MySQL 5.6)
      对于"LIMIT n查询,保留内存中n个顶级项的优先级队列而不是文件排序。 (MySQL 5.6)

Filesort 文件排序:

图 Filesort
[官方] mysql 性能优化文档(中英文自译)_第54张图片

Status variables 状态变量

图 Filesort+
[官方] mysql 性能优化文档(中英文自译)_第55张图片

Performance Schema 执行计划

图 Filesort Performance Schema
Sorting status per statement available from Performance Schema 可从执行计划中对每个语句进行排序
[官方] mysql 性能优化文档(中英文自译)_第56张图片

案例1

图 Filesort Case Study1
[官方] mysql 性能优化文档(中英文自译)_第57张图片

案例2

图 Filesort Case Study2
[官方] mysql 性能优化文档(中英文自译)_第58张图片

案例3

图 Filesort Case Study3
Increase sort buffer 增加排序缓冲区
SET sort_buffer_size = 1024*1024 默认256 KB。[官方] mysql 性能优化文档(中英文自译)_第59张图片

案例4

图 Filesort Case Study4
Increase sort buffer even more (8MB) 进一步增加排序缓冲区 (8MB)
SET sort_buffer_size = 8*1024*1024;
[官方] mysql 性能优化文档(中英文自译)_第60张图片

图 Using Index to Avoid Sorting
Using Index to Avoid Sorting 使用索引来避免排序
[官方] mysql 性能优化文档(中英文自译)_第61张图片

图 Using Index to Avoid Sorting Case study
Case study revisited 重新研究案例
[官方] mysql 性能优化文档(中英文自译)_第62张图片

Influencing the optimizer 影响优化器

  • Add indexes 添加索引
  • Force use of specific indexes: 强制使用特定的索引
    • USE INDEX, FORCE INDEX, IGNORE INDEX 使用索引,强制索引,忽略索引
  • Force specific join order: 强制特定的关联顺序
    • STRAIGHT_JOIN
  • Adjust session variables 调整会话变量
    • optimizer_switch flags: set optimizer_switch=“index_merge=off”
    • Buffer sizes: set sort_buffer=810241024;
    • Other variables: set optimizer_search_depth = 10;

MySQL 5.7: New Optimizer Hints MySQL 5.7:新的优化器暗示

  • Ny hint syntax:暗示语法:
    SELECT /*+ HINT1(args) HINT2(args) */ … FROM …

  • New hints: 新的暗示

    • BKA(tables)/NO_BKA(tables), BNL(tables)/NO_BNL(tables)
      • Batched Key Access (BKA) 批量key访问 Block Nested-Loop (BNL) 阻塞嵌套循环算法
    • MRR(table indexes)/NO_MRR(table indexes) (表的索引)
    • SEMIJOIN/NO_SEMIJOIN(strategies), SUBQUERY(strategy)
    • NO_ICP(table indexes)
    • Index Condition Pushdown (ICP) 索引命中情况下推
    • NO_RANGE_OPTIMIZATION(table indexes) 索引情况下该范围没有可优化的
    • QB_NAME(name) Query Block 查询阻塞
  • Finer granularilty than optimizer_switch session variable 比optimizer_switch会话变量更精细

Optimizer Hints

  • Future :
    • New hints in 8.0.0 Optimizer Labs Release Optimizer Labs 8.0.0 版本中的新暗示
    • Enable/disable merge of views and derived tables: 启用/禁用视图和派生表的合并
  • MERGE() NO_MERGE()
  • Join order 连接顺序
    • JOIN_ORDER(tables) JOIN_PREFIX(tables) JOIN_SUFFIX(tables) JOIN_FIXED_ORDER()
  • Hints we consider to add 考虑添加的暗示:
    • Force/ignore index_merge Alternatives 强制/忽略index_merge替代方案
    • Reimplement index hints in new syntax 重新实现新语法中的索引暗示
    • Temporarily set session variables for just one query 暂时为一个查询设置会话变量

MySQL 5.7: Query Rewrite Plugin 查询重写插件

  • Rewrite problematic queries without the need to make application
    changes 无需更改应用程序即可重写有问题的查询

  • Add hints 添加暗示

    • Modify join order 更新连接顺序
    • Much more … 更多
  • Add rewrite rules to table: 向表中添加重写规则:

图 Query Rewrite Plugin
[官方] mysql 性能优化文档(中英文自译)_第63张图片

  • New pre- and post-parse query rewrite APIs 新的解析前和解析后查询重写API

MySQL 5.7: Adjustable Cost Constants 可调成本常量
Experimental! Use with caution! No guarantees 实验! 谨慎使用! 不保证!!

图 Adjustable Cost Constants
[官方] mysql 性能优化文档(中英文自译)_第64张图片

图 Adjustable Cost Constants+
[官方] mysql 性能优化文档(中英文自译)_第65张图片

More information 更多信息:
MySQL Server Team blog 官方博客
http://mysqlserverteam.com/
My blog: 作者博客
http://oysteing.blogspot.com/
Optimizer team blog: 优化团队博客
http://mysqloptimizerteam.blogspot.com/
MySQL forums: 论坛
Optimizer & Parser: http://forums.mysql.com/list.php?115/
Performance: http://forums.mysql.com/list.php?24/

你可能感兴趣的:(Mysql)