当前位置: 首页 > news >正文

九【Python新手入门指南】极速搭建Python开发环境s

SQL 优化是数据库性能调优的核心环节。合理的 SQL 优化可以显著提升数据库性能,减少资源消耗。

1、查询性能分析

1.1 识别慢查询

-- 开启慢查询日志

SET GLOBAL slow_query_log = 'ON';

SET GLOBAL long_query_time = 2; -- 超过2秒的查询

SET GLOBAL slow_query_log_file = '/var/log/mysql/slow.log';

-- 查看慢查询

SHOW VARIABLES LIKE 'slow_query%';

SHOW VARIABLES LIKE 'long_query_time';

-- 使用性能模式监控

SELECT * FROM performance_schema.events_statements_summary_by_digest

ORDER BY SUM_TIMER_WAIT DESC LIMIT 10;

1.2 使用 EXPLAIN 分析查询

-- 基本分析

EXPLAIN SELECT * FROM users WHERE age > 30;

-- 详细分析(MySQL 8.0+)

EXPLAIN ANALYZE SELECT * FROM users WHERE age > 30;

-- JSON格式输出

EXPLAIN FORMAT=JSON SELECT * FROM users WHERE age > 30;

1.3 解读 EXPLAIN 结果

关键字段解读:

type:访问类型,从好到坏:system > const > eq_ref > ref > range > index > ALL

key:实际使用的索引

rows:预估扫描行数

Extra:额外信息

Using index:覆盖索引

Using where:使用 WHERE 过滤

Using temporary:使用临时表

Using filesort:使用文件排序

2、索引优化策略

2.1 选择合适的索引列

-- 为高频查询条件创建索引

CREATE INDEX idx_user_status ON orders(user_id, status);

-- 为排序和分组字段创建索引

CREATE INDEX idx_created_at ON orders(created_at);

-- 使用覆盖索引

CREATE INDEX idx_covering ON users(name, age, email);

2.2 避免索引失效

-- 1. 避免在索引列上使用函数

-- 错误:SELECT * FROM users WHERE YEAR(created_at) = 2023;

-- 正确:SELECT * FROM users WHERE created_at >= '2023-01-01' AND created_at < '2024-01-01';

-- 2. 避免 LIKE 以通配符开头

-- 错误:SELECT * FROM users WHERE name LIKE '%John%';

-- 正确:SELECT * FROM users WHERE name LIKE 'John%';

-- 3. 避免对索引列进行运算

-- 错误:SELECT * FROM users WHERE age + 1 > 30;

-- 正确:SELECT * FROM users WHERE age > 29;

-- 4. 注意 OR 条件的使用

-- 错误:SELECT * FROM users WHERE name = 'John' OR age = 30;

-- 正确:SELECT * FROM users WHERE name = 'John'

-- UNION

-- SELECT * FROM users WHERE age = 30;

2.3 索引优化技巧

-- 使用前缀索引

SELECT

COUNT(DISTINCT LEFT(name, 5)) / COUNT(*) AS selectivity_5,

COUNT(DISTINCT LEFT(name, 10)) / COUNT(*) AS selectivity_10

FROM users;

CREATE INDEX idx_name_prefix ON users(name(10));

-- 使用索引合并

SET SESSION optimizer_switch = 'index_merge=on';

3、查询语句优化

3.1 SELECT 优化

-- 只选择需要的列

-- 错误:SELECT * FROM users;

-- 正确:SELECT id, name, email FROM users;

-- 使用 LIMIT 限制结果集

SELECT * FROM users ORDER BY created_at DESC LIMIT 10;

-- 避免 SELECT DISTINCT 滥用

-- 错误:SELECT DISTINCT * FROM users;

-- 正确:SELECT DISTINCT department_id FROM users;

3.2 WHERE 优化

3.2.1 基础

-- 使用等值查询优先

SELECT * FROM users WHERE id = 100;

-- 避免使用 != 或 <>

SELECT * FROM users WHERE status IN ('active', 'inactive');

-- 使用 BETWEEN 代替范围查询

SELECT * FROM orders WHERE amount BETWEEN 100 AND 500;

3.2.2 避免索引失效的写法

失效场景 错误示例 优化示例

