分享几个简单MySQL优化小妙招


Posted in MySQL onMarch 31, 2022

SQL语句执行顺序

分享几个简单MySQL优化小妙招

设置大小写不敏感

  • 查看大小写是否敏感:show variables like '%lower_case_table_names%'; windows 系统默认大小写不敏感,但是 linux 系统是大小写敏感的。
  • 设置大小写不敏感:在 my.cnf 这个配置文件 [mysqld] 中加入 lower_case_table_names = 1 ,然后重启服务器。
属性设置 描述
0 大小写敏感
1 大小写不敏感。创建的表,数据库都是以小写形式存放在磁盘上,对于 sql 语句都是转换为小写对表和 DB 进行查找
2 创建的表和 DB 依据语句上格式存放,凡是查找都是转换为小写进行

注意:在设置属性为大小写不敏感前就需要将原来的数据库和表转换为小写,否则会找不到数据库名。 ​

MySql 的用户和权限管理

用户管理: ​

-- 创建用户
create user ahzoo identified by '123456'; 

-- 查看用户和权限的相关信息
select host,user,password,select_priv,insert_priv,drop_priv from mysql.user

-- 修改当前用户密码
set password =password('1234');

-- 修改其他用户密码
update mysql.user set password=password('123456') where user='ouo';
-- 所有通过user表的操作,都必须使用下面命令才能生效
flush privileges;

-- 修改用户名
update mysql.user set user='ahzoo' where user='ouo';
flush privileges;

-- 删除用户
drop user ouo;
-- 注意:删除用户时,不建议使用下面命令进行删除,因为系统会有残留信息保留
delete from user where user='ouo' 
flush privileges;

权限管理: ​

授予权限

grant 权限 1,权限 2,…权限 n on 数据库名称.表名称 to 用户名@用户地址 identified by '密码';

-- 授予数据库下所有表,所有权限
grant all privileges on testDB.* to ahzoo@localhost identified by '123456';
-- 授予所有库、表增删改查权限
grant select,insert,delete,drop on *.* to ahzoo@localhost identified by '123456';
-- 对网络用户授权;@'%' 表示对非本地主机用户授权,不包括localhost
grant all privileges on *.* to ouo@'%' identified by '123456'


-- 查看权限
show grants;

取消权限

revoke [权限 1,权限 2,…权限 n] on 库名.表名 from 用户名@用户地址;

revoke all privileges on testDB.* from ahzoo@localhost;

索引优化

在数据之外,数据库系统还维护着满足特定查找算法的数据结构,这些数据结构以某种方式引用(指向)数据, 这样就可以在这些数据结构上实现高级查找算法。这种数据结构,就是索引。

下图就是一种可能的索引方式示例:

分享几个简单MySQL优化小妙招

左边是数据表,一共有两列七条记录,最左边的是数据记录的物理地址。为了加快 Col2 的查找,可以维护一个 右边所示的二叉查找树,每个节点分别包含索引键值和一个指向对应数据记录物理地址的指 针,这样就可以运用 二叉查找在一定的复杂度内获取到相应数据,从而快速的检索出符合条件的记录。 一般来说索引本身也很大,不可能全部存储在内存中,因此索引往往以索引文件的形式存储的磁盘上。

索引优势: ​

  • 提高数据检索的效率,降低数据库的IO成本。
  • 通过索引列对数据进行排序,降低数据排序的成本,降低了CPU的消耗。

索引劣势: ​

  • 虽然索引大大提高了查询速度,同时却会降低更新表的速度,如对表进行INSERT、UPDATE和DELETE。因为更新表时,MySQL不仅要保存数据,还要保存一下索引文件每次更新添加了索引列的字段,都会调整因为 更新所带来的键值变化后的索引信息。
  • 实际上索引也是一张表,该表保存了主键与索引字段,并指向实体表的记录,所以索引列也是要占用空间的。

MySQL 索引

Btree

MySQL 使用的是 Btree 索引: ​

分享几个简单MySQL优化小妙招

一颗 b 树,浅蓝色的块我们称之为一个磁盘块,可以看到每个磁盘块包含几个数据项(深蓝色所示)和指针(黄色所示),如磁盘块 1 包含数据项 17 和 35,包含指针 P1、P2、P3,P1 表示小于 17 的磁盘块,P2 表示在 17 和 35 之间的磁盘块,P3 表示大于 35 的磁盘块。

真实的数据存在于叶子节点即 3、5、9、10、13、15、28、29、36、60、75、79、90、99。

