SQL优化 - 排序

文章目录

  • 排序和索引
    • 降序索引
  • Filesort
  • ORDER BY 顺序问题
  • ORDER BY + LIMIT


排序和索引

如果ORDER BY操作使用了索引,那么就可以避免排序操作,因为索引本身就是按索引 key 排好序的。那什么情况下,ORDER BY会走索引呢?

例如:sakila.rental 表有一个联合索引rental_date(rental_date, inventory_id, customer_id)

在这里插入图片描述
下面来看SELECT * FROM rental ORDER BY rental_date, inventory_id;这条 sql 是否走索引

mysql> EXPLAIN SELECT * FROM rental ORDER BY rental_date, inventory_id;
+----+-------------+--------+------------+------+---------------+------+---------+------+-------+----------+----------------+
| id | select_type | table  | partitions | type | possible_keys | key  | key_len | ref  | rows  | filtered | Extra          |
+----+-------------+--------+------------+------+---------------+------+---------+------+-------+----------+----------------+
|  1 | SIMPLE      | rental | NULL       | ALL  | NULL          | NULL | NULL    | NULL | 16008 |   100.00 | Using filesort |
+----+-------------+--------+------------+------+---------------+------+---------+------+-------+----------+----------------+
1 row in set, 1 warning (0.00 sec)

从执行计划来看是没走索引的,因为使用了SELECT *。在这种情况下,扫描整个索引并查找表行以查找不在索引中的列可能比扫描表并对结果进行排序成本更高,因此优化器可能不会使用索引。如果SELECT *仅选择索引列,也就是使用索引覆盖策略,则可以使用索引来避免排序。例如:

EXPLAIN SELECT inventory_id, rental_date, customer_id 
FROM rental ORDER BY rental_date, inventory_id;

那是不是SELECT *都不走索引?

如果索引不完全包含查询的所有列,需要回表的话,则需要WHERE子句的选择性足以使索引范围扫描比表扫描成本更低,则优化器会选择使用索引。也就是让索引的所有未使用部分和所有额外的ORDER BY列都是WHERE子句中的常量条件。这样即使ORDER BY的列与索引不完全匹配,也可以使用索引。例如:

SELECT * FROM t1 WHERE key_part1 = constantORDER BY key_part2;

降序索引

https://dev.mysql.com/doc/refman/8.0/en/descending-indexes.html
如果索引的排序和ORDER BY的排序不一致,可以考虑使用降序索引

Filesort

如果ORDER BY不满足用索引的条件,MySQL将执行文件排序操作,读取表的行并对其进行排序。

从MySQL 8.0.12开始,优化器会根据需要增量地分配内存缓冲区(叫做 Sort Buffer),直到超过sort_buffer_size的大小,而MySQL 8.0.12之前,是直接预先分配固定数量的sort_buffer-size字节大小的内存缓冲区。将sort_buffer_size设置为更大的值来加速更大的排序。增量分配的这种方式可以在小排序发生时不会占用过多的内存。

如果结果集太大(超过sort_buffer_size)而无法放入内存,文件排序操作会根据需要使用临时磁盘文件,这种情况性能就比较差了

mysql> EXPLAIN SELECT * FROM rental ORDER BY inventory_id;
+----+-------------+--------+------------+------+---------------+------+---------+------+-------+----------+----------------+
| id | select_type | table  | partitions | type | possible_keys | key  | key_len | ref  | rows  | filtered | Extra          |
+----+-------------+--------+------------+------+---------------+------+---------+------+-------+----------+----------------+
|  1 | SIMPLE      | rental | NULL       | ALL  | NULL          | NULL | NULL    | NULL | 16008 |   100.00 | Using filesort |
+----+-------------+--------+------------+------+---------------+------+---------+------+-------+----------+----------------+
1 row in set, 1 warning (0.00 sec)

ORDER BY 顺序问题

如果order by列有相同的值,那么MySQL可以自由地以任何顺序返回这些行。换言之,只要order by列的值不重复,就可以保证返回的顺序。可以在order by子句中包含附加列,以使顺序具有确定性。为了保证每次都返回的顺序一致可以额外增加一个排序字段(比如:id),用两个字段来尽可能减少重复的概率

MySQL具体的排序策略受以下几个因素影响:

  1. 是否可用的索引
  2. 预期结果大小
  3. MySQL版本