函数操作索引字段 WHERE YEAR(created_at) = 2024 WHERE created_at BETWEEN '2024-01-01' AND '2024-12-31'

隐式类型转换 WHERE phone = 13800138000 WHERE phone = '13800138000'

模糊查询以%开头 WHERE username LIKE '%张三%' WHERE username LIKE '张三%'

使用OR连接非索引字段 WHERE id = 1 OR age = 20 拆分查询或为age建索引

3.2.3 优化范围查询

范围条件(>, <, BETWEEN)右侧的字段无法使用索引,复合索引中应将范围字段放右侧。

-- 复合索引 (user_id, created_at)

-- 有效:范围条件在右侧

SELECT * FROM `order` WHERE user_id = 100 AND created_at > '2024-01-01';

-- 低效:范围条件在左侧,右侧字段无法使用索引

SELECT * FROM `order` WHERE created_at > '2024-01-01' AND user_id = 100;

3.3 JOIN 优化

确保连接字段建立索引(尤其是外键字段)。

小表驱动大表(左表数据量应小于右表,减少匹配次数)。

避免JOIN过多表(建议不超过 5 张表)。

优化前:

-- 无索引,多表连接效率低

SELECT * FROM `order` o

JOIN `user` u ON o.user_id = u.id

JOIN `order_item` oi ON o.id = oi.order_id;

优化后:

-- 为连接字段建索引

ALTER TABLE `order` ADD INDEX `idx_user_id` (`user_id`);

ALTER TABLE `order_item` ADD INDEX `idx_order_id` (`order_id`);

-- 只查询必要字段

SELECT o.order_no, u.username, oi.product_id

FROM `order` o

JOIN `user` u ON o.user_id = u.id

JOIN `order_item` oi ON o.id = oi.order_id;

3.4 GROUP BY 和 ORDER BY 优化

ORDER BY和GROUP BY的字段应包含在索引中,避免额外排序(Using filesort)。

复合索引中,排序字段需按同一方向(全升序或全降序)

优化前:

-- 无索引,产生Using filesort

SELECT * FROM `order` WHERE user_id = 100 ORDER BY created_at;

优化后:

-- 创建包含排序字段的复合索引

ALTER TABLE `order` ADD INDEX `idx_user_created` (`user_id`, `created_at`);

-- 索引覆盖排序,无filesort

SELECT id, order_no FROM `order` WHERE user_id = 100 ORDER BY created_at;

3.5 子查询优化

-- 使用 JOIN 代替子查询

-- 错误:SELECT * FROM users WHERE id IN (SELECT user_id FROM orders);

-- 正确:SELECT u.* FROM users u JOIN orders o ON u.id = o.user_id;

-- 使用 EXISTS 代替 IN

SELECT * FROM users u

WHERE EXISTS (SELECT 1 FROM orders o WHERE o.user_id = u.id);

-- 将子查询转换为连接

SELECT u.*, o.order_count

FROM users u

JOIN (SELECT user_id, COUNT(*) as order_count FROM orders GROUP BY user_id) o

ON u.id = o.user_id;

4、表结构优化

4.1 选择合适的数据类型

优先使用小字段类型(如INT代替BIGINT,VARCHAR(20)代替VARCHAR(255))。

时间用DATETIME(需时区转换)或TIMESTAMP(自动时区转换,范围小)。

枚举类型用ENUM(如状态字段:ENUM('active', 'inactive'))。

优化前:

CREATE TABLE `user` (

`id` BIGINT PRIMARY KEY, -- 无需大整数

`status` VARCHAR(20), -- 状态值有限,可用ENUM

`create_time` VARCHAR(50) -- 应用层转换,效率低

);

优化后:

CREATE TABLE `user` (

`id` INT UNSIGNED PRIMARY KEY AUTO_INCREMENT,

`status` ENUM('active', 'inactive') NOT NULL DEFAULT 'active',

`create_time` DATETIME DEFAULT CURRENT_TIMESTAMP

);

4.2 分表分库

当单表数据量超过 1000 万行时,需考虑拆分:

水平分表:按行拆分(如按用户 ID 哈希、按时间范围)。

垂直分表:按列拆分(如将大文本字段拆分到独立表)。

