mysql 数据库

http://www.importnew.com/22083.html
MySQL 事务
MySQL索引背后的数据结构及算法原理
MySQL索引类型
MySQL锁详解


事务用于处理操作量大,复杂度高的数据。

  • 在mysql中只有使用了Innodb引擎的数据库或表才支持事务
  • 事务处理可以用来维护数据库的完整性,保证成批的语句要么执行要么全部不执行。

ACID 数据库事务必须满足的四个条件:

  • 原子性(Atomicity):整个事务要么全部完成要么全部不完成。执行事务的过程如果发生错误,会- 回滚到事务开始之前,当做没发生过这个事务。
  • 一致性(Consistency):事务结束后系统的状态是一致的,不会出现数据不一致的情况
  • 隔离性(Isolation):防止多个事务并发执行由于交叉执行导致的数据的不一致。事务隔离级别
  • 持久性(Durability):事务完成后的改动都会被持久化,即使系统故障也不会丢失,通过日志和同步备份可以恢复数据。

多个事务访问同一个数据出现的问题

  • 脏读:事务A修改完数据后回滚,期间这个修改了的数据(脏数据)被其他事务读取到。(AupdateBqueryArollback)
  • 不可重复读:事务A修改完数据后提交。事务B在A修改前读取该数据,A提交后又一次读取该数据,结果与之前的不一样(重复读数据不一致)(BqueryAcommitBquery)
  • 幻读:事务A两次查询,B在两次查询中间插入了数据并提交。所以A第二次查询结果多了一些东西。(AselectBinsertAselect)
  • 第一类丢失更新,事务A回滚把已经提交的事务B的更新数据覆盖了。(ArollbaskBcommit)
  • 第二类丢失更新,事务A覆盖了事务B的数据,事务B的操作丢失。(ABcommit)

自动锁机制,事务隔离级别

隔离级别 脏读 不可重复读 幻读 第一类丢失更新 第二类丢失更新
READ UNCOMMITED 读未提交 X
READ COMMITTED 读提交 X X
REPEATABLE READ 可重复读 X X X X
SERIALIZABLE 串行化 X X X X X

事务隔离级别越高,并发性就越差。
回滚不会覆盖其他事务更新了的数据
mysql默认可重复读
数据库实现事务隔离的方式,一般分为两种:

  1. 一种是在读取数据前,对其加锁,阻止其他事务对数据进行修改。
  2. 另一种是不用加任何锁,通过一定机制生成一个数据请求时间点的一致性数据快照,并用这个快照来提供一定级别(语句级或事务级)的一致性读取。从用户的角度来看,好像是数据库可以提供统一数据的多个版本,因此这种技术叫做数据多版本并发控制(MultiVersion Concurrency Control,简称MVCC或MCC),也经常称为多版本数据库。

事务控制语句
mysql默认事务自动提交
begin/start transaction/set autocommit=0:禁止当前会话的自动提交。
set transaction 设置事务的隔离级别

JDBC操作

  • 加载驱动
    Class.forName("com.mysql.jdbc.Driver");

  • 创建连接
    Connection conn = DriverManager.getConnection(url,username,password);

  • 创建语句
    PrepareStatement ps = (PrepareStatement) conn.getPrepareStatement();
    ps.setString();
    ...

  • 执行语句
    ResultSet rs = ps.executeQuery(sql);

  • 处理结果
    int cols = rs.getMetaData.getColumnCount();
    while(rs.next()){
    for(int i=0;i rs.getString(i);
    }
    }

  • 关闭连接
    rs.close()
    ps.close()


MySQL索引背后的数据结构及算法原理
MySQL索引类型
主键将自动创建主键索引
innodb 不支持全文索引

主键索引和唯一索引的区别?
mysql什么时候哪些语句会使用到索引?
BTree索引、哈希索引??
聚集索引、非聚集索引、覆盖索引??

  1. 普通索引,没有任何限制
  2. 唯一索引
  • 索引列的值必须唯一;
  • 允许有空值
  • 组合索引的话列值组合必须唯一
  1. 主键索引
  • 不允许空值
  • 主键将自动创建索引
    primary key('id')
  1. 组合索引
  • 多个字段
  • 在查询条件中使用了索引的第一个字段,索引才会被使用。
  • 最左前缀集合
  1. 全文索引
  • 更像是搜索引擎
  • 必须是myisam引擎
  • match() against('') 语法

