MySQL 学习笔记
SQL查询的基本执行过程
- 应用通过MySQL API把查询命令发送给MySQL服务器,然后被解析
- 检查权限、MySQL optimizer进行优化,经过解析和优化后的查询命令被编译为CPU可运行的二进制形式的查询计划(query plan),并可以被缓存
- 如果存在索引,那么先扫描索引,如果数据被索引覆盖,那么不需要额外的查找,如果不是,根据索引查找和读取对应的记录
- 如果有关联查询,查询次序是扫描第一张表找到满足条件的记录,按照第一张表和第二张表的关联键值,扫描第二张表查找满足条件的记录,按此顺序循环
- 输出查询结果,并记录binary logs
导出数据:
1 | mysqldump -uroot -p --default-character-set=utf8 crawler > e:/crawler.sql |
导入数据:
导入时出现ERROR at line 206: Unknown command '\''.的错误提示,然后中断。是字符集的问题,加上 --default-character-set=utf8。
1 | mysql -uroot -p --default-character-set=utf8 crawler < e:/crawler.sql |
修改客户端连接编码:
1 | SET NAMES 'utf8'; |
查看最大连接数
1 | show variables like '%max_connections%' |
查看已使用最大连接数
1 | show global status like 'Max_used_connections'; |
使用慢查询记录查询慢的 SQL
1 | slow_query_log -- 慢查询开启状态 |
查看慢查询是否开启
1 | show variables like 'slow_query%'; -- slow_query_log 为 ON 表示开启了, OFF 表示未开启 |
开启慢查询(重启服务生效)
方法一:
1 | set global slow_query_log='ON'; |
方法二:修改配置文件,在 [mysqld] 下加入
1 | slow_query_log = ON |
其中 query_time 表示 query 语句的执行时间,但是为秒, lock time 是锁定的时间, rows_sent 是 query 语句执行返回的记录数,而 rows_examined 则是优化器估算的扫描行数
使用 Query Profiler 分析sql 性能
Query Profiler是MYSQL自带的一种query诊断分析工具,通过它可以分析出一条SQL语句的性能瓶颈在什么地方。Query Profiler是 5.0.37 之后添加的,要想使用此功能,要确保版本在 5.0.37 之后。
查看数据库版本
1 | select version(); |
查看 profiles 功能是否开启
方法一:
1 | show profiles; -- 返回 Empty set, 1 warning (0.00 sec) ,说明没有开启。 |
方法二:
1 | select @@profiling; -- 结果为 1 说明已开启 |
方法三:
1 | show variables like "profiling%"; -- 结果为 On 说明已开启 |
开启当前 session 会话 Query Profiler 功能
1 | set profiling=1; |
根据 query_id 查看某个查询的详细时间耗费
1 | show profile for query query_id; |
查看占用cpu、 io等信息
1 | show profile block io, cpu for query query_id; -- 另外还可以看到 memory,swaps,context switches,source 等信息 |
使用 EXPLAIN 查看 SQL 的执行计划
1 | mysql> explain select * from htmlentity; |
用 EXISTS 替换 DISTINCT:当提交一个包含一对多表信息(比如部门表和雇员表)的查询时,避免在 SELECT 子句中使用 DISTINCT ,一般可以考虑用 EXIST 替换, EXISTS 使查询更为迅速,因为RDBMS核心模块将在子查询的条件一旦满足后,立刻返回结果。
EXPLAIN 参数说明
SELECT_TYPE
SIMPLE: 简单 SELECT (不使用UNION或子查询等)PRIMARY: 最外层的 SELECTUNION: UNION 中的第二个或后面的 SELECT 语句DEPENDENT UNION: UNION 中的第二个或后面的SELECT语句,取决于外面的查询UNION RESULT: UNION 的结果(此时 ID 为 NULL)SUBQUERY: 子查询中的第一个 SELECTDEPENDENT SUBQUERY: 子查询中的第一个 SELECT ,取决于外面的查询DERIVED: 派生表的 SELECT ( FROM 子句的子查询)
TYPE
SYSTEM: CONST的特例,当表上只有一条元组匹配CONST: WHERE条件筛选后表上至多有一条元组匹配时,比如WHERE ID = 2 (ID是主键,值为2的要么有一条要么没有)EQ_REF: 参与连接运算的表是内表(在代码实现的算法中,两表连接时作为循环中的内循环遍历的对象,这样的表称为内表)。基于索引(连接字段上存在唯一索引或者主键索引,且操作符必须是“=”,索引值不能为NULL)做扫描,使得对外表的一条元组,内表只有唯一一条元组与之对应。REF: 可以用于单表扫描或者连接(参与连接运算的表是内表),基于索引(连接字段上的索引是非唯一索引,操作符必须是“=”,连接字段值不可为NULL)做扫描,使得对外表的一条元组,内表可有若干条元组与之对应。FULLTEXT: FULL TEXT,全文检索REF_OR_NULL: 类似REF,只是搜索条件包括:连接字段的值可以为NULL的情况,比如 where col = 2 or col is nullINDEX_MERGE: 多重范围扫描。两表连接的每个表的连接字段上均有索引存在且索引有序,结果合并在一起UNIQUE_SUBQUERY: 在子查询中,基于唯一索引进行扫描,类似于EQ_REFINDEX_SUBQUERY: 在子查询中,基于除唯一索引之外的索引进行扫描RANGE: 范围扫描,基于索引做范围扫描,为诸如BETWEEN,IN,>=,LIKE类操作提供支持INDEX: 索引做扫描,是基于索引在索引的叶子节点上找满足条件的数据(不需要访问数据文件)ALL: 全表扫描或者范围扫描:不使用索引,顺序扫描,直接读取表上的数据(访问数据文件)
KEY_LEN
- 一般地,key_len 等于索引列类型字节长度,例如int类型为 4-bytes , bigint 为 8-bytes
- 如果是字符串类型,还需要同时考虑字符集因素,例如:CHAR(30) UTF8则key_len至少是 90-bytes
- 若该列类型定义时允许 NULL ,其 key_len 还需要再加 1-bytes
- 若该列类型为变长类型,例如 VARCHAR( TEXT\BLOB 不允许整列创建索引,如果创建部分索引,也被视为动态列类型),其 key_len 还需要再加 2-bytes
EXTRA
USING WHERE: 使用了WHERE子句来过滤元组USING TEMPORARY: 用临时表保存中间结果,常用于 GROUP BY 和 ORDER BY 操作中USING FILESORT: 使用文件完成排序操作,这是可能是 ORDERY BY , GROUP BY 语句的结果USING INDEX: 不需要读取数据文件,从索引树(索引文件)中即可获得信息DISTINCT: 优化 DISTINCT 操作,在找到第一匹配的元组后即停止找同样值的动作
修改自增值从 1 开始
1 | ALTER TABLE table_name AUTO_INCREMENT = 1; |
查询库占用大小
1 | SELECT (sum(DATA_LENGTH)+sum(INDEX_LENGTH))/1048576 FROM information_schema.TABLES where TABLE_SCHEMA='knowledge'; |