MySql爱写日记的小海豚

关键字:缓存,日志才是本体,B+Tree


或许海豚才是本体

所谓的数据库,就是通过存储引擎,把数据按一定格式(压缩,加密)存在文件里。默认的存储引擎是InnoDB

结构:MySql简介

树型,按页储存,脉冲刷盘

MySql是B+Tree的形式储存数据;B+Tree就是将所有信息都保存在叶子节点的B-Tree(后面细说)。

使用的是聚簇索引,也就是索引和数据在一起,找到索引就找到数据(物理磁盘上的在一起)。

按页(Page)保存,每页16k,这16k在磁盘上是连续的;以脉冲的形式从内存向磁盘刷盘(就是一阵一阵的,减少I/O操作,减少对外设的操作。磁盘虽然在主机里,但它也是外设;只有CPU和内存是自己人)。

缓存:主要工作区域

主要工作都是在缓存中做的,所有的增删改查都是在缓存中完成,然后定期刷盘到物理磁盘保持(所以突然断电数据会丢失,所有的软件都是这样,只有ctrl+s了才是存盘)。

Buffer Pool:缓冲池,简称BP(查询缓存)

BP以Page页为单位,默认大小16K,在InnoDB访问表记录和索引时会在Page页中缓存,以后使用可以减少磁盘IO操作,提升效率。

脏页是什么?

dirty page:脏页,被使用page,数据被修改过,页中数据和磁盘的数据产生了不一致。

其他两个状态free page : 空闲page,未被使用。clean page:被使用page,数据没有被修改过

只有脏页需要刷盘。刷盘:将修改的数据更新到磁盘

热数据维护LRU算法

缓存中的数据越来越多,就需要删除不常用的数据;这个概念在别的数据库,比如Redis中也有(Redis就是大佬嫌MySql不够快才去创新的产物)。

具体方法就是末尾淘汰,BP缓存结构是一个链表,被访问过的数据移到头部,一直没被访问就掉到末尾了。不用担心淘汰了脏页,导致数据没有更新到。脏页还同时有另一个链表保存flush list,专门用来刷盘。

Change Buffer:写缓冲区,简称CB

很诡异啊,写操作怎么缓存?这其实是一个搭便车的操作。

如果读缓存中没有它要操作的数据,那SQL操作会先缓存到写缓冲区(减少一次I/O),等下次查询时先去磁盘查询到相关数据,再去更新读缓存的数据,然后等刷盘。

如果一直没读相关数据怎么办?

不用太担心,默认情况下,每个一秒(脏页达到75%,不满足条件的话最晚10秒)就会执行刷盘操作,所以最多就丢失一秒(是的就是一秒,不是十秒,因为还有日志可以恢复)的数据。本质是减少I/O,但是每秒都有一次I/O的机会。

Adaptive Hash Index:自适应哈希索引

神奇的东西,而且还是自动的。

InnoDB存储引擎会自动根据访问的频率和模式来为某些页建立哈希索引。

Log Buffffer:日志缓冲区

就是日志的缓存,和BP一样,定期写入磁盘。每隔一秒执行刷盘(日志是更新的最勤快的,所以说日志才是本体;什么都没了,只要还有有日志就不用跑路)。

线程:读写分工,甚至还有一个专门负责日志

在InnoDB中使用了大量的AIO(Async IO)来做读写处理。写要排队,读可以一起。

所以高并发场景可以先把要更新的数据都读到缓存中,修改后再慢慢写入,保证数据准确性;比如打卡的时候先读取用户信息+当前系统时间,然后排队插入,而不是插入的时候写当前时间,这样就不会有人明明踩点打卡但是迟到了。

日志:最重要的东西

日志即数据

日志不止记录操作,还可以还原数据的;甚至MySql对日志的写入比刷盘还频繁。

Undo Log:撤销日志

看名字就知道是用来回滚事务的,通过记录反向SQL语句来回滚。

Redo Log:重做日志

是用来恢复的?也是和事务有关,在发生故障时恢复事务。比如事务没执行完就断电了,这时候用Redo Log恢复数据,继续执行事务。

Binlog日志: Binary log(二进制日志)

主从复制,恢复表数据都用它。以二进制的方式保存了所有更新操作(增,删,改)。

主从复制就是跟踪主数据库Binlog的位置,有变化就更新。

慢查询日志

默认是10秒;查看超过这个数的SQL语句(不光是查询语句)。

索引:就是一个迷你表

索引也是B+Tree,只不过值是表id(主键)。

联合索引(很好用,一个顶多个):

一个A-B-C三个字段的索引等于

A

A-B

A-B-C

但是不等于(不能错位,不能乱序)

B-A

A-C

C-B-A

文本索引:需要分词;就是个玩具,有其他替代工具。

EXPLAIN 命令,分析查询

EXPLAIN SELECT * from city WHERE id < 1000;


type:效率由低到高

ALL:表示全表扫描,性能最差。

index:表示基于索引的全表扫描,先扫描索引再扫描全表数据。

range:表示使用索引范围查询。使用>、>=、<、<=、in等等。(好sql语句的标准)

ref:表示使用非唯一索引进行单值查询。

