mysql的随机IO,顺序IO,主键与外健的区别,before与after触发器,绑定变量,全文索引

顺序IO&随机IO

顺序IO是指读取和写入操作基于逻辑块逐个连续访问来自相邻地址的数据。在顺序IO访问中,HDD所需的磁道搜索时间显着减少,因为读/写磁头可以以最小的移动访问下一个块。数据备份和日志记录等业务是顺序IO业务。随机IO是指读写操作时间连续,但访问地址不连续,随机分布在磁盘LUN的地址空间中。产生随机IO的业务有OLTP服务,SQL,即时消息服务等。(其实就是说在数据库查询时读取的不是连续区域,是要在整个磁盘上进行查找,多数时间可能耗费在了磁头寻道上)

     ① 顺序I/O一般只需扫描一次数据、所以、缓存对它用处不大

     ② 顺序I/O比随机I/O快

     ③ 随机I/O通常只要查找特定的行、但I/O的粒度是页级的、其中大部分是寻址,耗费时间,顺序I/O所读取的数据、通常发生在想要的数据块上的所有行更加符合成本效益。 所以、缓存随机I/O可以节省更多的workload

SQL的主键和外键的作用

 外键取值规则:空值或参照的主键值。

(1)插入非空值时,如果主键表中没有这个值,则不能插入。

(2)更新时,不能改为主键表中没有的值。

(3)删除主键表记录时,你可以在建外键时选定外键记录一起级联删除还是拒绝删除。

(4)更新主键记录时,同样有级联更新和拒绝执行的选择。

简而言之,SQL的主键和外键就是起约束作用。 

关系型数据库中的一条记录中有若干个属性,若其中某一个属性组(注意是组)能唯一标识一条记录,该属性组就可以成为一个主键。

比如:

学生表(学号,姓名,性别,班级)

    其中每个学生的学号是唯一的,学号就是一个主键;

课程表(课程编号,课程名,学分)

    其中课程编号是唯一的,课程编号就是一个主键;

成绩表(学号,课程号,成绩)

    成绩表中单一一个属性无法唯一标识一条记录,学号和课程号的组合才可以唯一标识一条记录,所以,学号和课程号的属性组是一个主键。

 

成绩表中的学号不是成绩表的主键,但它和学生表中的学号相对应,并且学生表中的学号是学生表的主键,则称成绩表中的学号是学生表的外键;同理,成绩表中的课程号是课程表的外键。

 

定义主键和外键主要是为了维护关系数据库的完整性,总结一下:

一、主键是能确定一条记录的唯一标识,比如,一条记录包括身份正号,姓名,年龄。身份证号是唯一能确定你这个人的,其他都可能有重复,所以,身份证号是主键。

外键用于与另一张表的关联。是能确定另一张表记录的字段,用于保持数据的一致性。比如,A表中的一个字段,是B表的主键,那他就可以是A表的外键。

 

二、主键、外键和索引的区别

 

定义:

 主键--唯一标识一条记录,不能有重复的,不允许为空

 外键--表的外键是另一表的主键外键可以有重复的可以是空值

 索引--该字段没有重复值,但可以有一个空值

作用:

 主键--用来保证数据完整性

 外键--用来和其他表建立联系用的

 索引--是提高查询排序的速度

个数:

 主键--主键只能有一个

 外键--一个表可以有多个外键

 索引--一个表可以有多个唯一索引


触发器:

关于触发器可以先读这篇文章:

https://www.cnblogs.com/yank/p/4193820.html

Before与After区别:before:(insert、update)可以对new进行修改。 after不能对new进行修改,两者都不能修改old数据。

after:是先完成数据的增删改,然后再触发,触发的语句晚于监视的增删改,无法影响前面的增删改动作;也就是说先插入订单记录,再更新商品数量。当商品数量少于订单数量时造成爆库。 before:先完成触发,在进行增删改,触发语句先于监视的增删改,我们就有机会判断,修改即将发生的操作。 案例操作: 触发器使用after: 当某个订单的数量超过库存的数量时会出现库存为负数。造成所谓的爆库问题。

 触发器,顾名思义,就是当执行某个事件的时候触发另一个事件的执行!这个触发的时间分为BEFORE和AFTER两种,分别有before insert,before update,before delete和after insert,after update,after delete这六种情况

FOR EACH ROW 子句通知触发器每隔一行执行一次动作,而不是对整个表,在触发器中我们经常会用到NEWOLD这两个关键字,在这里我还是先解释下这两个字的意思!其中NEW是指刚刚插入到数据库的数据表中的一个域,也可以理解为对象(object)的意思。比如在一个insert触发器中我用到了NEW那他的意思就是说,要使用刚刚插入到数据表的某个值,要使用具体的某一个值的话需要这样子写:NEW.字段名(NEW.username)这样子就获取到了刚刚插入到数据表中的一个字段的值!!OLD,OLD是在delete触发器中有用的,意思是说我要删除一条数据,但是在触发器中要用到之前的那个数据,那么我就可以通过OLD来获取了!比如我删除了一条数据,里面包含一个email,现在我在触发器的内部sql中要用就可以这样子写:OLD.email!

