知识点:Mysql 数据库索引优化实战(4)

 

知识点:Mysql 索引原理完全手册(1)

知识点:Mysql 索引原理完全手册(2)

知识点:Mysql 索引优化实战(3)

知识点:Mysql 数据库索引优化实战(4)

一:插入订单

业务逻辑:插入订单数据,为了避免重复导单,一般会通过交易号去数据库中查询,判断该订单是否已经存在。

最基础的sql语句

mysql> select * from book_order where order_id = "10000";
+-------+--------------------+-------+------+----------+--------------+----------+------------------+-------------+-------------+------------+---------------------+ | id | order_id | general | net | stock_id | order_status | description | finance_desc | create_type | order_state | creator | create_time | +-------+--------------------+-------+------+----------+--------------+----------+------------------+-------------+-------------+------------+---------------------+ | 10000 | 10000 | 6.6 | 6.13 | 1 | 10 | ok | ok | auto | 1 | itdragon | 2018-06-18 17:01:52 | +-------+--------------------+-------+------+----------+--------------+----------+------------------+-------------+-------------+------------+---------------------+ mysql> explain select * from book_order where order_id = "10000"; +----+-------------+---------------------+------------+------+---------------+------+---------+------+------+----------+-------------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+---------------------+------------+------+---------------+------+---------+------+------+----------+-------------+ | 1 | SIMPLE | book_order | NULL | ALL | NULL | NULL | NULL | NULL | 3 | 33.33 | Using where | +----+-------------+---------------------+------------+------+---------------+------+---------+------+------+----------+-------------+ 

几百上千万的订单,全表扫描!

通过explain命令可以清楚MySQL是如何处理sql语句的。打印的内容分别表示:

  • id : 查询序列号为1。
  • select_type : 查询类型是简单查询,简单的select语句没有union和子查询。
  • table : 表是 book_order。
  • partitions : 没有分区。
  • type : 连接类型,all表示采用全表扫描的方式。
  • possible_keys : 可能用到索引为null。
  • key : 实际用到索引是null。
  • key_len : 索引长度当然也是null。
  • ref : 没有哪个列或者参数和key一起被使用。
  • Extra : 使用了where查询。

是type为ALL,全表扫描,假设数据库中有几百万条数据,在没有索引的帮助下会异常卡顿。

初步优化:为order_id创建索引

mysql> create unique index idx_order_transaID on book_order (order_id);
mysql> explain select * from book_order where order_id = "10000";
+----+-------------+---------------------+------------+-------+--------------------+--------------------+---------+-------+------+----------+-------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+---------------------+------------+-------+--------------------+--------------------+---------+-------+------+----------+-------+ | 1 | SIMPLE | book_order | NULL | const | idx_order_transaID | idx_order_transaID | 453 | const | 1 | 100 | NULL | +----+-------------+---------------------+------------+-------+--------------------+--------------------+---------+-------+------+----------+-------+ 

这里创建的索引是唯一索引,而非普通索引。

唯一索引打印的type值是const。表示通过索引一次就可以找到。即找到值就结束扫描返回查询结果。

普通索引打印的type值是ref。表示非唯一性索引扫描。找到值还要继续扫描,直到将索引文件扫描完为止。(这里没有贴出代码),显而易见,const的性能要远高于ref。并且根据业务逻辑来判断,创建唯一索引是合情合理的。

再次优化:覆盖索引

mysql> explain select order_id from book_order where order_id = "10000";
+----+-------------+---------------------+------------+-------+--------------------+--------------------+---------+-------+------+----------+-------------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+---------------------+------------+-------+--------------------+--------------------+---------+-------+------+----------+-------------+ | 1 | SIMPLE | book_order | NULL | const | idx_order_transaID | idx_order_transaID | 453 | const | 1 | 100 | Using index | +----+-------------+---------------------+------------+-------+--------------------+--------------------+---------+-------+------+----------+-------------+ 

这里将select * from改为了select order_id from后,Extra 显示 Using index,表示该查询使用了覆盖索引,说明该sql语句的性能很好。若提示的是Using filesort(使用内部排序)和Using temporary(使用临时表)则表明该sql需要立即优化了。

