数据库知识

Overview of database

Posted by wykxwyc on February 4, 2022

目录


一、MySQL架构与历史总结

数据库的事物与ACID概念

事物就是一组原子性的SQL查询,或者说一个独立的工作单元。
ACID表示原子性(atomiciyt)、一致性(consistency)、隔离性(isolation)和持久性(durability)。

四种隔离级别

READ UNCOMMITTED(未提交读)
READ COMMITED(提交读)
REPEATABLE READ(可重复读)
SERIALIZABLE(可串行化)

MySQL中死锁产生的原因

例子:两个事务都执行了第一条update语句,更新了一行数据,同时锁定了改行数据。接着每个事务都去尝试执行第二条update语句,却发现该行已经被对方锁定,然后两个事务都等待对方释放锁。
InnoDB解决死锁的方式:将持有最少行级排他锁的事务进行回滚。

多版本并发控制MVCC

MVCC的实现,是通过保存数据在某个时间点的快照实现的。即,不管需要执行多长时间,每个事物看到的数据都是一致的,根据事务开始的时间不同,每个事物对同一张表,同一时刻看到的数据可能是不一样的。
InnoDB采用MVCC来支持高并发,并且实现了四个标准的隔离级别,其默认级别是REPEATABLE READ(可重复读),并且通过间隙锁(next-key locking)策略防止幻读的出现。

MySQL的存储引擎

MyISAM:
加锁与并发:MyISAM对整张表加锁而不是针对行。
修复:对于MyISAM表,MySQL可以手工或者自动执行检查和修复操作。修复可能会导致数据丢失,并且速度非常慢。InnoDB则崩溃概率低,恢复速度也快。
压缩表:如果表格在导入数据以后不会在进行操作,那么这样的表使用MyISAM比较适合。
性能:MyISAM设计简单,数据以紧密的格式存储,所以在某些场景下性能很好,但是最典型的问题还是表锁问题。

其他: Archive引擎,Blackhole引擎,CSV引擎,Federated引擎,Memory引擎……

二、MySQL基准测试

基准测试的概念

必要性:基准测试是唯一方便有效的、可以学习系统在给定的工作负载下会发生什么的方法。
测试指标:吞吐量、响应时间或者延迟、并发性、可扩展性等指标。
收集数据和分析结果可以考虑自动化基准测试,这样做可以获得更精确的测试结果。

集成式测试工具

ab:可以测试HTTP服务器每秒最多可以处理多少请求。
参考:http://httpd.apache.org/docs/2.0/programs/ab.html

http_load:概念上和ab类似,也被设计为对Web服务器进行测试,但比ab更加灵活。
参考:http://www.acme.com/software/hppt-load/

JMeter:是一个java应用程序,可以加载其他应用并测试其性能。
参考:http://jakarta.apache.org/jmeter/

三、服务器性能剖析

性能剖析工具

oprofile:在Linux平台,可以使用oprofile在服务器内部诊断上。

strace:剖析服务器的系统调用。

tcpdump:剖析查询。

GDB:用于等待分析,先启动gdb,然后attach到mysqld进程,将所有线程的堆栈都转储出来,然后可以利用简短的脚本将类似的堆栈跟踪信息做汇总。

四、Schema与数据类型优化

数据类型

MySQL类型选择的原则:更小的、简单的、避免Null。

整数类型:存储整数类型可以选择这几类:TINYINT(8 bits), SMALLINT(16 bits), MEDIUMINT(24 bits), INT(32 bits), BIGINT(64 bits)。
证书可以选UNSIGNED属性,表示不允许负值。

实数类型:DECIMAL类型允许最多65个数字,FLOAT使用4个字节存储,DOUBLE使用8个字节,MySQL使用DOUBLE作为内部浮点计算的类型。