对于INSERT语句, 只有NEW是合法的;对于DELETE语句,只有OLD才合法;而UPDATE语句可以在和NEW以及OLD同时使

触发器的使用案例:http://database.51cto.com/art/201005/200671.htm

 绑定变量

绑定变量是为了减少解析的,比如你有个语句这样

select aaa,bbb from ccc where ddd=eee;

如果经常通过改变eee这个谓词赋值来查询,像如下

select aaa,bbb from ccc where ddd=fff;
select aaa,bbb from ccc where ddd=ggg;
select aaa,bbb from ccc where ddd=hhh;

每条语句都要被数据库解析一次,这样比较浪费资源,如果把eee换成“:1”这样的绑定变量形式,无论ddd后面是什么值,都不需要重复解析。

Java实现绑定变量的方法:

[java] view plaincopy
PreparedStatement pstmt = con.prepareStatement("UPDATE employees SET salay = ? WHERE id = ?");  
pstmt.setBigDecimal(1, 15.00);  
pstmt.setInt(2, 110592);   
/result statmement:   UPDATE employees SET salay = 15.00 WHERE id = 110592  
pstmt.executeQuery(); 

假设要将id从1到10000的员工的工资都更新为150.00元,不使用绑定变量,则:

[java] view plaincopy
sql.executeQuery("UPDATE employees SET salay = 150.00 WHERE id = 1");  
sql.executeQuery("UPDATE employees SET salay = 150.00 WHERE id = 2");  
sql.executeQuery("UPDATE employees SET salay = 150.00 WHERE id = 3");  
sql.executeQuery("UPDATE employees SET salay = 150.00 WHERE id = 4");  
....  
sql.executeQuery("UPDATE employees SET salay = 150.00 WHERE id = 10000");  

使用绑定变量,则:

[java] view plaincopy
PreparedStatement pstmt;  
for (id = 1; id < 10000; id  )  
{  
  if (null == pstmt)  
    pstmt = con.prepareStatement("UPDATE employees SET salay = ? WHERE id = ?");  
  pstmt.setBigDecimal(1, 150.00);  
  pstmt.setInt(2, id);   
  pstmt.executeQuery();  
}  

二者区别在于,不用绑定变量,则相当于反复解析、执行了1w个sql语句。使用绑定变量,解析sql语句只用了一次,之后的9999次复用第一次生成的执行计划。显然,后者效率会更高一些。

什么时候不应该/不必要使用绑定变量

  • 如果你用数据仓库,一条大查询一跑几个小时,根本没必要做绑定变量,因为解析的消耗微乎其微。
  • 变量对优化器产生执行计划有很重要的影响的时候:绑定变量被使用时,查询优化器会忽略其具体值,因此其预估的准确性远不如使用字面量值真实,尤其是在表存在数据倾斜(表上的数据非均匀分布)的列上会提供错误的执行计划。从而使得非高效的执行计划被使用。

全文索引

全文检索是对大数据文本进行索引,在建立的索引中对要查找的单词进行进行搜索,定位哪些文本数据包括要搜索的单词。因此,全文检索的全部工作就是建立索引和在索引中搜索定位,所有的工作都是围绕这两个来进行的。

建立全文索引中有两项非常重要,一个是如何对文本进行分词,一是建立索引的数据结构。分词的方法基本上是二元分词法、最大匹配法和统计方法。索引的数据结构基本上采用倒排索引的结构。

分词的好坏关系到查询的准确程度和生成的索引的大小。在中文分词发展中,早期经常使用分词方式是二元分词法,该方法的基本原理是将包含中文的句子进行二元分割,不考虑单词含义,只对二元单词进行索引。因此该方法所分出的单词数量较多,从而产生的索引数量巨大,查询中会将无用的数据检索出来,好处是算法简单不会漏掉检索的数据。之后又发展出最大匹配分词方法,该方法又分为正向最大分词和逆向最大分词。其原理和查字典类似,对常用单词生成一个词典,分析句子的过程中最大的匹配字典中的单词,从而将句子拆分为有意义的单词链。最大匹配法中正向分词方法对偏正式词语的分辨容易产生错误,比如“首饰和服装”会将“和服”作为单词分出。达梦数据库采用的是改进的逆向最大分词方法,该分词方法较正向正确率有所提高。最为复杂的是通过统计方式进行分词的方法。该方法采用隐式马尔科夫链,也就是后一个单词出现的概率依靠于前一个单词出现的概率,最后统计所有单词出现的概率的最大为分词的依据。这个方法对新名词和地名的识别要远远高于最大匹配法,准确度随着取样文本的数量的增大而提高。

 二元分词方法和统计方法是不依赖于词典的,而最大匹配法分词方法是依赖于词典的,词典的内容决定分词结构的好坏。

全文检索的索引被称为倒排索引,之所以成为倒排索引,是因为将每一个单词作为索引项,根据该索引项查找包含该单词的文本。因此,索引都是单词和唯一记录文本的标示是一对多的关系。将索引单词排序,根据排序后的单词定位包含该单词的文本。

上面这个感觉介绍的不是特别好,可以看高性能mysql的第299页到第301页


猜你喜欢

转载自blog.csdn.net/yanshuanche3765/article/details/80596668