MySQL必知必会

在这里插入图片描述

1.数据库设计(三范式)

第一范式(1NF)

第一范式就是属性不可分割,每个字段都应该是不可再拆分的。比如一个字段是姓名(NAME),在国内的话通常理解都是姓名是一个不可再拆分的单位,这时候就符合第一范式;但是在国外的话还要分为FIRST NAME和LAST NAME,这时候姓名这个字段就是还可以拆分为更小的单位的字段,就不符合第一范式了。

数据库表中的任何字段都是单一属性的,不可再分

第二范式(2NF)

第二范式就是要求表中要有主键,表中其他其他字段都依赖于主键,因此第二范式只要记住主键约束就好了。比如说有一个表是学生表,学生表中有一个值唯一的字段学号,那么学生表中的其他所有字段都可以根据这个学号字段去获取,依赖主键的意思也就是相关的意思,因为学号的值是唯一的,因此就不会造成存储的信息对不上的问题,即学生001的姓名不会存到学生002那里去。

第三范式(3NF)

第三范式就是要求表中不能有其他表中存在的、存储相同信息的字段,通常实现是在通过外键去建立关联,因此第三范式只要记住外键约束就好了。比如说有一个表是学生表,学生表中有学号,姓名等字段,那如果要把他的系编号,系主任,系主任也存到这个学生表中,那就会造成数据大量的冗余,一是这些信息在系信息表中已存在,二是系中有1000个学生的话这些信息就要存1000遍。因此第三范式的做法是在学生表中增加一个系编号的字段(外键),与系信息表做关联。

局部性原理与磁盘预读

由于存储介质的特性,磁盘本身存取就比主存慢很多,再加上机械运动耗费,磁盘的存取速度往往是主存的几百分分之一,因此为了提高效率,要尽量减少磁盘I/O。为了达到这个目的,磁盘往往不是严格按需读取,而是每次都会预读,即使只需要一个字节,磁盘也会从这个位置开始,顺序向后读取一定长度的数据放入内存。这样做的理论依据是计算机科学中著名的
局部性原理:当一个数据被用到时,其附近的数据也通常会马上被使用。程序运行期间所需要的数据通常比较集中

由于磁盘顺序读取的效率很高(不需要寻道时间,只需很少的旋转时间),因此对于具有局部性的程序来说,预读可以提高I/O效率。

预读的长度一般为页(page)的整倍数。页是计算机管理存储器的逻辑块,硬件及操作系统往往将主存和磁盘存储区分割为连续的大小相等的块,每个存储块称为一页(在许多操作系统中,页得大小通常为4k),主存和磁盘以页为单位交换数据。当程序要读取的数据不在主存中时,会触发一个缺页异常,此时系统会向磁盘发出读盘信号,磁盘会找到数据的起始位置并向后连续读取一页或几页载入内存中,然后异常返回,程序继续运行

2.Mysql的存储引擎,Myisam和Innodb的区别。

NULLmyisaminnodb
事务支持不支持支持
存储结构三种文件一种文件
存储空间体积小体积大
可移植性方便困难
锁力度表级锁表级锁,行级锁
全文索引支持不支持
表主键可以没有必须有,没有就自动生成
外键不支持支持

在MySQL中ENUM的用法是什么?

同一个属性里面包含多个字段,每个字段都有自己的索引.enum 在数据库底层以整型方式储存,从 1 开始,0 用于指代空或错误的字符串。

CHAR和VARCHAR的区别?

char 固定长度255,不足的部分补空格,取出时再去掉空格。varchar 不定长度

drop,delete与truncate的区别

drop删除表,truncate清空表,delete删除表、drop和truncate不能回滚。

3.锁

  • MyISAM 是非事务的存储引擎,适合用于频繁查询的应用。表锁,不会出现死锁,适合小数据,小并发。
  • Innodb是支持事务的存储引擎,合于插入和更新操作比较多的应用,设计合理的话是行锁(最大区别就在锁的级别上),适合大数据,大并发
    image

表锁和行锁的区别

表锁
  • 特点:开销小、加锁快、无死锁;锁粒度大,发生锁冲突的概率高,高并发下性能低
  • 加锁的方式:自动加锁。查询操作(SELECT),会自动给涉及的所有表加读锁,更新操作(UPDATE、DELETE、INSERT),会自动给涉及的表加写锁。
行锁
  • 特点:锁的粒度小,发生锁冲突的概率低、处理并发的能力强;开销大、加锁慢、会出现死锁

  • 加锁的方式:自动加锁。对于UPDATE、DELETE和INSERT语句,InnoDB会自动给涉及数据集加排他锁;对于普通SELECT语句,InnoDB不会加任何锁。

  • 乐观锁:不加锁,只有在更新时验证数据是否被其他线程更新,吞吐量较高,适用于多读场景。它假设多用户并发的事务在处理时不会彼此互相影响,各事务能够在不产生锁的情况下处理各自影响的那部分数据。在提交数据更新之前,每个事务会先检查在该事务读取数据后,有没有其他事务又修改了该数据。如果其他事务有更新的话,那么当前正在提交的事务会进行回滚

乐观锁实现方式是:版本号version和CAS(compare and swap)

  • 悲观锁:读取时加锁,更新完释放锁,再此过程中会造成其他线程阻塞,导致吞吐量低,适用于多写场景。当事务A对某行数据应用了锁,并且当这个事务把锁释放后,其他事务才能够执行与该锁冲突的操作,这里事务A所施加的锁就叫悲观锁。

行锁(共享锁和排他锁),间隙锁(next-keylock)都属于悲观锁。
InnoDB实现了以下两种类型的行锁:

  • 共享锁(S):允许一个事务去读一行,阻止其他事务获得相同数据集的排他锁

  • 排他锁(X):允许获得排他锁的事务更新数据,阻止其他事务取得相同数据集的共享读锁和排他写锁。
    另外,为了允许行锁和表锁共存,实现多粒度锁机制,InnoDB还有两种内部使用的意向锁(Intention Locks),这两种意向锁都是表锁。

  • 意向共享锁(IS):事务打算给数据行加行共享锁,事务在给一个数据行加共享锁前必须先取得该表的IS锁。

  • 意向排他锁(IX):事务打算给数据行加行排他锁* ,事务在给一个数据行加排他锁前必须先取得该表的IX锁。