根据业务逻辑来的,查询结构返回order_id 是可以满足业务逻辑要求的。

二:查询订单

业务逻辑:优先处理订单级别高,录入时间长的订单。

通过订单级别和订单录入时间排序

最基础的sql语句

mysql> explain select * from book_order order by order_state,create_time;
+----+-------------+---------------------+------------+------+---------------+------+---------+------+------+----------+----------------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+---------------------+------------+------+---------------+------+---------+------+------+----------+----------------+ | 1 | SIMPLE | book_order | NULL | ALL | NULL | NULL | NULL | NULL | 3 | 100 | Using filesort | +----+-------------+---------------------+------------+------+---------------+------+---------+------+------+----------+----------------+ 

首先,采用全表扫描就不合理,还使用了文件排序Using filesort,更加拖慢了性能。 MySQL在4.1版本之前文件排序是采用双路排序的算法,由于两次扫描磁盘,I/O耗时太长。后优化成单路排序算法。其本质就是用空间换时间,但如果数据量太大,buffer的空间不足,会导致多次I/O的情况。其效果反而更差。与其找运维同事修改MySQL配置,还不如自己乖乖地建索引。

初步优化:为order_state,create_time 创建复合索引

mysql> create index idx_order_stateDate on book_order (order_state,create_time);
mysql> explain select * from book_order order by order_state,create_time;
+----+-------------+---------------------+------------+------+---------------+------+---------+------+------+----------+----------------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+---------------------+------------+------+---------------+------+---------+------+------+----------+----------------+ | 1 | SIMPLE | book_order | NULL | ALL | NULL | NULL | NULL | NULL | 3 | 100 | Using filesort | +----+-------------+---------------------+------------+------+---------------+------+---------+------+------+----------+----------------+ 

创建复合索引后你会惊奇的发现,和没创建索引一样???都是全表扫描,都用到了文件排序。是索引失效?还是索引创建失败?

我们试着看看下面打印情况

mysql> explain select order_state,create_time from book_order order by order_state,create_time;
+----+-------------+---------------------+------------+-------+---------------+---------------------+---------+------+------+----------+-------------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+---------------------+------------+-------+---------------+---------------------+---------+------+------+----------+-------------+ | 1 | SIMPLE | book_order | NULL | index | NULL | idx_order_stateDate | 68 | NULL | 3 | 100 | Using index | +----+-------------+---------------------+------------+-------+---------------+---------------------+---------+------+------+----------+-------------+ 

将select * from 换成了 select order_state,create_time from 后。type从all升级为index,表示(full index scan)全索引文件扫描,Extra也显示使用了覆盖索引。可是不对啊!!!!检索虽然快了,但返回的内容只有order_state和create_time 两个字段,让业务同事怎么用?难道把每个字段都建一个复合索引?

MySQL没有这么笨,可以使用force index 强制指定索引。在原来的sql语句上修改 force index(idx_order_stateDate) 即可。

mysql> explain select * from book_order force index(idx_order_stateDate) order by order_state,create_time;
+----+-------------+---------------------+------------+-------+---------------+---------------------+---------+------+------+----------+-------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+---------------------+------------+-------+---------------+---------------------+---------+------+------+----------+-------+ | 1 | SIMPLE | book_order | NULL | index | NULL | idx_order_stateDate | 68 | NULL | 3 | 100 | NULL | +----+-------------+---------------------+------------+-------+---------------+---------------------+---------+------+------+----------+-------+ 

再次优化:订单级别真的要排序么?

对于这种重复且分布平均的字段,排序和加索引的作用不大。

我们能否先固定 order_state 的值,然后再给 create_time 排序?

mysql> explain select * from book_order where order_state=3 order by create_time;
+----+-------------+---------------------+------------+------+---------------------+---------------------+---------+-------+------+----------+-----------------------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+---------------------+------------+------+---------------------+---------------------+---------+-------+------+----------+-----------------------+ | 1 | SIMPLE | book_order | NULL | ref | idx_order_stateDate | idx_order_stateDate | 5 | const | 1 | 100 | Using index condition | +----+-------------+---------------------+------------+------+---------------------+---------------------+---------+-------+------+----------+-----------------------+ 