字符串类型:VARCHARCHAR类型。BINARYVARBINARY类型。BLOBTEXT类型。
VARCHAR类型用于存储可变长字符串,是最常见的字符串数据类型。
CHAR类型是定长的,存储CHAR值时,MySQL会删除所有的末尾空格。CHAR类型适合存储很短的字符串,或者所有值都接近同一个长度,例如适合存储密码的MD5值,因为这是一个定长的值。
BLOB和TEXT都是为存储很大的数据而设计的字符串数据类型,分别采用二进制和字符方式存储。两组不同的数据类型:TINYTEXT,SMALLTEXT,TEXT,MEDIUMTEXT,LONGTEXT,对应的二进制类型是TINYBLOB,SMALLBLOB,BLOB,MEDIUMBLOB,LONGBLOB。BLOB是SMALLBLOB的同义词,TEXT是SAMLLTEXT的同义词。

日期和时间类型:DATETIMETIMESTAMP类型。
位数据类型:BIT和SET。不管底层存储和处理方式如何,从技术上来说都是字符串类型。
特殊数据类型:IPv4地址实际上是一个32位无符号整数,不是字符串,应该用无符号整数进行存储,并使用MySQL提供的INET_ATON()和INET_NTOA()函数在这两种表示方法之间进行转换,不该使用VARCHAR(15)。

一些优化技巧

计数器表在web应用中很常见,可以用这种表缓存一个用户的朋友数、文件下载次数等,一般的方法是创建一张独立的表,只有一行数据,记录网站点击次数。
但是这条记录上每次更新都有一个全局的互斥锁,使得事务只能串行执行。
要获得更高的并发性能,可以将计数器保存在多行中,每次随机选择一行更新。

五、创建高性能索引

索引的类型

B-Tree索引:使用B-Tree数据结构来存储数据,大多数引擎都支持这种索引。NDB集群存储引擎内部实际使用T-Tree结构存储这种索引,虽然名字是BTREE。InnoDB则使用的是B+Tree。

哈希索引:只有Memory引擎显式支持哈希索引,这也是Memory引擎表的默认索引类型。NDB集群引擎也支持唯一哈希索引。InnoDB引擎有一个特殊功能叫“自适应哈希索引”,让B-Tree也具有哈希索引的一些优点,这个行为用户无法配置。

空间数据索引(R-Tree):MyISAM表支持空间数据索引,可以用作地理数据存储。

全文索引:全文索引类似于搜索引擎做的事情。

其他类别索引:TokuDB使用分形树索引,既有B-Tree的很多优点,也避免了B-Tree的一些缺点。

索引的优点

1、索引大大减少了服务器需要扫描的数据量。
2、索引可以帮助服务器避免排序和临时表。
3、索引可以将随机I/O变为顺序I/O。

索引并不总是是最好的工具。只有当索引帮助存储引擎快速查找到记录带来的好处大于其带来的额外工作时,索引才是有效的。非常小的表,大部分情况下简单的全表扫描更高效。

高性能的索引策略

1.独立的列
2.前缀索引和索引选择性
3.多列索引
4.选择合适的索引列顺序

聚簇索引

表有聚簇索引时,它的数据行实际上放在索引的叶子页中。
术语“聚簇”表示数据行和相邻的键值紧凑地存储在一起。

在InnoDB表中按主键顺序插入行

如果正在使用InnoDB表并且没有什么数据需要聚集,可以定义一个代理键作为主键,最简单的方式是使用一个AUTO_INCREMENT自增列。
这样可以保证数据行是按顺序写入的。最好避免随机的(不连续且值得分布范围非常大)聚簇索引。

覆盖索引

如果一个索引包含(或者说覆盖)所有需要查询的字段的值,我们就称之为“覆盖索引”。
覆盖索引非常有用,能够极大地提高性能。如果查询只需要扫描索引而无须回表,会带来很多好处。

使用索引扫描来做排序