间隙锁(Next-Key锁):
  • 当我们用范围条件而不是相等条件检索数据,并请求共享或排他锁时,InnoDB会给符合条件的已有数据记录的索引项加锁;
  • 对于键值在条件范围内但并不存在的记录,叫做“间隙(GAP)”,InnoDB也会对这个“间隙”加锁,这种锁机制就是所谓的间隙锁(Next-Key)锁。

  • 1:表级锁不会死锁,行级锁和页级锁可能死锁
  • 2:在数据库实现资源锁定的过程中,随着锁定资源颗粒度的减小,锁定相同数据量的数据所需要消耗的内存数量是越来越多的,实现算法也会越来越复杂。不过,随着锁定资源颗粒度的减小,应用程序的访问请求遇到锁等待的可能性也会随之降低,系统整体并发度也随之提升。
  • 3:从锁的角度来说,表级锁更适合于以查询为主,只有少量按索引条件更新数据的应用,如Web应用;而行级锁则更适合于有大量按索引条件并发更新少量不同数据,同时又有并发查询的应用,如一些在线事务处理(OLTP)系统。
  • 4:意向锁是InnoDB自动加的,不需用户干预。对于UPDATE、DELETE和INSERT语句,InnoDB会自动给涉及数据集加排他锁(X);对于普通SELECT语句,InnoDB不会加任何锁;
  • 5:InnoDB行锁实现方式: InnoDB行锁是通过给索引上的索引项加锁来实现的,只有通过索引条件检索数据,InnoDB才使用行级锁,否则,InnoDB将使用表锁
锁策略

Mysql中MVCC的使用及原理详解

MVCC是一种多版本并发控制机制。MVCC是通过保存数据在某个时间点的快照来实现的。在每个表后添加创建版本号和删除版本号,版本号为修改该项的事务版本号。

  • SELECT:InnoDB会根据以下两个条件检查每行记录

InnoDB只会查找版本早于当前事务版本的数据行(也就是,行的系统版本号小于或等于事务的系统版本号),这样可以确保事务读取的行,要么是在事务开始前已经存在的,要么是事务自身插入或者修改过的.

行的删除版本要么未定义,要么大于当前事务版本号,这可以确保事务读取到的行,在事务开始之前未被删除.
只有a,b同时满足的记录,才能返回作为查询结果.

  • DELETE:InnoDB会为删除的每一行保存当前系统的版本号(事务的ID)作为删除标识.

  • UPDATE:InnoDB执行UPDATE,实际上是新插入了一行记录,并保存其创建时间为当前事务的ID,同时保存当前事务ID到要UPDATE的行的删除时间。

4.SQL语句

MySQL的语句执行顺序

MySQL的语句一共分为11步,如下图所标注的那样,最先执行的总是FROM操作,最后执行的是LIMIT操作。其中每一个操作都会产生一张虚拟的表,这个虚拟的表作为一个处理的输入,只是这些虚拟的表对用户来说是透明的,但是只有最后一个虚拟的表才会被作为结果返回。如果没有在语句中指定某一个子句,那么将会跳过相应的步骤。

MySQL的语句执行顺序

下面我们来具体分析一下查询处理的每一个阶段
  1. FORM: 对FROM的左边的表和右边的表计算笛卡尔积。产生虚表VT1
  2. ON: 对虚表VT1进行ON筛选,只有那些符合<join-condition>的行才会被记录在虚表VT2中。
  3. JOIN: 如果指定了OUTER JOIN(比如left join、 right join),那么保留表中未匹配的行就会作为外部行添加到虚拟表VT2中,产生虚拟表VT3, rug from子句中包含两个以上的表的话,那么就会对上一个join连接产生的结果VT3和下一个表重复执行步骤1~3这三个步骤,一直到处理完所有的表为止。
  4. WHERE: 对虚拟表VT3进行WHERE条件过滤。只有符合<where-condition>的记录才会被插入到虚拟表VT4中。
  5. GROUP BY: 根据group by子句中的列,对VT4中的记录进行分组操作,产生VT5.
  6. CUBE | ROLLUP: 对表VT5进行cube或者rollup操作,产生表VT6.
  7. HAVING: 对虚拟表VT6应用having过滤,只有符合<having-condition>的记录才会被 插入到虚拟表VT7中。
  8. SELECT: 执行select操作,选择指定的列,插入到虚拟表VT8中。
  9. DISTINCT: 对VT8中的记录进行去重。产生虚拟表VT9.
  10. ORDER BY: 将虚拟表VT9中的记录按照<order_by_list>进行排序操作,产生虚拟表VT10.
  11. LIMIT:取出指定行的记录,产生虚拟表VT11, 并将结果返回。

由server层和存储引擎组成

server 层包括连接器、分析器、优化器、执行器,涵盖 MySQL的核心服务,以及所有的内置函数(如日期、时间、数学、加密函数等),还有所有跨存储引擎的功能,例如存储过程、触发器、视图等。

一条SQL更新语句是如何执行的

一条SQL更新语句是如何执行的?

里面包含binlog和redolog,两阶段提交

SQL语句菜鸟教程

SQL教程
  • AND运算符,如果第一个条件和第二个条件都成立,则 AND 运算符显示一条记录。
  • OR运算符如果第一个条件和第二个条件中只要有一个成立,则 OR 运算符显示一条记录。
SELECT * FROM Websites
WHERE alexa > 15
AND (country='CN' OR country='USA');
  • ORDER BY 关键字默认按照升序对记录进行排序。如果需要按照降序对记录进行排序,您可以使用 DESC 关键字。
  • IN操作符IN操作符允许在WHERE子句中规定多个值。
  • BETWEEN操作符用于选取介于两个值之间的数据范围内的值。
SELECT * FROM Websites
WHERE (alexa BETWEEN 1 AND 20)
AND country NOT IN ('USA', 'IND');
  • INNER JOIN:如果表中有至少一个匹配,则返回行
  • LEFT JOIN:即使右表中没有匹配,也从左表返回所有的行
  • RIGHT JOIN:即使左表中没有匹配,也从右表返回所有的行
  • FULL JOIN:只要其中一个表中存在匹配,则返回行
SQL高级教程
  • 模糊查询(like)
SELECT * FROM Websites
以"G"开始的所有客户WHERE name LIKE 'G%';
以"k"结尾的所有客户WHERE name LIKE '%k';
还可以写NOT LIKE做反向查询

解释MySQL外连接、内连接(outer join和inner join)与自连接的区别外连接
SQL JOINS

  • 左连接:连接两张表,左表数据完全显示,右表匹配,匹配不上的补null;在这里,t_employee就是左表,也就是基准表,用基准表的数据去匹配右表的数据,所以左表的记录是全部会查询出来的,如果右表没有记录对应的话就显示null

