社区所有版块导航
Python
python开源   Django   Python   DjangoApp   pycharm  
DATA
docker   Elasticsearch  
aigc
aigc   chatgpt  
WEB开发
linux   MongoDB   Redis   DATABASE   NGINX   其他Web框架   web工具   zookeeper   tornado   NoSql   Bootstrap   js   peewee   Git   bottle   IE   MQ   Jquery  
机器学习
机器学习算法  
Python88.com
反馈   公告   社区推广  
产品
短视频  
印度
印度  
Py学习  »  DATABASE

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

隐约喜欢萌萌哒 • 5 年前 • 476 次点击  

查询缓存、事务

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