• 1
  • 0
分享

1、MySQL基础

1.1 MySQL的基本知识

按照惯例,先介绍一下 MySQL基本知识:

MySQL 是一种关联数据库管理系统,关联数据库将数据保存在不同的表中,而不是将所有数据放在一个大仓库内,这样就增加了速度并提高了灵活性。

MySQL 的 SQL “结构化查询语言”,是用于访问数据库的最常用标准化语言。

MySQL 软件采用了 GPL(GNU 通用公共许可证),由于其体积小、速度快、总体拥有成本低,尤其是开放源码这一特点,许多中小型网站为了降低网站总体拥有成本,而选择 MySQL 作为其网站数据库。

1.2 MySQL的优势

MySQL的优势有哪些,我们来瞧瞧。

・MySQL开源的,无需支付额外费用的;

・MySQL使用标准的SQL数据语言形式;

・MySQL可以运行多个系统上,并支持多个语言(如:C、C++、Python、Java、Perl、PHP、Eiffel、Ruby 等);

・MySQL可以定制,采用 GPL 协议,可修改源码来开发自己的 MySQL 系统。 

所以,我们要搞好MySQL数据库,是不是非常有必要。

今天,

我们就先从 order by和group by来说起。

2、order by 原理

2.1 创建表

为了更好,更容易理解相关知识点,咱先举个例子。

也是小鱼的一贯作风, 举例说话 !

先创建一张测试表,

/* auth:carl_奕然  */
 /* 使用ClassDJ这个database */
 use ClassDJ;  
 /* 如果表t1存在则删除表t1 */
 drop table if exists t1;  
 /* 创建表t1 */
 CREATE TABLE 't1'(      
 'id' int(11) NOT NULL AUTO_INCREMENT,
 'a' int(20) DEFAULT NULL ,
 'b' int(20) DEFAULT NULL ,
 'c' int(20) DEFAULT NULL ,
 'd' datetime NOT NULL  DEFAULT CURRENT_TIMESTAMP ,
 PRIMARY KEY (`id`),
 KEY `idx_a_b` (`a`,`b`),
 KEY `idx_c` (`c`)
 )ENGINE=InnoDB CHARSET=utf8mb4 ;
 /* 如果存在存储过程insert_t1,则删除 */
 drop procedure if exists insert_t1;
 delimiter ;;
 /* 创建存储过程insert_t1 */
 create procedure insert_t1()
 begin 
   /* 声明变量i */
   declare i int;  
   /* 设置i的初始值为1 */
   set i=1; 
   /* 对满足i<=10000的值进行while循环 */
   while(i<=10000)do
   /* 写入表d1中a、b两个字段,值都为i当前的值 */
     insert into t1(a,b,c) values(i,i,i); 
     /* 将i加1 */
     set i=i+1;    
   end while;
 end ;;
 delimiter ;
  /* 运行存储过程insert_t1 */
 call insert_t1();       
 /* 将id大于9000的行的a字段更新为1000 */
 update t1 set a=1000 where id >9000;

创建完表,我们就来研究一下MySQL的排序原理 

2.2 MySQL的排序方式

按照排序原理分,MySQL 排序方式分两种:

    ①通过有序索引直接返回有序数据

    ②通过Filesort进行的排序 

那么,问题来了,

如何确定某条排序的SQL所使用的排序方式?

答:使用explain来查看该排序SQL的执行计划,重点关注****字段。

★如果Extra字段里显示是 Using index,则表示是通过有序索引直接返回有序数据 

例如;

explain select id,c from t1 order by c;

20201102171156796.png

★如果Extra字段里显示是 Using filesort,则表示该 SQL 是通过 Filesort 进行的排序 

例如:

explain select id,d from t1 order by d;

2020110217122756.png

是不是,这就一目了然 了。

Nice

2.3 Filesort 在哪里完成排序

MySQL 中的 Filesort 并不一定是在磁盘文件中进行排序的,也有可能在内存中排序,

内存排序还是磁盘排序取决于排序的数据大小和 sort_buffer_size 配置的大小。

・如果 “排序的数据大小” < sort_buffer_size: 内存排序

・如果 “排序的数据大小” > sort_buffer_size: 磁盘排序

同样,问了又来了, 

如何确定使用 Filesort 排序的 SQL 是在内存还是在磁盘中进行的排序操作? 

答:使用 trace 进行分析重点关注 number_of_tmp_files,

★如果等于 0,则表示排序过程没使用临时文件,在内存中就能完成排序;

★如果大于0,则表示排序过程中使用了临时文件。

举例

一、未使用临时文件排序

20201102171959866.png

上图中,因为 number_of_tmp_files 等于 0,表示未使用临时文件进行排序,所以是内存排序。

参数解析:

・rows:预计扫描的行数

・examined_rows:参与排序的行

・number_of_tmp_files:使用临时文件的个数

・sort_buffer_size:sort_buffer 的大小

・sort_mode:排序模式

二、使用临时文件排序

20201102172253996.png

上图中,因为 number_of_tmp_files 等于 7,所以表示使用的是磁盘排序。

 number_of_tmp_files 等于 7表示:

该SQL 将需要排序的数据分为 7 份,然后每份单独排序,再存放在 7 个临时文件中,最后把 7 个临时文件合并成一个大的有序文件。

2.4 Filesort 下的排序模式

一、排序模式

Filesort 下的排序模式有三种: 

    ・< sort_key, rowid >双路排序(又叫回表排序模式):是首先根据相应的条件取出相应的排序字段和可以直接定位行数据的行 ID,然后在 sort buffer 中进行排序,排序完后需要再次取回其它需要的字段;

    ・< sort_key, additional_fields >单路排序:是一次性取出满足条件行的所有字段,然后在sort buffer中进行排序;

    ・< sort_key, packed_additional_fields >打包数据排序模式:与单路排序相似,区别是将 char 和 varchar 字段存到 sort buffer 中时,更加紧缩。

