Py学习  »  DATABASE

2020-11-18-Mysql(缓存 事务 索引 分析SQL执行快慢流程)

隐约喜欢萌萌哒 • 3 年前 • 280 次点击  

查询缓存、事务

my.cnf加入以下配置,重启MySQL开启查询缓存

query_cache_type=1
query_cache_size=600000

执行命令开启缓存查询

set global query_cache_type=1;
set global query_cache_size=600000;

还可以通过sql_cache和sql_no_cache来控制某个查询语句是否需要缓存:

select sql_no_cache count(*) from usr;

事务的四大特性:
原子性(Atomicity): 事务是最小的执行单位,不允许分割。事务的原子性确保动作要么全部完成,要么完全不起作用;
一致性(Consistency): 执行事务后,数据库从一个正确的状态变化到另一个正确的状态;
隔离性(Isolation): 并发访问数据库时,一个用户的事务不被其他事务所干扰,各并发事务之间数据库是独立的;
持久性(Durability): 一个事务被提交之后。它对数据库中数据的改变是持久的,即使数据库发生故障也不应该对其有任何影响。

事务带来的并发问题:
脏读事务A修改了某条数据,还没提交,与此同时,另一个事务读取了这个未提交的数据,结果造成了数据的脏读
丢失修改:事务A修改了某条数据,与此同时另一个事务也修改了这条数据,结果导致事务A要修改值的更改,造成了数据的丢失
不可重复读:与脏读的区别是,读取的是已经提交的数据,事务中包含事务,事务A比较大,在更新某条数据后进行了其他的操作,内部的事务更新提交了数据,事务A要修改的值发现了变化.
幻读:对行的锁定,所有的事务依次逐个执行,与不可重复读的区别是幻读是插入数据,不可重复读是修改数据

子查询慢的原因

子查询的结果集无法使用索引,通常子查询的结果集会被存储到临时表中,不论是内存临时表还是磁盘临时表都不会存在索引,所以查询性能会受到一定的影响。特别是对于返回结果集比较大的子查询,其对查询性能的影响也就越大。

由于子查询会产生大量的临时表也没有索引,所以会消耗过多的 CPU 和 IO 资源,产生大量的慢查询。

分析一条SQL执行慢的原因的分析的流程

1、大多数情况是正常的,只是偶尔会出现很慢的情况。

  • 数据库在刷新脏页(flush)

当我们要往数据库插入一条数据、或者要更新一条数据的时候,我们知道数据库会在内存中把对应字段的数据更新了,但是更新之后,这些更新的字段并不会马上同步持久化到磁盘中去,而是把这些更新的记录写入到 redo log 日记中去,等到空闲的时候,在通过 redo log 里的日记把最新的数据同步到磁盘中去。

当内存数据页跟磁盘数据页内容不一致的时候,我们称这个内存页为“脏页”。内存数据写入到磁盘后,内存和磁盘上的数据页的内容就一致了,称为“干净页”。

刷脏页有下面4种场景:
redolog写满了
内存不够
系统认为空闲的时候
mysql正常关闭的时候

  • 拿不到锁:
    show processlist这个命令来查看当前的状态

2、在数据量不变的情况下,这条SQL语句一直以来都执行的很慢。

  • 没用索引
    字段没有索引
    没用索引
  • 数据库选错索引
    1.系统判断是否走索引,扫描行数的预测其实只是原因之一,这条查询语句是否需要使用使用临时表、是否需要排序等也是会影响系统的选择的。
    2.强制走索引

索引

(参考)

https://snailclimb.gitee.io/javaguide/#/docs/database/MySQL%20Index
https://juejin.im/post/6844903645125820424

聚集索引和非聚集索引

简单概括:
聚集索引就是以主键创建的索引
非聚集索引就是以非主键创建的索引
区别:
聚集索引在叶子节点存储的是表中的数据
非聚集索引在叶子节点存储的是主键和索引列
使用非聚集索引查询出数据时,拿到叶子上的主键再去查到想要查找的数据。(拿到主键再查找这个过程叫做回表)

聚合索引的二次查询问题

非聚集索引叶节点仍然是索引节点,只是有一个指针指向对应的数据块,此如果使用非聚集索引查询,而查询列中包含了其他该索引没有覆盖的列,那么他还要进行第二次的查询,查询节点上对应的数据行的数据。
非聚集索引是排序过的,与数据库中的数据并不是一一对应的
这里的二级查询是在原来的索引的基础上查找还是,重新查找另一包含要查找数据的非聚集索引?

理解:非聚集索引,逻辑位置和物理位置是不对应的,叶子节点存放的是主键id,假设存储的是索引列的物理位置,假设更新的话,就要更新这些物理位置,(非聚集索引是依赖于聚集索引的)

覆盖索引

如果一个索引包含(或者说覆盖)所有需要查询的字段的值,我们就称之为“覆盖索引”。我们知道InnoDB存储引擎中,如果不是主键索引,叶子节点存储的是主键+列值。最终还是要“回表”,也就是要通过主键再查找一次。这样就会比较慢覆盖索引就是把要查询出的列和索引是对应的,不做回表操作!

最左前缀原则

image.png

关于日期的格式

Datetime 和 Timestamp 之间抉择

DateTime 类型是没有时区信息的(时区无关) ,DateTime 类型保存的时间都是当前会话所设置的时区对应的时间。这样就会有什么问题呢?当你的时区更换之后,比如你的服务器更换地址或者更换客户端连接时区设置的话,就会导致你从数据库中读出的时间错误

Timestamp 和时区有关。Timestamp 类型字段的值会随着服务器时区的变化而变化,自动换算成相应的时间,说简单点就是在不同时区,查询到同一个条记录此字段的值会不一样。

Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/99314
 
280 次点击