eq_ref:一般情况下出现在多表join查询,表示前面表的每一个记录,都只能匹配后面表的一行结果。

const:表示使用主键或唯一索引做等值查询,常量查询。

NULL:表示不用访问表,速度最快

key

表示查询时真正使用到的索引,显示的是索引名称

rows

MySQL查询优化器会根据统计信息,估算SQL要查询到结果需要扫描多少行记录。原则上rows是越少效率越高,可以直观的了解到SQL效率高低。

Extra:

Extra表示很多额外的信息,各种操作会在Extra提示相关信息,常见几种如下:

Using where表示查询需要通过索引回表查询数据。

Using index表示查询需要通过索引,索引就可以满足所需数据。

Using fifilesort表示查询出来的结果需要额外排序,数据量小在内存,大的话在磁盘,因此有Using fifilesort建议优化。

Using temprorary查询使用到了临时表,一般出现于去重、分组等操作。

事物:不是所有存储引擎都支持事务,有的嫌事务影响效率

通过undo log中的反向sql

undo log内容//todo

事务也是通过日志回滚的,MySql精妙的地方都在日志里。

BTree:数据库的常用结构

B-Tree,B+Tree,红黑树

二叉查找树演化而来,为了查找设计出来的树。

红黑树适合少量数据;为了平衡需要旋转变色,大大增加了增加删除节点操作的复杂度。

BTree的一个节点容量刚好是磁盘一页的大小(转一圈读的是磁道,硬盘中有多个磁盘,形成柱面,柱面转一圈是页面,也就是读一个磁道的时候把其他磁盘这个磁道一起读了,就是页面),很科学因为磁盘读取的时候就会把整页(这个页和MySql的页不一样,但是可能设计理念上有相通的地方)都读取到内存,就算你只要这页里的一个字。所以不浪费每一次操作。

B+Tree是链表+树的模式


B+Tree的所有数据都存在叶子节点,所以查询任何数据的速度都很平均;叶子节点还是一个链表结构,加快了遍历速度。所以B+Tree相对于他的其他兄弟,更适合储存大量数据。

MySql动态建表

mysql可以动态建表来解决按日期建表的问题。

优化

避免回表查询,可以将经常查询的几个字段创建联合索引。大大加快查询速度。

大数据分页,比如10万后的分页查询,可以先通过主键定位到第10万个数据,再向后查询,避免遍历前10万条数据。

select * from XXX where id>100000 limit 10;(前提是id有序,如果是雪花算分怎么用呢?)

select * from user where id>= (select id from user limit 10000,1) limit 100;

模糊查询,左边不加%,还是可以使用索引。

尽可能扩大内存中的数据量,加大内存,最优的状态是数据都在内存里;(这就有了redis)

为什么redis可以撑住高并发,但是MySql不行,只查询内存里的也不行吗?

redis缓存读写性能碾轧MySql。

加大innodb_buffer_pool_size(innoDB引擎下缓存池尺寸),看自己机子情况,给别的工具留点内存。

数据预热,启动时先将一些数据移到缓存;编写预热脚本,运行脚本。

降低磁盘写入次数,增大redolog,减少刷盘,innodb_log_file_size 设置为 0.25 * innodb_buffer_pool_size;会不会导致丢失更多数据?

不会,写日志频率还是一样的,可以用日志恢复。

设计优化:

统计表,专门统计数据,而不是查询的时候再去计算。

冗余字段,减少关联查找,最好是不会修改的字段,比如公司名称,用户名称;最好再做一个补偿功能,比如每周半夜同步这些数据。

拆表,拆一个副表出来,保存一些不经常用的信息。

主键,建议雪花,不重复而且有序。

其他字段,大小够用就行,不要太大,默认不要为null(null比空更长,设置0或空)。数字比字符串快。

加索引,alter table XXX add index index名称(字段名)(虽然说加索引会影响表更新效率,但是数据库90%操作都是查询)

in包含值不要过多,最好是排序的。

不要用*,多余字段产生回表查询。不如说是只查询索引字段。

MySql一条数据的结构到底是什么样的?既然要数据类型,说明会预先申请空间,那一条数据应该在连续空间中,所以查到任何字段,其他字段就在旁边不会影响效率,而且根据读盘读一页的原则,可能数据都已经取出在内存里了;为什么*会影响效率,就是顺手取的事。

索引是另一张表,不用*就是怕触发回表,如果字段里有不在索引都字段,那用不用*都无所谓了。

当查一条数据当时候使用limit 1

排序字段要加索引

不用or而是拼两条sql,这样至少有一个可以用到索引。

分段查询(个人经常用),分开查,然后用应用程序遍历组合;一般超过3张表关联就使用分段查询。

关联当时候,小表驱动大表;减少IO总量,小表数据少,连接次数就少;inner join会自动选小表做驱动表,比left join好。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 221,198评论 6 514
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 94,334评论 3 398
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 167,643评论 0 360
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,495评论 1 296
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,502评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 52,156评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,743评论 3 421
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,659评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,200评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,282评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,424评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 36,107评论 5 349
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,789评论 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,264评论 0 23
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,390评论 1 271
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,798评论 3 376
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,435评论 2 359

推荐阅读更多精彩内容