非叶子节点只不存储真实的数据,只存储指引搜索方向的数据项,如 17、35 并不真实存在于数据表中。

查找过程: ​

如果要查找数据项 29,那么首先会把磁盘块 1 由磁盘加载到内存,此时发生一次 IO,在内存中用二分查找确定 29在 17 和 35 之间,锁定磁盘块 1 的 P2 指针,内存时间因为非常短(相比磁盘的 IO)可以忽略不计,通过磁盘块 1的 P2 指针的磁盘地址把磁盘块 3 由磁盘加载到内存,发生第二次 IO,29 在 26 和 30 之间,锁定磁盘块 3 的 P2 指针,通过指针加载磁盘块 8 到内存,发生第三次 IO,同时内存中做二分查找找到 29,结束查询,总计三次 IO。

真实的情况是,3 层的 b+树可以表示上百万的数据,如果上百万的数据查找只需要三次 IO,性能提高将是巨大的,如果没有索引,每个数据项都要发生一次 IO,那么总共需要百万次的 IO,显然成本非常非常高。

​B+tree

分享几个简单MySQL优化小妙招

B+Tree 与 B-Tree 的区别: ​

1、B-树的关键字和记录是放在一起的,叶子节点可以看作外部节点,不包含任何信息;B+树的非叶子节点中只有关键字和指向下一个节点的索引,记录只放在叶子节点中。

2、在 B-树中,越靠近根节点的记录查找时间越快,只要找到关键字即可确定记录的存在;而 B+树中每个记录的查找时间基本是一样的,都需要从根节点走到叶子节点,而且在叶子节点中还要再比较关键字。从这个角度看 B- 树的性能好像要比 B+树好,而在实际应用中却是 B+树的性能要好些。因为 B+树的非叶子节点不存放实际的数据,这样每个节点可容纳的元素个数比 B-树多,树高比 B-树小,这样带来的好处是减少磁盘访问次数。尽管 B+树找到一个记录所需的比较次数要比 B-树多,但是一次磁盘访问的时间相当于成百上千次内存比较的时间,因此实际中B+树的性能可能还会好些,而且 B+树的叶子节点使用指针连接在一起,方便顺序遍历(例如查看一个目录下的所有文件,一个表中的所有记录等),这也是很多数据库和文件系统使用 B+树的缘故。

为什么 B+树比 B-树更适合实际应用中操作系统的文件索引和数据库索引: ​

B+树的磁盘读写代价更低

B+树的内部结点并没有指向关键字具体信息的指针。因此其内部结点相对 B 树更小。如果把所有同一内部结点的关键字存放在同一盘块中,那么盘块所能容纳的关键字数量也越多。一次性读入内存中的需要查找的关键字也就越多。相对来说 IO 读写次数也就降低了。

B+树的查询效率更加稳定

由于非终结点并不是最终指向文件内容的结点,而只是叶子结点中关键字的索引。所以任何关键字的查找必须走一条从根结点到叶子结点的路。所有关键字查询的路径长度相同,导致每一个数据的查询效率相当。

​聚簇索引和非聚簇索引

聚簇索引并不是一种单独的索引类型,而是一种数据存储方式。术语‘聚簇’表示数据行和相邻的键值聚簇的存储 在一起。
如下图,左侧的索引就是聚簇索引,因为数据行在磁盘的排列和索引排序保持一致。

分享几个简单MySQL优化小妙招

聚簇索引的好处:

按照聚簇索引排列顺序,查询显示一定范围数据的时候,由于数据都是紧密相连,数据库不不用从多 个数据块中提取数据,所以节省了大量的 io 操作。

聚簇索引的限制:

对于 mysql 数据库目前只有 innodb 数据引擎支持聚簇索引,而 Myisam 并不支持聚簇索引。 由于数据物理存储排序方式只能有一种,所以每个 Mysql 的表只能有一个聚簇索引。一般情况下就是 该表的主键。 为了充分利用聚簇索引的聚簇的特性,所以 innodb 表的主键列尽量选用有序的顺序 id,而不建议用 无序的 id,比如 uuid 这种

Mysql 索引分类

-- 创建
CREATE [UNIQUE] INDEX [indexName] ON table_name(column))
-- 删除 
DROP INDEX [indexName] ON tableName;
-- 查看 
SHOW INDEX FROM tableName;

-- 使用Alter命令:

-- 该语句添加一个主键,这意味着索引值必须是唯一的,且不能为 NULL:
ALTER TABLE tbl_name ADD PRIMARY KEY (column_list) 

