Mysql学习

显示字符集编码

Mysql学习

mysql架构

Mysql学习

逻辑架构

Mysql学习
  • Client :
    提供连接MySQL服务器功能的常用工具集
  • Server :
    MySQL实例,真正提供数据存储和数据处理功能的MySQL服务器进程
  • mysqld:
    MySQL服务器守护程序,在后台运行。它管理着客户端请求。mysqld是一个多线程的进程,允许多个会话连接,端口监听连接,管理MySQL实例
  • MySQL memory allocation:
    MySQL的要求的内存空间是动态的,比如 innodb_buffer_pool_size (from 5.7.5), key_buffer_size。每个会话都有独一无二的执行计划,我们只能共享同一会话域内的数据集。
  • SESSION
    为每个客户端连接分配一个会话,动态分配和回收。用于查询处理,每个会话同时具备一个缓冲区。每个会话是作为一个线程执行的
  • Parser
    检测SQL语句语法,为每条SQL语句生成 SQL_ID,用户认证也发生在这个阶段
  • Optimizer
    创造一个有效率的执行计划(根据具体的存储引擎)。它将会重写查询语句。比如:InnoDB有共享缓冲区,所以,优化器会首先从预先缓存的数据中提取。使用 table statistics optimizer将会为SQL查询生成一个执行计划。用户权限检查也发生在这个阶段。
  • Metadata cache
    缓存对象元信息和统计信息
  • Query cache
    共享在内存中的完全一样的查询语句。如果完全相同的查询在缓存命中,MySQL服务器会直接从缓存中去检索结果。缓存是会话间共享的,所以为一个客户生成的结果集也能为另一个客户所用。查询缓存基于 SQL_ID。将SELECT语句写入视图就是查询缓存最好的例子。
  • key cache
    缓存表索引。 MySQL keys是索引。如果索引数据量小,它将缓存索引结构和叶子节点(存储索引数据)。如果索引很大,它只会缓存索引结构,通常供MyISAM存储引擎使用

数据库引擎:

Mysql学习

引擎对比:

Mysql学习

Mysql学习

SQL性能下降的原因

  • 查询语句写的差。
  • 索引失效:索引建了,但是没有用上。
  • 关联 查询太多 join(设计缺陷或者不得已的需求)。
  • 服务器调优以及各个参数的设置(缓冲、线程数等)。

机读顺序

Mysql学习

七种JOIN理论

Mysql学习
/* 1 */
SELECT <select_list> FROM TableA A LEFT JOIN TableB B ON A.Key = B.Key;

/* 2 */
SELECT <select_list> FROM TableA A RIGHT JOIN TableB B ON A.Key = B.Key;

/* 3 */
SELECT <select_list> FROM TableA A INNER JOIN TableB B ON A.Key = B.Key;

/* 4 */
SELECT <select_list> FROM TableA A LEFT JOIN TableB B ON A.Key = B.Key WHERE B.Key IS NULL;

/* 5 */
SELECT <select_list> FROM TableA A RIGHT JOIN TableB B ON A.Key = B.Key WHERE A.Key IS NULL;

/* 6 */
SELECT <select_list> FROM TableA A FULL OUTER JOIN TableB B ON A.Key = B.Key;
/* MySQL&#x4E0D;&#x652F;&#x6301;FULL OUTER JOIN&#x8FD9;&#x79CD;&#x8BED;&#x6CD5; &#x53EF;&#x4EE5;&#x6539;&#x6210; 1+2 */
SELECT <select_list> FROM TableA A LEFT JOIN TableB B ON A.Key = B.Key
UNION
SELECT <select_list> FROM TableA A RIGHT JOIN TableB B ON A.Key = B.Key;

/* 7 */
SELECT <select_list> FROM TableA A FULL OUTER JOIN TableB B ON A.Key = B.Key WHERE A.Key IS NULL OR B.Key IS NULL;
/* MySQL&#x4E0D;&#x652F;&#x6301;FULL OUTER JOIN&#x8FD9;&#x79CD;&#x8BED;&#x6CD5; &#x53EF;&#x4EE5;&#x6539;&#x6210; 4+5 */
SELECT <select_list> FROM TableA A LEFT JOIN TableB B ON A.Key = B.Key WHERE B.Key IS NULL;
UNION
SELECT <select_list> FROM TableA A RIGHT JOIN TableB B ON A.Key = B.Key WHERE A.Key IS NULL;</select_list></select_list></select_list></select_list></select_list></select_list></select_list></select_list></select_list></select_list></select_list>

训练:

Mysql学习

笛卡尔积

Mysql学习

inner join

Mysql学习

left join

Mysql学习

right join

Mysql学习

返回所有记录

Mysql学习

索引

索引的本质:索引是排好序的快速查找数据结构。

重点:索引会影响到MySQL查找(WHERE的查询条件)和排序(ORDER BY)两大功能!

除了数据本身之外,数据库还维护着一个满足特定查找算法的数据结构,这些数据结构以某种方式指向数据,这样就可以在这些数据结构的基础上实现高级查找算法,这种数据结构就是索引。

一般来说,索引本身也很大,不可能全部存储在内存中,因此索引往往以索引文件的形式存储在磁盘上

Linux&#x4E0B;&#x67E5;&#x770B;&#x78C1;&#x76D8;&#x7A7A;&#x95F4;&#x547D;&#x4EE4; df -h
[root@VM-16-3-centos ~]# df -h
Filesystem      Size  Used Avail Use% Mounted on
devtmpfs        908M     0  908M   0% /dev
tmpfs           919M   32K  919M   1% /dev/shm
tmpfs           919M  624K  919M   1% /run
tmpfs           919M     0  919M   0% /sys/fs/cgroup
/dev/vda1        59G  7.4G   50G  14% /
tmpfs           184M     0  184M   0% /run/user/0

我们平时所说的索引,如果没有特别指明,都是指B树(多路搜索树,并不一定是二叉的)结构组织的索引。其中聚集索引,次要索引,覆盖索引,复合索引,前缀索引,唯一索引默认都是使用B+树索引,统称索引。当然,除了B+树这种数据结构的索引之外,还有哈希索引(Hash Index)等。

索引的优势和劣势

优势:

  • 查找:类似大学图书馆的书目索引,提高数据检索的效率,降低数据库的IO成本。
  • 排序:通过索引対数据进行排序,降低数据排序的成本,降低了CPU的消耗。

劣势:

  • 实际上索引也是一张表,该表保存了主键与索引字段,并指向实体表的记录,所以索引列也是要占用空间的。
  • 虽然索引大大提高了查询速度,但是同时会降低表的更新速度,例如对表频繁的进行 INSERTUPDATEDELETE。因为更新表的时候,MySQL不仅要保存数据,还要保存一下索引文件每次更新添加的索引列的字段,都会调整因为更新所带来的键值变化后的索引信息。
  • 索引只是提高效率的一个因素,如果MySQL有大数据量的表,就需要花时间研究建立最优秀的索引。

MySQL索引分类

索引分类:

  • 单值索引:一个索引只包含单个列,一个表可以有多个单列索引。
  • 唯一索引:索引列的值必须唯一,但是允许空值。
  • 复合索引:一个索引包含多个字段。

建议:一张表建的索引最好不要超过5个!

