设为首页 收藏本站
查看: 587|回复: 0

[经验分享] MySQL数据库中对前端和后台进行系统优化

[复制链接]

尚未签到

发表于 2016-10-23 04:22:41 | 显示全部楼层 |阅读模式
  本文中介绍的系统优化,主要针对前端和后台这两方面(后台方面主要对SQL语句和数据存储进行了优化),下文中我们将介绍一些优化技巧和经验。
  技巧:
  1. 如何查出效率低的语句?
  在MySQL下,在启动参数中设置 --log-slow-queries=[文件名],就可以在指定的日志文件http://www.zoomino.cn/static-ox/images/blank.gif中记录执行时间超过long_query_time(缺省为10秒)的SQL语句。你也可以在启动配置文件中修改long query的时间,如:
  # Set long query time to 8 seconds
  long_query_time=8
  2. 如何查询某表的索引http://www.zoomino.cn/static-ox/images/blank.gif
  可使用SHOW INDEX语句,如:
  SHOW INDEX FROM [表名]
  3. 如何查询某条语句的索引使用情况?
  可用EXPLAIN语句来看一下某条SELECT语句的索引使用情况。如果是UPDATE或DELETE语句,需要先转换为SELECT语句。
  4. 如何把导出INNODB引擎的内容到错误日志http://www.zoomino.cn/static-ox/images/blank.gif文件中?
  我们可以使用SHOW INNODB STATUS命令来查看INNODB引擎的很多有用的信息,如当前进程、事务、外键错误、死锁http://www.zoomino.cn/static-ox/images/blank.gif问题和其它一些统计数据http://www.zoomino.cn/static-ox/images/blank.gif。如何让该信息能记录在日志文件中 呢?只要使用如下语句创建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表用于保存系统监测任务,相关字段http://www.zoomino.cn/static-ox/images/blank.gif及索引如下:
  ID:主键;
  MON_TIME:监测时间;建了索引;
  STATUS_ID:任务状态;与SYS_HIER_INFO.ID建立了外键http://www.zoomino.cn/static-ox/images/blank.gif关系。
  注MySQL自动会为外键建立索引,在本次优化http://www.zoomino.cn/static-ox/images/blank.gif过程中,发现这些自动建立的外键索引会对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表中存放很多天数据的话,那扫描的记录数会很多,速度较慢。可以有以下几个优化方案:
  如果一天http://www.zoomino.cn/static-ox/images/blank.gif的任务数不多的话,我们删除索引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)到多个数据库中,以分担负载,提高系统的整体性能与效率。

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-289885-1-1.html 上篇帖子: MySQL对字符集的支持及对乱码出现原因【转】 下篇帖子: java 连接 MySQL 、MS SQL server2000及MS SQL server2005数据库
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表