ALTER TABLE tbl_name ADD PRIMARY KEY (column_list)

-- 添加普通索引,索引值可出现多次:
ALTER TABLE tbl_name ADD INDEX index_name (column_list) 

--该语句指定了索引为 FULLTEXT ,用于全文索引:
ALTER TABLE tbl_name ADD FULLTEXT index_name (column_list)

单值索引

即一个索引只包含单个列,一个表可以有多个单列索引。 ​

-- 在表创建时直接创建索引
CREATE TABLE customer (
  id INT(10) UNSIGNED AUTO_INCREMENT ,
  customer_no VARCHAR(200),
  customer_name VARCHAR(200), 
  PRIMARY KEY(id),  
  KEY (customer_name)
);
-- 单独创建索引:

CREATE INDEX idx_customer_name ON customer(customer_name);

唯一索引

索引列的值必须唯一,但允许有空值。 ​

随表一起创建:

CREATE TABLE customer (
  id INT(10) UNSIGNED AUTO_INCREMENT ,
  customer_no VARCHAR(200),
  customer_name
    VARCHAR(200), 
  PRIMARY KEY(id), 
  KEY (customer_name), 
  UNIQUE (customer_no)
);

 单独建唯一索引:

CREATE UNIQUE INDEX idx_customer_no ON customer(customer_no

主键索引

设定为主键后数据库会自动建立索引,innodb为聚簇索引。 ​

-- 随表创建
CREATE TABLE customer (
  id INT(10) UNSIGNED AUTO_INCREMENT ,
  customer_no VARCHAR(200),
  customer_name
    VARCHAR(200), 
  PRIMARY KEY(id)
);

-- 单独建主键索引:
ALTER TABLE customer add PRIMARY KEY customer(customer_no)

-- 删除建主键索引:
ALTER TABLE customer drop PRIMARY

复合索引

即一个索引包含多个列。 ​

-- 随表一起建索引:
CREATE TABLE customer (
  id INT(10) UNSIGNED AUTO_INCREMENT ,
  customer_no VARCHAR(200),
  customer_name
    VARCHAR(200), 
  PRIMARY KEY(id), 
  KEY (customer_name), 
  UNIQUE (customer_name), 
  KEY (customer_no,customer_name)
);

-- 单独建索引:
CREATE INDEX idx_no_name ON customer(customer_no,customer_name);

索引优化

  • 最佳左前缀法则

使用复合索引时,需遵循最左前缀法则(查询从索引的最左前列开始并且不跳过索引中的列)。即过滤条件要使用索引必须按照索引建立时的顺序,依次满足,一旦跳过某个字段,索引后面的字段都无法被使用。

  • 不要在索引列上做任何计算

索引列上做【计算、函数、(自动\手动)类型转换】等操作时,会导致索引失效而转向全表扫描。

  • 索引列上不能有范围查询

执行mysql命令时应将可能做范围查询的字段的索引顺序放在最后。

  • 尽量使用覆盖索引

覆盖索引:SQL 只需要通过索引就可以返回查询所需要的数据,而不必通过二级索引查到主键之后再去查询数据。即查询列和索引列时不要使用 select *…而是使用select a,b,c….。

  • 1、使用不等于(!= 或者<>)时,有时会无法使用索引会导致全表扫描。
  • 2、字段的 is null 可以用到索引 而 is not null 不会使用索引。
  • 3、不能使用前缀进行模糊匹配:
... like '%a%'  √... like '%a'     √... like 'a%'     ×

使用 union all 或者 union 来替代or示例:

假设abc为索引

-- 索引被使用:
where a = 3;
where a = 3 and b = 5;
where a = 3 and b = 5 and c = 4;

-- 索引未被使用:
where a <> 3;
where abs(a) =3;
where b = 3;
where b = 3 and c = 4;
where c = 4;

-- 使用到a索引,但是未使用b、c索引
where a = 3 and c = 5;
where a = 3 and b > 4 and c = 5;
where a is null and b is not null;

子查询优化

在范围判断时,尽量不要使用 not in 和 not exists,使用 left join on xxx i。

排序分组优化

  • 无过滤,不索引

where,limt 都相当于一种过滤条件,所以才能使用上索引。

  • 顺序错,必排序

where 两侧列的顺序可以变换,效果相同,但是 order by 列的顺序不能随便变换。

  • 方向反,必排序

如果可以用上索引的字段都使用正序或者逆序,实际上是没有任何影响的,无非将结果集调换顺序。

-- 两个排序方式都是desc:
select * from mytest where name='ahzoo' order by deptid desc, name desc

如果排序的字段,顺序有差异,就需要将差异的部分,进行一次倒置顺序,因此还是需要手动排序的。

-- 两个排序方式相反,一个是降序一个是升序
select * from mytest where name='ahzoo' order by deptid desc, name asc

到此这篇关于分享几个简单MySQL优化小妙招的文章就介绍到这了,更多相关MySQL优化小妙招内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

MySQL 相关文章推荐
MySQL之高可用集群部署及故障切换实现
Apr 22 MySQL
MySQL时间盲注的五种延时方法实现
May 18 MySQL
MySQL 亿级数据导入导出及迁移笔记
Jun 18 MySQL
MySQL系列之十 MySQL事务隔离实现并发控制
Jul 02 MySQL
Centos7中MySQL数据库使用mysqldump进行每日自动备份的编写
Aug 02 MySQL
MySQL分库分表详情
Sep 25 MySQL
MySQL中varchar和char类型的区别
Nov 17 MySQL
关于MySQL中的 like操作符详情
Nov 17 MySQL
mysql的Buffer Pool存储及原理
Apr 02 MySQL
MySQL表锁、行锁、排它锁及共享锁的使用详解
Apr 02 MySQL
MySQL数据库如何查看表占用空间大小
Jun 10 MySQL
MYSQL中文乱码问题的解决方案
Jun 14 MySQL
MySQL Server 层四个日志
MySQL RC事务隔离的实现
mysql中DCL常用的用户和权限控制
Mar 31 #MySQL
Mysql分析设计表主键为何不用uuid
你真的会用Mysql的explain吗
MySQL限制查询和数据排序介绍
MySQL学习必备条件查询数据
You might like
PHP 表单提交给自己
2008/07/24 PHP
joomla内置的表单验证功能使用方法
2010/06/11 PHP
php去除头尾空格的2种方法
2015/03/16 PHP
php代码架构的八点注意事项
2016/01/25 PHP
php数组指针操作详解
2017/02/14 PHP
PHP实现将几张照片拼接到一起的合成图片功能【便于整体打印输出】
2017/11/14 PHP
laravel ORM关联关系中的 with和whereHas用法
2019/10/16 PHP
jquery获取iframe中的dom对象(两种方法)
2013/07/02 Javascript
JS获取节点的兄弟,父级,子级元素的方法
2014/01/09 Javascript
jQuery实现仿路边灯箱广告图片轮播效果
2015/04/15 Javascript
js实现向右横向滑出的二级菜单效果
2015/08/27 Javascript
JS两个数组比较,删除重复值的巧妙方法(推荐)
2016/06/03 Javascript
js 上传文件预览的简单实例
2016/08/16 Javascript
完美解决jQuery的hover事件在IE中不停闪动的问题
2017/02/10 Javascript
BootStrap表单控件之文本域textarea
2017/05/23 Javascript
vue脚手架中配置Sass的方法
2018/01/04 Javascript
解决layui数据表格Date日期格式的回显Object的问题
2019/09/19 Javascript
详解vue修改elementUI的分页组件视图没更新问题
2020/11/13 Javascript
[01:45]亚洲邀请赛互动指南虚拟物品介绍
2015/01/30 DOTA
[02:28]DOTA2 2015国际邀请赛中国区预选赛首日现场百态
2015/05/26 DOTA
Python多线程学习资料
2012/12/19 Python
Python的Django框架中自定义模版标签的示例
2015/07/20 Python
利用Python爬取微博数据生成词云图片实例代码
2017/08/31 Python
Django中使用第三方登录的示例代码
2018/08/20 Python
PyQt5的安装配置过程,将ui文件转为py文件后显示窗口的实例
2019/06/19 Python
python标识符命名规范原理解析
2020/01/10 Python
如何利用CSS3制作3D效果文字具体实现样式
2013/05/02 HTML / CSS
小学庆六一活动方案
2014/02/28 职场文书
歌唱比赛主持词
2014/03/18 职场文书
解除财产保全担保书
2014/05/20 职场文书
机械机修工岗位职责
2014/08/03 职场文书
2014年国庆节寄语
2014/09/19 职场文书
2015年办公室主任工作总结
2015/04/09 职场文书
因身体原因离职的辞职信范文
2015/05/12 职场文书
同意落户证明
2015/06/19 职场文书
python常见的占位符总结及用法
2021/07/02 Python