MySQL调优实战

各位小伙伴是否在工作中遇到过类似的问题?一个简单的用户查询居然用时15s,接到优化sql语句的任务又无从下手。今天,我们简单的讲讲MySql如何调优。

sql

SELECT * FROM users WHERE age > 18 ORDER BY create_time DESC;

如上图,一个简单的查询sql为啥用时如此之久呢,我们先看这个sql可能存在的问题。

1. 索引缺失或不合理

  • 问题:该查询涉及两个字段条件(age > 18ORDER BY create_time),但很可能没有合适的复合索引

  • 影响

    • 如果没有age索引,会进行全表扫描

    • 即使有age索引,排序操作会导致"filesort"(磁盘临时文件排序)

2. 使用了SELECT *

  • 问题:查询所有字段,包括可能不需要的大字段(如TEXT/BLOB)

  • 影响:增加I/O负担和网络传输量

3. 范围查询+排序的组合

  • 问题age > 18是范围查询,与排序字段create_time无直接关联

  • 影响:MySQL难以同时利用两个条件的索引

4. 数据量过大

  • 问题:如果users表数据量很大(如百万级)

  • 影响:即使有索引,范围查询仍可能扫描大量数据

优化建议

方案1:创建合适的复合索引(推荐)

sql

ALTER TABLE users ADD INDEX idx_age_create_time (age, create_time DESC);

优点

  • 索引可以同时满足过滤和排序需求

  • 避免filesort操作

方案2:使用覆盖索引

sql

-- 修改查询语句只查询需要的列
SELECT id, name, age FROM users WHERE age > 18 ORDER BY create_time DESC;

-- 创建包含所有查询字段的索引
ALTER TABLE users ADD INDEX idx_age_create_time_cover (age, create_time DESC, id, name);

方案3:分页优化(适用于列表展示)

sql

SELECT * FROM users 
WHERE age > 18 
ORDER BY create_time DESC
LIMIT 20 OFFSET 0;  -- 添加分页限制

方案4:数据归档(长期优化)

sql

-- 将历史数据迁移到归档表
CREATE TABLE users_archive LIKE users;
INSERT INTO users_archive SELECT * FROM users WHERE create_time < '2020-01-01';
DELETE FROM users WHERE create_time < '2020-01-01';

一般的简单查询语句可以参考以上优化方式,遇到大段的sql需要优化时,最好先查看该sql的执行计划,先分析导致查询慢的具体原因,再去做对应优化,例如

用JOIN替代子查询

sql

-- 优化前
SELECT * FROM products 
WHERE category_id IN (SELECT id FROM categories WHERE type = 'electronics');

-- 优化后
SELECT p.* FROM products p 
JOIN categories c ON p.category_id = c.id 
WHERE c.type = 'electronics';

强制索引使用

sql

-- 强制使用特定索引
SELECT * FROM orders FORCE INDEX(idx_user_status) 
WHERE user_id = 100 AND status = 'paid';

 

使用临时表

sql

-- 创建临时表存储中间结果
CREATE TEMPORARY TABLE temp_products AS
SELECT * FROM products WHERE price > 1000;

-- 基于临时表查询
SELECT * FROM temp_products p 
JOIN inventory i ON p.id = i.product_id;

使用物化视图(MySQL 8.0+)

sql

-- 创建视图
CREATE VIEW expensive_products AS
SELECT * FROM products WHERE price > 1000;

-- 查询物化视图
SELECT * FROM expensive_products;

 上述优化建议需根据实际情况去使用,希望这篇文章可以帮助大家!

 

 

 

你可能感兴趣的:(mysql,数据库)