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的展示
const(查询唯一索引时)
eq_ref(左表有主键索引 且左表每一行和右表刚好匹配)
举个例子:我们创建两个表 user2 和 user2_ex
结果所示:当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;