数据库基本概念
连接
有时,查询数据库时会有将两个数据表连接在一起的需求,这个时候需要用到数据库的连接。
数据库连接技术将数据库用一个笛卡尔积连接在一起。下面举个例子。
有两个表t1和t2
Id(t1) | Value(t1) |
---|---|
1 | 11 |
2 | 22 |
3 | 33 |
Id(t2) | Value(t2) |
---|---|
3 | 11 |
2 | 22 |
1 | 33 |
用下面的命令连接并查询连接在一起之后的表
SELECT *
FROM t1
JOIN t2;
会得到以下结果
Id(t1) | Value(t1) | Id(t2) | Value(t2) |
---|---|---|---|
1 | 11 | 3 | 11 |
1 | 11 | 2 | 22 |
1 | 11 | 1 | 33 |
2 | 22 | 3 | 11 |
2 | 22 | 2 | 22 |
2 | 22 | 1 | 33 |
3 | 33 | 3 | 11 |
3 | 33 | 2 | 22 |
3 | 33 | 1 | 33 |
然后我们根据我们的条件在这个连接成笛卡尔积中的表中筛选
这在数据库中叫做内连接。实际上数据库还有外连接。外连接又分为左外连接,右外连接和全外连接。
用左外连接举个例子
有两个表t1和t2
Id(t1) | Value(t1) |
---|---|
1 | 11 |
2 | 22 |
3 | 33 |
Id(t2) | Value(t2) |
---|---|
3 | 11 |
2 | 22 |
1 | null |
假设我们要找到t1,t2中value相同的值
SELECT *
FROM t1
JOIN t2
ON t1.value(t1) = t2.value(t2)
最终结果为
Id(t1) | Value(t1) | Id(t2) | Value(t2) |
---|---|---|---|
1 | 11 | 3 | 11 |
2 | 22 | 2 | 22 |
这是使用内连接的结果,如果使用左外连接的话用这个语句
SELECT *
FROM t1
LEFT JOIN t2
ON t1.value(t1) = t2.value(t2)
结果为
Id(t1) | Value(t1) | Id(t2) | Value(t2) |
---|---|---|---|
1 | 11 | 3 | 11 |
2 | 22 | 2 | 22 |
3 | 33 | 1 | null |
此时会保留左表中所有的记录
右连接则会保留右表所有的记录。
全外连接则是左连接和右连接的结合。
索引
索引是一个比较大的知识点。
问题描述
数据库中拥有海量数据,要从海量数据中找到我们需要的数据不是一件简单事,要解决这个问题,有很多相关办法。
解决策略及策略分析
解决快速查询数据的方法就是组织有效的数据结构,索引的方法有几种
首先是哈希表。
利用哈希函数将关键字映射为数据库中的位置,如果产生哈希冲突则拉出一张链表。
但是由于哈希表维护的是一个无序结构,所以哈希表只适合等值查询,在区间查询中的效果会较差。
其次是使用有序数组。
在有序数组中,我们可以用二分查找快速的找到数据,而且,由于有序数组维护的是一个有序结构,其同样适合区间查询。
但是有序数组有一个致命的缺陷,那就是在每次插入和删除数据时都会触发数据搬移,这导致了有序数组的维护困难,所以也不适合做数据库的索引来存储数据。
第三种策略是使用搜索树。
搜索树最有名的是二叉搜索树,其特点是左节点小于父节点,右节点大于父节点。利用该数结构能实现快速的检索数据。
为了避免搜索树深度太深,又有了平衡二叉树,保证二叉树的子树的深度尽可能平衡。
而且,平衡二叉树的插入和删除能效率较高地维护。
不过还有一个问题,内存的存取速率远高于磁盘,所以我们应该使得访问磁盘的次数尽可能少,数据库的开发者使用的做法是将二叉树改造为M叉数,通过加大宽度来减少深度。这样就使得磁盘的访问次数得到了降低。
所以,最终选定的数据结构为M叉数,也叫B+数。
再来看看B+数的维护。
插入数据时,如果数据排在最后一位,我们在最后面直接插入。
在数据应该排在中间时,插入应该使后面数据逻辑后移。
数据页满时会触发分页,搬移一部分数据到新的页中。
如果两个相邻的页删除了一些数据,导致它们的利用率不高,就会触发页的合并。
MYSQL实现的索引
主要分成3类。主键索引,非主键索引。
主键索引中,叶子节点维护的实际的数据记录。
非主键索引中,叶子节点维护的是主键的值。
联合索引有主键索引和非主键索引,其符合最左浅醉原则,即我们查询数据时按照建立索引的顺序来给出关键字的顺序,可以使得查询效率更高。
使用索引的最佳实践
主键长度越小普通索引占据的空间也就越小。
使用索引时,我们应该尽量使用自增主键做索引,这样可以使非主键索引占的空间尽可能少。
也可以避免在插入过程中导致的数据搬移行为。
尽量使用主键查询,避免查询两棵树。
覆盖索引:我们可以利用普通索引查询主键,避免产生再次查询主索引树。
索引越多维护越困难。
在建立联合索引,我们需要选定联合索引顺序时,如果通过调整顺序,可以少维护一个索引,那么这个顺序往往就是需要优先考虑采用的。
还有一个索引下推,这是MYSQL内部做的优化。
在查询索引时,会对索引包含的字段先做优化,之后再回表判断
事务
事务的作用
事务的出现主要是为了保证一次操作的完整性。避免因为某些命令执行到一半导致的数据出现不一致的情况。
事务主要有以下的特性(ACID):
A,也就是原子性(Atomicity)。原子的概念就是不可分割,你可以把它理解为组成物质的基本单位,也是我们进行数据处理操作的基本单位。
C,就是一致性(Consistency)。一致性指的就是数据库在进行事务操作后,会由原来的一致状态,变成另一种一致的状态。也就是说当事务提交后,或者当事务发生回滚后,数据库的完整性约束不能被破坏。
I,就是隔离性(Isolation)。它指的是每个事务都是彼此独立的,不会受到其他事务的执行影响。也就是说一个事务在提交之前,对其他事务都是不可见的。
最后一个 D,指的是持久性(Durability)。事务提交之后对数据的修改是持久性的,即使在系统出故障的情况下,比如系统崩溃或者存储介质发生故障,数据的修改依然是有效的。因为当事务完成,数据库的日志就会被更新,这时可以通过日志,让系统恢复到最后一次成功的更新状态。
使用事务
使用事务有两种方式,分别为隐式事务和显式事务。
隐式事务实际上就是自动提交。
显示事务在使用事务前使用begin说明一个事务的开始,使用commit说明一个事务的结束。