一般来说,排序处理过程如下

  1. 读取与WHERE子句匹配的行
  2. 对于每一行,记录一个由排序 key 和行位置组成的值元组,以及查询所需的列
  3. 按排序 key 的值对元组进行排序
  4. 按排序好的顺序根据行未知检索行,但直接从排序的元组中读取所需的列,而不是第二次访问表

ORDER BY + LIMIT

对于order by查询,带或者不带limit可能返回行的顺序是不一样的。

如果limit row_count 与 order by 一起使用,那么在找到第一个row_count就停止排序,直接返回。

例如平时开发常见的分页查询

SELECT * FROM rental ORDER BY inventory_id LIMIT 1, 10

会导致多页出现同一条数据
在这里插入图片描述
如果想在limit存在或不存在的情况下,都保证排序结果相同,可以额外加一个排序条件。例如id字段是唯一的,可以考虑在排序字段中额外加个id排序去确保顺序稳定。这样分页的问题就解决了。

SELECT * FROM rental ORDER BY rental_id, inventory_id LIMIT 1, 10

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

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

相关文章

阿里云域名注册购买和备案

文章目录 1、阿里云首页搜索 域名注册2、点击 控制台3、域名控制台 1、阿里云首页搜索 域名注册 2、点击 控制台 3、域名控制台

【08】纯血鸿蒙HarmonyOS NEXT星河版开发0基础学习笔记-Scroll容器与Tabs组件

序言: 本文详细讲解了关于我们在页面上经常看到的可滚动页面和导航栏在鸿蒙开发中如何用Scroll和Tabs组件实现,介绍了Scroll和Tabs的基本用法与属性。 笔者也是跟着B站黑马的课程一步步学习,学习的过程中添加部分自己的想法整理为笔记分享出…

【漏洞复现】泛微OA E-Office do_excel.php 任意文件写入漏洞

》》》产品描述《《《 泛微0-0fice是一款标准化的协同 OA办公软件,泛微协同办公产品系列成员之一,实行通用化产品设计,充分贴合企业管理需求,本着简洁易用、高效智能的原则,为企业快速打造移动化、无纸化、数字化的办公平台。 》》…

深度学习:基于MindSpore实现CycleGAN壁画修复

关于CycleGAN的基础知识可参考: 深度学习:CycleGAN图像风格迁移转换-CSDN博客 以及MindSpore官方的教学视频: CycleGAN图像风格迁移转换_哔哩哔哩_bilibili 本案例将基于CycleGAN实现破损草图到线稿图的转换 数据集 本案例使用的数据集里…

【含文档】基于Springboot+Vue的护肤品推荐系统(含源码+数据库+lw)

1.开发环境 开发系统:Windows10/11 架构模式:MVC/前后端分离 JDK版本: Java JDK1.8 开发工具:IDEA 数据库版本: mysql5.7或8.0 数据库可视化工具: navicat 服务器: SpringBoot自带 apache tomcat 主要技术: Java,Springboot,mybatis,mysql,vue 2.视频演示地址 3.功能 系统定…

企望制造ERP系统存在RCE漏洞

漏洞描述 企望制造纸箱业erp系统由深知纸箱行业特点和业务流程的多位IT专家打造,具有国际先进的管理方式,将现代化的管理方式融入erp软件中,让企业分分钟就拥有科学的管理经验。erp的功能包括成本核算、报价定价、订单下达、生产下单、现场管…

五子棋双人对战项目(3)——匹配模块

目录 一、分析需求 二、约定前后端交互接口 匹配请求: 匹配响应: 三、实现游戏大厅页面(前端代码) game_hall.html: common.css: game_hall.css: 四、实现后端代码 WebSocketConfig …

vue3 环境配置vue-i8n国际化

一.依赖和插件的安装 主要是vue-i18n和 vscode的自动化插件i18n Ally https://vue-i18n.intlify.dev/ npm install vue-i18n10 pnpm add vue-i18n10 yarn add vue-i18n10 vscode在应用商城中搜索i18n Ally:如图 二.实操 安装完以后在对应项目中的跟package.jso…

计算机毕业设计 基于协同过滤算法的个性化音乐推荐系统的设计与实现 Java实战项目 附源码+文档+视频讲解

