Mysql数据库Sql优化

2023-11-18

1.选择合适的字段属性

  • mysql中表越小,查询速度越快,所以,我们在创建表时,字段尽可能的设置最小,如果可以的话,可以用MEDIUMINT而不是BIGIN来定义整型字段。
  • 应该尽量把字段设置为NOTNULL,这样在将来执行查询的时候,数据库不用去比较NULL值。
  • 对于某些文本字段,例如“省份”或者“性别”,我们可以将它们定义为ENUM类型。因为在MySQL中,ENUM类型被当作数值型数据来处理,而数值型数据被处理起来的速度要比文本类型快得多。

2、使用连接(JOIN)来代替子查询(Sub-Queries)

用union all代替union

使用union关键字后,可以获取排重后的数据。而如果使用union all关键字,可以获取所有数据,包含重复的数据。

排重的过程需要遍历、排序和比较,它更耗时,更消耗cpu资源。所以如果能用union all的时候,尽量不用union。

SELECT*
FROM customerinfo
WHERE CustomerID
NOT in(
SELECT CustomerID
FROM salesinfo)

如果使用连接(JOIN)..来完成这个查询工作,速度将会快很多。尤其是当salesinfo表中对CustomerID建有索引的话,性能将会更好,查询如下:

SELECT *
FROM customerinfo
LEFT JOIN salesinfo
ON customerinfo.CustomerID=salesinfo.CustomerID
WHERE salesinfo.CustomerID
IS NULL

连接(JOIN)..之所以更有效率一些,是因为MySQL不需要在内存中创建临时表来完成这个逻辑上的需要两个步骤的查询工作。

 3、使用联合(UNION)来代替手动创建的临时表

临时表会被自动删除,从而保证数据库整齐、高效,使用union来创建查询的时候,我们只需要用UNION作为关键字把多个select语句连接起来就可以了

4.事务 

事物以BEGIN关键字开始,COMMIT关键字结束

5.锁表

6.使用外键

7.使用索引

8.优化sql语句

  • 在建有索引的字段上尽量不要使用函数进行操作
  • 尽量不要使用like和通配符,以牺牲系统性能为代价
  • 查询中尽量不要让mysql自动进行类型转换,这样也会使索引失效
  • 只要列中包含有NULL值都将不会被包含在索引中,复合索引中只要有一列含有NULL值,那么这一列对于此复合索引就是无效的。所以我们在数据库设计时不要让字段的默认值为NULL。
  • 使用短索引,如果一个char(255)前面10-20数字都是唯一的,那么应创建指定长度的短索引
  • mysql只会使用一个索引,如果where已经使用了索引,那么orderBy索引就不会生效,在数据库默认排序符合需求的时候,尽量不要使用排序,尽量不要给多个列进行排序,如果需要,应该给这些列建立复合索引
  • like语句因使用‘%name’,而不是'%name%'导致索引失效
  • 不要在列上进行运算操作,这样会导致扫全表,索引失效
  • 不使用NOT IN和<>操作(都会导致索引失效),用not exist和>3 or<3代替!=和<>

.应尽量避免在 where 子句中使用 or 来连接条件,如果一个字段有索引,一个字段没有索引,将导致引擎放弃使用索引而进行全表扫描,如:

select id from t where num=10 or Name = 'admin'

可以这样查询:

select id from t where num = 10
union all
select id from t where Name = 'admin'
  • in 和 not in 也要慎用,否则会导致全表扫描,如:
select id from t where num in(1,2,3)

对于连续的数值,能用 between 就不要用 in 了:

select id from t where num between 1 and 3

很多时候用 exists 代替 in 是一个好的选择:

select num from a where num in(select num from b)

用下面的语句替换:

select num from a where exists(select 1 from b where num=a.num)
  • 不要使用select * from t:select不会走覆盖索引,会出现大量的回表操作,而从导致查询sql的性能很低。此外,多查出来的数据,通过网络IO传输的过程中,也会增加数据传输的时间。
  • 小表驱动大表:这个需求中,order表有10000条数据,而user表有100条数据。order表是大表,user表是小表。如果order表在左边,则用in关键字性能更好。
select * from order
where user_id in (select id from user where status=1)
  • 分批插入

循环插入io消耗过大,也不建议一次批量操作太多的数据,如果数据太多数据库响应也会很慢。批量操作需要把握一个度,建议每批数据尽量控制在500以内。如果数据多于500,则分多批次处理。

  • 多用limit
select id, create_date 
from order 
where user_id=123 
order by create_date asc 
limit 1;