缺点:

  1. 因为对表进行insert、update和delete更新的时候不进要保存数据,还要更新索引文件,所以虽然索引提高了查询速度,但是会降低表的更新速度。
  2. 建立索引会占用磁盘空间

注意:

  1. 索引不包含null值的行??
  2. 使用短索引,指定前缀长度,提高查询速度,节省磁盘空间和I/O操作。
  3. 多个列排序最好创建复合索引??
  4. like 只有“a%”可以使用索引
  5. 在列上进行运算会导致索引失效,那应该怎么做??
  6. 不用not in、 <>???

索引本质是数据结构(以某种方式指向数据),使查询的复杂度更小。
如二叉查找树,每个结点包含索引键值对和指向对应数据记录物理地址的指针。
实际的数据库使用B树

BTree(B-Tree)

度d(d>1),约束结点内值的数量
高度h,所有叶子结点深度都是树高
每个非叶子结点有n-1个key和n个指针组成,其中d<=n<=2d
(key与指针相互间隔,节点两端是指针,指针数在度和2倍度之间)
叶子结点指针都是null
key从做到右递增排列
最左指针指向结点的所有key都小于右边key
中间指针指向结点的所有key都大于左边key、小于右边key
最右指针指向结点的所有key都大于左边key
树高上限logd ((N+1)/2)
查找节点O(logd N)


image.png

变种B+Tree