LEFT JOIN 关键字从左表(table1)返回所有的行,即使右表(table2)中没有匹配。如果右表中没有匹配,则结果为 NULL。

  • 右连接:同上,换个方向;
    全外连接:两表字段都匹配,匹配不上的补null;
  • 内连接:所有查询出的结果都是能够在连接的表中有对应记录的。这就是内连接的特点,只查询在连接的表中能够有对应的记录

INNER JOIN关键字在表中存在至少一个匹配时返回行。

  • 全外连接:mysql是没有全外连接的(mysql中没有full outer join关键字),想要达到全外连接的效果,可以使用union关键字连接左外连接和右外连接如果在Oracle中,直接就使用full outer join关键字连接两表就行了。
  • UNION

SQL UNION 操作符合并两个或多个 SELECT 语句的结果。

SELECT country FROM Websites
UNION
SELECT country FROM apps
ORDER BY country;
  • SELECT INTO

通过 SQL,您可以从一个表复制信息到另一个表。SELECT INTO 语句从一个表复制数据,然后把数据插入到另一个新表中

CREATE TABLE 新表
AS
SELECT * FROM 旧表 
  • INSERT INTO SELECT

通过 SQL,您可以从一个表复制信息到另一个表。INSERT INTO SELECT 语句从一个表复制数据,然后把数据插入到一个已存在的表中。

INSERT INTO table2
SELECT * FROM table1;
  • 自连接:找到两表的公共字段,然后和内连接一样。
  • 交叉连接: 生成笛卡尔积-它不使用任何匹配或者选取条件,而是直接将一个数据源中的每个行与另一个数据源的每个行都一一匹配

SELECT type,pub_name FROM titles CROSS JOIN publishers ORDER BY type

子查询

一个SELECT语句嵌套在另一个SELECT语句中,子查询也叫做内部查询,而包含子查询的语句又称为外部查询或主查询,子查询自身可以包含一个或多个子查询,一个查询语句中可以嵌套任意数量的子查询。

SQL查询重复记录

MySQL两道经典SQL面试题(行转列/列转行/求最值)

SQL函数

  • GROUP BY

GROUP BY 语句用于结合聚合函数,根据一个或多个列对结果集进行分组。

统计 access_log 各个 site_id 的访问量:
SELECT site_id, SUM(access_log.count) AS nums
FROM access_log GROUP BY site_id;
SELECT Websites.name,COUNT(access_log.aid) AS nums FROM access_log
LEFT JOIN Websites
ON access_log.site_id=Websites.id
GROUP BY Websites.name;
  • HAVING

在 SQL 中增加 HAVING 子句原因是,WHERE 关键字无法与聚合函数一起使用。HAVING 子句可以让我们筛选分组后的各组数据。

查找总访问量大于 200 的网站。
SELECT Websites.name, Websites.url, SUM(access_log.count) AS nums FROM (access_log INNER JOIN Websites
ON access_log.site_id=Websites.id)
GROUP BY Websites.name
HAVING SUM(access_log.count) > 200;
  • 查询分页
查询admin表中前10条记录,换句话说,就是查询10条记录,并且是从第1条数据开始查
(注意:第一条数据的索引是0,第二条数据的索引是1,以此类推)
SELECT * FROM admin LIMIT 0, 10;

如果你要查询admin表中前10条记录,并且是从第1条数据开始查,那么索引0可以省略不写,如下:
SELECT * FROM admin LIMIT 10;

#从第5条数据开始查,查3条记录(注意:第一条数据的索引是0,第二条数据的索引是1,以此类推)
SELECT * FROM admin LIMIT 4,3;
#从第5条数据开始查,查3条记录(注意:第一条数据的索引是0,第二条数据的索引是1,以此类推)
SELECT * FROM admin LIMIT 3 OFFSET 4;#可以把OFFSET理解成开端索引或者叫起始索引,OFFSET后面跟索引

limit 1000 10

从1000开始,往后10个

SQL注入

SQL优化

  • 全值匹配我最爱,最左前缀要遵守;
  • 带头大哥不能死,中间兄弟不能断;
  • 索引列上少计算,范围之后全失效;
  • Like百分写最右,覆盖索引不写星;
  • 不等空值还有or,索引失效要少用;
  • VAR引号不可丢,SQL高级也不难!
