自从今年10月1日正式版上线以来,YMU
websiste monitoring系统的客户数量增加很快,最近系统速度有点慢了,赶紧做一下系统优化吧。主要从前端和后台这两方面做了优化,现在速度快多了,哈哈!
后台方面主要对SQL语句和数据存储进行了优化,感觉自己成了小半个DBA了,记录一下MySQL下SQL语句优化的一些技巧和经验。
一些小技巧
1. 如何查出效率低的语句?
在MySQL下,在启动参数中设置 --log-slow-queries=[文件名],就可以在指定的日志文件中记录执行时间超过long_query_time(缺省为10秒)的SQL语句。你也可以在启动配置文件中修改long query的时间,如:
# Set long query time to 8 seconds
long_query_time=8
2. 如何查询某表的索引?
可使用SHOW INDEX语句,如:
SHOW INDEX FROM [表名]
3. 如何查询某条语句的索引使用情况?
可用EXPLAIN语句来看一下某条SELECT语句的索引使用情况。如果是UPDATE或DELETE语句,需要先转换为SELECT语句。
4. 如何把导出INNODB引擎的内容到错误日志文件中?
我们可以使用SHOW INNODB STATUS命令来查看INNODB引擎的很多有用的信息,如当前进程、事务、外键错误、死锁问题和其它一些统计数据。如何让该信息能记录在日志文件中呢?只要使用如下语句创建innodb_monitor表,MySQL就会每15秒钟把该系统写入到错误日志文件中:
CREATE TABLE innodb_monitor (a INT) ENGINE=INNODB;
如果你不再需要导出到错误日志文件,只要删除该表即可:
DROP TABLE innodb_monitor;
5. 如何定期删除庞大的日志文件?
只要在启动配置文件中设置日志过期时间即可:
expire_logs_days=10
经验教训
1. 重点关注索引
下面以表TSK_TASK表为例说明SQL语句优化过程。TSK_TASK表用于保存系统监测任务,相关字段及索引如下:
- ID:主键;
- MON_TIME:监测时间;建了索引;
- STATUS_ID:任务状态;与SYS_HIER_INFO.ID建立了外键关系。
注MySQL自动会为外键建立索引,在本次优化过程中,发现这些自动建立的外键索引会对SQL语句的效率产生不必要的干扰,需要特别注意!
首先,我们在日志文件中查到下面语句的执行比较慢,超过10秒了:
# Query_time: 18 Lock_time: 0 Rows_sent: 295 Rows_examined: 88143
select * from TSK_TASK WHERE STATUS_ID = 1064 and MON_TIME >= '2007-11-22' and MON_TIME < '2007-11-23';
哦,原来在88143条记录中要查出符合条件的295条记录,那当然慢了。赶紧用EXPLAIN语句看一下索引使用情况吧:
+----+-------------+----------+------+----------------------------------------------------------+------------------------------------+---------+-------+--------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+----------+------+----------------------------------------------------------+------------------------------------+---------+-------+--------+-------------+
| 1 | SIMPLE | TSK_TASK | ref | FK_task_status_id_TO_SYS_HIER_INFO,TSK_TASK_KEY_MON_TIME | FK_task_status_id_TO_SYS_HIER_INFO | 9 | const | 276168 | Using where |
+----+-------------+----------+------+----------------------------------------------------------+------------------------------------+---------+-------+--------+-------------+
可以看出,有两个索引可用FK_task_status_id_TO_SYS_HIER_INFO,TSK_TASK_KEY_MON_TIME,而最终执行语句时采用了STATUS_ID上的外键索引。
再看一下TSK_TASK表的索引情况吧:
+----------+------------------------------------+-------------+-------------+
| Table | Key_name | Column_name | Cardinality |
+----------+------------+------------------------------------+--------------+
| TSK_TASK | PRIMARY | ID | 999149 |
| TSK_TASK | FK_task_status_id_TO_SYS_HIER_INFO | STATUS_ID | 16 |
| TSK_TASK | TSK_TASK_KEY_MON_TIME | MON_TIME | 13502 |
+----------+------------------------------------+-------------+-----------+--
在Oracle或其他关系数据库下,WHERE条件中的字段顺序对索引的选择起着很重要的作用。我们调整一下字段顺序,把STATUS_ID放在后面,再EXPLAIN一下:
EXPLAIN select * from TSK_TASK WHERE MON_TIME >= '2007-11-22' and MON_TIME < '2007-11-23' and STATUS_ID = 1064;
但是没什么效果,MySQL还是选用系统建立的STATUS_ID外键索引。
仔细分析一下,看来Cardinality属性(即索引中的唯一值的个数)对索引的选择起了极其重要的作用,MySQL选择了索引值唯一值个数小的那个索引作为整条语句的索引。
针对这条语句,如果使用FK_task_status_id_TO_SYS_HIER_INFO做索引,而TSK_TASK表中存放很多天数据的话,那扫描的记录数会很多,速度较慢。可以有以下几个优化方案:
- 如果一天的任务数不多的话,我们删除索引FK_task_status_id_TO_SYS_HIER_INFO,那MySQL会使用索引TSK_TASK_KEY_MON_TIME,然后在该天的数据中在扫描STATUS_ID为1064的记录,那速度也不慢;
- 如果一天的任务数多的话,我们需删除索引FK_task_status_id_TO_SYS_HIER_INFO和TSK_TASK_KEY_MON_TIME,然后再建立STATUS_ID,MON_TIME的联合索引,这样效率肯定会很高。
因此建议,对那些记录数多的表,建议不要使用外键,以避免造成性能效率的严重降低。
2. 尽量控制每张表的记录数
当一张表的记录数很大时,管理和维护就会很麻烦,如索引维护就会占用很长时间,从而会给系统的正常运行造成很大的干扰。
对随时间推移数据量不断增长的表,我们可以根据时间来区分实时数据和历史数据,可以使用后台服务程序定期移动实时表中的数据到历史表中,从而控制实时表的记录数,提高查询和操作效率。但注意每次移动的时间要足够短,不要影响正常程序的数据写入。如果占用时间太长,可能会造成死锁问题。
3. 数据散列(partition)策略
当客户数达到一定规模后,单个数据库将无法支撑更高的并发访问,此时可以考虑把客户数据散列(partition)到多个数据库中,以分担负载,提高系统的整体性能与效率。
数据散列可以考虑采用federeated或sharded方式,网上有不少这方面的资料。
YMU目前正在考虑做数据散列,等以后有实际经验后,再写文章介绍吧。
分享到:
相关推荐
最优化的SQL语句能够在最小的资源消耗下,完成特定的数据库操作,并且保证响应速度和数据处理效率。 2. MySQL数据库简介:MySQL是一个开放源代码的关系型数据库管理系统,广泛应用于Web应用中。它使用结构化查询...
本项目提供了一个Java源码工具,能够帮助用户便捷地将Oracle SQL语句转换为MySQL SQL语句。 Oracle SQL与MySQL SQL的主要差异在于以下几个方面: 1. **数据类型**:Oracle支持的数据类型如NUMBER、LONG、RAW等在...
《Effective MySQL之SQL语句最优化》提供了很多可以用于改进数据库和应用程序性能的最佳实践技巧,并对这些技巧做了详细的解释。《Effective MySQL之SQL语句最优化》希望能够通过一步步详细介绍SQL优化的方法,帮助...
### MySQL优化之SQL语句与索引优化 #### 数据库设计合理性 在MySQL数据库的优化过程中,合理设计数据库(表)至关重要。一个合理的数据库设计能够有效地提高查询性能、减少数据冗余并确保数据完整性。 - **3NF**...
执行计划可以帮助我们了解SQL语句的执行过程,从而对其进行优化。执行计划可以通过EXPLAIN语句来查看。 二、SELECT语句优化 SELECT语句是MySQL数据库中最常用的语句之一。SELECT语句的优化是非常重要的。通过优化...
《Effective MySQL之SQL语句最优化》是一本深入探讨如何提升数据库性能的专业手册,它针对SQL语句的优化提供了一系列实用且高效的策略。在数据库管理领域,SQL优化是提升系统性能的关键环节,尤其是在处理大数据量时...
《Effective MySQL之SQL语句最优化》是一本深入探讨如何提升数据库性能,特别是针对SQL查询进行优化的专业书籍。在数据库管理中,SQL语句的优化是至关重要的,它直接影响到系统的响应速度和整体效率。本篇文章将依据...
下面是MySQL中一些常用的SQL语句: 创建、删除和基本查询 * 显示数据库:`show databases;` * 创建数据库:`create database db;` * 删除数据库:`drop database db;` * 选择数据库:`use db;` 创建和删除表 * ...
"Effective MySQL之SQL语句最优化"这本书深入探讨了如何通过优化SQL查询来提高MySQL数据库的效率。以下是基于这个主题的一些关键知识点: 1. **索引优化**:索引是数据库性能提升的核心。书中的内容可能涵盖如何...
浅谈 MySQL 中优化 SQL 语句查询常用的 30 种方法 MySQL 是一种广泛使用的关系数据库管理系统,优化 SQL 语句查询是提高数据库性能的关键。下面是浅谈 MySQL 中优化 SQL 语句查询常用的 30 种方法: 一、避免全表...
32丨MySQL调优之SQL语句:如何写出高性能SQL语句?.html
在不同的数据库系统中,如MySQL、Oracle、SQL Server等,都有相应的命令或工具用于查看SQL语句的执行计划,例如SQL Server的`SET SHOWPLAN_ALL`或`SET SHOWPLAN_TEXT`,Oracle的`EXPLAIN PLAN`。 4. **执行计划的...
Python 使用 SQL 语句对 MySQL 数据库多条件模糊查询 Python 是一种广泛使用的编程语言,而 MySQL 是一种常用的关系型数据库管理系统。在实际应用中,我们经常需要使用 Python 连接 MySQL 数据库,并执行多条件...
2. 转换规则应用:根据SQL Server的语法特性,工具会将MySQL的SQL语句转化为相应的SQL Server语法。 3. 数据导出:将MySQL中的数据导出为SQL脚本,或者直接导入到SQL Server中。 4. 验证与调整:迁移后,需要验证...
标题 "PB 从SQL语句获取数据存储(MySQL)" 指的是使用PowerBuilder (PB) 开发工具,通过SQL语句从MySQL数据库中检索和处理数据存储的过程。在这个Demo中,PB11.5 版本被用作开发环境,而MySQL作为后台数据库系统。...
"7天带你玩转Mysql数据库之SQL语句"的学习资料旨在帮助初学者快速掌握MySQL的基础知识,并通过LeetCode的面试题来提升实战技能。本文将深入探讨MySQL中的SQL语句及其在实际操作中的应用。 SQL(Structured Query ...
sql语句优化.chmmssql优化 mysql优化 oracle优化
本文档是有关于MySQL的最常用的sql语句,非常的方便查询和复习
《EffectiveMySQL之SQL语句最优化》提供了很多可以用于改进数据库和应用程序性能的最佳实践技巧,并对这些技巧做了详细的解释。《EffectiveMySQL之SQL语句最优化》希望能够通过一步步详细介绍SQL优化的方法,帮助...