博主介绍:✌从事软件开发10年之余,专注于Java技术领域、Python人工智能及数据挖掘、小程序项目开发和Android项目开发等。CSDN、掘金、华为云、InfoQ、阿里云等平台优质作者✌ 🍅文末获取源码联系🍅 👇🏻 精…

Charles+socksdroid手机抓包配置

证书配置 保存一个证书 使用abd将证书推送到手机 找手机的加密与凭据 点击从存储设备安装 选择刚刚导入手机的证书 证书按照成功 手机安装socksdroid 端口对应 ip对应 开启 点击allow 成功手机抓包 将用户证书移动到系统证书 系统证书路径:/etc/security/cacerts…

【springboot】整合LoadBalancer

目录 问题产生背景解决方案:实现LoadBalancer1. 添加依赖2. 配置文件3. 使用LoadBalancer4. 使用 RestTemplate 进行服务调用5. 测试 问题产生背景 以下是一个购物车项目,通过调用外部接口获取商品信息,并添加到购物车中,这段代码…

【Android 14源码分析】WMS-窗口显示-第二步:relayoutWindow -1

忽然有一天,我想要做一件事:去代码中去验证那些曾经被“灌输”的理论。                                                                                  – 服装…

【JAVA开源】基于Vue和SpringBoot的宠物咖啡馆平台

本文项目编号 T 064 ,文末自助获取源码 \color{red}{T064,文末自助获取源码} T064,文末自助获取源码 目录 一、系统介绍二、演示录屏三、启动教程四、功能截图五、文案资料5.1 选题背景5.2 国内外研究现状5.3 可行性分析 六、核心代码6.1 查…

使用CSS实现酷炫加载

使用CSS实现酷炫加载 效果展示 整体页面布局 <div class"container"></div>使用JavaScript添加loading加载动画的元素 document.addEventListener("DOMContentLoaded", () > {let container document.querySelector(".container&q…

初识Linux · 自主Shell编写

目录 前言&#xff1a; 1 命令行解释器部分 2 获取用户命令行参数 3 命令行参数进行分割 4 执行命令 5 判断命令是否为内建命令 前言&#xff1a; 本文介绍是自主Shell编写&#xff0c;对于shell&#xff0c;即外壳解释程序&#xff0c;我们目前接触到的命令行解释器&am…

数据提取之JSON与JsonPATH

第一章 json 一、json简介 json简单说就是javascript中的对象和数组&#xff0c;所以这两种结构就是对象和数组两种结构&#xff0c;通过这两种结构可以表示各种复杂的结构 > 1. 对象&#xff1a;对象在js中表示为{ }括起来的内容&#xff0c;数据结构为 { key&#xff1…

区块链+Web3学习笔记(METAMASHK、密码学知识)

学习资料来源于B站&#xff1a; 17小时最全Web3教程&#xff1a;ERC20&#xff0c;NFT&#xff0c;Hardhat&#xff0c;CCIP跨链_哔哩哔哩_bilibili 该课程提供的Github代码地址&#xff0c;相关资料详见README.md&#xff1a; Web3_tutorial_Chinese/README.md at main sm…

银河麒麟系统内存清理

银河麒麟系统内存清理 1、操作步骤2、注意事项 &#x1f490;The Begin&#x1f490;点点关注&#xff0c;收藏不迷路&#x1f490; 当银河麒麟系统运行较长时间&#xff0c;内存中的缓存可能会积累过多&#xff0c;影响系统性能。此时&#xff0c;你可以通过简单的命令来清理这…

JS | 如何解决ajax无法后退的问题?

Ajax请求通常不支持浏览器的后退按钮&#xff0c;因为它们是异步的&#xff0c;不会导致页面重新加载(刷新)。但如果你想要用户能够通过浏览器的后退按钮回到之前的页面状态&#xff0c;你可以通过几种方法来解决这个问题&#xff1a; 1、使用pushState和replaceState方法 hi…

【Android】数据存储

本章介绍Android五种主要存储方式的用法&#xff0c;包括共享参数SharedPreferences、数据库SQLite、SD卡文件、App的全局内存&#xff0c;另外介绍重要组件之一的应用Application的基本概念与常见用法&#xff0c;以及四大组件之一的内容提供器ContentProvider的基本概念与常见…