慢查询解决的基本步骤
500万数量级查询优化
我们是如何对实际项目进行查询优化的
巧用这19条MySQL优化,效率至少提高3倍
一次SQL查询优化原理分析(900W+数据,从17s到300ms
创建表时候的优化
  • 整数TinyInt,SmallInt,MediumInt,Int,BigInt 使用的存储 8,16,24,32,64 位存储空间。使用 Unsigned 表示不允许负数,可以使正数的上线提高一倍。
  • 实数Float,Double , 支持近似的浮点运算。
    Decimal,用于存储精确的小数。
  • 字符串VarChar,存储变长的字符串。需要 1 或 2 个额外的字节记录字符串的长度。Char,定长,适合存储固定长度的字符串,如 MD5 值。
  • Blob,Text为了存储很大的数据而设计的。分别采用二进制和字符的方式。
  • 时间类型DateTime,保存大范围的值,占 8 个字节。TimeStamp,推荐,与 UNIX 时间戳相同,占 4 个字节。
SQL语句优化
  • 应尽量避免在 where 子句中使用!=或<>操作符,否则将引擎放弃使用索引而进行全表扫描。
  • 应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索引而进行全表扫描,如:select id from t where num is null可以在num上设置默认值0,确保表中num列没有null值,然后这样查询:select id from t where num=0
  • 用EXISTS替代IN、用NOT EXISTS替代NOT IN

in和exist区别是exists能使用索引,in适合查询小表,会乱序 in里面数量多会导致全表搜索in本质是or

  • 用Where子句替换HAVING 子句 因为HAVING 只会在检索出所有记录之后才对结果集进行过滤。
  • 尽量避免在where子句中对字段进行表达式操作,这将导致引擎放弃使用索引而进行全表扫描
  • Where子句中:where表之间的连接必须写在其他Where条件之前,那些可以过滤掉最大数量记录的条件必须写在Where子句的末尾.HAVING最后。
  • 对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引
索引优化(选择索引的数据类型)

MySQL支持很多数据类型,选择合适的数据类型存储数据对性能有很大的影响。

  • 越小的数据类型通常更好:越小的数据类型通常在磁盘、内存和cpu缓存中都需要更少的空间,处理起来更快。
  • 简单的数据类型更好:整形数据比起字符,处理开销更小,因为字符串的比较更复杂。在MySQL中,应用内置的日期和时间数据类型,而不是字符串来存储时间;以及用整形数据存储IP地址。
  • 尽量避免NULL:应该制定列为NOT NULL,除非你想存储NULL。在MySQL中,含有空值的列很难进行查询优化,因为他们使得索引、索引的统计信息以及比较运算更加复杂。
  • 为了更多的提高mysql效率可建立组合索引,遵循“最左前缀”原则。创建复合索引应该将最常用(频率)做限制条件的列放在最左边,一次递减。组合索引最左字段用in是可以用到索引的。相当于建立了col1,col1col2,col1col2col3三个索引。

分库分表

分库分表优化

数据超过500万,查询超过3S

  • 垂直拆分:解决问题:表与表之间的io竞争 不解决问题:单表中数据量增长出现的压力

方案: 把产品表和用户表放到一个server上 订单表单独放到一个server上。

  • 水平拆分: 解决问题:单表中数据量增长出现的压力 不解决问题:表与表之间的io争夺

用户表通过性别拆分为男用户表和女用户表 订单表通过已完成和完成中拆分为已完成订单和未完成订单 产品表 未完成订单放一个server上 已完成订单表盒男用户表放一个server上 女用户表放一个server上(女的爱购物 哈哈),
可以把学校范围内的用户单独独立出来一张表

MySQL不需要执行后面的复杂操作,就可以直接返回结果,效率很高,但是查询缓存失效非常频繁,只要有对一个表的更新,这个表的所有查询缓存都会被清空,因此可能你费力地把结果缓存起来,还没使用,就被一个更新全部清空了。除非你的业务是一张静态表,很长时间才会更新一次,这种情况下可以使用查询缓存。(把管理员信息放进去)。

谈一下数据库分库分表之后,你是如何解决事务问题

为什么要分区,分表和分库?
面试官:给我讲一下分库分表方案
MyCAT

4.索引

MYSQL 主键索引-聚簇索引-二级索引

在这里插入图片描述

各种名字的索引

聚簇索引和非聚簇索引的区别

聚集索引和非聚集索引

索引是对数据库表中一列或多列的值进行排序的一种结构,使用索引可快速访问数据库表中的特定信息。数据库中索引可以分为两种类型:聚簇索引(聚集索引)和非聚簇索引(非聚集索引)。MyISAM 的B+ Tree的叶子节点上的data并不是数据本身,而是数据的存放地址。所以物理存储上MyISAM引擎的表会有三个文件(表结构文件,数据文件,索引文件)。
InnoDB的数据文件本身就是索引文件,B+Tree的叶子节点上的data就是数据本身,key为主键,这是聚簇索引,聚簇索引一张表是唯一的,不然表的数据存储的顺序就乱了(就是说innodb表只能有一个主键)

  • 聚集索引:表数据是按照索引的顺序来存储的,也就是说,索引项的顺序与表中记录的物理顺序一致。对于聚集索引,叶子结点即存储了真实的数据行,不再有另外单独的数据页。正因为索引的数据需与数据物理存储的顺序一致,在一张表上最多只能创建一个聚集索引。
  • 非聚集索引:表数据存储顺序与索引顺序无关。对于非聚集索引,叶结点包含索引字段值及指向数据页、数据行的逻辑指针。为了提高索引的性能,一般采用B树来实现。

多个索引匹配

  • 覆盖索引可以减少回表的次数.MySql5.6以后还支持索引下推的功能,把覆盖索引覆盖的字段记忆布筛选,减少回表的次数,可以再explain看Sql执行计划时,Extra字段有Using index condition可以看到。
  • 然后进一步优化,如何存储介质为机械硬盘,比较怕随机读写,有磁盘寻址的开销。可以把Mrr开开,也就是multi range read,可以在回表之前将ID读到buffer里面进行排序,把随机操作变为顺序操作。
  • 用最左原则配合覆盖索引,减少为索引的维护。
  • 对写多读少的普通索引,如果业务是唯一性服务,就用普通索引,因为普通索引可以Change buffer,Change buffer可以把一些写操作缓存下来,在读时进行merge操作,可以提高写入速度和内存命中率。

多种引擎的实现区别?聚族索引,非聚族索引,二级索引,唯一索引、最左匹配原则等等(非常重要)

  • 唯一索引

唯一索引是不允许其中任何两行具有相同索引值的索引。当现有数据中存在重复的键值时,大多数数据库不允许将新创建的唯一索引与表一起保存。数据库还可能防止添加将在表中创建重复键值的新数据。例如,如果在employee表中职员的姓(lname)上创建了唯一索引,则任何两个员工都不能同姓。

  • 主键索引

数据库表经常有一列或列组合,其值唯一标识表中的每一行。该列称为表的主键。在数据库关系图中为表定义主键将自动创建主键索引,主键索引是唯一索引的特定类型。该索引要求主键中的每个值都唯一。当在查询中使用主键索引时,它还允许对数据的快速访问。

  • 聚集索引

表中行的物理顺序与键值的逻辑(索引)顺序相同。一个表只能包含一个聚集索引。如果某索引不是聚集索引,则表中行的物理顺序与键值的逻辑顺序不匹配。与非聚集索引相比,聚集索引通常提供更快的数据访问速度。

  • 全文索引

全文索引(FULLTEXT)=mysql的myISAM搜索引擎默认的索引类型不过切记对于大容量的数据表,生成全文索引是一个非常消耗时间非常消耗硬盘空间的做法

文本字段上的普通索引只能加快对出现在字段内容最前面的字符串(也就是字段内容开头的字符)进行检索操作。如果字段里存放的是由几个、甚至是多个单词构成的较大段文字,普通索引就没什么作用了。这种检索往往以LIKE%word%的形式出现,这对MySQL来说很复杂,如果需要处理的数据量很大,响应时间就会很长。

这类场合正是全文索引(full-textindex)可以大显身手的地方。在生成这种类型的索引时,MySQL将把在文本中出现的所有单词创建为一份清单,查询操作将根据这份清单去检索有关的数据记录。全文索引即可以随数据表一同创建,也可以等日后有必要时再使用下面这条命令添加:
ALTER TABLE table_name ADD FULLTEXT(column1, column2)

有了全文索引,就可以用SELECT查询命令去检索那些包含着一个或多个给定单词的数据记录了。下面是这类查询命令的基本语法:
  
SELECT * FROM table_name WHERE MATCH(column1, column2) AGAINST('word1', 'word2', 'word3')

上面这条命令将把column1和column2字段里有word1、word2和word3的数据记录全部查询出来。

建索引有哪些原则

索引是建立在数据库表中的某些列的上面。在创建索引的时候,应该考虑在哪些列上可以创建索引,在哪些列上不能创建索引。一般来说应该在这些列上创建索引:

  • 在经常需要搜索的列上,可以加快搜索的速度
  • 在作为主键的列上,强制该列的唯一性和组织表中数据的排列结构;
  • 在经常用在连接的列上,这些列主要是一些外键,可以加快连接的速度;
  • 在经常需要根据范围进行搜索的列上创建索引,因为索引已经排序,其指定的范围是连续的;
  • 在经常需要排序的列上创建索引,因为索引已经排序,这样查询可以利用索引的排序,加快排序查询时间;
  • 在经常使用在WHERE子句中的列上面创建索引,加快条件的判断速度。

什么情况下设置了索引但无法使用

  • 条件中使用了 or,而相关列不全有索引
  • 条件中使用了and,而相关列不满足最左原则
  • 索引列的数据类型出现隐形转换,如varchar不加单引号的话可能会自动转换为int型)
  • like查询是以%开头
  • where 子句里对索引列上有数学运算/函数
  • mysql估计使用全表扫描要比使用索引快

