发布时间:2023-04-28 19:00
MySQL 客户端连接成功后,通过 show [session|global] status 命令可以查看服务器状态信息。通过查看状态信息可以查看对当前数据库的主要操作类型。
--下面的命令显示了当前 session 中所有统计参数的值
show session status like \'Com_______\'; -- 查看当前会话统计结果
show global status like \'Com_______\'; -- 查看自数据库上次启动至今统计结果
show status like \'Innodb_rows_%’; -- 查看针对Innodb引擎的统计结果
可以通过以下两种方式:
慢查询日志 : 通过慢查询日志定位那些执行效率较低的 SQL 语句。
show processlist:该命令查看当前MySQL在进行的线程,包括线程的状态、是否锁表等,可以实时地查看 SQL 的执行情况,同时对一些锁表操作进行优化。
-- 查看慢日志配置信息
show variables like \'%slow_query_log%’;
-- 开启慢日志查询
set global slow_query_log=1;
-- 查看慢日志记录SQL的最低阈值时间
show variables like \'long_query_time%’;
-- 修改慢日志记录SQL的最低阈值时间
set global long_query_time=4;
show processlist;
各个参数的意义:
通过以上步骤查询到效率低的 SQL 语句后,可以通过 EXPLAIN命令获取 MySQL如何执行 SELECT 语句的信息,包括在 SELECT 语句执行过程中表如何连接和连接的顺序。
各个type的展示
结果所示:当user2 和 user_ex的行恰好一一对应的时候查找模式为all(因为有 * )和eq_ref
而添加一个重复元素后,就不能使用eq_ref了,效率降低。
ref允许左表匹配右表多行。
重点是这个比较的大于顺序,一定要记牢,优化时候尽量把它维持在index等级之上。
查找步骤 : 使用查找语句> show profiles展示>找到你要分析语句的序号> show profile for 你要找的语句
可以如上图最后一条 查找语句的cpu占用。
创建组合索引,提高查找速度。要时刻遵循最左匹配法则,不能跳过。 要注意,实际查询值越高,就使用了越多的索引,速度越高。
对比
同样的道理password没加索引,效率下降。
当我们一个列重复的数据较多时,我们查找重复的数据时,比如在下图找地址在北京的数据。数据库会自动为我们全表查询,此时全表查询效率较高。
而查找西安市的时候,会使用索引查询。
not in和in跟上面 道理一样 多就不用索引。
下面的显示来自extra
尽量顺序一致,排序方式相同
当我们迫不得已使用Filesort 时
通过创建合适的索引,能够减少 Filesort 的出现,但是在某些情况下,条件限制不能让Filesort消失,那就需要加快 Filesort的排序操作。对于Filesort , MySQL 有两种排序算法:
1) 两次扫描算法 :MySQL4.1 之前,使用该方式排序。首先根据条件取出排序字段和行指针信息,然后在排序区 sort buffer 中排序,如果sort buffer不够,则在临时表 temporary table 中存储排序结果。完成排序之后,再根据行指针回表读取记录,该操作可能会导致大量随机I/O操作。
2)一次扫描算法:一次性取出满足条件的所有字段,然后在排序区 sort buffer 中排序后直接输出结果集。排序时内存开销较大,但是排序效率比两次扫描算法要高。
MySQL 通过比较系统变量 max_length_for_sort_data 的大小和Query语句取出的字段总大小, 来判定是否那种排序算法,如果max_length_for_sort_data 更大,那么使用第二种优化之后的算法;否则使用第一种。
可以适当提高 sort_buffer_size 和 max_length_for_sort_data 系统变量,来增大排序区的大小,提高排序的效率。
或者
当我们要用.log
文件导入大量数据,怎么做才更有效率呢?
插入方法
-- 1、首先,检查一个全局系统变量 \'local_infile\' 的状态, 如果得到如下显示 Value=OFF,则说明这是不可用的
show global variables like \'local_infile\';
-- 2、修改local_infile值为on,开启local_infile
set global local_infile=1;
-- 3、加载数据
load data local infile \'D:\\\\sql_data\\\\sql1.log\' into table tb_user fields terminated by \',\' lines terminated by \'\\n\';
关闭唯一检索
mysql在添加数据时会检测唯一索引的数据是否重复。如果我们事先已经检查好,就可以关闭唯一检索,提高效率。
-- 关闭唯一性校验
SET UNIQUE_CHECKS=0;
truncate table tb_user;
load data local infile \'D:\\\\sql_data\\\\sql1.log\' into table tb_user fields terminated by \',\' lines terminated by \'\\n\';
SET UNIQUE_CHECKS=1;
三个方向
有序插入
-- 数据有序插入
insert into tb_test values(4,\'Tim\');
insert into tb_test values(1,\'Tom\');
insert into tb_test values(3,\'Jerry\');
insert into tb_test values(5,\'Rose\');
insert into tb_test values(2,\'Cat\');
-- 优化后
insert into tb_test values(1,\'Tom\');
insert into tb_test values(2,\'Cat\');
insert into tb_test values(3,\'Jerry\');
insert into tb_test values(4,\'Tim\');
insert into tb_test values(5,\'Rose\');
尽量集中插入
-- 如果需要同时对一张表插入很多行数据时,应该尽量使用多个值表的insert语句,这种方式将大大的缩减客户端与数据库之间的连接、关闭等消耗。使得效率比分开执行的单个insert语句快。
-- 原始方式为:
insert into tb_test values(1,\'Tom\');
insert into tb_test values(2,\'Cat\');
insert into tb_test values(3,\'Jerry\');
-- 优化后的方案为 :
insert into tb_test values(1,\'Tom\'),(2,\'Cat\'),(3,\'Jerry\');
用一个事务插入(记得提前关了自动提交)
-- 在事务中进行数据插入。
begin;
insert into tb_test values(1,\'Tom\');
insert into tb_test values(2,\'Cat\');
insert into tb_test values(3,\'Jerry\');
commit;