Mysql cpu 100% 服务接口性能定位 (二)
Mysql 服务器 CPU 接近100%后; 一般由于计算过多导致CPU负荷计算,使其达到100%;
通过记录的慢sql分析后,发现几条sql语句出现的特别平凡;肯定是当中的sql没有用到数据库对应的索引导致;分析之后发现以下sql
# Query_time: 2.752636 Lock_time: 0.000074 Rows_sent: 0 Rows_examined: 56473
SET timestamp=1447741352;
SELECT ORDER_NO, SCENIC_ID, SCENIC_NAME,SERVICE_OP_ID,SERVICE_OP_NAME, CHANNEL_TYPE_CODE, CHANNEL_SALE_TYPE_CODE,
CHANNEL_ID, CHANNEL_NAME, REF_ORDER_NO, CUSTOMER_ID, PLACE_USER_NAME, PLACE_USER_MOBILE_NO,
ACCEPT_VOUCHER_MOBILE_NO, STATUS, ORDER_TYPE, PAY_TYPE, QUANTITY,
SALE_AMOUNT, SETTLER_AMOUNT, PAY_MODULE, PAY_STATUS, PAY_TIME, TO_PAY_VALIDATE_CODE,
IS_INVOICE, ID_CARD_NUMBER, PLACE_TIME, ORDER_OVER_TIME, LAST_UPDATE_TIME, REMARK, BUSSINESS_MODEL
FROM S0113_S_COMMON_ORDER
WHERE CHANNEL_ID = 10017
AND REF_ORDER_NO = 'O204113120313';
检查对应的 Order 表中的 refOrderNo没有对应的索引
SELECT ORDER_NO, SCENIC_ID, SCENIC_NAME,SERVICE_OP_ID,SERVICE_OP_NAME, CHANNEL_TYPE_CODE, CHANNEL_SALE_TYPE_CODE,
CHANNEL_ID, CHANNEL_NAME, REF_ORDER_NO, CUSTOMER_ID, PLACE_USER_NAME, PLACE_USER_MOBILE_NO,
ACCEPT_VOUCHER_MOBILE_NO, STATUS, ORDER_TYPE, PAY_TYPE, QUANTITY,
SALE_AMOUNT, SETTLER_AMOUNT, PAY_MODULE, PAY_STATUS, PAY_TIME, TO_PAY_VALIDATE_CODE,
IS_INVOICE, ID_CARD_NUMBER, PLACE_TIME, ORDER_OVER_TIME, LAST_UPDATE_TIME, REMARK, BUSSINESS_MODEL
FROM S0113_S_COMMON_ORDER
WHERE CHANNEL_ID = 10017
AND REF_ORDER_NO = 'O204113110312';
voucher凭证表中的orderNo没有对应的索引;
SELECT COALESCE(SUM(MAX_USE_NUMBER-USED_NUMBER-INVALID_NUMBER), 0)
FROM S0113_S_COMMON_VOUCHER WHERE GOODS_ID = 10036;
这条sql语句写的实在就是烂透了,实际业务就是要查看销售了多少;根据当个商品销售量,来判断库存是否满足,查找了凭证当中所有的门票信息,虽然有索引,但是也会全局检索所有的数据;
处理方式:1,2的对应sql 表结构增加索引之后,再次启动测试,发现稍有好转,不会再出现以上两个对应的sql;但是最后一条还得改下逻辑,因为商品的购买规则中已经存了对应的销售数量,所以直接修改查询其他的表即可,而且商品表由于业务,也不会存在大数据量,而且有对应的索引; 修改处理方式之后;再次启动性能测试发现完全达标;
遇到以上这种问题,就得静下心来思考,把所有可能会影响性能点列出来,然后一一排查即可;
1.对 WHERE, JOIN, MAX(), MIN(), ORDER BY 等子句中的条件判断中用到的字段,应该根据其建立索引 INDEX。索引被用来快速找出在一个列上用一特定值的行。没有索引,MySQL不得不首先以第一条记录开始并然后读完整个表直到它找出相关的行。表越大,花费时间越多。如果表对于查询的列有一个索引,MySQL能快速到达一个位置去搜寻到数据文件的中间,没有必要考虑所有数据。如果一个表有1000行,这比顺序读取至少快100倍。所有的MySQL索引(PRIMARY、UNIQUE和INDEX)在B树中存储。
-
根据 mysql 的开发文档:
索引 index 用于:
- 快速找出匹配一个WHERE子句的行
- 当执行联结(JOIN)时,从其他表检索行。
- 对特定的索引列找出MAX()或MIN()值
- 如果排序或分组在一个可用键的最左面前缀上进行(例如,ORDER BY key_part_1,key_part_2),排序或分组一个表。如果所有键值部分跟随DESC,键以倒序被读取。
- 在一些情况中,一个查询能被优化来检索值,不用咨询数据文件。如果对某些表的所有使用的列是数字型的并且构成某些键的最左面前缀,为了更快,值可以从索引树被检索出来。
假定你发出下列SELECT语句:
mysql> SELECT * FROM tbl_name WHERE col1=val1 AND col2=val2;如果一个多列索引存在于col1和col2上,适当的行可以直接被取出。如果分开的单行列索引存在于col1和col2上,优化器试图通过决定哪个索引将找到更少的行并来找出更具限制性的索引并且使用该索引取行。
开发人员做 SQL 数据表设计的时候,一定要通盘考虑清楚,是否增加对应的索引以及查询条件;表数据量是否会有大数据量