什么情况下不宜建立索引?

  • 对于那些在查询中很少使用或者参考的列不应该创建索引。这是因为,既然这些列很少使用到,因此有索引或者无索引,并不能提高查询速度。相反,由于增加了索引,反而降低了系统的维护速度和增大了空间需求。
  • 对于那些只有很少数据值的列也不应该增加索引。举例比如性别只有男和女
  • 对于那些定义为text,image和bit数据类型的列不应该增加索引。这是因为,这些列的数据量要么相当大,要么取值很少
  • 常频繁更新的列不要建立索引,因为肯定会影响插入或更新的效率
  • 尽量避免在 where 子句中使用 != 或者 <> 操作符,查询引用会放弃索引而进行全表扫描。
  • 修改性能远远大于检索性能时,不应该创建索引。这是因为,修改性能和检索性能是互相矛盾的。当增加索引时,会提高检索性能,但是会降低修改性能。当减少索引时,会提高修改性能,降低检索性能。因此,当修改性能远远大于检索性能时,不应该创建索引。
  • 尽量避免NULL:在MySQL中,含有空值的列很难进行查询优化,因为它们使得索引、索引的统计信息以及比较运算更加复杂。可以采用0、一个特殊的值或者一个空串代替空值

创建索引和维护索引要耗费时间,这种时间随着数据量的增加而增加。索引需要占物理空间,除了数据表占数据空间之外,每一个索引还要占一定的物理空间,如果要建立聚簇索引,那么需要的空间就会更大。当对表中的数据进行增加、删除和修改的时候,索引也要动态的维护,这样就降低了数据的维护速度。

MySQL索引失效情况。

例如: 在WHERE条件的LIKE关键字匹配的字符串以”%“开头,这种情况下,索引是不会起到作用的;WHERE条件中使用OR关键字来连接多个查询条件,如果有一个条件没有使用索引,那么其他的索引也不会起作用;多列索引的第一个字段没有使用,那么这个多列索引也不会起作用。 使用in查询时,in查询条件超过数据库表的一半的时候也会失效。

最左匹配原则

  • 索引字段要尽量的小
  • 索引的最左匹配特性(即从左往右匹配):当b+树的数据项是复合的数据结构,比如(name,age,sex)的时候,b+数是按照从左到右的顺序来建立搜索树的,比如当(张三,20,F)这样的数据来检索的时候,b+树会优先比较name来确定下一步的所搜方向,如果name相同再依次比较age和sex,最后得到检索的数据;但当(20,F)这样的没有name的数据来的时候,b+树就不知道下一步该查哪个节点,因为建立搜索树的时候name就是第一个比较因子,必须要先根据name来搜索才能知道下一步去哪里查询。比如当(张三,F)这样的数据来检索时,b+树可以用name来指定搜索方向,但下一个字段age的缺失,所以只能把名字等于张三的数据都找到,然后再匹配性别是F的数据了, 这个是非常重要的性质,即索引的最左匹配特性。

通过执行计划优化索引

MySQL索引优化深入分析执行计划

如果有2级索引怎么存

检索原理

检索原理:B+树索引不能找到一个给定key的具体value,B+树索引能找到的只是被查找的key所在的page。然后数据库在把找到的这个page读取到缓冲池(buffer poll)中,然后在内存中通过二分查找法进行查找对应的value。

  • 聚集索引一个表只能有一个,而非聚集索引一个表可以存在多个。(因为这个聚簇索引的顺序就决定了数据的顺序)
  • 聚集索引存储记录是物理上连续存在,而非聚集索引是逻辑上的连续,物理存储并不连续。
  • 聚集索引查询数据速度快,插入数据速度慢;非聚集索引反之。

为什么用B-树

上文说过一般使用磁盘I/O次数评价索引结构的优劣。先从B-Tree分析,根据B-Tree的定义,可知检索一次最多需要访问h个节点。数据库系统的设计者巧妙利用了磁盘预读原理,将一个节点的大小设为等于一个页,这样每个节点只需要一次I/O就可以完全载入 为了达到这个目的,在实际实现B-Tree还需要使用如下技巧:

每次新建节点时,直接申请一个页的空间,这样就保证一个节点物理上也存储在一个页里,加之计算机存储分配都是按页对齐的,就实现了一个node只需一次I/O。

为什么不用红黑树

红黑树这种结构,h(层数)明显要深的多。由于逻辑上很近的节点(父子)物理上可能很远,无法利用局部性,所以红黑树的I/O渐进复杂度也为O(h),效率明显比B-Tree差很多。

B+树的数据只出现在叶子节点上,因此在查询单条数据的时候,查询速度非常稳定。因此,在做单一数据的查询上,其平均性能并不如B树。但是,B+树的叶子节点上有指针进行相连,因此在做数据遍历的时候,只需要对叶子节点进行遍历即可,这个特性使得B+树非常适合做范围查询

  • 没准是Mysql中数据遍历操作比较多,所以用B+树作为索引结构。凡做这种关联查询,你躲不开join操作的!既然涉及到了Join操作,无外乎从一个表中取一个数据,去另一个表中逐行匹配,如果索引结构是B+树,叶子节点上是有指针的,能够极大的提高这种一行一行的匹配速度
  • 而Mongodb是做单一查询比较多,数据遍历操作比较少,所以用B树作为索引结构。

那么为什么Mysql做数据遍历操作多?而Mongodb做数据遍历操作少呢?因为Mysql是关系型数据库,而Mongodb是非关系型数据。

