数据库开发考试复习

2023-11-17

B树索引结构

B树索引的结构和使用方式

B树索引的结构:由根指向子节点,B树将索引按顺序存储,在叶节点保存索引到字段及其对应数据在表中的位置指针。从根节点开始搜索,通过节点中的指针进入下一级节点,通过比较要查找的索引值和节点中的指针大小选择进入哪个子节点,最终要么找到对应叶节点,要么没找到。叶节点中有指向表中数据的指针。

B树索引的使用

  1. 前缀查询

  2. 键值索引

  3. 键值范围查询

不能做的:后缀查询,顺序检索(不同于B+树,没有前一个叶节点扫后一个叶节点的指针)

什么时候使用B树索引

  1. 仅需要通过索引访问基本表的很少一部分行
  2. 如果要处理表中的多行,可以使用索引而不使用表(要访问的字段全部包含在索引中时)

为什么为外键建立索引是普遍的要求

为确保数据的完整性,在对主表操作时,需要对参照表进行加锁操作。如果外键没有索引,查找子记录就会很慢,且参照表被锁的时间很长,进而使很多更改操作阻塞,甚至可能发生死锁。进行连接查询时,如果不对外键使用索引则会发现查询的速度大大降低,引起全表扫描。

上面一个问题的例外情况

不从父表中删除记录

不更新父表中的主键的值

一般不进行父表和子表的连接查询