示例:按时间水平分表

-- 订单表按年份拆分

CREATE TABLE `order_2023` (LIKE `order` INCLUDING ALL);

CREATE TABLE `order_2024` (LIKE `order` INCLUDING ALL);

4.3 分区表优化

-- 按范围分区

CREATE TABLE sales (

id INT AUTO_INCREMENT,

sale_date DATE,

amount DECIMAL(10,2),

PRIMARY KEY (id, sale_date)

) PARTITION BY RANGE (YEAR(sale_date)) (

PARTITION p2020 VALUES LESS THAN (2021),

PARTITION p2021 VALUES LESS THAN (2022),

PARTITION p2022 VALUES LESS THAN (2023),

PARTITION p2023 VALUES LESS THAN (2024)

);

-- 按列表分区

CREATE TABLE users (

id INT AUTO_INCREMENT,

region VARCHAR(20),

name VARCHAR(100),

PRIMARY KEY (id, region)

) PARTITION BY LIST COLUMNS(region) (

PARTITION p_north VALUES IN ('Beijing', 'Tianjin'),

PARTITION p_south VALUES IN ('Guangzhou', 'Shenzhen'),

PARTITION p_west VALUES IN ('Chengdu', 'Chongqing')

);

5、服务器参数

通过调整 MySQL 配置文件(my.cnf或my.ini)提升性能

[mysqld]

# 缓存相关

innodb_buffer_pool_size = 4G # InnoDB缓存池(建议物理内存的50%-70%)

query_cache_size = 0 # 禁用查询缓存(MySQL 8.0已移除)

# 连接相关

max_connections = 1000 # 最大连接数

wait_timeout = 600 # 连接超时时间(10分钟)

# 日志相关

slow_query_log = 1 # 开启慢查询日志

long_query_time = 1 # 慢查询阈值(1秒)

slow_query_log_file = /var/log/mysql/slow.log

# InnoDB优化

innodb_flush_log_at_trx_commit = 1 # 事务提交时同步日志(安全性优先)

innodb_flush_method = O_DIRECT # 绕过OS缓存,直接写磁盘

http://www.dtcms.com/a/453720.html

相关文章:

  • 四川成都企业高端网站建设一站式的手机网站制作
  • 【LeetCode热题100(36/100)】二叉树的中序遍历
  • 企业建立网站的必要性画网页前端界面的软件
  • Docker 基础命令的 6 大核心模块
  • 十大购物网站产品50个关键词
  • Kiln AI:重新定义AI系统构建的全栈开源平台深度解析
  • 测试epoll、io_uring的百万连接、建连、qps,以及qps客户端的实现
  • 做游戏女角色去衣的网站网站名 注册
  • Rust中所有权和作用域及生命周期
  • 外贸网站啥需要掌握在自己手里中企动力手机邮政登录
  • 二维码制作网站有哪些618网络营销策划方案
  • 【论文学习】2025年图像处理顶会论文
  • 【MyBatis】——执行过程
  • 修改配置文件之后,重启edge浏览器收藏夹消失怎么办?
  • 网站推广优化外包公司个人网站设计开题报告
  • 组播实验-IGMP、IGMP Snooping及PIM-DM协议
  • 企业seo网站推广公司wordpress 下载受限
  • 第十二篇:std::shared_ptr和std::weak_ptr:共享所有权与解决循环引用
  • 第十九章:千变万化,随心而动——State的状态艺术
  • Harmony中EventHub实现发布订阅
  • 高效学习方法——知识关联性
  • 教育类网站素材总部在上海的世界500强企业
  • CCF编程能力等级认证GESP—C++6级—20250927
  • libopenssl-1_0_0-devel-1.0.2p RPM 包安装教程(openSUSE/SLES x86_64)​
  • 网站开发栏目需求1仪征网站建设公司哪家好
  • FK 外键上需要创建index 避免 主表update时 的lock
  • 三剑合璧:C++11 lambda、variadic template 与 wrapper 的协奏
  • 空间智能找文献方向
  • 儒枫网网站建设惠州 企业网站建设
  • 基于 GEE 平台用 Sentinel-1 SAR 数据实现山区潜在滑坡检测