- 1 MySQL 简介
- MySQL 版本和产品线说明
- MySQL 安装
- 2 MySQL 基础教程
- 2.1 SQL 语法:SELECT/INSERT/UPDATE/DELETE
- 2.2 MySQL 列类型
- 2.3 使用用户变量
- 2.4 MySQL 的日期和时间管理
- 2.5 集合运算
- 3 MySQL 高级教程
- 3.1 触发器
- 3.2 视图
- 3.3 复制 Replication~主从库配置
- 3.4 分区存储
- 本章参考
- 4 MySQL 优化
- 4.1 优化数据库结构
- 4.2 优化 SQL 语句
- 4.3 优化索引
- 4.4 优化数据库服务器 mysql_serverd
- 4.5 修改配置文件 my.cnf/my.ini
- 5 MySQL 管理
- 5.1 MySQL 管理常用命令
- 5.2 MySQL 权限管理
- 5.3 MySQL 备份和恢复
- 5.4 MySQL 数据库安全
- 常见问题 FAQ
- 使用的常见问题
- MySQL 字符集乱码
- MySQL 存储二进制图片
- 参考资料
4.2 优化 SQL 语句
4.2.1 SQL 语句速度比较
SQL 语句 | 独特影响因素 | 改进关键 |
---|---|---|
INSERT | 插入记录+插入索引 | 批量插入,50 万记录 5000~1000 次批量最佳 |
UPDATE | 更新记录+更新索引 | |
DELETE | 删除记录+删除索引 | |
SELECT | 查询 | 批量获取,1000~5000 次最佳。建立有效索引。 |
注:一个 SQL 查询的基本流程:
连接+发送 SQL+分析 SQL+执行 SQL 插入+返回结果+关闭。连接和发送的时间是相对最长的,所以数据库操作中连接池是个有效优化手段。
INSERT 语句的速度
插入一个记录需要的时间由下列因素组成,其中的数字表示大约比例:
- 连接:(3)
- 发送查询给服务器:(2)
- 分析查询:(2)
- 插入记录:(1x 记录大小)
- 插入索引:(1x 索引)
- 关闭:(1)
这不考虑打开表的初始开销,每个并发运行的查询打开。
表的大小以 logN (B 树) 的速度减慢索引的插入。
UPDATE 语句的速度
更新查询的优化同 SELECT 查询一样,需要额外的写开销。写速度依赖于更新的数据大小和更新的索引的数量。没有更改的索引不被更新。
使更改更快的另一个方法是推迟更改然后在一行内进行多次更新。如果锁定表,同时做多个更新比一次做一个快得多。
请注意对使用动态记录格式的 MyISAM 表,更新一个较长总长的记录可能会切分记录。如果经常这样该,偶尔使用 OPTIMIZE TABLE 很重要。参见 13.5.2.5 节,OPTIMIZE TABLE 语法 。
DELETE 语句的速度
删除一个记录的时间与索引数量确切成正比。为了更快速地删除记录,可以增加键高速缓冲的大小
SELECT 语句
参考:索引
总的来说,要想使一个较慢速 SELECT ... WHERE
更快,应首先检查是否能增加一个索引。不同表之间的引用通常通过索引来完成。你可以使用 EXPLAIN
语句来确定 SELECT
语句使用哪些索引。
4.2.2 优化 WHERE
在 MySQL 中,优化 WHERE
子句是提高查询性能的关键。以下是一些优化建议,可以帮助你更有效地编写 WHERE
子句。
1. 使用索引
- 创建索引 :确保在
WHERE
子句中使用的列上有索引。对于经常用于过滤的列,尤其是大表,创建索引可以显著提高查询速度。CREATE INDEX idx_column ON your_table(column_name);
- 复合索引 :如果
WHERE
子句涉及多个列,可以考虑创建复合索引。例如:CREATE INDEX idx_multiple ON your_table(col1, col2);
2. 避免使用函数
在 WHERE
子句中使用函数会导致索引失效。例如,避免使用 WHERE DATE(column) = '2023-01-01'
,而应使用 WHERE column >= '2023-01-01' AND column < '2023-01-02'
。
3. 使用合适的数据类型
确保 WHERE
子句中的数据类型匹配。例如,如果列是 INT
类型,不要用字符串进行比较:
WHERE id = '123' -- 不推荐
WHERE id = 123 -- 推荐
4. 使用 EXPLAIN
分析查询
使用 EXPLAIN
命令来分析查询性能,并查看索引是否被使用:
EXPLAIN SELECT * FROM your_table WHERE column_name = 'value';
5. 简化条件
- 使用简单的条件 :尽量避免复杂的条件,例如嵌套的子查询和过多的 OR 条件。可以使用 UNION 或简单的逻辑运算符来重构查询。
- 避免使用
!=
和<>
:这些操作符通常会导致全表扫描,尽量使用其他条件。
6. 使用 EXISTS 替代 IN
在某些情况下,使用 EXISTS
代替 IN
可以提高性能,特别是当子查询返回大量结果时。
-- IN
SELECT * FROM table1 WHERE column1 IN (SELECT column2 FROM table2);
-- EXISTS
SELECT * FROM table1 WHERE EXISTS (SELECT 1 FROM table2 WHERE table1.column1 = table2.column2);
7. 限制返回结果
尽量使用 LIMIT
来限制查询返回的行数,这样可以减少数据库负担。
SELECT * FROM your_table WHERE condition LIMIT 10;
8. 使用 JOIN 代替子查询
在某些情况下,使用 JOIN
代替子查询可以提高性能:
-- 子查询
SELECT * FROM table1 WHERE column IN (SELECT column FROM table2);
-- JOIN
SELECT t1.* FROM table1 t1 JOIN table2 t2 ON t1.column = t2.column;
9. 确保统计信息更新
确保表的统计信息是最新的,以便优化器能够做出更好的决策。可以使用 ANALYZE TABLE
命令更新统计信息。
ANALYZE TABLE your_table;
10. 分区表
对于非常大的表,可以考虑使用分区表,以提高查询性能。
通过这些优化策略,你可以提高 MySQL 查询中 WHERE
子句的性能,从而加快数据检索速度。
4.2.3 优化 ORDER BY 和 GROUP BY
ORDER BY
在某些情况中,MySQL 可以使用一个索引来满足 ORDER BY 子句,而不需要额外的排序。
即使 ORDER BY 不确切匹配索引,只要 WHERE 子句中的所有未使用的索引部分和所有额外的 ORDER BY 列为常数,就可以使用索引。
GROUP BY
满足 GROUP BY 子句的最一般的方法是扫描整个表并创建一个新的临时表,表中每个组的所有行应为连续的,然后使用该临时表来找到组并应用累积函数(如果有)。在某些情况中,MySQL 能够做得更好,通过索引访问而不用创建临时表。
为 GROUP BY 使用索引的最重要的前提条件是 所有 GROUP BY 列引用同一索引的属性,并且索引按顺序保存其关键字(例如,这是 B-树索引,而不是 HASH 索引)。是否用索引访问来代替临时表的使用还取决于在查询 中使用了哪部分索引、为该部分指定的条件,以及选择的累积函数。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论