MySQL有两种方式可以生成有序的结果:通过排序操作,或者按照索引顺序扫描。
MySQL可以使用同一个索引既满足排序,又用于查找行。因此设计索引时应该尽可能地同时满足这两种任务。

压缩(前缀压缩)索引

MyISAM使用前缀压缩来减少索引的大小,从而让更多的索引可以放入内存中,这在某些情况下能极大地提高性能。
MyISAM压缩每个索引块的方法是:先完全保存索引块中的第一个值,然后将其他值和第一个值进行比较得到相同前缀的字节数和剩余的不同后缀部分,把这部分存储起来即可。例如,索引第一个值是“perform”,第二个值是“performance”,那么第二个值压缩后存储成类似“7,ance”这样的形式。

冗余和重复索引

冗余索引通常发生在为表添加新索引的时候。
例如,如果创建了索引(A,B),再创建索引(A)就是冗余索引,因为(A)是(A,B)的前缀索引。

大多数情况下都不需要冗余索引。
应该尽量扩展已有的索引而不是创建索引,但也有时候出于性能方面的考虑需要冗余索引,因为扩展已有的索引会导致其变得太大,从而影响其他使用该索引的查询的性能。

索引和锁

索引可以让查询锁定更少的行。InnoDB只有在访问行的时候才会对其加锁,而索引能够减少InnoDB访问的行数,从而减少锁的数量。
只有当InnoDB在存储引擎层能够过滤掉所有不需要的行时才有效。

六、查询性能优化

慢查询

查询性能低下最基本的问题是访问的数据太多。
大部分性能低下的查询都可以通过减少访问的数据量的方式进行优化。
向数据库请求了不需要的数据:查询不需要的记录、多表关联时返回全部列、总是取出全部列、重复查询相同的数据。

重构查询的方式

一个复杂查询还是多个简单查询切分查询分解关联查询

七至十六章

暂时不需要看这几个章节

用到时再做笔记记录

MySQL小记

聚簇索引和非聚簇索引

索引分为聚簇索引和非聚簇索引。

以一本英文课本为例,要找第8课,直接翻书,若先翻到第5课,则往后翻,再翻到第10课,则又往前翻。这本书本身就是一个索引,即“聚簇索引”。

如果要找”fire”这个单词,会翻到书后面的附录,这个附录是按字母排序的,找到F字母那一块,再找到”fire”,对应的会是它在第几课。这个附录,为“非聚簇索引”。

由此可见,聚簇索引,索引的顺序就是数据存放的顺序,所以,很容易理解,一张数据表只能有一个聚簇索引。

聚簇索引要比非聚簇索引查询效率高很多,特别是范围查询的时候。所以,至于聚簇索引到底应该为主键,还是其他字段,这个可以再讨论。
参考:
https://www.cnblogs.com/my_life/articles/10219877.html
https://www.cnblogs.com/balfish/p/8288891.html

MySQL中的InnoDB和MyISAM之间是什么关系,分别有什么特点?

其实InnoDB和MyISAM 是 MySQL 的两个存储引擎
差异在于:
1.InnoDB 支持事务,MyISAM 不支持,对于 InnoDB 每一条 SQL 语句都默认封装成事务进行提交,这样就会影响速度,优化速度的方式是将多条 SQL 语句放在 begin 和 commit之间,组成一个事务;
2.InnoDB 支持外键,而 MyISAM 不支持。
3.InnoDB 不支持全文索引,而 MyISAM 支持全文索引,查询效率上 MyISAM 要高;

外键和主键的概念

定义:
1.主键是能确定一条记录的唯一标识,比如,一条记录包括身份证号,姓名,年龄,身份证号是主键。
2.外键用于与另一张表的关联,是能确定另一张表记录的字段,用于保持数据的一致性。

有3张表:
1.学生表(学号,姓名,性别,班级)
2.课程表(课程编号,课程名,学分)
3.成绩表(学号,课程号,成绩)

表1中学号是主键;表2中课程编号是主键,表3中学号和课程号的属性组是一个主键;