指针上限是2d+1(最左是数据最右是指针,最左的数据和父节点的一样
非叶子节点不存值data只存key
叶子节点不存储指针,存key和data
比BTree更适合实现外存储索引结构
因为可以有更大的出度

  • 主存存取原理
  • 磁盘存取原理,需要机械运动,旋转、寻道,耗费时间大。
  • 局部性原理和磁盘预读,每次磁盘I/O从找到的位置开始预读页(4k)的倍数的数据。
    (缺页,LRU算法)
  • 利用磁盘预读原理,将一个节点的大小设为一个页,这样每个节点只需要一次I/O就可以完全载入。
  • 根节点常驻内存。
  • O(h)=O(logd N) 出度越大高度越小,索引性能越好
  • 出度取决于节点大小
    d=pagesize/(keysize+datasize+pointsize)

myisam 数据文件和文件分开,树的结点的data存的是物理地址(非聚集索引)
innodb 树的结点存的是数据
主键索引文件存的数据是完整的数据(聚集索引(数据聚集??))
辅助索引(二级索引)data存的是主键值所以需要两次索引,通过检索辅助索引获得主键后再通过检索主键索引来获得数据。

  • 必须有主键,没有的话也会创建一个隐含字段当作主键
  • 主键字段不能太大,否则会使辅助索引过大
  • 因为插入效率低,所以尽量用自增字段做主键。自增只需要添加在树后面。插入需要挪数据,甚至目标页面可能已经被写回磁盘从缓存里清掉了,得从磁盘上读回来,增加了很多开销。

OPTIMIZE TABLE来重建表并优化填充页面。

不建议建索引

  1. 表记录少
  2. 重复索引值多

索引失效:

  1. 条件中有or,每个列都有索引才能用索引
  2. like查询,以%开头
  3. 条件中对应列的字符串不用引号引起来
  4. 若mysql估计使用全表扫描要比索引快,则不使用索引
  5. 对索引进行运算导致索引列失效
  6. 使用内部函数导致索引失效,应当创建基于函数的索引
  7. b树,is null不会用,is not null 会用。

创建复合索引(A,B,C)时,相当于创建了(A,B,C)、(A、B)、(A)这叫最佳左前缀特性。因此创建复合索引时,应将最常用的放在最左边。


mysiam:

  • 默认的存储引擎
  • 提供高速存储和检索,
  • 以及全文搜索能力
  • 表级锁
  • 损坏不能恢复数据
  • 不支持事务
    查询频繁、做很多count的计算时可使用

innodb:

  • 支持事务和外键
  • 索引多,主键应该尽可能小
  • 行级锁

使用情况:
更新查询频繁,多重并发
要求事务,可靠性要求高
外键约束,只有innodb支持
一般需要事务支持,有较高的并发读取频率是可选择innodb

memory:
数据存在内存
archive:
支持压缩数据
适合存储大量日志、历史数据
blackhole:
csv:


《高性能mysql第三版》

一些关于b树(b+)索引的限制

它只适用于全键值、键值范围或键前缀查找,其中键前缀查找只适用于根据最左前缀的查找。

  1. 如果不是按照索引的最左列开始查找,则无法使用索引。如,索引为(lastname,firstname,age),那么查找firstname为bill的查询无法用到这个索引,因为firstname不是最左数据列。
  2. 不能跳过索引中的列。如,不能用这个索引查lastname和age
  3. 如果查询有某个列的范围查询,则其右边所有列都无法使用索引优化查找。如果范围查询列值的数量有限,那么可以通过使用多个等于条件来代替范围条件。

以上限制都和索引列的顺序有关。在优化性能时可能需要使用相同的列但顺序不同的索引来满足不同类型的查询需求。

哈希索引

对于每一行数据,存储引擎都会对所有的索引列计算一个哈希码,哈希索引将所有的哈希码存储在索引中,同时在哈希表中保存指向每个数据行的指针。
在mysql中,只有memory引擎显示支持哈希索引。(非唯一哈希索引)
限制:

  1. 只包含哈希值和行指针
  2. 无序,无法用于排序
  3. 不支持部分索引列匹配查找
  4. 只支持等值比较查询
  5. 哈希冲突

自适应哈希索引:当innoDB注意到某些索引值被使用得非常频繁时,它会在内存中基于btree索引再建一个哈希索引。
自定义哈希索引:还是用btree进行查找,但是使用哈希值而不是键本身进行索引查找。需要在查询语句中手动指定使用哈希函数。例如,需要存储大量的url,并需要根据url进行搜索查找。如果使用btree来存储url,存储的内容会很大。

crc32做哈希函数,不用sha1和md5是因为他们计算出来的哈希值是非常长的字符串,浪费大量空间。
处理哈希冲突。在where中包含常量值,以免返回多行结果。

正确使用索引

  1. 索引列不能是表达式的一部分,也不能是函数的参数。应该始终将索引列单独放在比较符号的一侧。
  2. 前缀索引,有时需要索引很长的字符列会让索引变得大且慢,这时除了模拟哈希索引还可以只索引开始的部分字符,但是这样会降低索引的选择性(不重复的索引值数量和记录总数的比值)。索引的选择性越高则查询效率越高。
    可通过计算完整列的选择性,和前缀的选择性来相互比较。
  3. 多列索引。
    索引合并策略,5.0版本
  4. 选择合适的索引顺序
    可先预测一下哪个列的选择性更高,select sum(x1=2),sum(x2=5) from xx
    然后将选择性高的列放在前面
    但是如果这样子根据具体的值来优化会对其他的查询不公平
  5. 聚簇索引,行数据都在叶子结点中,在innodb中按主键顺序插入行
  6. 覆盖索引,一个索引包含所有需要查询的字段的值,就称之为“覆盖索引”

优化

  1. in代替范围查询
  2. 排序和分页,用延迟关联,先用索引拿到主键,再通过主键去表里取行数据

总结

  1. 单行访问很慢,如果服务器从存储(硬盘)中读取一个数据块(页)只是为了获取其中一行,那么就浪费了很多资源。最好读取出来的块中能包含尽可能多所需要的行。使用索引可以创建位置引用以提升效率。
  2. 按顺序访问范围数据是很快的,因为顺序i/o不需要多次磁盘寻道,所以比随机i/o要快得多
  3. 索引覆盖查询是很快的,因为不需要再回表查找行。这避免了大量的单行访问。

你可能感兴趣的:(mysql 数据库)