平衡二叉树则是子树高读不能超过2,B树非叶子节点也可以存储数据,B+树则是叶子节点才可以存储数据。

  • 我们说的平衡二叉树结构,指的是逻辑结构上的平衡二叉树,其物理实现是数组。然后由于在逻辑结构上相近的节点在物理结构上可能会差很远。因此,每次读取的磁盘页的数据中有许多是用不上的。因此,查找过程中要进行许多次的磁盘读取操作。而适合作为索引的结构应该是尽可能少的执行磁盘IO操作,因为执行磁盘IO操作非常的耗时。因此,平衡二叉树并不适合作为索引结构
  • 红黑树这种结构h明显要深的多。由于逻辑上很近的节点(父子)物理上可能很远,无法利用局部性,所以红黑树的I/O渐进复杂度也为O(h),效率明显比B-Tree差很多。也就是说,使用红黑树(平衡二叉树)结构的话,每次磁盘预读中的很多数据是用不上的数据。因此,它没能利用好磁盘预读的提供的数据。然后又由于深度大(较B树而言),所以进行的磁盘IO操作更多。
  • B树的每个节点可以存储多个关键字,它将节点大小设置为磁盘页的大小,充分利用了磁盘预读的功能。每次读取磁盘页时就会读取一整个节点。也正因每个节点存储着非常多个关键字,树的深度就会非常的小。进而要执行的磁盘读取操作次数就会非常少,更多的是在内存中对读取进来的数据进行查找。
  • B树的查询,主要发生在内存中,而平衡二叉树的查询,则是发生在磁盘读取中。因此,虽然B树查询查询的次数不比平衡二叉树的次数少,但是相比起磁盘IO速度,内存中比较的耗时就可以忽略不计了。因此,B树更适合作为索引。