使用limit 1,只返回该用户下单时间最小的那一条数据即可。

update order set status=0,edit_time=now(3) 
where id>=100 and id<200 limit 100;

 这样即使误操作,比如把id搞错了,也不会对太多的数据造成影响。

select id,name from category
where id in (1,2,3...100)
limit 500;

可以在sql中对数据用limit做限制。

  • 增量查询,按条件分批查询
  • 控制索引的数量(不超过五个)
  • 提升group by的效率,先筛选,再分组

  • 索引优化

索引优化的第一步是:检查sql语句有没有走索引。

那么,如何查看sql走了索引没?

可以使用explain命令,查看mysql的执行计划。

explain select * from `order` where code='002';

通过这几列可以判断索引使用情况,执行计划包含列的含义如下图所示:
 

如果没有走索引,排除没有创建,那么就是失效了,检查sql原因改就行

 

有时候mysql会选错索引。

必要时可以使用force index来强制查询sql走某个索引

  • 查看详细信息:show PROFILE cpu,block io for QUERY id;
  • Show Profile 是 MySQL 提供的可以用来分析当前查询 SQL 语句执行的资源消耗情况的工具,可用于 SQL 调优的测量。默认情况下处于关闭状态,开启会消耗一定的性能,一般在 SQL 分析和优化的时候使用,只保存最近15次的运行结果。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Mysql数据库Sql优化 的相关文章

  • PDO获取最后插入的ID

    我有一个查询 我想获取插入的最后一个 ID 字段ID是主键并且自动递增 我知道我必须使用这个声明 LAST INSERT ID 该语句适用于如下查询 query INSERT INTO cell place ID VALUES LAST I
  • 如何调试参数化 SQL 查询

    我使用 C 连接到数据库 然后使用 Ad hoc SQL 来获取数据 这个简单的 SQL 查询非常方便调试 因为我可以记录 SQL 查询字符串 如果我使用参数化 SQL 查询命令 有没有办法记录 sql 查询字符串以进行调试 我想就是这样的
  • 处理大数据表时应该如何使用Hibernate Mapping

    问题定义 我有一个包含大量数据 超过 100 000 行 的数据库表 表结构如下 AppID DocID DocStatus 1 100 0 1 101 1 2 200 0 2 300 1 每个 applicationID 可能有数千个文档
  • Magento - 无法重新索引产品价格 - 外键约束失败

    我最近刚刚将我的 magento 商店从 1 4 2 升级到 1 7 0 2 升级进行得很顺利 但是当我尝试在升级后重新索引数据时 产品价格失败了 我尝试过使用php shell indexer php reindexall来自 SSH 它
  • 在内连接中重用 mysql 子查询

    我正在尝试优化查询 试图避免重复用 指示的查询 复杂查询 使用两次 结果相同 原始查询 SELECT news FROM news INNER JOIN SELECT myposter FROM SELECT COMPLEX QUERY U
  • 使用显式创建表语句与 select into 创建表

    使用显式创建表语句和加载数据与选择数据之间是否存在性能差异 此示例仅显示 2 列 但问题是针对使用非常大的表 下面的示例也使用临时表 尽管我也想知道使用常规表的效果 我认为无论表格类型如何 它们都是相同的 临时表场景 Explicitly
  • 当我尝试计算 mysqli 结果时,为什么会收到警告?

    下面的代码会导致此警告 警告 count 参数必须是数组或实现 Countable 的对象 为什么要这样做 如何防止出现警告 if isset GET edit sonum GET edit update true result mysql
  • MySQL - 查找接近的匹配项

    MySQL 有没有办法在文本字段中找到紧密匹配的内容 说找到 email protected cdn cgi l email protection当搜索时 email protected cdn cgi l email protection
  • 火鸟删除速度很慢

    我正在做这个简单的交易 DELETE FROM ominve01 WHERE CVE OBS IN SELECT CVE OBS FROM minve01 M WHERE M FECHA DOCU lt 31 12 2010 OR FECH
  • 将自动递增值添加到只有一列的表中

    我需要创建一个基本上仅保留索引列表的表 因此 我创建了一个只有一个名为 id 的自动递增列的表 但是 我似乎无法隐式地将自动递增值添加到该表中 我知道通常当您在表中有这样一列 不仅仅是此列 时 您可以执行以下操作 插入表 col1 col2
  • MySQL 组合两个查询

    我有两个 MySQL 查询 QUERY SELECT sodnik 1 FROM prihodnji krog WHERE file id 8778 AND sodnik 1 UNION SELECT sodnik 2 FROM priho
  • mysql时间比较

    我有 job start 和 job end 时间 timediff 会给我时间差 现在我想看看这项工作是否花费了超过 2 小时 30 分钟 我如何比较它 如果我这样做 我会收到错误 timediff job start job end g
  • SQL Server - SQL 替换整个数据库中所有表中的所有列

    这是一个很遥远的事情 我猜这个问题没有简单的答案 但是 我继承了一个数据库 其中填充了一些可怕的数据 许多包含描述的行都有回车符 这意味着当我们 BCP 输出数据时 它会带有回车符 我的问题 有没有办法在 MS SQL Server 中对整
  • SQLite 使用循环重新编号 ID

    您好 我有一个包含许多插入行的表 我需要按 id 对所有行重新编号并排序 我找到了这段代码 但它对我不起作用 SET i 100 UPDATE main Categories SET ID i i 1 WHERE Name White AL
  • 从一张表更新并插入另一张表

    我有两张桌子 table1 ID 代码 姓名 table2 ID 代码 姓名 具有相同的列 我想将数据从 table1 插入到 table2 或更新列 如果 table2 中存在 table1 ID table2 ID 执行此操作的简单方法
  • INTEGER 到 DATETIME 的转换与 VB6 不同

    我正在查看一些遗留的 VB6 代码 比我的时代早很多年 它对 SQL 2005 数据库运行查询 它提供了日期限制WHERE子句 其中日期作为整数值给出CLng VB6 中的日期 e g WHERE SomeDateField gt 4006
  • 如何在 Postgresql 中将 GIST 或 GIN 索引与 hstore 列一起使用?

    我正在使用 postgresql 9 3 的 hstore 我正在尝试对 hstore 列使用索引就像文档所述 http www postgresql org docs 9 3 static hstore html 我的问题是索引似乎没有被
  • LEFT JOIN 比 INNER JOIN 快得多

    我有一张桌子 MainTable 有超过 600 000 条记录 它通过第二个表连接到自身 JoinTable 在父 子类型关系中 SELECT Child ID Parent ID FROM MainTable AS Child JOIN
  • MySQL 两种日期格式之间的转换

    用户将以这种格式输入日期 2017 年 2 月 17 日 存储在 mysql 数据库中的日期格式如下 2015 02 17 00 00 00 我想做的是 SELECT FROM insurance where DATE FORMAT in
  • MySQL 连接器 C++ 64 位在 Visual Studio 2012 中从源代码构建

    我正在尝试建立mySQL 连接器 C 从源头在视觉工作室2012为了64 bit建筑学 我知道这取决于一些boost头文件和C 连接器 跑步CMake生成一个项目文件 但该项目文件无法编译 因为有一大堆非常令人困惑的错误 这些错误可能与包含