盲目为外键加索引还可能造成索引重复(同一字段,多个索引

IOT(大概率不考)

在IOT所对应的B树结构中,每个索引项包括<主键列值,非主键列值>而不是ROWID,对于普通堆组织表,oracle会有对应的索引与之对应,且分开存储。换句话说,IOT既是索引,又是实际的数据。

索引组织表(IOT)不仅可以存储数据,还可以存储为表建立的索引。索引组织表的数据是根据主键排序后的顺序进行排列的,这样就提高了访问的速度。但是这是由牺牲插入和更新性能为代价的(每次写入和更新后都要重新进行重新排序)。

注意两点:

● 创建IOT时,必须要设定主键,否则报错。

● 索引组织表实际上将所有数据都放入了索引中

B树索引练习

不少数据库都有自己的处理方式,比如,MySQL中不同的存储引擎使用了 不同的方式把索引保存到磁盘上,他们会影响性能。

MyISAM:使用前缀省略进行储存,每一个索引依赖于前一个值,例如,前一个值为7 perform,后一个值为performance,则保存为7,ance

特点:压缩块(生成索引)使用更少的空间,但某些查询速度可能会变慢,比如倒序查询(上一条特点的影响)

InnoDB基于聚簇索引建立,对主键查询具有很高的性能,不过二级索引必须包含主键列,如果主键列很大的话,其他的所有索引都很大,更新主键代价较高,在InnoDB中,默认主键不可以更新

索引

  1. 索引目的:提高查询效率

  2. 索引的另一面(问题)

    磁盘空间的开销
    处理的开销
    数据库系统处理的开销
    索引的使用是否合理,首先取决于它是否有用

  3. 判断索引适用性的依据是检索比例(retrieval ratios)

    索引的建立必须慎重,对每个索引的必要性都应该经过仔细分析,要有建立的依据。因为太多的索引与不充分、不正确的索引对性能都毫无益处:在表上建立的每个索引都会增加存储开销,索引对于插入、删除、更新操作也会增加处理上的开销。另外,过多的复合索引,在有单字段索引的情况下,一般都是没有存在价值的;相反,还会降低数据增加删除时的性能,特别是对频繁更新的表来说,负面影响更大

  4. 这些列不应该建立索引

    对于那些在查询中很少使用或者参考的列不应该创建索引。这是因为,既然这些列很少使用到,因此有索引或者无索引,并不能提高查询速度。相反,由于增加了索引,反而降低了系统的维护速度和增大了空间需求。
    对于那些只有很少数据值的列也不应该增加索引。这是因为,由于这些列的取值很少,例如人事表的性别列,在查询的结果中, 结果集的数据行占了表中数据行的很大比例,即需要在表中搜索的数据行的比例很大。增加索引,并不能明显加快检索速度。
    对于那些定义为 text, image和bit数据类型的列不应该增加索引。这是因为,这些列的数据量要么相当大,要么取值很少,不利于使用索引。
    当修改性能远远大于检索性能时,不应该创建索引。这是因为,修改性能和检索性能是互相矛盾的。当增加索引时,会提高检索性能,但是会降低修改性能。当减少索引时,会提高修改性能,降低检索性能。因此,当修改性能远远大于检索性能时,不应该创建索引。

系统生成键

系统生成键

  1. 系统生成键远好于寻找当前最大值并加 1以及用一个专用表保存”下一个值“且加锁更新

  2. 系统生成键是串行插入

  3. 如果插入并发性过高,在主键索引的创建操作上会发生严重的资源竞争

  4. 解决方案:反向键索引(逆向索引);哈希索引

  5. 系统生成键使用数字比使用字符串效率高

  6. 不使用系统生成键,可能会导致插入时主键取值不唯一,使用系统生成键有利于主键的唯一性

含有索引但未使用的几种情况

  1. 情况 1 :我们在使用 B+树索引,而且谓词中没有使用索引的最前列

  2. 情况 2:使用 SELECT COUNT(*) FROM T,而且 T 上有索引,但是优化器仍然全表扫描,不带任何条件的 count 会引起全表扫描。

  3. 情况 3:对于一个有索引的列作出函数查询

  4. 隐形函数查询(主要是时间和类型变化这种隐形函数查询)

    不等于符”<>”会限制索引,引起全表扫描,如果改成 or 就可以使用索引了。is null 查询条件也会屏蔽索引。

  5. 情况 5 :此时如果用了索引,实际反而会更慢,CBO会默认不使用索引。

  6. 情况 6 :没有正确的统计信息,造成 CBO 无法做出正确的选择;

位图索引

主要针对大量相同值的列而创建(例如:类别,操作员,部门 ID,库房 ID 等),

索引块的一个索引行中存储键值和起止 Rowid,以及这些键值的位置编码,位置编码中的每一位表示键值对应的数据行的有无.一个块可能指向的是几十甚至成百上千行数据的位置.

非常紧凑,块变得复杂,更新操作会导致整个块被锁住,不利于更新,所以创建位图索引的目的是为了查询而不是为了更新

B树索引不能存空值。位图索引可以存空值。

哈希索引

所谓 Hash 索引,实际上就是通过一定的 Hash 算法,将需要索引的键值进行 Hash 运算,然后将得到的 Hash 值存入一个 Hash 表中。每次需要检索的时候,都会将检索条件进行相同算法的 Hash 运算,再和 Hash 表中的 Hash 值进行比较,并得出相应的信息。HASH 索引在有限制条件(需要指定一个确定的值而不是一个值范围)的情况下非常有用。

HASH 的缺点

(1)Hash 索引仅仅能满足"=",“IN"和”<=>"查询,不能使用范围查询。由于 Hash 索引比较的是进行 Hash 运算之后的 Hash 值,所以它只能用于等值的过滤,不能用于基于范围的过滤,因为经过相应的 Hash 算法处理之后的 Hash 值的大小关系,并不能保证和 Hash 运算前完全一样。

(2)Hash 索引无法被用来避免数据的排序操作。由于 Hash 索引中存放的是经过 Hash 计算之后的 Hash 值,而且 Hash 值的大小关系并不一定和 Hash 运算前的键值完全一样,所以数据库无法利用索引的数据来避免任何排序运算;

(3)Hash 索引不能利用部分索引键查询。对于组合索引,Hash 索引在计算 Hash 值的时候是组合索引键合并后再一起计算 Hash 值,而不是单独计算 Hash 值,所以通过组合索引的前面一个或几个索引键进行查询的时候,Hash 索引也无法被利用。

(4)Hash 索引在任何时候都不能避免表扫描。前面已经知道,Hash 索引是将索引键通过 Hash 运算之后,将 Hash 运算结果的 Hash 值和所对应的行指针信息存放于一个 Hash 表中,由于不同索引键存在相同 Hash 值,所以即使取满足某个 Hash 键值的数据的记录条数,也无法从 Hash 索引中直接完成查询,还是要通过访问表中的实际数据进行相应的比较,并得到相应的结果。

(5)Hash 索引遇到大量 Hash 值相等的情况后性能并不一定就会比 B-Tree 索引高。对于选择性比较低的索引键,如果创建 Hash 索引,那么将会存在大量记录指针信息存于同一个 Hash 值相关联。这样要定位某一条记录时就会非常麻烦,会浪费多次表数据的访问,而造成整体性能低下。

SQL执行顺序

image-20210427111047022

语法检查:检查 SQL 拼写是否符合语法规范
语义检查:检查访问对象是否符合存在及用户是否具有相应权限
解析:在共享池中检查是否有完全相同的之前完全解析好的,如果存在,跳过选择执行计划和产生计划,直接运行

​ 硬解析:就是对提交的 SQL 完全重新从头进行解析,创建解析树,生成执行计划对 SQL 的执行来说是开销昂贵的动作,在很多项目中对功能相同的代码要保持一致性,用绑定变量
​ 软解析:在共享池(shared pool)中找到了与之完全相同的 SQL 解析好的结果会跳过硬解析后面的两个步骤

硬解析变成软解析的方法:设置session_cached_cursors,绑定变量

执行计划:以缩排列表的方式显示 SQL 语句的执行步骤

优化

对过滤条件进行优化

降低表链接数量(内嵌视图)

事务隔离

image-20210427104950222

脏读:一个事务读取到另外一个事务修改但未提交的数据时,可能发生脏读

不可重复读:在当执行SELECT 操作时没有获得读锁或SELECT操作执行 完后马上释放了读锁; 另外一个事务对数据进行了更新,读到了不同的结果

“幻读”又叫"幻象读“ • 是’‘不可重复读’‘的一种特殊场景 • 当事务1两次执行’‘SELECT … WHERE’'检索一定范围内数据的操作中间 • 事务2在这个表中创建了(如[[INSERT]])了一行新数据,这条新数据正好满足事务1的 “WHERE”子句。

区别

脏读:指读到了其他事务未提交的数据.

不可重复读:读到了其他事务已提交的数据(update).

不可重复读与幻读都是读到其他事务已提交的数据,但是它们针对点不同.

• 不可重复读:update. • 幻读:delete,insert.

隔离级别

未提交读:未提交读(READ UNCOMMITTED)是最低的隔离级别,在这种隔离级别下,如果一个事务 已经开始写数据,则另外一个事务则不允许同时进行写操作,但允许其他事务读此行数据。

已提交读:读取数据的事务允许其他事务继续访问该行数据,但是未提交的写事务将会禁止其他事务 访问该行,会对该写锁一直保持直到到事务提交.

可重复读(REPEATABLE READS)是介于已提交读和可串行化之间的一种隔 离级别,要求查询在事务开始之前一致(对原来开始查询时刻的表进行查询),它是InnoDb的默认隔离级别。(第一次查询不会出现幻读,但第二次会)

可串行化(Serializable )是高的隔离级别,它求在选定对象上的读锁和写 锁保持直到事务结束后才能释放,所以能防住上诉所有问题,但因为是串行化的,所以效率较低。

数据库范式与逆范式

逆范式概念

有时候,在设计表的时候,如果一张表中有几个字段是需要从另外的表中去获取信息,理论上讲,的确可以获取到想要的数据,但是就是效率低一点,会刻意的在某些表中,不去保存另外一张表的主键(逻辑主键)而是直接保存想要的数据信息,这样一来,在查询数据的时候,一张表可以直接提供数据,而不需要多表查询(效率低),但是会导致数据冗余。

使用逆范式的条件

在以下情况下考虑反规范化,特别是速度增加频繁或关键交易:
•模式1 结合1:1关系
•模式2 在1:关系中复制非键列以减少连接
•模式3 在1中复制FK列:关系以减少连接
•模式4 在1关系中复制列以减少连接
•模式5 引入重复组
•模式6 创建提取表
•模式7 分区表

例子

资源竞争

DBA解决方案(数据库管理员)

• 事务空间(Transaction space )

• 可用列表(Free list )

架构解决方案

• 分区(Partitioning )

• 逆序索引(Reverse index )(倒置)

• 索引组织表(Index organized table )

开发解决方案

• 调节并发数

• 不使用系统产生值(随机数代替)

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

数据库开发考试复习 的相关文章

  • JDBC 错误:在结果集开始之前[重复]

    这个问题在这里已经有答案了 我在 Java Eclipse 中收到错误消息 我在 MySql 中有一个数据库 它有列 String user name int id time int id desk int user password 我想
  • 显示和随机化 php 数组

    我有一个显示结果的数组 如下所示 Array 0 gt 71 1 gt 56 2 gt 64 3 gt 82 4 gt 90 5 gt 80 6 gt 65 7 gt 62 8 gt 14 9 gt 3 我的代码是 while row my
  • 无法连接到 MAMP 上的 phpMyAdmin

    我收到此错误消息 MySQL 说道 无法连接 设置无效 phpMyAdmin 尝试连接 MySQL 服务器 但服务器拒绝连接 您应该检查配置中的主机 用户名和密码 并确保它们与 MySQL 服务器管理员提供的信息相对应 用户和通行证是默认的
  • 休眠以持久保存日期

    有没有办法告诉 Hibernate java util Date 应该持久保存 我需要这个来解决 MySQL 中缺少的毫秒分辨率问题 您能想到这种方法有什么缺点吗 您可以自己创建字段long 或者使用自定义的UserType 实施后User
  • 如何为 MySQL 中的字段或列添加别名?

    我正在尝试做这样的事情 但我收到未知的列错误 SELECT SUM field1 field2 AS col1 col1 field3 AS col3 from core 基本上 我只想使用别名 这样我就不需要执行之前执行的操作 这在mys
  • 防止 Propel 插入空字符串

    当未设置列时 如何防止 Propel ORM 插入空字符串 CREATE TABLE user uid INTEGER PRIMARY KEY AUTO INCREMENT email VARCHAR 255 NOT NULL UNIQUE
  • 使用什么框架来引导我的第一个生产 scala 项目?

    我正在第一次涉足 scala 的生产应用程序 该应用程序当前打包为 war 文件 我的计划是创建 scala 编译工件的 jar 文件 并将其添加到 war 文件的 lib 文件夹中 我的增强功能是通过 Jersey 公开的 mysql 支
  • mysql 如何将 varchar(10) 转换为 TIMESTAMP?

    我已将所有日期存储到数据库中varchar 10 现在我想将它们转换为 TIMESTAMP 当我运行sql时 ALTER TABLE demo3 CHANGE date date TIMESTAMP NOT NULL 它提醒 1292 In
  • MySQL:@@ 是什么意思?

    我正在阅读本页上的 MySQL 文档 http dev mysql com doc refman 5 1 en set statement html http dev mysql com doc refman 5 1 en set stat
  • 在 MySQL 数据库中保持 TEXT 字段唯一的最佳方法

    我想让 TEXT 字段的值在我的 MySQL 表中唯一 经过小型研究 我发现由于性能问题 每个人都不鼓励在 TEXT 字段上使用 UNIQUE INDEX 我现在想用的是 1 创建另一个字段来包含 TEXT 值的哈希值 md5 text v
  • 奇怪的 MySQL Python mod_wsgi 无法连接到 'localhost' (49) 上的 MySQL 服务器问题

    StackOverflow上也有类似的问题 但我还没有发现完全相同的情况 这是在使用 MySQL 的 OS X Leopard 机器上 一些起始信息 MySQL Server version 5 1 30 Apache 2 2 13 Uni
  • 使用函数的 SQL 查询 - 如何获取列表的最大计数

    如何查询 MAXIMUM COUNT 交易次数 我的代码如下 SELECT customer id COUNT customer id FROM rental GROUP BY customer id HAVING MAX COUNT cu
  • 选择获取与 MySQL Group 中 max 对应的整行

    当我使用Max使用后查找特定 MySQL 组中字段的最大值GROUP BY 是否可以获取包含最大值的整行 我在处理一些论坛代码时偶然发现了这个线程 我想获取每个线程的最新帖子并将其显示在特定板的线程列表中 Quassnoi上面的回答对我非常
  • phpActiveRecord 日期时间格式不正确

    当尝试使用 phpActiveRecord 在表中创建记录时 出现以下错误 Invalid datetime format 1292 Incorrect datetime value 2013 06 20 11 59 08 PDT for
  • 统计mysql中的总行数并按列分组

    所以我已经看这个有一段时间了 但我似乎无法弄清楚 我有一个具有以下格式和示例数据的 mysql 表 ID Customer Time Error Code Duration 1 Test1 00 12 00 400 120 2 Test2
  • 处理ON INSERT触发器时,innodb表如何锁定?

    我有两个 innodb 表 articles id title sum votes 1 art 1 5 2 art 2 8 3 art 3 35 votes id article id vote 1 1 1 2 1 2 3 1 2 4 2
  • 复杂的sql树行

    表结构 id message reply id 1 help me 0 434 love to 1 852 didn t work 434 0110 try this 852 2200 this wont 0 5465 done 0110
  • 如何使用php在mysql数据库中添加照片? [关闭]

    这个问题不太可能对任何未来的访客有帮助 它只与一个较小的地理区域 一个特定的时间点或一个非常狭窄的情况相关 通常不适用于全世界的互联网受众 为了帮助使这个问题更广泛地适用 访问帮助中心 help reopen questions 我对 PH
  • Mac OSX 10.6 上的 Python mysqldb 不工作

    我正在使用 Python 2 7 并尝试让 Django 项目在 MySQL 后端运行 我已经下载了 mysqldb 并按照此处的指南进行操作 http cd34 com blog programming python mysql pyth
  • MYSQL 按喜欢/不喜欢和受欢迎程度排序

    我有评论表 其中包括喜欢和不喜欢的内容 现在我在正确的顺序上遇到了问题 实际上 我的系统在顶部显示了最多点赞的评论 我正在 youtube 上寻找类似系统的东西 这意味着 100like 100dislikes 的评论的顺序高于 1 1 我

随机推荐