/* &#x57FA;&#x672C;&#x8BED;&#x6CD5; */

/* 1&#x3001;&#x521B;&#x5EFA;&#x7D22;&#x5F15; [UNIQUE]&#x53EF;&#x4EE5;&#x7701;&#x7565;*/
/* &#x5982;&#x679C;&#x53EA;&#x5199;&#x4E00;&#x4E2A;&#x5B57;&#x6BB5;&#x5C31;&#x662F;&#x5355;&#x503C;&#x7D22;&#x5F15;&#xFF0C;&#x5199;&#x591A;&#x4E2A;&#x5B57;&#x6BB5;&#x5C31;&#x662F;&#x590D;&#x5408;&#x7D22;&#x5F15; */
CREATE [UNIQUE] INDEX indexName ON tabName(columnName(length));

/* 2&#x3001;&#x5220;&#x9664;&#x7D22;&#x5F15; */
DROP INDEX [indexName] ON tabName;

/* 3&#x3001;&#x67E5;&#x770B;&#x7D22;&#x5F15; */
/* &#x52A0;&#x4E0A;\G&#x5C31;&#x53EF;&#x4EE5;&#x4EE5;&#x5217;&#x7684;&#x5F62;&#x5F0F;&#x67E5;&#x770B;&#x4E86; &#x4E0D;&#x52A0;\G&#x5C31;&#x662F;&#x4EE5;&#x8868;&#x7684;&#x5F62;&#x5F0F;&#x67E5;&#x770B; */
SHOW INDEX FROM tabName \G;

使用 ALTER命令来为数据表添加索引

/* 1&#x3001;&#x8BE5;&#x8BED;&#x53E5;&#x6DFB;&#x52A0;&#x4E00;&#x4E2A;&#x4E3B;&#x952E;&#xFF0C;&#x8FD9;&#x610F;&#x5473;&#x7740;&#x7D22;&#x5F15;&#x503C;&#x5FC5;&#x987B;&#x662F;&#x552F;&#x4E00;&#x7684;&#xFF0C;&#x5E76;&#x4E14;&#x4E0D;&#x80FD;&#x4E3A;NULL */
ALTER TABLE tabName ADD PRIMARY KEY(column_list);

/* 2&#x3001;&#x8BE5;&#x8BED;&#x53E5;&#x521B;&#x5EFA;&#x7D22;&#x5F15;&#x7684;&#x952E;&#x503C;&#x5FC5;&#x987B;&#x662F;&#x552F;&#x4E00;&#x7684;(&#x9664;&#x4E86;NULL&#x4E4B;&#x5916;&#xFF0C;NULL&#x53EF;&#x80FD;&#x4F1A;&#x51FA;&#x73B0;&#x591A;&#x6B21;) */
ALTER TABLE tabName ADD UNIQUE indexName(column_list);

/* 3&#x3001;&#x8BE5;&#x8BED;&#x53E5;&#x521B;&#x5EFA;&#x666E;&#x901A;&#x7D22;&#x5F15;&#xFF0C;&#x7D22;&#x5F15;&#x503C;&#x53EF;&#x4EE5;&#x51FA;&#x73B0;&#x591A;&#x6B21; */
ALTER TABLE tabName ADD INDEX indexName(column_list);

/* 4&#x3001;&#x8BE5;&#x8BED;&#x53E5;&#x6307;&#x5B9A;&#x4E86;&#x7D22;&#x5F15;&#x4E3A;FULLTEXT&#xFF0C;&#x7528;&#x4E8E;&#x5168;&#x6587;&#x68C0;&#x7D22; */
ALTER TABLE tabName ADD FULLTEXT indexName(column_list);

MySQL索引数据结构

索引数据结构:

  • BTree索引。
  • Hash索引。
  • Full-text全文索引。
  • R-Tree索引。

BTree索引检索原理:

Mysql学习

哪些情况不要建索引

  • 记录太少的表。
  • 经常增删改的表。
  • 频繁更新的字段不适合创建索引。
  • Where条件里用不到的字段不创建索引。
  • 假如一个表有10万行记录,有一个字段A只有true和false两种值,并且每个值的分布概率大约为50%,那么对A字段建索引一般不会提高数据库的查询速度。索引的选择性是指索引列中不同值的数目与表中记录数的比。如果一个表中有2000条记录,表索引列有1980个不同的值,那么这个索引的选择性就是1980/2000=0.99。一个索引的选择性越接近于1,这个索引的效率就越高。

性能分析

EXPLAIN简介

EXPLAIN是什么?

EXPLAIN:SQL的执行计划,使用EXPLAIN关键字可以模拟优化器执行SQL查询语句,从而知道MySQL是如何处理SQL语句的。

EXPLAIN怎么使用?

语法: explain + SQL

mysql> explain select * from tbl_emp\G;
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: tbl_emp
         type: ALL
possible_keys: NULL
          key: NULL
      key_len: NULL
          ref: NULL
         rows: 8
        Extra: NULL
1 row in set (0.00 sec)

ERROR:
No query specified

EXPLAIN能干嘛?

可以查看以下信息:

  • id:表的读取顺序。
  • select_type:数据读取操作的操作类型。
  • possible_keys:哪些索引可以使用。
  • key:哪些索引被实际使用。
  • ref:表之间的引用。
  • rows:每张表有多少行被优化器查询。

EXPLAIN字段

id

id:表的读取和加载顺序。

值有以下三种情况:

  • id相同,执行顺序由上至下。
  • id不同,如果是子查询,id的序号会递增,id值越大优先级越高,越先被执行。
  • id有相同有不同,同时存在。永远是id大的优先级最高,id相等的时候顺序执行。

select_type