MySQL 通过比较系统变量 max_length_for_sort_data 的大小和需要查询的字段总大小来判断使用哪种排序模式 

二、判断排序模式

通过 max_length_for_sort_data 的大小和需要查询的字段总大小来判断使用哪种排序模式。

・如果 max_length_for_sort_data 比查询字段的总长度大,那么使用 < **sort_key, additional_fields >**排序模式;

・如果 max_length_for_sort_data 比查询字段的总长度小,那么使用 <sort_key, rowid> 排序模式。

三、实例举例

① 

set session optimizer_trace="enabled=on",end_markers_in_json=on;
 SET max_length_for_sort_data = 20;
 /* 查询表d1的id、a、d三个字段的值,按照字段d进行排序  */
 select a,d from t1 order by d; 
 SELECT * FROM information_schema.OPTIMIZER_TRACE\G

 OPTIMIZER_TRACE 结果中排序信息,如下图:

202011021733387.png

可以看到,使用的是**<sort_key,additional_fields>**排序模式。

我们要是变成 <sort_key, rowid>,怎么整呢?

思路:因为 a、d 两个字段的总长度为 12,可以尝试把 max_length_for_sort_data 改为小于 12 的值,看排序模式是否有改变。

操作:

set session optimizer_trace="enabled=on",end_markers_in_json=on;
SET max_length_for_sort_data = 4;
/* 查询表d1的id、a、d三个字段的值,按照字段d进行排序  */
select a,d from t1 order by d; 
SELECT * FROM information_schema.OPTIMIZER_TRACE\G

OPTIMIZER_TRACE 结果中排序信息,如下图:

20201102173732939.png

看看,是不是变成 <sort_key ,rowid>排序模式了。

非常Nice。

嗯,今天的就到这里,

关于如何优化orderby 及groupby ,我会在下一篇中着重介绍:

深聊MySQL之:让orderby、groupby查询速度飞起来(下)


  • 【留下美好印记】
    赞赏支持
登录 后发表评论
+ 关注

热门文章

    最新讲堂

      • 推荐阅读
      • 换一换
          • 沐沐一开始学习python的时候也会觉得枯燥无味,面对各种python的变量、赋值、数字、字符串、列表、元祖等基本知识总是昏昏欲睡。似乎怎么学习都很难将python应用于实际的测试工作。直到我遇到了django,才慢慢的对python有了进一步的实践和认知,所以很有必要安利给大家。比如大家可以用django框架进行简单的博客开发、测试框架开发等、或者可以下载一些开源的测试框架,在本地搭建起来后,熟悉框架的源码,会在框架学习的过程中,慢慢掌握python的各种语法。这里先简单介绍一下,Django是一个开源的Web应用框架,是Python众多框架中的爆款,采用了经典的MVC设计模式。Django...
            1 0 3962
            分享
          • Selenium 操作被检测屏蔽selenium打开浏览器模仿人工操作是诸多爬虫小白最万能的网页数据获取方式,但是在做自动化爬虫时,经常被检测到是selenium驱动。前段时间selenium打开维普高级搜索时得到的页面是空白页。Selenium为何会被检测主要原因是selenium打开的浏览器指纹和人工操作打开的浏览器指纹是不同的,比如最熟知的window.navigator.webdriver关键字,在selenium打开的浏览器打印返回结果为true,而正常浏览器打印结果返回为undefined,我们可以在网站比较各关键字。Selenium防检测方法1. 修改window.navigat...
            2 4 10374
            分享
          •   当使用FastAPI进行单元测试时,一个重要的工具是TestClient类。TestClient类允许我们模拟对FastAPI应用程序的HTTP请求,并测试应用程序的响应。这使我们能够在不启动服务器的情况下对API进行全面的测试。  下面我将详细讲解TestClient的使用方法和常见操作:  安装和导入TestClient  首先,确保你的项目已经安装了FastAPI和pytest库。然后,从FastAPI库中导入TestClient类:  from fastapi.testclient import TestClient  创建TestClient实例  ...
            0 0 335
            分享
          •   Web应用程序的验收测试常常涉及一些手工任务,例如打开一个浏览器,并执行一个测试用例中所描述的操作。但是手工执行的任务容易出现操作人员人为的错误,花费的时间成本也比较多。因此,将这些任务自动化,就可以消除人为因素。Selenium可以帮助我们自动完成验收测试,通过构建更严格的测试,从而使软件更为可靠也更易于维护。  Selenium 测试框架及用例编写。  Selenium是什么?  Selenium 是用于测试 Web 应用程序用户界面 (UI) 的常用框架。它是一款用于运行端到端功能测试的超强工具。您可以使用多个编程语言编写测试,并且 Selenium 是能够在一个或多个浏览器中执行这...
            0 0 1000
            分享
          •   提起自动化测试,大家脑中立即能浮现的大多数是Python开发语言、JAVA开发语言、Appium测试框架、Selenium测试框架等,大部分WEB公司只要做自动化测试基本上都离不开上面谈到的开发语言和框架。  不过仍然有很多公司会有不一样的自动化测试需求,例如万次级别断常电、手机行业的开关机、功耗满负载测试等。  笔者在工作中就遇到过以上“另类”自动化测试,会遇上很多沟沟坎坎,但是非常有意思,各位看官且慢慢往下看。  进行断常电测试的背景与需求  笔者供职于国内某新能源汽车企业,以前听到汽车两个字,能联想到的肯定是外观、加速、舒适、油耗等等,进入新能源时代,不得不提互联网、安卓、科技等等词...
            13 13 3481
            分享
      • 51testing软件测试圈微信