在数据库管理中,MySQL的SQL语句调优是提升系统性能、确保高效数据访问和处理的关键环节。本文旨在简要探讨MySQL SQL语句调优的重要性、基本原则以及一些常用的调优策略。
EXPLAIN FORMAT=JSON
SELECT o.order_id, c.name
FROM orders o
JOIN customers c USING(customer_id)
WHERE o.total > 1000;
attached_condition
字段确认实际过滤条件optimized_away_subqueries
识别被优化的子查询cost_info
计算各步骤执行成本EXPLAIN ANALYZE
SELECT product_id, COUNT(*)
FROM sales
WHERE sale_date BETWEEN '2023-01-01' AND '2023-06-30'
GROUP BY product_id;
rows_examined_per_scan
的真实扫描行数materialized
标记的物化操作-- 原始索引
ALTER TABLE log ADD INDEX (created_at, user_id);
-- 优化为覆盖索引
ALTER TABLE log ADD INDEX (created_at, user_id, ip_address);
INCLUDE
语法(MySQL 8.0+)包含非索引字段-- 日期范围查询优化
ALTER TABLE orders
ADD INDEX idx_month ((MONTH(order_date)));
-- JSON字段查询优化
ALTER TABLE products
ADD INDEX idx_price_range ((CAST(properties->'$.price' AS UNSIGNED)));
SELECT * FROM employees
WHERE department_id = 10
AND YEAR(hire_date) = 2020;
(department_id, hire_date)
组合索引-- 原始查询
SELECT e.*,
(SELECT COUNT(*) FROM sales s
WHERE s.employee_id = e.id) AS sales_count
FROM employees e;
-- 优化为窗口函数
SELECT e.*,
COUNT(s.id) OVER (PARTITION BY s.employee_id) AS sales_count
FROM employees e
LEFT JOIN sales s ON e.id = s.employee_id;
SELECT u.name, latest_post.content
FROM users u
JOIN LATERAL (
SELECT content
FROM posts p
WHERE p.user_id = u.id
ORDER BY created_at DESC
LIMIT 1
) latest_post;
WITH RECURSIVE cte AS (
SELECT ...
)
SELECT /*+ MATERIALIZE */ ...
UNION ALL
SELECT /*+ MERGE */ ...
SET optimizer_switch='batched_key_access=on';
SELECT * FROM orders
FORCE INDEX (customer_id)
JOIN customers USING(customer_id)
WHERE orders.value > 5000;
SET join_buffer_size = 256*1024*1024;
SET optimizer_switch='hash_join=on';
SELECT /*+ JOIN_ORDER(t1, t3, t2) */
t1.col, t2.col, t3.col
FROM t1
JOIN t2 ON ...
JOIN t3 ON ...;
ALTER TABLE big_table
ROW_FORMAT=COMPRESSED
KEY_BLOCK_SIZE=8;
innodb_compression_level
调整压缩级别INFORMATION_SCHEMA.INNODB_CMP
观察压缩效率SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
START TRANSACTION;
-- 批量处理操作
COMMIT;
[mysqld]
# 内存配置
innodb_buffer_pool_size = 80% of RAM
join_buffer_size = 64M
sort_buffer_size = 8M
# 并行配置
innodb_parallel_read_threads = 16
max_connections = 500
# 查询优化
optimizer_search_depth = 5
range_optimizer_max_mem_size = 256M
sysbench oltp_read_write \
--mysql-host=127.0.0.1 \
--mysql-user=test \
--mysql-password=pass \
--mysql-db=sbtest \
--tables=16 \
--table-size=1000000 \
--threads=64 \
--time=600 \
--report-interval=10 \
run
-- 查看当前执行计划
SELECT * FROM sys.session
WHERE conn_id = PROCESSLIST_ID;
-- 锁等待分析
SELECT * FROM sys.innodb_lock_waits;
CREATE TABLE sensor_data (
id BIGINT PRIMARY KEY,
metrics BLOB COMPRESSED
) ROW_FORMAT=DYNAMIC;
SET global prepared_stmt_count = 16384;
ALTER TABLE orders
STATS_SAMPLE_PAGES = 128
STATS_PERSISTENT = 1;
增加内存:增加服务器的内存可以提高缓存命中率,减少磁盘I/O。
优化磁盘I/O:使用更快的磁盘(如SSD),配置合适的RAID级别。
调整MySQL配置:调整MySQL的配置参数,如 innodb_buffer_pool_size、query_cache_size 等,以适应你的应用场景。
使用缓存:对于频繁访问但不经常变更的数据,可以使用缓存机制(如Memcached、Redis)来减少数据库访问。
读写分离:通过主从复制实现读写分离,将读操作分担到多个从库上。
水平拆分:对于特别大的表,可以进行水平拆分,将数据分布到多个数据库实例上。
通过以上深度优化策略的组合应用,配合系统化的监控验证体系,可使复杂查询性能提升10倍以上。建议每次优化后使用
FLUSH STATUS
和SHOW GLOBAL STATUS
对比关键指标变化,确保优化效果符合预期。