Mysql

关注公众号 jb51net

关闭
首页 > 数据库 > Mysql > MySQL优化

MySQL常用命令与内部组件及SQL优化详情

作者:Hz488​​​​​​​

这篇文章主要介绍了MySQL常用命令与内部组件及SQL优化详情,文章围绕主题展开详细的内容介绍,具有一定的参考价值,需要的朋友可以参考一下

1. 一些常用的 MySQL 命令

#连接MySQL
mysql -h 127.0.0.1 -u UserName -p  pwd -P 3306
#创建新用户
CREATE USER 'username'@'host' IDENTIFIED BY 'password';
#赋权限,%表示所有(host):
grant all privileges on *.* to 'username'@'%';
#修改密码
update user set password=password("123456") where user='root';
#查看当前用户的权限
show grants for root@"%";
#显示所有数据库
show databases; 
#打开数据库
use dbname; 
#查看库中有哪些表
show tables
#显示表mysql数据库中user表的列信息)
describe user
#查看连接(包括用户、正在执行的操作、状态等)
show processlist 
#刷新连接
flush privileges
#关闭某连接
kill id
#查询库中所有的表
select * from information_schema.tables where table_schema='zhebase';
#查询表信息(字段,字段类型,是否为空,编码,备注等)
select * from information_schema.columns where table_schema='zhebase' and table_name='student_inndb';
#查看MySQL权限 Host列表示那个Ip可以连接,User表示用户,后面的字段是权限
select * from mysql.user;
#查看全局服务器关闭非交互连接之前等待活动的秒数
show global variables like "wait_timeout";
#设置全局服务器关闭非交互连接之前等待活动的秒数(默认8小时不发送命令自动断连)
set global wait_timeout=28800; 

开发当中我们大多数时候用的都是长连接,把连接放在 Pool 内进行管理,但是长连接有时候会导致 MySQL 占用内存飙升,这是因为 MySQL 在执行过程中临时使用的内存是管理在连接对象里面的。这些资源会在连接断开的时候才释放。所以如果长连接累积下来,可能导致内存占用太大,被系统强行杀掉(OOM),从现象看就是 MySQL 异常重启了。 怎么解决这类问题呢?  1、定期断开长连接。 使用一段时间,或者程序里面判断执行过一个占用内存的大查询后,断开连接,之后要查询再重连。  2、如果你用的是 MySQL 5.7 或更新版本,可以在每次执行一个比较大的操作后,通过执行 mysql_reset_connection 来重新初始化连接资源。 这个过程不需要重连和重新做权限验证,但是会将连接恢复到刚刚创建完时的状态。

为什么说MySQL查询缓存是否鸡肋?

#my.cnf配置文件中,一般将my.cnf参数 query_cache_type 设置成 DEMAND
query_cache_type有3个值 0代表关闭查询缓存OFF,1代表开启ON,2(DEMAND)代表当sql语句中有SQL_CACHE 关键词时才缓存

2.MySQL的内部组件结构

 连接MySQL的过程:

MySQL优化器与执行计划

工作过程:

SQL执行过程

词法分析器原理

词法分析器分成6个主要步骤完成对sql语句的分析  1、词法分析  2、语法分析  3、语义分析  4、构造执行树  5、生成执行计划  6、计划的执行

查询优化器

举例:

Select  EMPLOYEE.Name , WELFARE.Bonus From  EMPLOYEE , WELFARE  Where  EMPLOYEE.Seniority > 5  And  EMPLOYEE.Seniority = WELFARE.Seniority ;
Select  EMPLOYEE.Name , WELFARE.Bonus From  EMPLOYEE , WELFARE  Where  EMPLOYEE.Seniority > 5  And  EMPLOYEE.Seniority = WELFARE.Seniority   And  EMPLOYEE.Seniority > 5;

查询重写: 因为第一条将EMPLOYEE中Seniority > 5 的行与 WELFARE 中的所有行作外连接再来找 Seniority 相等的行,而第二条则是将 EMPLOYEE 中 Seniority > 5 的行和 WELFARE 中 Seniority > 5 的行作外连接再来找 Seniority 相等的行,第二条语句只有更少的行参与外连接,效率更高。写 SQL 时查询优化器自动重写。