一步步分析为什么B+树适合作为索引的结构 以及索引原理(阿里面试,写的很好

B+Tree是mysql使用最频繁的一个索引数据结构,是Inodb和Myisam存储引擎模式的索引类型。相对Hash索引,B+Tree在查找单条记录的速度比不上Hash索引(Memory表只存在内存中),但是因为更适合排序等操作,所以它更受欢迎。毕竟不可能只对数据库进行单条记录的操作。

  • 带顺序访问指针的B+Tree

B+Tree所有索引数据都在叶子节点上,并且增加了顺序访问指针,每个叶子节点都有指向相邻叶子节点的指针。这样做是为了提高区间效率,例如查询key为从18到49的所有数据记录,当找到18后,只要顺着节点和指针顺序遍历就可以以此向访问到所有数据节点,极大提高了区间查询效率。

  • 大大减少磁盘I/O读取

数据库系统的设计者巧妙利用了磁盘预读原理,将一个节点的大小设为等于一个页,这样每个节点需要一次I/O就可以完全载入

MySQL索引背后的数据结构及算法原理
MySQL索引:深入理解InnoDb聚集索引与Myisam非聚集索引值得一看

彻底搞懂系列B-树、B+树、B-树、B*树

MySQL索引背后的数据结构及算法原理

B树和B+树的插入、删除图文详解

关系型数据库和非关系型数据库为什么用B树或B+树

5.事务和日志

MVCC (MultiVersion Concurrency Control) 叫做多版本并发控制。由undolog和记录版本的一个东西组成

InnoDB的 MVCC,是通过在每行记录的后面保存两个隐藏的列来实现的。这两个列,一个保存了行的创建时间,一个保存了行的过期时间,当然存储的并不是实际的时间值,而是系统版本号。

以上片段摘自《高性能Mysql》这本书对MVCC的定义。他的主要实现思想是通过数据多版本来做到读写分离。从而实现不加锁读进而做到读写并行。

MVCC在mysql中的实现依赖的是undo log与read view

  • undolog :undolog中记录某行数据的多个版本的数据。
  • read view :用来判断当前版本数据的可见性

InnoDB如何解决幻读

使用MVCC

MVCC

MVCC的特点就是在同一时刻,不同事务可以读取到不同版本的数据,从而可以解决脏读和不可重复读的问题。

MVCC实际上就是通过数据的隐藏列和回滚日志(undo log),实现多个版本数据的共存。这样的好处是,使用MVCC进行读数据的时候,不用加锁,从而避免了同时读写的冲突。

在实现MVCC时,每一行的数据中会额外保存几个隐藏的列,比如当前行创建时的版本号和删除时间和指向undo log的回滚指针。这里的版本号并不是实际的时间值,而是系统版本号。每开始新的事务,系统版本号都会自动递增。事务开始时的系统版本号会作为事务的版本号,用来和查询每行记录的版本号进行比较。

每个事务又有自己的版本号,这样事务内执行数据操作时,就通过版本号的比较来达到数据版本控制的目的。

另外,InnoDB实现的隔离级别RR时可以避免幻读现象的,这是通过next-key lock(不仅锁定行,而且锁定行所在的范围)机制实现的。

在这里插入图片描述

ACID特性中的一致性是如何实现的

  • 事务的原子性是通过 undo log 来实现的

  • 事务的持久性性是通过 redo log来实现的

  • 事务的隔离性是通过 (读写锁+MVCC)来实现的

  • 而事务的终极大boss一致性是通过原子性,持久性,隔离性来实现的!!!

两阶段提交

在这里插入图片描述

  • 原子性(Atomicity) :语句要么全执行,要么全不执行,是事务最核心的特性,事务本身就是以原子性来定义的;实现主要基于undo log日志实现的。

  • 持久性(Durability :保证事务提交后不会因为宕机等原因导致数据丢失;实现主要基于redo log日志。

  • 隔离性(Isolation) :保证事务执行尽可能不受其他事务影响;InnoDB默认的隔离级别是RR,RR的实现主要基于锁机制、数据的隐藏列、undo log和类next-key lock机制。

  • 一致性(Consistency) :事务追求的最终目标,一致性的实现既需要数据库层面的保障,也需要应用层面的保障。

原子性,持久性,隔离性折腾半天的目的也是为了保障数据的一致性!ACID只是个概念,事务最终目的是要保障数据的可靠性,一致性

数据库事务的隔离级别有4种,由低到高分别为Read uncommitted 、Read committed 、Repeatable read 、Serializable 。而且,在事务的并发操作中可能会出现脏读,不可重复读,幻读。下面通过事例一一阐述它们的概念与联系。

脏读、不可重复读、幻象读概念说明:

  • 脏读:
    指当一个事务正在访问数据,并且对数据进行了修改,而这种数据还没有提交到数据库中,这时,另外一个事务也访问这个数据,然后使用了这个数据。因为这个数据还没有提交那么另外一个事务读取到的这个数据我们称之为脏数据。依据脏数据所做的操作肯能是不正确的。

  • 不可重复读:
    指在一个事务内,多次读同一数据。在这个事务还没有执行结束,另外一个事务也访问该同一数据,那么在第一个事务中的两次读取数据之间,由于第二个事务的修改第一个事务两次读到的数据可能是不一样的,这样就发生了在一个事物内两次连续读到的数据是不一样的,这种情况被称为是不可重复读。

幻象读:一个事务先后读取一个范围的记录,但两次读取的纪录数不同,我们称之为幻象读(两次执行同一条 select 语句会出现不同的结果,第二次读会增加一数据行,并没有说这两次执行是在同一个事务中)

读未提交 (Read uncommitted)

读未提交,顾名思义,就是一个事务可以读取另一个未提交事务的数据。

事例:老板要给程序员发工资,程序员的工资是3.6万/月。但是发工资时老板不小心按错了数字,按成3.9万/月,该钱已经打到程序员的户口,但是事务还没有提交,就在这时,程序员去查看自己这个月的工资,发现比往常多了3千元,以为涨工资了非常高兴。但是老板及时发现了不对,马上回滚差点就提交了的事务,将数字改成3.6万再提交。

分析:实际程序员这个月的工资还是3.6万,但是程序员看到的是3.9万。他看到的是老板还没提交事务时的数据。这就是脏读。因此,在这种隔离级别下,查询是不会加锁的,也由于查询的不加锁,所以这种隔离级别的一致性是最差的,可能会产生“脏读”、“不可重复读”、“幻读”。如无特殊情况,基本是不会使用这种隔离级别的。

那怎么解决脏读呢?Read committed!读提交,能解决脏读问题。

读提交(Read Committed)

读提交,顾名思义,就是只能读到已经提交了的内容

事例:程序员拿着信用卡去享受生活(卡里当然是只有3.6万),当他埋单时(程序员事务开启),收费系统事先检测到他的卡里有3.6万,就在这个时候!!程序员的妻子要把钱全部转出充当家用,并提交。当收费系统准备扣款时,再检测卡里的金额,发现已经没钱了(第二次检测金额当然要等待妻子转出金额事务提交完)。程序员就会很郁闷,明明卡里是有钱的…

分析:这就是读提交,若有事务对数据进行更新(UPDATE)操作时,读操作事务要等待这个更新操作事务提交后才能读取数据,可以解决脏读问题。但在这个事例中,出现了一个事务范围内两个相同的查询却返回了不同数据,这就是不可重复读。

这是各种系统中最常用的一种隔离级别,也是SQL Server和Oracle的默认隔离级别。这种隔离级别能够有效的避免脏读,但除非在查询中显示的加锁,如:

select * from T where ID=2 lock in share mode;
select * from T where ID=2 for update;

不然,普通的查询是不会加锁的。

那为什么“读提交”同“读未提交”一样,都没有查询加锁,但是却能够避免脏读呢?

这就要说道另一个机制“快照(snapshot)”,而这种既能保证一致性又不加锁的读也被称为“快照读(Snapshot Read)”

假设没有“快照读”,那么当一个更新的事务没有提交时,另一个对更新数据进行查询的事务会因为无法查询而被阻塞(因为上了X锁,即写锁,所以不能得到S锁,即读锁),这种情况下,并发能力就相当的差。而“快照读”就可以完成高并发的查询,不过,“读提交”只能避免“脏读”,并不能避免“不可重复读”和“幻读”。

那怎么解决可能的不可重复读问题?Repeatable read !

可重复读(Repeated Read)

可重复读,顾名思义,就是专门针对“不可重复读”这种情况而制定的隔离级别,自然,它就可以有效的避免“不可重复读”。而它也是MySql的默认隔离级别。

事例:程序员拿着信用卡去享受生活(卡里当然是只有3.6万),当他埋单时(事务开启,不允许其他事务的UPDATE修改操作),收费系统事先检测到他的卡里有3.6万。这个时候他的妻子不能转出金额了。接下来收费系统就可以扣款了。

分析:重复读可以解决不可重复读问题。写到这里,应该明白的一点就是,不可重复读对应的是修改,即UPDATE操作。但是可能还会有幻读问题。因为幻读问题对应的是插入INSERT操作,而不是UPDATE操作。

什么时候会出现幻读?

事例:程序员某一天去消费,花了2千元,然后他的妻子去查看他今天的消费记录(全表扫描FTS,妻子事务开启),看到确实是花了2千元,就在这个时候,程序员花了1万买了一部电脑,即新增INSERT了一条消费记录,并提交。当妻子打印程序员的消费记录清单时(妻子事务提交),发现花了1.2万元,似乎出现了幻觉,这就是幻读。

在这个级别下,普通的查询同样是使用的“快照读”,但是,和“读提交”不同的是,当事务启动时,就不允许进行“修改操作(Update)”了,而“不可重复读”恰恰是因为两次读取之间进行了数据的修改,因此,“可重复读”能够有效的避免“不可重复读”,但却避免不了“幻读”,因为幻读是由于“插入或者删除操作(Insert or Delete)”而产生的。

那怎么解决幻读问题?Serializable!

序列化 Serializable

这是数据库最高的隔离级别,这种级别下,事务“串行化顺序执行”,也就是一个一个排队执行。这种级别下,“脏读”、“不可重复读”、“幻读”都可以被避免,但是执行效率奇差,性能开销也最大,所以基本没人会用。

值得一提的是:大多数数据库默认的事务隔离级别是Read committed,比如Sql Server , Oracle。Mysql的默认隔离级别是Repeatable read。

MySql如何解决幻读问题?

(1)什么是幻读
前提条件:InnoDB引擎,可重复读隔离级别,使用当前读时。
  在一次事务里面,多次查询之后,结果集的个数不一致的情况叫做幻读。而多出来或者少的哪一行被叫做 幻行
表现:一个事务(同一个read view)在前后两次查询同一范围的时候,后一次查询看到了前一次查询没有看到的行。两点需要说明:
  1、在可重复读隔离级别下,普通查询是快照读,是不会看到别的事务插入的数据的,幻读只在当前读下才会出现。

2、幻读专指新插入的行,读到原本存在行的更新结果不算。因为当前读的作用就是能读到所有已经提交记录的最新值。

(2)幻读产生的原因

行锁只能锁住行,即使把所有的行记录都上锁,也阻止不了新插入的记录。

(3)如何解决幻读?
在快照读读情况下,mysql通过mvcc来避免幻读。
在当前读读情况下,mysql通过next-key来避免幻读

备注:什么是快照读、当前读

  • 快照读, 读取专门的快照 (对于RC,快照(ReadView)会在每个语句中创建。对于RR,快照是在事务启动时创建的)
简单的select操作即可(不需要加锁,如: select ... lock in share mode, select ... for update)

针对的也是select操作

  • 当前读, 读取最新版本的记录, 没有快照。 在InnoDB中,当前读取根本不会创建任何快照。
select ... lock in share mode

select ... for update

insert

update

delete

针对如下操作, 会让如下操作阻塞:    
insert
update
delete
  • 在RR(可重复读)级别下, 快照读是通过MVVC(多版本控制)和undo log来实现的,

当前读是通过手动加record lock(记录锁)和gap lock(间隙锁)来实现的。所以从上面的显示来看,如果需要实时显示数据,还是需要通过加锁来实现。这个时候会使用next-key技术来实现。所以说

总结一下:
为什么会出现“脏读”?因为没有“select”操作没有规矩。
为什么会出现“不可重复读”?因为“update”操作没有规矩。
为什么会出现“幻读”?因为“insert”和“delete”操作没有规矩。
“读未提(Read Uncommitted)”能预防啥?啥都预防不了。
“读提交(Read Committed)”能预防啥?使用“快照读(Snapshot Read)”,避免“脏读”,但是可能出现“不可重复读”和“幻读”。
“可重复读(Repeated Red)”能预防啥?使用“快照读(Snapshot Read)”,锁住被读取记录,避免出现“脏读”、“不可重复读”,但是可能出现“幻读”。
“串行化(Serializable)”能预防啥?排排坐,吃果果,有效避免“脏读”、“不可重复读”、“幻读”,不过效果谁用谁知道。

事务是如何通过日志实现的

  • Mysql 为了提升性能不会把每次的修改都实时同步到磁盘,而是会先存到Buffer Pool(缓冲池)里头,把这个当作缓存来用。然后使用后台线程去做缓冲池和磁盘之间的同步。

事务日志图

在这里插入图片描述

Redolog,binlog,undolog对事务的影响

Undolog

undolog 叫做回滚日志,用于记录数据被修改前的信息。他正好跟前面所说的重做日志所记录的相反,redolog记录数据被修改后的信息。undolog主要记录的是数据的逻辑变化,为了在发生错误时回滚之前的操作,需要将之前的操作都记录下来,然后在发生错误时才可以回滚。undolog记录事务修改之前版本的数据信息,因此假如由于系统错误或者rollback操作而回滚的话可以根据undolog的信息来进行回滚到没被修改前的状态。

Redolog

redolog来记录已成功提交事务的修改信息,并且会把redolog持久化到磁盘,系统重启之后在读取redo log恢复最新数据。redolog是用来恢复数据的 用于保障,已提交事务的持久化特性

redo和undo基本流程如下:
因为事务在修改页时,要先记 undo,在记 undo 之前要记 undo 的 redo, 然后修改数据页,再记数据页修改的 redo。 Redo(里面包括 undo 的修改) 一定要比数据页先持久化到磁盘。 当事务需要回滚时,因为有 undo,可以把数据页回滚到前镜像的状态,崩溃恢复时,如果 redo log 中事务没有对应的 commit 记录,那么需要用 undo把该事务的修改回滚到事务开始之前。 如果有 commit 记录,就用 redo 前滚到该事务完成时并提交掉。

在这里插入图片描述

Binlog

  • binlog
  • redolog,保证事务的持久性,缓存区中数据会慢慢更新到数据库的硬盘上。
  • undolog,记录了修改几率,可以随便回滚,保证原子性。

MYSQL的主从同步延迟的原因及解决方案

  • mysql主从复制用途

从库生成两个线程,一个I/O线程,一个SQL线程;i/o线程去请求主库的binlog,并将得到的binlog日志写到relaylog(中继日志)文件中;主库会生成一个 log dump 线程,用来给从库i/o线程传binlog;
SQL 线程,会读取relay log文件中的日志,并解析成具体操作,来实现主从的操作一致,而最终数据一致;

实时灾备,用于故障切换,读写分离(主写从读比例为10:1),提供查询服务
备份,避免影响业务

7.常见语句

  • 查询只有一个
SELECT ** 
FROM table 
Having(count(nums) = 1)
  • 在表 orders 中找到订单数最多客户对应的 customer_numbe
select customer_number
from orders
group by customer_number
order by count(customer_number) desc
limit 1

N.存储过程与触发器

  • 触发器是一种特殊的存储过程,主要是通过事件来触发而被执行的。它可以强化约束,来维护数据的完整性和一致性,可以跟踪数据库内的操作从而不允许未经许可的更新和变化。可以联级运算。如,某表上的触发器上包含对另一个表的数据操作,而该操作又会导致该表触发器被触发。
  • 存储过程是一个预编译的SQL语句,优点是允许模块化的设计,就是说只需创建一次,以后在该程序中就可以调用多次。如果某次操作需要执行多次SQL,使用存储过程比单纯SQL语句执行要快。可以用一个命令对象来调用存储过程。可以供外部程序调用,比如:java程序。

存储过程是预编译过的,执行效率高。存储过程的代码直接存放于数据库中,通过存储过程名直接调用,减少网络通讯。安全性高,执行存储过程需要有一定权限的用户。存储过程可以重复使用,可减少数据库开发人员的工作量。缺点:移植性差

2)可以供外部程序调用,比如:java程序。

完整性约束包括哪些

数据完整性(Data Integrity)是指数据的精确(Accuracy)和可靠性(Reliability)。

  • 实体完整性:规定表的每一行在表中是惟一的实体。
  • 域完整性:是指表中的列必须满足某种特定的数据类型约束,其中约束又包括取值范围、精度等规定。
  • 参照完整性:是指两个表的主关键字和外关键字的数据应一致,保证了表之间的数据的一致性,防止了数据丢失或无意义的数据在数据库中扩散。
  • 用户定义的完整性:不同的关系数据库系统根据其应用环境的不同,往往还需要一些特殊的约束条件。用户定义的完整性即是针对某个特定关系数据库的约束条件,它反映某一具体应用必须满足的语义要求。

与表有关的约束:包括列约束(NOT NULL(非空约束))和表约束(PRIMARY KEY、foreign key、check、UNIQUE)

MySql不支持check

什么叫视图?游标是什么?

  • 视图是一种虚拟的表,具有和物理表相同的功能。可以对视图进行增,改,查,操作,视图通常是有一个表或者多个表的行或列的子集。对视图的修改不影响基本表。它使得我们获取数据更容易,相比多表查询。
  • 游标是对查询出来的结果集作为一个单元来有效的处理。游标可以定在该单元中的特定行,从结果集的当前行检索一行或多行。可以对结果集当前行做修改。一般不使用游标,但是需要逐条处理数据的时候,游标显得十分重要。
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值