正文

公司订单系统每日订单量庞大,有很多表数据超千万。公司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

转载于:https://www.cnblogs.com/wappin/p/7725049.html

记一次mysql千万订单汇总查询优化相关推荐

  1. 详记一次MySQL千万级大表优化过程!

    来自:知乎,作者:互联网编程 链接:https://www.zhihu.com/question/19719997/answer/549041957 问题概述 使用阿里云rds for MySQL数据 ...

  2. 分享:详记一次MySQL千万级大表优化过程!

    问题概述 使用阿里云rds for MySQL数据库(就是MySQL5.6版本),有个用户上网记录表6个月的数据量近2000万,保留最近一年的数据量达到4000万,查询速度极慢,日常卡死.严重影响业务 ...

  3. 记一次mysql千万级数据量(上千亿都行)的处理(java)

    1.前言 项目一个表经历着一天3W条数据入表,一年就有1000W,单表随着数据的增多,查询都会逐渐卡,加了索引依旧出现查询卡 2.经过 因为我用的是java,起初解决方案是用[shardingsphe ...

  4. mysql千万级大数据SQL查询优化

    1.对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引.2.应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索引 ...

  5. Mysql数据库千万级数据查询优化方案

    Mysql数据库中一个表里有一千多万条数据,怎么快速的查出第900万条后的100条数据? 面试官问:Mysql数据库千万级数据查询优化方案- 首先创建一张表,里面模拟了1000w数据: CREATE ...

  6. 30个mysql千万级大数据SQL查询优化技巧详解

    点击上方关注 "终端研发部" 设为"星标",和你一起掌握更多数据库知识 文章来自:脚本之家 http://www.jb51.net/article/136701 ...

  7. 记一次mysql性能优化过程

    2019独角兽企业重金招聘Python工程师标准>>> 转发自:记一次mysql性能优化过程 由于配置是运行过那么长时间,很稳定,基本上不考虑,所以本次主要是sql的优化,并且集中在 ...

  8. phpstudy mysql建表_MySQL_总结MySQL建表、查询优化的一些实用小技巧,MySQL建表阶段是非常重要的一 - phpStudy...

    总结MySQL建表.查询优化的一些实用小技巧 MySQL建表阶段是非常重要的一个环节,表结构的好坏.优劣直接影响着后续的管理维护,赶在明天上班前分享总结个人MySQL建表.MySQL查询优化积累的一些 ...

  9. go mysql slave_【Golang+mysql】记一次mysql数据库迁移(一)

    # [记一次mysql数据库迁移(一)](https://github.com/stayfoo/stayfoo-hub/blob/master/docs/mysql/blog/%E8%AE%B0%E4 ...

最新文章

  1. 计算机网络应用和计算机应用有什么区别,什么是计算机网络技术?和计算机应用技术区别...
  2. 分布式锁双重防死锁演进
  3. 浅析 EF Core 5 中的 DbContextFactory
  4. Ubuntu10.04No init found. Try passing init= bootarg解决方案
  5. 轻量高效的开源JavaScript插件和库 【转】
  6. php 日期 间隔,PHP实现计算日期间隔天数的方法
  7. 一只青蛙跳向三个台阶_在藏区流传的青蛙王子的故事
  8. 【华为云技术分享】玩转华为物联网IoTDA服务系列三-自动售货机销售分析场景示例
  9. 我的世界rpg服务器背包位置,我的世界:如何识别MC老玩家?看他背包中有没有这五种道具...
  10. 2021级C语言大作业 - 涂鸦跳跃
  11. C++ mutable 的用法
  12. 抱怨一下有些邮件列表的气氛
  13. Arm汇编 位置无关代码 adr 指令
  14. sonar 加载mysql_Sonar MySQL设置
  15. 物联网感知-光纤光栅传感器技术
  16. 样条曲线转换为NUBRS曲线
  17. 电子科大+矩阵理论+真题总结
  18. 解决quartus与modelsim-se以及modelsim-altera同时使用导致的仿真失败问题
  19. 爬虫重试模块retry,自动重试
  20. EasyX 图片透明设置

热门文章

  1. 开园第一篇献给找不回来的园子。。
  2. Android蓝牙开发浅析
  3. 大型企业Exchange 2010部署方案 – 分割全局地址列表
  4. 问题 F: Search Problem (III)
  5. ping下主服务器mysql_mysql主从同步配置
  6. 微信十年,领取纪念勋章头像!
  7. 测试面试题集-3.生活物品测试:杯子、伞、钢笔、桌子
  8. 性能测试(三)Jmeter工具
  9. 翁恺老师C语言学习笔记(十一)字符串
  10. Layer 2 DAO 基础协议 Metis 上线 Alpha 测试网