4. SQL执行顺序

(7) SELECT (8) DISTINCT <select_list>
(1) FROM <left_table>
(3) <join_type> JOIN <right_table>
(2) ON <join_condition>
(4) WHERE <where_condition>
(5) GROUP <group_by_list>
(6) HAVING <having_condition>
(9) ORDER BY <order_by_list>
(10) LIMIT <limit_number>

5.MySQL数据类型选择

在设计表时,选择数据类型时一般先确定大的类型(数字,字符串,时间,二进制),然后再根据有无符号、取值范围、是否定长等确定具体的数据类型。在设计时,尽量使用更小的数据类型以达到更优的性能。并且在定义时尽量使用 NOT NULL,避免 NULL 值。

数值类型

首先了解:

类型大小范围(有符号)范围(无符号)用途
TINYINT1 字节[27,27-1][0,28-1]小整数值
SMALLINT2 字节[215,215-1][0,216-1]大整数值
MEDIUMINT3 字节[223,223-1][0,224-1]大整数值
INT/INTEGER4 字节[231,231-1][0,232-1]大整数值
BIGINT8 字节[263,263-1][0,264-1]极大整数值
FLOAT4 字节约-3.40E+38 ~ 3.40E+38约0~3.40E+38单精度浮点数值
DOUBLE8 字节约1.7E-308~1.7E+308约0~1.7E+308双精度浮点数值
DECIMALDECIMAL(M,D)依赖于M和D的值依赖于M和D的值小数值

建议:

日期和时间

 建议:

字符串

类型大小用途
CHAR0-255字节定长字符串,char(n)当插入的字符串实际长度不足n时, 插入空格进行补充保存。在进行检索时,尾部的空格会被去掉。
VARCHAR0-65535 字节变长字符串,varchar(n)中的n代表最大列长度,插入的字符串实际长度不足n时不会补充空格
TINYBLOB0-255字节不超过 255 个字符的二进制字符串
TINYTEXT0-255字节短文本字符串
BLOB0-65535字节二进制形式的长文本数据
TEXT0-65535字节长文本数据
MEDIUMBLOB0-16777215字节二进制形式的中等长度文本数据
MEDIUMTEXT0-16777215字节中等长度文本数据
LONGBLOB0-4 294967295字节二进制形式的极大文本数据
LONGTEXT0-4 294967295字节极大文本数据

建议

6.MySQL优化

MySQL优化分类

优化方法

SQL优化原则

减少访问量: 数据存取是数据库系统最核心功能,所以 IO 是数据库系统中最容易出现性能瓶颈,减少 SQL 访问 IO 量是 SQL 优化的第一步;数据块的逻辑读也是产生CPU开销的因素之一。

减少计算操作: 计算操作进行优化也是SQL优化的重要方向。SQL 中排序、分组、多表连接操作等计算操作都是十分消耗 CPU 的。

EXPLAIN 查看执行计

 type列,连接类型。一个好的SQL语句至少要达到range级别。杜绝出现all级别。

key列,使用到的索引名。如果没有选择索引,值是NULL。 key_len列,索引长度。 rows列,扫描行数。该值是预估值。 extra列,详细说明。注意,常见的不太友好的值,如下:Using filesort,Using temporary。

processlist干预执行计划

SELECT语句务必指明字段名称

SELECT * 增加很多不必要的消耗(CPU、IO、内存、网络带宽) 直接使用select字段名称还增加了使用覆盖索引的可能性

select id,name from customer limit 100000, 10 //查询从十万条开始的20条数据

上述代码,随着分页的后移,效率越来越慢,优化方法如下:可以取上一页的最大行数的 id(前提是ID 递增,且非联合主键,一般不建议设置联合主键,主键前面都可以加上ID作为主键),然后根据这个最大的 ID 来限制下一页的起点。或者通过索引查 id,在通过id查询出数据