select_type:数据查询的类型,主要是用于区别,普通查询、联合查询、子查询等的复杂查询。

  • SIMPLE:简单的 SELECT查询,查询中不包含子查询或者 UNION&#xA0;
  • PRIMARY:查询中如果包含任何复杂的子部分,最外层查询则被标记为 PRIMARY
  • SUBQUERY:在 SELECT或者 WHERE子句中包含了子查询。
  • DERIVED:在 FROM子句中包含的子查询被标记为 DERIVED(&#x884D;&#x751F;),MySQL会递归执行这些子查询,把结果放在临时表中。
  • UNION:如果第二个 SELECT出现在 UNION之后,则被标记为 UNION;若 UNION包含在 FROM子句的子查询中,外层 SELECT将被标记为 DERIVED
    Mysql学习

type

type:访问类型排列。

从最好到最差依次是: system> const> eq_ref> ref> range> index> ALL。除了 ALL没有用到索引,其他级别都用到索引了。

一般来说,得保证查询至少达到 range级别,最好达到 ref

  • system:表只有一行记录(等于系统表),这是 const类型的特例,平时不会出现,这个也可以忽略不计。
  • const:表示通过索引一次就找到了, const用于比较 primary key或者 unique索引。因为只匹配一行数据,所以很快。如将主键置于 where列表中,MySQL就能将该查询转化为一个常量。
  • eq_ref:唯一性索引扫描,读取本表中和关联表表中的每行组合成的一行,查出来只有一条记录。除 了 system&#xA0;const 类型之外, 这是最好的联接类型。
  • ref:非唯一性索引扫描,返回本表和关联表某个值匹配的所有行,查出来有多条记录。
  • range:只检索给定范围的行,一般就是在 WHERE语句中出现了 BETWEEN< >in等的查询。这种范围扫描索引比全表扫描要好,因为它只需要开始于索引树的某一点,而结束于另一点,不用扫描全部索引。
  • indexFull Index Scan,全索引扫描, indexALL的区别为 index类型只遍历索引树。也就是说虽然 ALLindex都是读全表,但是 index是从索引中读的, ALL是从磁盘中读取的。
  • ALLFull Table Scan,没有用到索引,全表扫描。

possible_keys 和 key

possible_keys:显示可能应用在这张表中的索引,一个或者多个。查询涉及到的字段上若存在索引,则该索引将被列出,但不一定被查询实际使用。

key:实际使用的索引。如果为 NULL,则没有使用索引。查询中如果使用了覆盖索引,则该索引仅仅出现在 key列表中。

key_len

key_len:表示索引中使用的字节数,可通过该列计算查询中使用的索引的长度。 key_len显示的值为索引字段的最大可能长度,并非实际使用长度,即 key_len是根据表定义计算而得,不是通过表内检索出的。在不损失精度的情况下,长度越短越好。

key_len计算规则:https://blog.csdn.net/qq_34930488/article/details/102931490

mysql> desc category;
+---------------+------------+------+-----+---------+----------------+
| Field         | Type       | Null | Key | Default | Extra          |
+---------------+------------+------+-----+---------+----------------+
| cat_id        | bigint(20) | NO   | PRI | NULL    | auto_increment |
| name          | char(50)   | YES  |     | NULL    |                |
| parent_cid    | bigint(20) | YES  |     | NULL    |                |
| cat_level     | int(11)    | YES  |     | NULL    |                |
| show_status   | tinyint(4) | YES  |     | NULL    |                |
| sort          | int(11)    | YES  |     | NULL    |                |
| icon          | char(255)  | YES  |     | NULL    |                |
| product_unit  | char(50)   | YES  |     | NULL    |                |
| product_count | int(11)    | YES  |     | NULL    |                |
+---------------+------------+------+-----+---------+----------------+
9 rows in set (0.00 sec)

mysql> explain select cat_id from category where cat_id between 10 and 20 \G;
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: category
   partitions: NULL
         type: range
possible_keys: PRIMARY
          key: PRIMARY  # &#x7528;&#x5230;&#x4E86;&#x4E3B;&#x952E;&#x7D22;&#x5F15;&#xFF0C;&#x901A;&#x8FC7;&#x67E5;&#x770B;&#x8868;&#x7ED3;&#x6784;&#x77E5;&#x9053;&#xFF0C;cat_id&#x662F;bigint&#x7C7B;&#x578B;&#xFF0C;&#x5360;&#x7528;8&#x4E2A;&#x5B57;&#x8282;
      key_len: 8        # &#x8FD9;&#x91CC;&#x53EA;&#x7528;&#x5230;&#x4E86;cat_id&#x4E3B;&#x952E;&#x7D22;&#x5F15;&#xFF0C;&#x6240;&#x4EE5;&#x957F;&#x5EA6;&#x5C31;&#x662F;8&#xFF01;
          ref: NULL
         rows: 11
     filtered: 100.00
        Extra: Using where; Using index
1 row in set, 1 warning (0.00 sec)

ref

ref:显示索引的哪一列被使用了,如果可能的话,是一个常数。哪些列或常量被用于查找索引列上的值。

rows

rows:根据表统计信息及索引选用情况,大致估算出找到所需的记录需要读取的行数。

Extra

Extra:包含不适合在其他列中显示但十分重要的额外信息。

  • Using filesort:说明MySQL会对数据使用一个外部的索引排序,而不是按照表内的索引顺序进行读取。MySQL中无法利用索引完成的排序操作成为”文件内排序”。
&#x6392;&#x5E8F;&#x6CA1;&#x6709;&#x4F7F;&#x7528;&#x7D22;&#x5F15;
mysql> explain select name from category where name='Tangs' order by cat_level \G
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: category
   partitions: NULL
         type: ref
possible_keys: idx_name_parentCid_catLevel
          key: idx_name_parentCid_catLevel
      key_len: 201
          ref: const
         rows: 1
     filtered: 100.00
        Extra: Using where; Using index; Using filesort
1 row in set, 1 warning (0.00 sec)

#~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
&#x6392;&#x5E8F;&#x4F7F;&#x7528;&#x5230;&#x4E86;&#x7D22;&#x5F15;

mysql> explain select name from category where name='zz' order by parent_cid,cat_level\G
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: category
   partitions: NULL
         type: ref
possible_keys: idx_name_parentCid_catLevel
          key: idx_name_parentCid_catLevel
      key_len: 201
          ref: const
         rows: 1
     filtered: 100.00
        Extra: Using where; Using index
1 row in set, 1 warning (0.00 sec)
  • Using temporary:使用了临时表保存中间结果,MySQL在対查询结果排序时使用了临时表。常见于排序 order by和分组查询 group by。临时表対系统性能损耗很大。
  • Using index:表示相应的 SELECT操作中使用了覆盖索引,避免访问了表的数据行,效率不错!如果同时出现 Using where,表示索引被用来执行索引键值的查找;如果没有同时出现 Using where,表明索引用来读取数据而非执行查找动作。
&#x8986;&#x76D6;&#x7D22;&#x5F15;
&#x5C31;&#x662F;select&#x7684;&#x6570;&#x636E;&#x5217;&#x53EA;&#x7528;&#x4ECE;&#x7D22;&#x5F15;&#x4E2D;&#x5C31;&#x80FD;&#x591F;&#x53D6;&#x5F97;&#xFF0C;&#x4E0D;&#x5FC5;&#x4ECE;&#x6570;&#x636E;&#x8868;&#x4E2D;&#x8BFB;&#x53D6;&#xFF0C;&#x6362;&#x53E5;&#x8BDD;&#x8BF4;&#x67E5;&#x8BE2;&#x5217;&#x8981;&#x88AB;&#x6240;&#x4F7F;&#x7528;&#x7684;&#x7D22;&#x5F15;&#x8986;&#x76D6;&#x3002;
&#x6CE8;&#x610F;&#xFF1A;&#x5982;&#x679C;&#x8981;&#x4F7F;&#x7528;&#x8986;&#x76D6;&#x7D22;&#x5F15;&#xFF0C;&#x4E00;&#x5B9A;&#x4E0D;&#x80FD;&#x5199;SELECT *&#xFF0C;&#x8981;&#x5199;&#x51FA;&#x5177;&#x4F53;&#x7684;&#x5B57;&#x6BB5;&#x3002;
mysql> explain select cat_id from category \G;
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: category
   partitions: NULL
         type: index
possible_keys: NULL
          key: PRIMARY
      key_len: 8
          ref: NULL
         rows: 1425
     filtered: 100.00
        Extra: Using index   # select&#x7684;&#x6570;&#x636E;&#x5217;&#x53EA;&#x7528;&#x4ECE;&#x7D22;&#x5F15;&#x4E2D;&#x5C31;&#x80FD;&#x591F;&#x53D6;&#x5F97;&#xFF0C;&#x4E0D;&#x5FC5;&#x4ECE;&#x6570;&#x636E;&#x8868;&#x4E2D;&#x8BFB;&#x53D6;
1 row in set, 1 warning (0.00 sec)
  • Using where:表明使用了 WHERE过滤。
  • Using join buffer:使用了连接缓存。
  • impossible whereWHERE子句的值总是false,不能用来获取任何元组。
mysql> explain select name from staffs where name = 'zz' and name = 'cc'\G
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: NULL
   partitions: NULL
         type: NULL
possible_keys: NULL
          key: NULL
      key_len: NULL
          ref: NULL
         rows: NULL
     filtered: NULL
        Extra: Impossible WHERE   # &#x4E0D;&#x53EF;&#x80FD;&#x5B57;&#x6BB5;&#x540C;&#x65F6;&#x67E5;&#x5230;&#x4E24;&#x4E2A;&#x540D;&#x5B57;
1 row in set, 1 warning (0.00 sec)

MySQL中Explain的Extra字段值Using index和Using where;Using index和Using where以及Using index condition的区别

在分别介绍以上四个值之前,我们需要知道,MySQL的架构分成了server层和存储引擎层(storage engine),server层通过调用存储引擎层来返回数据。

其中Using index表示查询的列被索引覆盖,因而无需再回表查询,因而效率较高。例如:select id from test where id = 5;其中id为主键。

​ Using where;Using index表示查询的列被索引覆盖,且where筛选条件是索引列前导列的一个范围,或者是索引列的非前导列,例如:select id from test where id > 5;。很明显,效率也很高。

​ Using where表示查询的列未被索引覆盖,且where筛选条件是索引列前导列的一个范围,或者是索引列的非前导列,或者是非索引列,例如:select * from test where id > 30; 。因为未被索引覆盖,所以需要回表,因而性能比前两者差。

​ Extra为null表示查询的列未被索引覆盖,且where筛选条件是索引的前导列,这意味着用到了索引,但是部分字段未被索引覆盖,必须通过”回表”来实现,因而性能也比前两者差。

​ Using index condition是MySQL 5.6中引入的一种新特性,叫做索引下推,是一种在存储引擎层使用索引过滤数据的一种优化方式。优化了二级索引,减少回表次数,将判断条件传递给引擎,引擎判断索引是否符合条件,符合才会返回数据给服务器。

Mysql学习

索引分析

单表索引分析

数据准备
案例:查询 category_id为1且 comments大于1的情况下, views最多的 article_id

1&#x3001;sql&#x8BED;&#x53E5;
SELECT id,author_id FROM article WHERE category_id = 1 AND comments > 1 ORDER BY views DESC LIMIT 1;

2&#x3001;sql&#x6267;&#x884C;&#x8BA1;&#x5212;
mysql> EXPLAIN SELECT id,author_id FROM article WHERE category_id = 1 AND comments > 1 ORDER BY views DESC LIMIT 1\G
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: article
   partitions: NULL
         type: ALL  #&#x6700;&#x574F;&#x7684;&#x60C5;&#x51B5;
possible_keys: NULL
          key: NULL
      key_len: NULL
          ref: NULL
         rows: 5
     filtered: 20.00
        Extra: Using where; Using filesort  # &#x4EA7;&#x751F;&#x4E86;&#x6587;&#x4EF6;&#x5185;&#x6392;&#x5E8F;&#xFF0C;&#x9700;&#x8981;&#x4F18;&#x5316;SQL
1 row in set, 1 warning (0.00 sec)

2、创建索引 idx_article_ccv

CREATE INDEX idx_article_ccv ON article(category_id,comments,views);

3、查看当前索引。

Mysql学习

4、查看现在SQL语句的执行计划。

Mysql学习

发现创建符合索引 idx_article_ccv之后,虽然解决了全表扫描的问题,但是在 order by排序的时候没有用到索引,MySQL居然还是用的Using filesort

5、我们试试把SQL修改为 SELECT id,author_id FROM article WHERE category_id = 1 AND comments = 1 ORDER BY views DESC LIMIT 1;看看SQL的执行计划。

Mysql学习

推论:当 comments > 1的时候 order by排序 views字段索引就用不上,但是当 comments = 1的时候 order by排序 views字段索引就可以用上!!!

所以,范围值使索引失效。

6、我们现在知道范围之后的索引会失效,原来的索引 idx_article_ccv最后一个字段 views会失效,那么我们如果删除这个索引,创建 idx_article_cv索引呢????

/* &#x521B;&#x5EFA;&#x7D22;&#x5F15; idx_article_cv */
CREATE INDEX idx_article_cv ON article(category_id,views);

查看当前的索引

Mysql学习

7、当前索引是 idx_article_cv,来看一下SQL执行计划。

Mysql学习

成功了

两表索引分析

数据准备

Mysql学习
两表连接查询的SQL执行计划

1、不创建索引的情况下,SQL的执行计划。

Mysql学习

bookclass两张表都是没有使用索引,全表扫描,那么如果进行优化,索引是创建在 book表还是创建在 class

2、左表(book表)创建索引。

创建索引 idx_book_card

/* &#x5728;book&#x8868;&#x521B;&#x5EFA;&#x7D22;&#x5F15; */
CREATE INDEX idx_book_card ON book(card);

book表中有 idx_book_card索引的情况下,查看SQL执行计划

Mysql学习

3、删除 book表的索引,右表(class表)创建索引。

创建索引 idx_class_card

/* &#x5728;class&#x8868;&#x521B;&#x5EFA;&#x7D22;&#x5F15; */
CREATE INDEX idx_class_card ON class(card);

class表中有 idx_class_card索引的情况下,查看SQL执行计划

Mysql学习

由此可见,左连接将索引创建在右表上更合适,右连接将索引创建在左表上更合适。

三张表索引分析

数据准备

DROP TABLE IF EXISTS phone;

CREATE TABLE IF NOT EXISTS phone(
phone_id INT(10) UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT COMMENT '&#x4E3B;&#x952E;',
card INT(10) UNSIGNED NOT NULL COMMENT '&#x5206;&#x7C7B;'
) COMMENT '&#x624B;&#x673A;';

三表连接查询SQL优化

1、不加任何索引,查看SQL执行计划。

Mysql学习

2、根据两表查询优化的经验,左连接需要在右表上添加索引,所以尝试在 book表和 phone表上添加索引。

/* &#x5728;book&#x8868;&#x521B;&#x5EFA;&#x7D22;&#x5F15; */
CREATE INDEX idx_book_card ON book(card);

/* &#x5728;phone&#x8868;&#x4E0A;&#x521B;&#x5EFA;&#x7D22;&#x5F15; */
CREATE INDEX idx_phone_card ON phone(card);

再次执行SQL的执行计划

Mysql学习

结论

JOIN语句的优化:

  • 尽可能减少 JOIN语句中的 NestedLoop(嵌套循环)的总次数:永远都是小的结果集驱动大的结果集。
  • 优先优化 NestedLoop的内层循环。
  • 保证 JOIN语句中被驱动表上 JOIN条件字段已经被索引。
  • 当无法保证被驱动表的 JOIN条件字段被索引且内存资源充足的前提下,不要太吝惜 Join Buffer 的设置。

索引失效

建表:

Mysql学习

建立索引

ALTER TABLE staffs ADD INDEX index_staffs_nameAgePos(name,age,pos);

查看效果

三条查询语句

Mysql学习

只有长度在变化,其他都是好的

索引失效(应该避免)

从左开始且不跳列才不会失效

  • 最佳左前缀法则 – 如果索引了多列,要遵守最左前缀法则。指的是查询从索引的最左前列开始并且不跳过复合索引中间列。

Mysql学习

Mysql学习

Mysql学习

key_len不对,索引失效,不符合最佳左前缀

索引列上不做额外操作才不会失效

不在索引列上做任何操作(计算、函数、(自动or手动)类型转换),会导致索引失效而转向全表扫描。

Mysql学习

少用>,

  • 存储引擎不能使用索引中 &#x8303;&#x56F4;&#x6761;&#x4EF6;&#x53F3;&#x8FB9;&#x7684;&#x5217;。(就是>,

Mysql学习

减少select *

  • 尽量使用覆盖索引(只访问索引的查询(索引列和查询列一致))
    区别在于extra,索引的不同,速度不一样

Mysql学习

不用 is null, is not null

  • is null, is not null 也无法使用索引。

Mysql学习

模糊查询

  • like以通配符开头(’%abc…’),mysql索引失效会变成全表扫描的操作。

Mysql学习

只有xx%前缀查询才不会失效

解决方法:

把*替换为索引的字段值(id可以不加索引)

Mysql学习

类型要正确

即使类型不正确也可以查询,但是底层会帮你转换类型,在判断,但会浪费时间,索引直接失效,变成了全表查询

  • 字符串不加单引号索引失效。
    Mysql学习

Mysql学习

不用or关键字就不会失效

  • 少用or,用它来连接时会索引失效。

Mysql学习

面试常考

建表

Mysql学习

建立索引

Mysql学习

explain

正常顺序

Mysql学习

Mysql学习

Mysql学习

Mysql学习

乱序

Mysql学习

打乱顺序mysql的最左前缀原则仍符合,因为mysql有优化器会帮你查询是否匹配

范围

Mysql学习

如果开始限定范围
第一条会用到3个索引,前两个用来查找,c3用来排序
第二条用到了4个索引,前3个用来查找,c4用来排序

因为mysql引擎会优化第二个sql语句在底层已经变成

explain select * from test03 where c1=’a1′ and c2=’a2′ and c3=’a3′ and c4>’a4′;

使用order by
下面那个例子都是一样的
前两个都是在查找,第三个只是在排序,到了这里就已经断了,所以c4可有可无

Mysql学习

如果使用c4排序,会出现Using filesort。,因为优化器会给你文件排序(因为中间跳了一个)

Mysql学习

这个也会出现Using filesort,因为顺序颠倒了

 explain select * from test03 where c1='a1' and c5='a5' order by c3,c2;

这个就不会出现filesort,因为c2的值已经确认了

Mysql学习

groupby之前必排序,规则和orderby差不多

模糊查询

%在左边会导致索引失效,在右边可以不失效

Mysql学习

总结

对于单键索引,尽量选择针对当前query过滤性更好的索引。
在选择组合索引的时候,当前Query中过滤性最好的字段在索引字段顺序中,位置越靠前越好。
在选择组合索引的时候,尽量选择可以能够包含当前query中的where字句中更多字段的索引。
尽可能通过分析统计信息和调整query的写法来达到选择合适索引的目的。

口诀:

全值匹配我最爱, 最左前缀要遵守;

带头大哥不能死, 中间兄弟不能断;

索引列上少计算, 范围之后全失效;

LIKE 百分写最右, 覆盖索引不写 \*

不等空值还有 OR, 索引影响要注意;

VAR 引号不可丢, SQL 优化有诀窍。

查询截取分析

SQL调优过程:

观察,至少跑1天,看看生产的慢SQL情况。
开启慢查询日志,设置阙值,比如超过5秒钟的就是慢SQL,并将它抓取出来。
explain + 慢SQL分析。
show profile。
运维经理 or DBA,进行SQL数据库服务器的参数调优。

总结:

慢查询的开启并捕获
explain + 慢SQL分析
show profile查询SQL在Mysql服务器里面的执行细节和生命周期情况
SQL数据库服务器的参数调优。

in和exists的区别

小表驱动大表

RBO原理:

当B表的数据集必须小于A表的数据集时,用in优于exists。

select * from A where id in (select id from B)
等价于:
for select id from B
for select * from A where A.id = B.id
当A表的数据集系小于B表的数据集时,用exists优于in

select * from A where exists (select 1 from B where B.id = A.id)
等价于:
for select * from A
for select * from B where B.id = A.id

关于exists的关键字

该语法可以理解为:将主查询的数据,放到子查询中做条件验证,根据验证结果(TRUE或FALSE)来决定主查询的数据结果是否得以保留。

提示

EXSTS(subquey)只返回TRUE或FALSE,因此子查询中的SELECT * 也可以是 SELECT 1 或select ‘X’,官方说法是实际执行时会忽略SELECT清单,因此没有区别。
EXISTS子查询的实际执行过程可能经过了优化而不是我们理解上的逐条对比,如果担忧效率问题,可进行实际检验以确定是否有效率问题。
EXISTS子查询往往也可以用条件表达式,其他子查询或者JOIN来替代,何种最优需要具体问题具体分析
3.2 OrderBy优化
ORDER BY子句,尽量使用Index方式排序,避免使用FileSort方式排序

建立一张表以及一个索引

Mysql学习

如果索引的时候也是按照顺序,两种情况都是一样的

但是索引的时候不按顺序
就会出现这样的情况

MySQL支持二种方式的排序:FileSort和lIndex

Index效率高,它指MySQL扫描索引本身完成排序,FileSort方式效率较低。

ORDER BY满足两情况,会使用Index方式排序:

1.ORDER BY语句使用索引最左前列。
2.使用where子句与Order BY子句条件列组合满足索引最左前列。
如果不在索引列上,mysql的filesort有两种算法:双路排序、单路排序

双路排序:MySQL4.1之前是使用双路排序,字面意思就是两次扫描磁盘,最终得到数据,读取行指针和OrderBy列,对他们进行排序,然后扫描已经排序好的列表,按照列表中的值重新从列表中读对应的数据输出。
从磁盘取排序字段,在buffer进行排序,再从磁盘取其他字段。取一批数据,要对磁盘进行了两次扫描,众所周知,I\O是很耗时的,所以在mysql4.1之后,出现了第二种改进的算法,就是单路排序。

单路排序:从磁盘读取查询需要的所有列,按照order by列在buffer对它们进行排序,然后扫描排序压的列表进行输出,它的效率更快一些,避免了第二次读取数据。并且把随机IO变成了顺序IO,但是它会使用更多的空间,因为它把每一行都保存在内存中了。
但是用单路有问题

在sort_buffer中,单路排序比双路排序要多占用很多空间,因为单路排序是把所有字段都取出,所以有可能取出的数据的总大小超出了sort_buffer的容量,导致每次只能取sort_buffer容量大小的数据,进行排序(创建tmp文件,多路合并),排完再取取sort_buffer容量大小,再排……从而多次I/O。
本来想省一次I/O操作,反而导致了大量的I/O操作,反而得不偿失。

优化策略

1.增大sort_buffer_size参数的设置
2.增大max_length_for_sort_data参数的设置
3.为什么设置sort_buffer_size、max_length_for_sort_data参数能优化排序?

主要是因为可以提高Order By的速度

具体原因如下:

Order by时select * 是一个Query需要的字段,这点非常重要。在这里的影响是;

当Query的字段大小总和小于max_length_for_sort_data而且排序字段不是TEXT|BLOB类型时,会用改进后的算法——单路排序,否则用老算法——多路排序。
两种算法的数据都有可能超出sort_buffer的容量,超出之后,会创建tmp文件进行合并排序,导致多次IO,但是用单路排序算法的风险会更大一些,所以要提高sort_buffer__size。
尝试提高sort_buffer_size,不管用哪种算法,提高这个参数都会提高效率,当然,要根据系统的能力去提高,因为这个参数是针对每个进程的。
尝试提高max_length_for_sort_data,提高这个参数,会增加用改进算法的概率。但是如果设的太高,数据总容量超出sort_buffer_size的概率就增大,明显症状是高的磁盘I/O活动和低的处理器使用率。

小结

为排序使用索引

MySql两种排序方式∶文件排序 或 扫描有序索引排序

MySql能为 排序 与 查询 使用相同的索引

创建复合索引 a_b_c (a, b, c)

order by能使用索引最左前缀

ORDER BY a
ORDER BY a, b
ORDER BY a, b, c
ORDER BY a DESC, b DESC, c DESC

如果WHERE使用素引的最左前缀定义为常量,则order by能使用索引

WHERE a = const ORDER BY b,c
WHERE a = const AND b = const ORDER BY c
WHERE a = const ORDER BY b, c
WHERE a = const AND b > const ORDER BY b, c

不能使用索引进行排序的情况

ORDER BY a ASC, b DESC, c DESC //&#x6392;&#x5E8F;&#x4E0D;&#x2014;&#x81F4;
WHERE g = const ORDER BY b, c //&#x4EA7;&#x4E22;&#x5931;a&#x7D22;&#x5F15;
WHERE a = const ORDER BY c //&#x4EA7;&#x4E22;&#x5931;b&#x7D22;&#x5F15;
WHERE a = const ORDER BY a, d //d&#x4E0D;&#x662F;&#x7D20;&#x5F15;&#x7684;&#x4E00;&#x90E8;&#x5206;
WHERE a in (&#x2026;) ORDER BY b, c //&#x5BF9;&#x4E8E;&#x6392;&#x5E8F;&#x6765;&#x8BF4;,&#x591A;&#x4E2A;&#x76F8;&#x7B49;&#x6761;&#x4EF6;&#x4E5F;&#x662F;&#x8303;&#x56F4;&#x67E5;&#x8BE2;

GroupBy优化

GroupBy优化(和order by差不多)

group by实质是先排序后进行分组,遵照索引建的最佳左前缀。
当无法使用索引列,增大max_length_for_sort_data参数的设置 + 增大sort_buffer_size参数的设置。
where高于having,能写在where限定的条件就不要去having限定了。

慢查询日志

MySQL的慢查询日志是MySQL提供的一种日志记录,它用来记录在MySQL中响应时间超过阀值的语句,具体指运行时间超过long_query_time值的SQL,则会被记录到慢查询日志中。long_query_time的默认值为10,意思是运行10秒以上的语句。
由他来查看哪些SQL超出了我们的最大忍耐时间值,比如一条sql执行超过5秒钟,我们就算慢SQL,希望能收集超过5秒的sql,结合之前explain进行全面分析
默认情况下,MySQL数据库没有开启慢查询日速,需要我们手动来设置这个参数。

一般不建议启动该参数,因为开启慢查询日志会或多或少带来一定的性能影响。慢查询日志支持将日志记录写入文件。

通过如下命令进行操作

查看日志是否开启

SHOW VARIABLES LIKE '%slow_query_log%';

Mysql学习

开启 set global slow_query_log=1,只对当前数据库生效,默认关闭的
结果如下

永久生效
修改配置文件my.cnf
[mysqld]下增加或修改参数slow_query_log和slow_query_log_file后,然后重启MySQL服务器。也即将如下两行配置进my.cnf文件

slow_query_log =1
slow_query_log_file=/var/lib/manongyanjiuseng-slow.log

关于慢查询的参数slow_query_log_file,它指定慢查询日志文件的存放路径,系统默认会给一个缺省的文件host_name-slow.log(如果没有指定参数slow_query_log_file的话)

什么样的数据会放到慢查询日志

需要设置一个多长的时间段就会放到日志中
这个是由参数long_query_time控制,默认情况下long_query_time的值为10秒

命令:

SHOW VARIABLES LIKE 'long_query_time%';

运行时间正好等于long_query_time的情况,并不会被记录下来,需大于

设置阈值时间后还需要重启才可以生效

set global long_query_time=3;

查询当前系统中有多少条慢查询记录

show global status like '%Slow_queries%';

如果在配置文件中设置阈值
具体配置如下

[mysqld]下配置:

slow_query_log=1;
slow_query_log_file=/var/lib/mysql/atguigu-slow.log
long_query_time=3;
log_output=FILE;

==结合工具进行分析mysqldumpslow ==

在生产环境中,如果要手工分析日志,查找、分析SQL,显然是个体力活,MySQL提供了日志分析工具mysql dump slow。

查看mysqldumpslow的帮助信息,mysqldumpslow –help。

工作常用参考

&#x5F97;&#x5230;&#x8FD4;&#x56DE;&#x8BB0;&#x5F55;&#x96C6;&#x6700;&#x591A;&#x7684;10&#x4E2A;SQL &#xFF0C;
mysqldumpslow -s r -t 10 /var/lib/mysql/atguigu-slow.log
&#x5F97;&#x5230;&#x8BBF;&#x95EE;&#x6B21;&#x6570;&#x6700;&#x591A;&#x7684;10&#x4E2A;SQL&#xFF0C;
mysqldumpslow -s c -t 10 /var/lib/mysql/atguigu-slow.log
&#x5F97;&#x5230;&#x6309;&#x7167;&#x65F6;&#x95F4;&#x6392;&#x5E8F;&#x7684;&#x524D;10&#x6761;&#x91CC;&#x9762;&#x542B;&#x6709;&#x5DE6;&#x8FDE;&#x63A5;&#x7684;&#x67E5;&#x8BE2;&#x8BED;&#x53E5;&#xFF0C;
mysqldumpslow -s t -t 10 -g "left join" /var/lib/mysql/atguigu-slow.log
&#x53E6;&#x5916;&#x5EFA;&#x8BAE;&#x5728;&#x4F7F;&#x7528;&#x8FD9;&#x4E9B;&#x547D;&#x4EE4;&#x65F6;&#x7ED3;&#x5408;&#x2502;&#x548C;more &#x4F7F;&#x7528;&#xFF0C;&#x5426;&#x5219;&#x6709;&#x53EF;&#x80FD;&#x51FA;&#x73B0;&#x7206;&#x5C4F;&#x60C5;&#x51B5;&#xFF0C;
mysqldumpslow -s r-t 10 /ar/lib/mysql/atguigu-slow.log | more

3.5 批量插入数据脚本
为了更好的展示
先建立一张表

create database bigData;
use bigData;

CREATE TABLE dept(
    id INT UNSIGNED PRIMARY KEY AUTO_INCREMENT,
    deptno MEDIUMINT UNSIGNED NOT NULL DEFAULT 0,
    dname VARCHAR(20)NOT NULL DEFAULT "",
    loc VARCHAR(13) NOT NULL DEFAULT ""
)ENGINE=INNODB DEFAULT CHARSET=utf8;

CREATE TABLE emp(
    id int unsigned primary key auto_increment,
    empno mediumint unsigned not null default 0,
    ename varchar(20) not null default "",
    job varchar(9) not null default "",
    mgr mediumint unsigned not null default 0,
    hiredate date not null,
    sal decimal(7,2) not null,
    comm decimal(7,2) not null,
    deptno mediumint unsigned not null default 0
)ENGINE=INNODB DEFAULT CHARSET=utf8;

开启了可以创建存储函数的权限,主要是这个功能

设置参数log_bin_trust_function_creators

show variables like 'log_bin_trust_function_creators';
set global log_bin_trust_function_creators=1;

这是在终端上输入的
但是重启后会失效

如果要配置永久的,需要在配置文件上配置

windows下my.ini[mysqld]加上

log_bin_trust_function_creators=1

linux下/etc/my.cnf 下my.cnf[mysqld]加上

log_bin_trust_function_creators=1

创建函数,保证每条数据都不同

随机产生字符串

delimiter $$ # &#x4E24;&#x4E2A; $$ &#x8868;&#x793A;&#x7ED3;&#x675F;
create function rand_string(n int) returns varchar(255)
begin
    declare chars_str varchar(100) default 'abcdefghijklmnopqrstuvwxyz';
    declare return_str varchar(255) default '';
    declare i int default 0;
    while i < n do
        set return_str = concat(return_str,substring(chars_str,floor(1+rand()*52),1));
        set i=i+1;
    end while;
    return return_str;
end $$

执行完语句后,在终端上输入select rand_string(2)$$;,要以$$结尾

随机产生部门编号

delimiter $$
create function rand_num() returns int(5)
begin
    declare i int default 0;
    set i=floor(100+rand()*10);
    return i;
end $$

执行完语句后,在终端上输入select rand_num()$$,要以$$结尾

创建存储过程,创建往emp表中插入数据的存储过程

delimiter $$
create procedure insert_emp(in start int(10),in max_num int(10))
begin
    declare i int default 0;
    set autocommit = 0;
    repeat
        set i = i+1;
        insert into emp(empno,ename,job,mgr,hiredate,sal,comm,deptno) values((start+i),rand_string(6),'salesman',0001,curdate(),2000,400,rand_num());
        until i=max_num
        end repeat;
    commit;
end $$

创建往dept表中插入数据的存储过程

delimiter $$
create procedure insert_dept(in start int(10),in max_num int(10))
begin
    declare i int default 0;
    set autocommit = 0;
    repeat
        set i = i+1;
        insert into dept(deptno,dname,loc) values((start+i),rand_string(10),rand_string(8));
        until i=max_num
        end repeat;
    commit;
end $$

调用存储过程
往dept表中插入数据

DELIMITER ;
CALL insert_dept(100, 10);

往emp表中插入50万数据

DELIMITER ;
CALL insert_emp(100001, 500000);

Show Profile

Show Profile是mysql提供可以用来分析当前会话中语句执行的资源消耗情况。可以用于SQL的调优的测量

默认情况下,参数处于关闭状态,并保存最近15次的运行结果。

查看当前状态是否开启了,

show variables like 'profiling';

开启 ,

set profiling=on;

Mysql学习

通过执行show profiles;

  • 诊断SQL,show profile cpu,block io for query 上一步前面的问题SQL数字号码;
    例如
show profile cpu,block io for query 3;

Mysql学习

具体的参数介绍

ALL:显示所有的开销信息。

BLOCK IO:显示块lO相关开销。
CONTEXT SWITCHES :上下文切换相关开销。
CPU:显示CPU相关开销信息。
IPC:显示发送和接收相关开销信息。
MEMORY:显示内存相关开销信息。
PAGE FAULTS:显示页面错误相关开销信息。
SOURCE:显示和Source_function,Source_file,Source_line相关的开销信息。
SWAPS:显示交换次数相关开销的信息。
在查询该文件的时候如果出现了这些一定要特别注意

不理想字段

converting HEAP to MyISAM 查询结果太大,内存都不够用了往磁盘上搬了。
Creating tmp table 创建临时表,拷贝数据到临时表,用完再删除
Copying to tmp table on disk 把内存中临时表复制到磁盘,危险!

locked

全局查询日志

General log默认不开启的原因有两个:

日志将会非常大,对磁盘是一个很大的压力。因为所有的操作都会被记录下来。
对MySQL数据的性能有一定的影响。

不要在生产环境开启这个功能。

  • 开启
set global general_log=1

记录日志文件的路径

general_log_file=/path/logfile

输出格式

log_output=FILE

查看状态是否开启,show variables like ‘general_log’;

set global general_log=1;
set global log_output='TABLE';

log_output=’FILE’表示将日志存入文件,默认值是’FILE’

log_output=’TABLE’表示将日志存入数据库,这样日志信息就会被写入到mysql.slow_log表中.

所编写的sql语句,将会记录到mysql库里的geneial_log表,可以用下面的命令查看:

select * from mysql.general_log;

查出来会有输出语句

Mysql学习

锁机制

从读写来分

读锁:可共同读

写锁:不可共同写,在任务完成前,会阻断其他读锁和写锁

表锁:

Mysql学习

Mysql学习

Mysql学习

innoDB索引失效行锁会切换为表锁

间隙锁的危害

什么是间隙锁?

当我们用范围条件而不是相等条件检索数据,并请求共享或者排他锁时, InnoDB会给符合条件的已有数据记录的索引项加锁,对于键值在条件范文内但并不存在的记录,叫做”间隙(GAP)”。

InnoDB也会对这个”间隙”加锁,这种锁的机制就是所谓的”间隙锁”。

间隙锁的危害

因为 Query执行过程中通过范围查找的话,他会锁定整个范围内所有的索引键值,即使这个键值不存在。

间隙锁有一个比较致命的缺点,就是当锁定一个范围的键值后,即使某些不存在的键值也会被无辜的锁定,而造成在锁定的时候无法插入锁定键值范围内的任何数据。在某些场景下这可能会対性能造成很大的危害。

Mysql学习

行锁

SELECT .....FOR UPDATE在锁定某一行后,其他写操作会被阻塞,直到锁定的行被

行锁分析

mysql> SHOW STATUS LIKE 'innodb_row_lock%';
+-------------------------------+-------+
| Variable_name                 | Value |
+-------------------------------+-------+
| Innodb_row_lock_current_waits | 0     |
| Innodb_row_lock_time          | 11131 |
| Innodb_row_lock_time_avg      | 11131 |
| Innodb_row_lock_time_max      | 11131 |
| Innodb_row_lock_waits         | 1     |
+-------------------------------+-------+
5 rows in set (0.00 sec)
  • Innodb_row_lock_current_waits:当前正在等待锁定的数量。
  • Innodb_row_lock_time:从系统启动到现在锁定总时间长度(重要)。
  • Innodb_row_lock_time_avg:每次等待所花的平均时间(重要)。
  • Innodb_row_lock_time_max:从系统启动到现在等待最长的一次所花的时间。
  • Innodb_row_lock_waits:系统启动后到现在总共等待的次数(重要)。

尤其是当等待次数很高,而且每次等待时长也不小的时候,我们就需要分析系统中为什么会有如此多的等待,然后根据分析结果着手制定优化策略。

主从复制

https://www.cnblogs.com/phpstudy2015-6/p/6485819.html

八股

Mysql学习

MySQL采用页存储数据和索引,索引有三层就要有3次io。

查询数据库时,不论读一行,还是读多行,都是将这些行所在的整页数据加载,然后在内存中匹配过滤出最终结果。

buffer pool

存储空白页的链表——-free链表

从磁盘加载一页数据到buffer pool——–》内部组成为成对的控制块和缓存页———–》为了记录哪些缓存页为空———–》取对应的控制块组成free链表———》当需要加载到内存数据时,就从free链表中取一个空闲的缓存页,并且把相应的控制块从free链表中移除

存储脏页(修改过数据)的链表——–flush链表

缓存不够—————LRU链表

预读机制导致读进来不用,或者全表扫描导致只读一次(劣币驱逐良币)——————-》lru分区(young old)

Mysql学习

​ 针对预读机制: 规定当磁盘上的某个页面在初次加载到Buffer Pool中的某个缓存页时,该缓存页对应的控制块会被放到old区域的头部

​ 针对全表扫描:对old区的缓存页进行第一次访问时就记录访问时间到控制块,如果后续访问时间与第一次访问时间的时间间隔在一个规定范围内,该数据页就不会移动到young区,否则就移动到young区的头部。

我们可以通过指定 innodb_buffer_pool_instances 来控制 Buffer Pool 实例的个数,每个 Buffer Pool 实
例中都有各自独立的链表,互不干扰。

自 MySQL 5.7.5 版本之后,可以在服务器运行过程中调整 Buffer Pool 大小。每个 Buffer Pool 实例由若
干个 chunk 组成,每个 chunk 的大小可以在服务器启动时通过启动参数调整。

日志

redo log 主要节省的是随机写磁盘的IO消耗(转成顺序写),而change buffer主要节省的则是随机读磁盘的IO消耗

Original: https://www.cnblogs.com/zz01/p/16493535.html
Author: 山野村夫01
Title: Mysql学习

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/621108/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • LeetCode 26. 删除有序数组中的重复项

    给你一个 升序排列 的数组nums,请你 原地 删除重复出现的元素,使每个元素只出现一次,返回删除后数组的新长度。元素的相对顺序应该保持一致。 由于在某些语言中不能改变数组的长度,…

    数据库 2023年6月11日
    074
  • Java学习-第一部分-第三阶段-第二节:反射

    反射 笔记目录:(https://www.cnblogs.com/wenjie2000/p/16378441.html) 一个需求引出反射 请看下面的问题 根据配置文件 re.pr…

    数据库 2023年6月11日
    060
  • Hadoop生态一—分布式文件系统HDFS

    分布式文件系统: 统一管理分布在集群上的文件系统设计思想分而治之:将大文件、大批量文件,分布式存放在大量服务器上,以便于采取分而治之的方式对海量数据进行运算分析; 在大数据系统中作…

    数据库 2023年6月6日
    074
  • leetcode 543. Diameter of Binary Tree 二叉树的直径(简单)

    给定一棵二叉树,你需要计算它的直径长度。一棵二叉树的直径长度是任意两个结点路径长度中的最大值。这条路径可能穿过也可能不穿过根结点。 示例 :给定二叉树 1 / \ 2 3 / \ …

    数据库 2023年6月16日
    088
  • day04-2发送文件

    多用户即时通讯系统04 4.编码实现03 4.6功能实现-发送文件功能实现 4.6.1思路分析 客户端(发送者): 先把文件a.jpg读取到客户端的字节数组 把文件对应的字节数组封…

    数据库 2023年6月11日
    071
  • JDK安装

    环境变量–>新建JAVA_HOME–>D:\Environment\java\jdk1.8 配置path变量–>新建%JAVA…

    数据库 2023年6月11日
    080
  • ASP.NET CORE WEB项目介绍

    首先创建一个asp.net core web应用程序 第二步 目前官方预置了7种模板项目供我们选择。从中我们可以看出,既有我们熟悉的MVC、WebAPI,又新添加了Razor Pa…

    数据库 2023年6月14日
    088
  • 【SQL实战】一条SQL统计全国各地疫情分布情况

    — 疫情表,三个字段:城市/地区 省份 当前确诊人数DROP TABLE IF EXISTS yiqing;CREATE TABLE datacenter.yiqing…

    数据库 2023年5月24日
    089
  • 2 Java中 == 和 equals 和 hashCode 的区别

    ==是一个比较运算符; 若比较的是基本数据类型,则比较的是值; 若比较的是引用数据类型,则比较的是它们在内存中的内存地址。 说明:对象是存放在堆中,栈中存放的是对象的引用,因此==…

    数据库 2023年6月6日
    090
  • 慢SQL,压垮团队的最后一根稻草!

    一、什么是慢 SQL 什么是慢SQL? 顾名思义,运行时间较长的 SQL 语句即为慢 SQL! 那问题来了,多久才算慢呢? 这个慢其实是一个相对值,不同的业务场景下,标准要求是不一…

    数据库 2023年6月14日
    092
  • 1_requests基础用法

    requests 模块的基本使用 什么是requests 模块? Python 中封装好的一个基于网络请求的模块 requests 模块的作用? 用来模拟浏览器发请求 reques…

    数据库 2023年6月11日
    070
  • MySQL特性:ICP,Index Condition Pushdown

    ICP,Index Condition Pushdown 理解ICP特性前,先去前面理解MRR特性,了解where条件中的三阶段提取: index key、index filter…

    数据库 2023年6月16日
    073
  • MySQL删除重复数据

    重复数据如图所示 自关联,保留id最小的那一条,其它的都删除 DELETE t1 FROM invest_year t1, invest_year t2 WHERE t1.pro_…

    数据库 2023年6月14日
    076
  • Mysql 实现数据库读写分离

    一、Amoeba 是什么 Amoeba(变形虫)项目,专注 分布式数据库 proxy 开发。座落与Client、DB Server(s)之间。对客户端透明。具有负载均衡、高可用性、…

    数据库 2023年5月24日
    089
  • 695.岛屿的最大面积

    695.岛屿的最大面积 给你一个大小为 m x n 的二进制矩阵 grid 。 岛屿 是由一些相邻的 1 (代表土地) 构成的组合,这里的「相邻」要求两个 1 必须在 水平或者竖直…

    数据库 2023年6月16日
    070
  • eclipse调用MySQL数据库的方法

    今天来总结一下使用如何使用eclipse调用MySQL数据库的数据。 一、设置eclipse 我们首先来设置一下eclipse。 在下部的Servers中右键选择new,选择ser…

    数据库 2023年6月11日
    0122
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球