Mysql篇(三):SQL优化经验全方位解析

MySQL篇(三):SQL优化经验全方位解析

一、SQL查询优化经验

(一)合理使用查询条件

  1. 避免select *
    实际开发中,SELECT *会增加数据传输与解析开销。
    • 反例
      -- 获取用户信息时返回所有字段,包含冗余数据  
      SELECT * FROM users;  
      
    • 正例
      -- 只查询必要字段,减少数据量  
      SELECT user_id, user_name, email FROM users;  
      
  2. 优化where条件
    • 使用合适的比较操作符:根据需求选择精准操作符,如查询年龄大于30的用户:
      SELECT * FROM users WHERE age > 30;  
      
    • 避免函数操作在查询条件字段上:对字段使用函数会导致索引失效,可用范围查询替代:
      -- 反例:对字段使用函数,索引失效  
      SELECT * FROM orders WHERE YEAR(order_date) = 2024;  
      -- 正例:通过范围查询替代  
      SELECT * FROM orders WHERE order_date >= '2024-01-01' AND order_date < '2025-01-01';  
      

(二)JOIN操作优化

  1. 选择合适的JOIN类型
    • 明确JOIN目的INNER JOIN用于获取匹配记录,LEFT JOIN保留左表所有记录。
      -- INNER JOIN:获取有订单的用户  
      SELECT u.user_name, o.order_id  
      FROM users u  
      INNER JOIN orders o ON u.user_id = o.user_id;  
      -- LEFT JOIN:获取所有用户及其订单(包括无订单用户)  
      SELECT u.user_name, o.order_id  
      FROM users u  
      LEFT JOIN orders o ON u.user_id = o.user_id;  
      
    • 避免不必要的JOIN:减少JOIN表数量,降低关联复杂度。
  2. 确保JOIN字段有索引
    对JOIN关联字段创建索引,提升效率:
    -- 为orders表的user_id创建索引  
    CREATE INDEX idx_orders_user_id ON orders (user_id);  
    

(三)子查询与连接查询的选择

  1. 评估子查询和连接查询的性能
    • 子查询适用场景:逻辑清晰,适合简单查询。
      -- 子查询:获取订单金额高于平均金额的订单  
      SELECT * FROM orders  
      WHERE order_amount > (SELECT AVG(order_amount) FROM orders);  
      
    • 连接查询适用场景:多表关联且数据量大时性能更优。
      -- 连接查询:获取用户及其订单总金额  
      SELECT u.user_name, SUM(o.order_amount) AS total_amount  
      FROM users u  
      LEFT JOIN orders o ON u.user_id = o.user_id  
      GROUP BY u.user_id;  
      

二、创建表时的优化策略

(一)字段设计优化

  1. 选择合适的数据类型
    • 数值类型:根据数据范围选择,如用户年龄用TINYINT
      CREATE TABLE users (  
          user_id INT PRIMARY KEY,  
          age TINYINT  
      );  
      
    • 字符串类型VARCHAR用于长度不确定的字符串,CHAR用于固定长度(如MD5值):
      CREATE TABLE user_credentials (  
          md5_hash CHAR(32)  
      );  
      
  2. 避免可为空的字段
    设置字段为NOT NULL,提升处理效率:
    -- 反例:email字段允许为空,增加复杂度  
    CREATE TABLE users (  
        email VARCHAR(100)  
    );  
    -- 正例:设置email为NOT NULL  
    CREATE TABLE users (  
        email VARCHAR(100) NOT NULL  
    );  
    

(二)存储引擎选择

  1. InnoDB引擎
    • 适用场景:支持事务、外键,适合OLTP场景(如电商订单系统):
      CREATE TABLE orders (  
          order_id INT PRIMARY KEY,  
          user_id INT,  
          FOREIGN KEY (user_id) REFERENCES users(user_id)  
      ) ENGINE = InnoDB;  
      
    • 优势:数据安全高,支持行级锁,并发性能好。
  2. MyISAM引擎
    • 适用场景:读多写少,对事务要求不高(如日志记录):
      CREATE TABLE access_logs (  
          log_id INT PRIMARY KEY,  
          access_time DATETIME  
      ) ENGINE = MyISAM;  
      
    • 优势:查询性能高,存储结构简单。