合理使用in和exits

select * from A where id in (select id from B)
select * from A where exists(select id from B where id=A.id)

in先执行子查询再执行主查询,exits先执行主查询再执行子查询。如果子查询得出的结果集记录较少,主查询中的表较大且又有索引时应该用in反之如果外层的主查询记录较少,子查询中的表大,又有索引时使用exists

原则:小表驱动大表

关于not in 和not exists

如果查询语句使用了 not in 那么内外表都会放弃索引进行全表扫描;而 not extsts 的子查询依然能用到表上的索引。所以 not exists 都比 not in 要快。也可以使用一些方法转换逻辑来进行优化

//原SQL语句:
select name from A where A.id not in (select B.id from B)
//优化后的SQL语句:
select name from A Left join B on where A.id = A.id where B.id is null

order by排序字段和where条件要匹配(关于联合索引)

当 where 条件和 order by 排序字段不匹配时,即使where条件中用到了索引,但执行 order by 时仍然会进行全表扫描(索引只能生效一个,且遵循最左匹配原则);order by后的索引生效时(索引本质是倒排表)效率会得到极大的提升。

select a,b,c from customer where a = 'xxx' and b = 'xxx' order by c;

不建议使用%前缀模糊查询

使用like '%name%'或者like '%name'会导致索引失效而导致全表扫描。但使用like 'name%'不会。

解决方法:

注意:  1.全文索引的存储引擎一定是Myisam,InnoDB没有全文索引  2.全文索引对中文不太友好

//创建全文索引
ALTER TABLE cust ADD FULLTEXT INDEX idx_cust_address ('cust_address');
//使用全文索引
select name from cust where match(cust_address) against('湖南');

倒排索引是一种索引数据结构:从文本数据内容中提取出不重复的单词进行分词,每1个单词对应1个ID对单词进行区分,还对应1个该单词在那些文档中出现的列表 把这些信息组建成索引。倒排索引还记录了该单词在文档中出现位置、频率(次数/TF)用于快速定位文档和对搜素结果进行排序。

关于范围查询

对于联合索引来说,如果存在范围查询,比如between、>、<等条件时,会造成后面的索引字段失效

避免在where子句中对字段进行null值判断及!=和<>

对于null的判断以及!=和<>会导致引擎放弃使用索引而进行全表扫描。

关于OR

尽量使用union all或者是union方式来代替or。  union和union all的区别主要是union需要将结果集合并后再进行过滤操作过滤掉重复数据,这就会涉及到排序,增加大量的CPU运算,加大资源消耗及延迟。使用union all的前提条件是两个结果集没有重复数据。

只需要一条数据的时候,使用limit 1

可以使EXPLAIN中type列达到const类型

分段查询

在一些用户选择页面中,可能一些用户选择的时间范围过大,造成查询缓慢。主要的原因是扫描行数过多。这个时候可以通过程序,分段进行查询,循环遍历,将结果合并处理进行展示。

避免在where子句中对字段进行表达式及函数操作

应避免在where子句中对字段进行函数等操作,这将导致引擎放弃使用索引而进行全表扫描。

//原SQL
select id,name from customer where salary/2 > 5000;
//优化后
select id,name from customer where salary > 5000*2;

尽量使用 inner join,避免 left join

参与联合查询的表至少为2张表,一般都存在大小之分。如果连接方式是inner join,在没有其他过滤条件的情况下,MySQL会自动选择小表作为驱动表,但是left join在驱动表的选择上遵循的是左边驱动右边的原则,即left join左边的表名为驱动表。

IN包含的值不应过多

MySQL对于IN做了相应的优化,即将IN中的常量全部存储在一个数组里面,而且这个数组是排好序的。但是如果数值较多,产生的消耗也是比较大的。再例如:select id from t where num in(1,2,3) 对于连续的数值,能用between就不要用in了。或者使用连接来替换。

关于索引

到此这篇关于MySQL常用命令与内部组件及SQL优化详情的文章就介绍到这了,更多相关MySQL优化内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文