随机推荐

  • LVM逻辑卷与条带卷管理

    逻辑卷管理器LVM Logical Volume Manager 在硬盘分区和文件系统之间添加了一个逻辑层 提供了一个抽象的卷组 允许多块硬盘进行卷组合并 不必关注物理硬盘设备的底层架构和布局 实现对硬盘资源的动态调整 条带化逻辑卷在物理卷
  • 组网学习之可扩展性设计(一)

    可扩展性设计策略 可靠性 1 设计冗余链路 为了保证可靠性 问题 会有环路 生成广播风暴 利用树协议解决广播风暴 增加网络带宽 聚合链路 采用分层的网络协议 rip 小型网络 与ospf 大规模 area用来划区域 0为骨干层 采用ap 无
  • 关于Visual Studio编译scanf报错问题以及一劳永逸的解决方法!

    前言 相信很多使用vs编译器初学C语言的同学 刚开始都能碰到这个问题 当你在代码使用了scanf vs编译器就会报错 不管你是2013还是2022以及其他版本都会报错 如上图所示 注意 C语言当中本身scanf是不会错的 怎么解决呢 先来看
  • in _create_inference_session raise ValueError(“This ORT build has {} enabled

    问题 line 363 in create inference session raise ValueError This ORT build has enabled format available providers ValueErro
  • Linux宝塔面板搭建Discuz论坛, 并公网远程访问【内网穿透】

    文章目录 前言 1 安装基础环境 2 一键部署Discuz 3 安装cpolar工具 4 配置域名访问Discuz 5 固定域名公网地址 6 配置Discuz论坛 前言 Crossday Discuz Board 以下简称 Discuz 是
  • jupyter notebook导入模块时报错:ModuleNotFoundError: No module named

    背景 基于anaconda创建虚拟环境后 在虚拟环境中打开jupyter notebook 创建python文件在文件中导入模块时报错 原因 1 虚拟环境中未安装此模块 2 安装完模块后 没有添加核 kernel 解决办法 1 激活虚拟环境
  • IIS7解析漏洞复现

    首先我们在win7上安装IIS7 控制面板 程序 打开或关闭windows功能 勾选如下信息 尽量勾选多一点防止实验失败 点击确定 稍等 在windows7虚拟机安装phpstudy2018版本 可先在物理机下载压缩包 然后上传到虚拟机 然
  • 工程职业伦理_Mooc_2018_期末考试答案

    1 直接在浏览器中在此页面按下ctrl F打开搜索框 2 复制原题目的部分 全部 3 在此页面的搜索框中粘贴复制的内容 即可直接找到此题目 加粗字体为正确答案 直接复制过来的 格式不太好看 单选题 1 1分数 当工程风险产生的不利后果比较严
  • delphi listview动态添加图片_南通启东【长泰海滨城】售楼处电话-位置-价格-开盘时间-最新动态【官网】...

    南通启东 长泰海滨城 售楼处电话 位置 价格 开盘时间 最新动态 官网 2020 10 29 14 38 来源 搜狐焦点淮北站 原标题 南通启东 长泰海滨城 售楼处电话 位置 价格 开盘时间 最新动态 官网 南通启东 长泰海滨城 售楼中心
  • 05笔趣阁小说爬取--爬取作者所有小说

    前面的程序已经实现了从笔趣阁自动爬取整部小说 接下来在之前的基础上 将功能进一步扩展 实现自动爬取某一作者在笔趣阁中的所有小说 继续以方想为例 下图是方想作品列表的页面 https www 52bqg com modules article
  • 伺服怎么接单相220伏_220v电表怎么接线?如何接单相电表?普通家用电表怎么接线...

    以下文章来源于电工电气学习 作者 电工电气学习 单相有功电度表 简称 单相电度表 由接线端子 电流线圈 电压线圈 计量转盘 计数器构成 只要电流线圈通过电流 同时电压线圈加有电压 转盘就受到电磁力而转动 单相电度表共有5个接线端子 其中有两
  • 如何把桌面显示的文件都放在D盘

    1 改目录 具体如下 先在d盘建一个文件夹 然后点开始 运行 regedit 点击HKEY CURRENT USER Software Microsoft Windows CurrentVersion Explorer user Shell
  • leetcode 34. 在排序数组中查找元素的第一个和最后一个位置

    虽然只是一道中等难度的题目 但是看了官方的解答 有很精彩的地方 但是总体代码写得不算优雅 class Solution returns leftmost or rightmost index at which target should b
  • 使用 mock 模拟登录接口数据

    mock js模拟登录接口 第一步 打开apipost 通过mock服务来进行编写登录接口 选择为mock环境 第二步 编写自己的登录接口 apipost支持 req body对象 当 post 请求以 x www form urlenco
  • SpringSecurity+JWT认证流程解析

    楔子 本文适合 对Spring Security有一点了解或者跑过简单demo但是对整体运行流程不明白的同学 对SpringSecurity有兴趣的也可以当作你们的入门教程 示例代码中也有很多注释 大家在做系统的时候 一般做的第一个模块就是
  • 【内外网映射】通过外网ip来访问虚拟机服务器【原创】

    经试验 可以通过外网访问家里笔记本win 7里面的虚拟机vmvare的Ubuntn服务器 比如用手机来访问笔记本电脑的虚拟机的服务器等 注意 win 7的ip地址和虚拟机的ip地址的网段是不一样的 特别注意 只适用于公网ip是固定的 不固定
  • 一看就懂的ReactJs入门教程-精华版

    现在最热门的前端框架有AngularJS React Bootstrap等 自从接触了ReactJS ReactJs的虚拟DOM Virtual DOM 和组件化的开发深深的吸引了我 下面来跟我一起领略ReactJs的风采吧 文章有点长 耐
  • Dbeaver 修改SQL编辑器字体

    Dbeaver 版本 23 1 0 字体链接 YaHei Consolas Hybrid 1 12 YaHei Consolas Hybrid 1 12 如何换字体 窗口 gt 首选项 gt 用户界面 gt Appearance gt Co
  • 30数据类型检测

  • Mysql数据库Sql优化

    1 选择合适的字段属性 mysql中表越小 查询速度越快 所以 我们在创建表时 字段尽可能的设置最小 如果可以的话 可以用MEDIUMINT而不是BIGIN来定义整型字段 应该尽量把字段设置为NOTNULL 这样在将来执行查询的时候 数据库