正文

公司订单系统每日订单量庞大,有很多表数据超千万。公司SQL优化这块做的很不好,可以说是没有做,所以导致查询很慢。

节选某个功能中的一句SQL EXPLAIN查看执行计划,EXPLAIN + SQL 查看SQL执行计划

一个索引没用到,受影响行接近2000万,难怪会慢。

原来的SQL打印出来估计有好几张A4纸,我发个整理后的简版。

SELECT
  COUNT(t.w_order_id) lineCount,
  SUM(ROUND(t.feel_total_money / 100, 2)) AS lineTotalFee,
  SUM(ROUND(t.feel_fact_money / 100, 2)) AS lineFactFee
FROM
  w_orders_his t
WHERE 1=1
  AND DATE_FORMAT(t.create_time, '%Y-%m-%d') >= STR_TO_DATE(#{beginTime},'%Y-%m-%d')
  AND DATE_FORMAT(t.create_time, '%Y-%m-%d') <= STR_TO_DATE(#{endTime},'%Y-%m-%d')
  AND t.pay_state = #{payState}
  AND t.store_id LIKE '%#{storeId}%'
  limit 0,10

这条sql需求是在两千万的表中捞出指定时间和条件的订单进行总数总金额汇总处理。

优化sql需要根据公司的业务,技术的架构等,且针对不同业务每条SQL的优化都是有差异的。

  优化点1:

AND DATE_FORMAT(t.create_time, '%Y-%m-%d') >= STR_TO_DATE(#{beginTime},'%Y-%m-%d')
AND DATE_FORMAT(t.create_time, '%Y-%m-%d') <= STR_TO_DATE(#{endTime},'%Y-%m-%d')

我们知道sql中绝对要减少函数的使用,像左边DATE_FORMAT(t.create_time, '%Y-%m-%d') 是绝对禁止使用的,如果数据库有一百万数据那么就会执行一百万次函数,非常非常影响效率。右边STR_TO_DATE(#{beginTime},'%Y-%m-%d')的函数会执行一次,但还是不建议使用函数。所以去掉函数直接使用 >=,<= 或BETWEEN AND速度就会快很多,但有的数据库设计时间字段只有日期没有时间,所以需要在日期后面拼接时间如:"2017-01-01" + " 00:00:00"。

更好的办法是用时间戳,数据库中存时间戳,然后拿时间戳去比较,如:BETWEEN '开始时间时间戳' AND '结束时间时间戳'

优化点2:

AND t.store_id LIKE '%#{storeId}%'

这句使用了LIKE并且前后匹配,前后匹配会导致索引失效,一般情况下避免使用,应该改成 AND t.store_id LIKE '#{storeId}%'

优化点3:

一般利用好索引,根据主键、唯一索引查询某一条记录,就算上亿数据查询也是非常快的。但这条sql需要查询数据统计需要用到COUNT和SUM,所以可以建立联合索引。

联合索引有一点需要注意:key index (a,b,c)可以支持a | a,b| a,b,c 3种组合进行查找,但不支持 b,c进行查找 ,当最左侧字段是常量引用时,索引就十分有效。

所以把必要字段排放在左边key index(create_time,w_order_id,feel_total_money,feel_fact_money,payState,storeId)

结果

  优化之前大概几分钟,现在是毫秒级。其实改的东西也不多,避免在语句上踩雷,善用EXPLAIN查询SQL效率。 

  有时间我会举点别的SQL优化的例子

      

  说几点平常可以优化的地方

  • JOIN 后的的条件必须是索引,最好是唯一索引,否则数据一旦很多会直接卡死
  • 一般禁止使用UNIION ON,除非UNION ON 前后的记录数很少
  • 禁止使用OR
  • 查总数使用COUNT(*)就可以,不需要COUNT(ID),MYSQL会自动优化
  • 数据库字段设置 NOT NULL,字段类型 INT > VARCHAR 越小越好
  • 禁止SELECT  * ,需要确定到使用的字段
  • 一般情况不在SQL中进行数值计算
  • SQL要写的简洁明了

      

参考

EXPLAIN type(从上到下,性能从差到好)

  • all 全表查询
  • index 索引全扫描
  • range 索引范围扫描
  • ref 使用非唯一或唯一索引的前缀扫描,返回相同值的记录
  • eq_ref 使用唯一索引,只返回一条记录
  • const,system 单表中最多只有一行匹配,根据唯一索引或主键进行查询
  • null 不访问表或索引就可以直接得到结果

MYSQL 五大引擎

  • ISAM :读取快,不占用内存和存储资源。 不支持事物,不能容错。
  • MyISAM :读取块,扩展多。
  • HEAP :驻留在内存里的临时表格,比ISAM和MyISAM都快。数据是不稳定的,关机没保存,数据都会丢失。
  • InnoDB :支持事物和外键,速度不如前面的引擎块。
  • Berkley(BDB) :支持事物和外键,速度不如前面的引擎块。

一般需要事物的设为InnoDB,其他设为MyISAM

记一次mysql千万订单汇总查询优化的更多相关文章

  1. MySQL索引原理以及查询优化

    转载自:https://www.cnblogs.com/bypp/p/7755307.html MySQL索引原理以及查询优化 一.介绍 1.什么是索引? 一般的应用系统,读写比例在10:1左右,而且 ...

  2. mysql 索引原理及查询优化 -转载

    转载自 mysql 索引原理及查询优化 https://www.cnblogs.com/panfb/p/8043681.html 潘红伟   mysql 索引原理及查询优化 一 介绍 为何要有索引? ...

  3. DB-SQL-MySQL-杂项-调优:Mysql千万以上数据优化、SQL优化方法

    ylbtech-DB-SQL-MySQL-杂项-调优:Mysql千万以上数据优化.SQL优化方法 1.返回顶部 1. 1,单库表别太多,一般保持在200以下为宜 2,尽量避免SQL中出现运算,例如se ...

  4. mysql千万级测试1亿数据的分页分析测试

    本文为本人最近利用几个小时才分析总结出的原创文章,希望大家转载,但是要注明出处 http://blog.sina.com.cn/s/blog_438308750100im0e.html 有什么问题可以 ...

  5. [置顶]生鲜配送管理系统_升鲜宝V2.0 销售订单汇总_采购任务分配功能_操作说明

    做好生鲜供应链系统,要注意三个方面,1.分拣 2 采购  3 库存,市面上做的比较成熟的功能,还是分拣这一块(按客户分拣.按订单分拣.按商品分类分拣.按商品分拣.按线路分拣.客户自由组合分拣)[下篇文 ...

  6. Mysql千万级大表优化

    Mysql的单张表的最大数据存储量尚没有定论,一般情况下mysql单表记录超过千万以后性能会变得很差.因此,总结一些相关的Mysql千万级大表的优化策略. 1.优化sql以及索引 1.1优化sql 1 ...

  7. 如何优化Mysql千万级快速分页,limit优化快速分页,MySQL处理千万级数据查询的优化方案

    如何优化Mysql千万级快速分页,limit优化快速分页,MySQL处理千万级数据查询的优化方案

  8. 记一次 mysql 启动没反应

    记一次 mysql 启动没反应 ,重启linux又可以启动 vim /var/log/mysqld.log 2018-02-04 13:22:49 28507 [ERROR] InnoDB: Cann ...

  9. mysql千万级数据库插入速度和读取速度的调整记录

    一般情况下mysql上百万数据读取和插入更新是没什么问题了,但到了上千万级就会出现很慢,下面我们来看mysql千万级数据库插入速度和读取速度的调整记录吧. 1)提高数据库插入性能中心思想:尽量将数据一 ...

随机推荐

  1. python2/python3 内存中打包/压缩文件

    python2:(包含压缩选项,如果只打包,可以调整zipfile.ZIP_DEFLATED) import zipfile import StringIO class InMemoryZip(obj ...

  2. Servlet第三篇【request和response简介、response的常见应用】

    response.request对象 Tomcat收到客户端的http请求,会针对每一次请求,分别创建一个代表请求的request对象.和代表响应的response对象 既然request对象代表ht ...

  3. firebug离线安装方法-拖入法

    这里介绍的是如何在Firefox中离线安装firebug插件. 1, 下载firebug离线包, 一般就是一个*.xpi文件; 2, 打开Firefox浏览器,直接将*.xpi文件拖入Firefox浏 ...

  4. 【Spring源码深度解析系列 】Spring整体架构

    一.Spring的整体架构和模块 二.模块分类: 1.Core Container Core Container包含有Core .Beans.Context.和Expression  Language ...

  5. 【个人笔记】《知了堂》MySQL三种关系:一对一,一对多,多对多。

    一对一:比如一个学生对应一个身份证号.学生档案: 一对多:一个班可以有很多学生,但是一个学生只能在一个班: 多对多:一个班可以有很多学生,学生也可以有很多课程: 一对多关系处理: 我们以学生和班级之间 ...

  6. java编程基础复习-------第二章

    一.标识符 java中标识符的命名规则: 以数字.字母.下划线和$符号组成:不能用数字开头:不能是java的关键字. 注意:不要用$命名标识符.习惯上,$只用在机器自动产生的源代码中. 二.关键字 1 ...

  7. Android 从ImageView中获取Bitmap对象方法

    showImageView.setDrawingCacheEnabled(true); Bitmap bitmap=showImageView.getDrawingCache(); showImage ...

  8. BP算法

    1986年Rumelhart和McCelland在<并行分布式处理>中提出了BP算法,即非线性连续变换函数的多层感知器网络误差反向传播算法. 该算法的思想是:学习过程分为信号的正向传播与误 ...

  9. S2_OOP第二章

    第一章 继承 语法 修饰符 子类 extends 父类{ //类定义不封 } 使用extends继承父类的属性和方法.使用super关键字调用父类的方法. 概念 继承是面向对象的三大特特之一,Java ...

  10. cs224d 自然语言处理作业 problem set3 (一) 实现Recursive Nerual Net Work 递归神经网络

    1.Recursive Nerual Networks能够更好地体现每个词与词之间语法上的联系这里我们选取的损失函数仍然是交叉熵函数 2.整个网络的结构如下图所示: 每个参数的更新时的梯队值如何计算, ...