成绩表中的学号不是成绩表的主键,但它和学生表中的学号相对应,并且学生表中的学号是学生表的主键,称成绩表中的学号是对应于学生表的外键。

同理,成绩表中的课程号是对应课程表的外键。

主键,外键和索引的对比
比较项目 主键 外键 索引
定义 唯一标识,非重复,非空 是另一表主键, 可重复, 可以为空 非重复,可有一个空值
作用 保证数据完整性 用来和其他表建立联系用的 提高查询排序的速度
个数 只能有一个 可以有多个外键 可以有多个惟一索引

摘录地址:https://blog.csdn.net/f45056231p/article/details/81070437

left join、join、right join和inner join的区别

用一张图来说明各种join的区别

left join
左连接,表1左连接表2,以左为主,表示以表1为主,关联上表2的数据,查出来的结果显示左边的所有数据,然后右边显示的是和左边有交集部分的数据。

right join
右连接,表1右连接表2,以右为主,表示以表2为主,关联查询表1的数据,查出表2所有数据以及表1和表2有交集的数据。

join
join,其实就是inner join,为了简写才写成join,两个是表示一个的,内连接,表示以两个表的交集为主,查出来是两个表有交集的部分,其余没有关联就不额外显示出来。

摘录地址:https://www.codeproject.com/Articles/33052/Visual-Representation-of-SQL-Joins

MyISAM 和 InnoDB 两种引擎所使用的索引的数据结构是什么?

都是 B+ 树,不过区别在于:

1.MyISAM 中 B+ 树的数据结构存储的内容是实际数据的地址值,它的索引和实际数据是分开的,只不过使用索引指向了实际数据。这种索引的模式被称为非聚集索引。

2.InnoDB 中 B+ 树的数据结构中存储的都是实际的数据,这种索引有被称为聚集索引。

参考:https://mp.weixin.qq.com/s/4gztFew5FdA2hUv1c0WdLw

什么是索引?

索引:在MySQL中也叫做键(key),是存储引擎用于快速找到记录的一种数据结构。
唯一索引:唯一索引不允许两行具有相同的索引值
主键索引:为表定义一个主键将自动创建主键索引,主键索引是唯一索引的特殊类型。主键索引要求主键中的每个值是唯一的,并且不能为空
聚集索引(Clustered):表中各行的物理顺序与键值的逻辑(索引)顺序相同,每个表只能有一个
非聚集索引(Non-clustered):非聚集索引指定表的逻辑顺序。数据存储在一个位置,索引存储在另一个位置,索引中包含指向数据存储位置的指针。可以有多个,小于 249 个

切分

水平切分
水平切分又称为 Sharding,它是将同一个表中的记录拆分到多个结构相同的表中。
例子:将数据分布到集群的不同节点上,从而缓存单个数据库的压力(数据库的分片,按地区/时间等)。

垂直切分
垂直切分是将一张表按列切分成多个表,通常是按照列的关系密集程度进行切分。
例子:将原来的电商数据库垂直切分成商品数据库、用户数据库等。

内连接和外连接

内连接语法:

SELECT  xxx FROM xxx INNER JOIN xxx ON xxx;

内连接的意思是,把表连接时表与表之间匹配的数据行查询出来,就是两张表之间数据行匹配时,要同时满足ON语句后面的条件才行。

左连接语法(外连接的一种):

SELECT xxx FROM xxx LEFT OUTER JOIN xxx ON xxx

左连接的意思是,无论是否符合ON语句后面的表连接条件,都会把左边那张表的记录全部查询出来,右边的那张表只匹配符合条件的数据行。
右连接则与之相反(这里同样OUTER 可以省略)。

内连接与外连接的区别就在于内连接中不匹配的就不列出来了

参考文献

1.https://mp.weixin.qq.com/s/4gztFew5FdA2hUv1c0WdLw