和之前的sql比起来,type从index 升级为 ref(非唯一性索引扫描)。索引的长度从68变成了5,说明只用了一个索引。ref也是一个常量。Extra 为Using index condition 表示自动根据临界值,选择索引扫描还是全表扫描。总的来说性能远胜于之前的sql。

小结

建索引:

    1. 主键,唯一索引
    1. 经常用作查询条件的字段需要创建索引
    1. 经常需要排序、分组和统计的字段需要建立索引
    1. 查询中与其他表关联的字段,外键关系建立索引

不要建索引:

    1. 百万级以下的数据不需要创建索引
    1. 经常增删改的表不需要创建索引
    1. 数据重复且分布平均的字段不需要创建索引
    1. 频发更新的字段不适合创建索引
    1. where条件里用不到的字段不需要创建索引

talk is esay , show me the code

转载于:https://www.cnblogs.com/yizhiamumu/p/9226142.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/465638.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

看漫画学电子,非常精彩!有些概念以前模糊现在真的懂了

来源:gadgetronicx.com,排版:晓宇微信公众号:芯片之家(ID:chiphome-dy)1、按键消抖,在机械按键断开与闭合时,按键的触电是有一点弹性的,按下去的时候不会马上…

STM32F7xx —— 串口通信

STM32F7xx —— 串口通信 目录 STM32F7xx —— 串口通信 一、串口初始化过程 二、几个重要的串口函数 三、几个重要的结构 四、基本接口设计 一、串口初始化过程 1、时钟使能; 2、GPIO初始化; 3、串口波特率设置; 4、串口控制&#…

一个跳楼博士生的遗书:这个世界是一沟绝望的死水

o(︶︿︶)o 唉北邮跳楼博士生给母亲堵塞遗书:这个世界是一沟绝望的死水 这个世界是一沟绝望的死水,我在这里再怎么折腾也激不起半点涟漪。所有的努力都会被既得利益集团踩在脚下,所有的奋斗都面临着举步维艰。冷漠的人,谢谢你…

jquery插件课程1 幻灯片、城市选择、日期时间选择、拖放、方向拖动插件

jquery插件课程1 幻灯片、城市选择、日期时间选择、拖放、方向拖动插件 一、总结 一句话总结:都是jquery插件,都还比较小,参数(配置参数、数据)一般都是通过json传递。 1、插件配置数据或者参数的时候用的是什么数据结…

由c语言转向c++,我们需要做什么?

点击上方蓝字添加关注在此送大家一份小礼物,公众号内回复linux0001即可获得一本Linux电子教程“c语言和c到底有什么不同和联系呢?”毫无疑问,c语言和c是两种不同的语言,但是又有着千丝万缕的联系。语法上c语言与c一脉相承&#xf…

黄聪:【强烈推荐】搜索引擎排名决定一切吗!

在点石看到一篇《搜索引擎排名决定一切么》,作者cqqc626。写的太赞的,Kyw看后都有点激动,希望天下所有要需要SEO服务的客户们,都能明白其中道理,明白排名不是一切。正文如下: 前段时间经常看到很多和自己差…

STM32F7xx —— CAN通信

STM32F7xx —— CAN通信 目录 STM32F7xx —— CAN通信 一、CAN基础 二、几个重要的CAN函数 三、几个重要的结构 四、接口设计 一、CAN基础 差分信号:显性电平对应逻辑0,CAN_H和CAN_L差为2.5V;隐形电平对应逻辑1,CAN_H和CAN_…

[leetcode] 14. 最长公共前缀