(三)表结构规范化与反规范化

  1. 规范化表结构
    • 减少数据冗余:遵循范式设计,如用户表与订单表分离:
      -- 用户表  
      CREATE TABLE users (  
          user_id INT PRIMARY KEY,  
          user_name VARCHAR(50),  
          email VARCHAR(100)  
      );  
      -- 订单表  
      CREATE TABLE orders (  
          order_id INT PRIMARY KEY,  
          user_id INT,  
          FOREIGN KEY (user_id) REFERENCES users(user_id)  
      );  
      
    • 优点:数据一致性高,易于维护。
  2. 反规范化处理
    • 提升查询性能:适当增加冗余字段减少JOIN。如订单表添加用户姓名:
      CREATE TABLE orders (  
          order_id INT PRIMARY KEY,  
          user_id INT,  
          user_name VARCHAR(50), -- 冗余字段  
          FOREIGN KEY (user_id) REFERENCES users(user_id)  
      );  
      
    • 适用场景:读多写少,对查询性能要求高的场景。

三、索引使用优化经验

(一)索引创建原则

  1. 基于查询频率创建
    WHEREORDER BYGROUP BY字段创建索引:
    -- 为查询条件age字段创建索引  
    CREATE INDEX idx_age ON users (age);  
    -- 为排序字段order_date创建索引  
    CREATE INDEX idx_order_date ON orders (order_date);  
    
  2. 组合索引的创建
    遵循最左匹配原则,如查询WHERE country = 'China' AND city = 'Beijing'
    CREATE INDEX idx_country_city ON addresses (country, city);  
    

(二)索引优化策略

  1. 避免过多索引
    过多索引影响写性能,定期评估并删除冗余索引:
    -- 删除冗余索引  
    DROP INDEX idx_useless ON table_name;  
    
  2. 使用覆盖索引
    确保索引包含查询字段,避免回表:
    -- 创建覆盖索引  
    CREATE INDEX idx_user_id_name ON users (user_id, user_name);  
    -- 查询语句(无需回表)  
    SELECT user_id, user_name FROM users WHERE age > 30;  
    

四、日常SQL语句优化实践

(一)使用执行计划分析

  1. EXPLAIN关键字
    通过EXPLAIN分析执行计划,查看索引使用:
    EXPLAIN SELECT * FROM users WHERE age > 30;  
    
    • 关键列分析
      • type:连接类型,consteq_ref为优,indexALL需优化。
      • key:显示使用的索引。
      • rows:预估扫描行数,越小越好。

(二)慢查询优化

  1. 慢查询日志分析
    开启慢查询日志(配置my.cnf):
    [mysqld]  
    slow_query_log = 1  
    slow_query_log_file = /var/log/mysql/mysql-slow.log  
    long_query_time = 2  
    
    使用mysqldumpslowpt-query-digest分析日志,优化慢查询。
  2. 重构复杂SQL
    将复杂SQL分解为子查询或临时表:
    -- 复杂查询  
    SELECT * FROM a  
    JOIN b ON a.id = b.a_id  
    JOIN c ON b.id = c.b_id;  
    -- 优化:使用临时表  
    CREATE TEMPORARY TABLE temp_b AS  
    SELECT * FROM b;  
    CREATE TEMPORARY TABLE temp_c AS  
    SELECT * FROM c;  
    SELECT * FROM a  
    JOIN temp_b ON a.id = temp_b.a_id  
    JOIN temp_c ON temp_b.id = temp_c.b_id;  
    

(三)事务优化

  1. 控制事务范围
    减少事务内操作,缩短持续时间:
    -- 反例:事务包含大量操作  
    START TRANSACTION;  
    -- 多个查询和更新  
    COMMIT;  
    -- 正例:精简事务内容  
    START TRANSACTION;  
    -- 必要更新  
    COMMIT;  
    
  2. 合理使用事务隔离级别
    根据业务选隔离级别,如读已提交(READ COMMITTED):
    SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;  
    START TRANSACTION;  
    -- 事务操作  
    COMMIT;  
    

通过SQL编写、建表设计、索引使用到日常维护的优化,可全面提升数据库性能。实际项目中需结合业务场景,灵活运用优化策略,不断调试以达最佳效果。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值