14. 最长公共前缀 超级简单。。。 class Solution { public:string longestCommonPrefix(vector<string> &strs) {if (strs.size() 0) {return "";}string common strs[0];for (int i 1; i < strs.size(); i) {common findCommon(strs[i], common);…

Cmake确实应该用到的时候再学

最近在做项目用到Cmake相关的知识&#xff0c;之前做的是BSP驱动开发&#xff0c;基本用不到Cmake&#xff0c;唯一和Cmake有交集的应该是我们移植网关项目&#xff0c;不过也只是修修改改&#xff0c;直到最近用到Cmake开发项目&#xff0c;才真正是接触了这个东西。前天加载一…

手机吞吃蛇游戏的设计与开发

为什么80%的码农都做不了架构师&#xff1f;>>> J2ME(Java 2 Micro Edition) 是近年来随着各种不同设备&#xff0c;尤其是移动通信设备的飞速发展而诞生的一项新的开发技术。它定位在消费性电子产品的应用上&#xff0c;对设备的智能化、www.21cnlunwen.com Write…

STM32F7xx —— 内部flash

STM32F7xx —— 内部flash 这个就没什么好说的了&#xff0c;直接上代码了&#xff0c;主要封装了三个函数&#xff0c;擦除&#xff0c;写flash&#xff0c;读flash。 // STM32F767IGT6: 1M flash // STM32F767ZIT6: 2M flash #define ADDR_FLASH_SECTOR_0 ((uint32_t)0x…

深入理解 Vue Computed 计算属性

Computed 计算属性是 Vue 中常用的一个功能&#xff0c;我们今天来说一下他的执行过长 拿官网简单的例子来看一下&#xff1a; <div id"example"><p>Original message: "{{ message }}"</p><p>Computed reversed message: "{…

vscode 使用 ssh 登录

// 执行 // 使用你自己的服务器IP与登录账户 export USER_AT_HOST"服务器账户名服务器IP" // PUBKEYPATH是你公钥的路径 export PUBKEYPATH"$HOME/.ssh/id_rsa.pub"ssh-copy-id -i "$PUBKEYPATH" "$USER_AT_HOST"

SNMP4J的一点缺陷

最近在使用SNMP4J的过程中发现一个缺陷&#xff0c;不知道应不应该算是个bug&#xff0c;但我想终究算是一个不完善的地方。 问题描述如下&#xff1a; 在通过SNMP4J去获取某些交换机上的MAC地址转发表(dot1dTpFdbTable, OID为1.3.6.1.2.1.17.4.3&#xff09;时&#xff0c;发现…

3-3 数数字

算法入门经典 P57 把前n&#xff08;n<100000&#xff09;个整数顺序写在一起&#xff0c;123456789...数一数0-9各出现多少次。 #include<stdio.h>#include<string.h>#include "stdafx.h"#include "iostream" #include <string&…

如何用示波器测量串口波特率

这是前段时间遇到的问题&#xff0c;刚好这里找到了答案&#xff0c;记录下分享给大家。如何确定时基假如要测量的波特率为9600, 则每一比特位的时间为&#xff1a;1/9600 ≈ 104 μs&#xff0c;一般示波器横向上每个大格子里5个小格子&#xff0c;要想看清一比特位一般需要一…

STM32F7xx —— ADC

STM32F7xx —— ADC 基础知识参考&#xff1a;ADC /***************************************************************************** * ADC1 ADC2 ADC3 * 通道0 PA0 PA0 PA0 * 通道1 PA1 PA1 PA1 * 通道2 PA2 PA2 …

一键了结CUP100%问题

1、dllhost进程造成CPU使用率占用100%<?xml:namespace prefix o ns "urn:schemas-microsoft-com:office:office" />服务器正常CPU消耗应该在75%以下&#xff0c;而且CPU消耗应该是上下起伏的&#xff0c;出现这种问题的服务器&#xff0c;CPU会突然一直处10…

Linux内核工程师是怎么步入内核殿堂的?

上图是公众号冠名参加的篮球赛对我来说&#xff0c;要搞好Linux内核&#xff0c;首先要做的就是买一块Linux开发板&#xff0c;然后就使劲捣鼓。下面是一位大神对于入门Linux内核的看法。以下的「我」不是公众号作者作者&#xff1a;Coly Lihttps://www.zhihu.com/question/304…

Newtonsoft.Json 获取匿名类数据

很简单。 1 using System;2 using System.Collections.Generic;3 4 namespace Test5 {6 class Program7 {8 9 static string Message "{\"Result\":0,\"ErrMsg\":\"执行失败。索引超出范围。必须为非负值并小于集合大小。\r\n参…