程序员的SQL(进阶)

一、游标

在存储过程中使用游标可以对一个结果集进行顺序移动遍历

游标只能向一个方向前进,并且不可以跳过任何一行数据

游标主要用于交互式应用,其中用户需要对数据集中的任意行进行浏览和修改。

使用游标的四个步骤

1、游标的定义

DECLARE cursor_name CURSOR FOR select_statement  

2、打开游标

OPEN cursor_name;

3、取游标中的数据

FETCH cursor_name INTO var_name [, var_name]...

4、关闭游标

CLOSE cursor_name;

5、释放游标

DEALLOCATE cursor_name

二、存储过程

定义:简单的说,就是一组SQL语句集,功能强大,可以实现一些比较复杂的逻辑功能,类似于JAVA语言中的方法(函数

ps:存储过程跟触发器有点类似,都是一组SQL集,但是存储过程是主动调用的,且功能比触发器更加强大,触发器是某件事触发后自动调用

delimiter //

create procedure myprocedure( out ret int )
    begin
        declare y int;
        select sum(col1)
        from mytable
        into y;
        select y*y into ret;
    end //
delimiter ;

call myprocedure(@ret);
select @ret;

三、触发器

定义:触发器定义在表上,在满足定义条件触发,并执行触发器定义的语句集合。(与存储过程不同在于:触发器会自动执行,存储过程需要手动执行

CREATE TRIGGER mytrigger AFTER INSERT ON mytable
FOR EACH ROW SELECT NEW.col;

CREATE TRIGGER 触发器名 BEFORE|AFTER 触发事件

ON 表名 FOR EACH ROW

BEGIN

        执行语句列表

END;

四、事务处理

定义:事务指一组SQL语句,事务在执行过程能创建保留点(savepoint),在执行过程中可以回退到任何保留点或者全部回退,事务执行完毕会进行提交

无法回退:select,create,drop语句!只针对update,delete,insert语句!

隐式提交:MySQL 的事务提交默认是隐式提交,也就是每执行一条语句就把这条语句当成一个事务然后进行提交。

ps:当出现 START TRANSACTION 语句时,会关闭隐式提交;当 COMMIT 或 ROLLBACK 语句执行后,事务会自动关闭,重新恢复隐式提交。

将自动提交功能置为ON

  1. SET AUTOCOMMIT=0;

将自动提交功能置为OFF

  1. SET AUTOCOMMIT=1;

注意:autocommit 标记是针对每个连接不是针对服务器的 。

上述SQL修改只对当前实例有效,如果MySQL服务重启的话,这些设置就会丢失,如果要永久生效,就必须在配置文件中修改系统变量

START TRANSACTION
// ...
SAVEPOINT delete1
// ...
ROLLBACK TO delete1
// ...
COMMIT

五、索引

B树:数据量过大导致平衡二叉树深度过深情况下I/O效率很差,引进了多叉平衡树-B树,数据分布在整棵树上。(不适合区间范围查找) 

B+树:在B树上进行改进,把数据全部放在叶子节点上并且用双向链表进行连接起来变为一个有序链表,非叶子节点只存放键!

1.B+树索引(进行了排序+范围查找

分为聚集索引和辅助索引:

聚集索引(主键索引 引擎:InnoDB):就是对每张表中的主键构造一颗B+树,叶子节点存放所有的数据信息。(每张表上只能有一个聚集索引

辅助索引:叶子节点不包含所有的数据,而是包含索引的标签(在用于聚集索引的二次查找数据)(每张表上可以有多个辅助索引

InnoDB的数据规定按主键聚集构成一颗B+树,所以InnoDB要求表必须有主键(MyISAM可以没有),如果没有显式指定,则MySQL系统会自动选择一个可以唯一标识数据记录的列作为主键,如果不存在这种列,则MySQL自动为InnoDB表生成一个隐含字段作为主键,这个字段长度为6个字节,类型为长整形。

聚集索引这种实现方式使得按主键的搜索十分高效,但是辅助索引搜索需要检索两遍索引首先检索辅助索引获得主键,然后用主键到主索引中检索获得记录

知道了InnoDB的索引实现后,就很容易明白为什么不建议使用过长的字段作为主键,因为所有辅助索引都引用主索引,过长的主索引会令辅助索引变得过大。并且使用自增字段作为主键则是一个很好的选择(减少B+树维护的成本)。

http://blog.codinglabs.org/articles/theory-of-mysql-index.html好文一生推!

2.哈希索引

在 MySQL 中只有 Memory 引擎显式支持哈希索引,人为可以加上哈希索引!

InnoDB 引擎有一个特殊的功能叫“自适应哈希索引”(自动为表生成索引),当某个索引值被使用的非常频繁时,会在 B+Tree 索引之上再自动创建一个哈希索引

3.全文检索

使用倒排索引的功能来实现的,进行了关键词句子/文档的映射关系(与正常索引相反),类似于搜索引擎里的关键词搜索

目前只支持CHAR,VARCHAR,TEXT数据类型。

4.索引使用

1.普通索引

–直接创建索引(length表示使用名称前1ength个字符)  
CREATE INDEX index_name ON table_name(column_name(length))  
–修改表结构的方式添加索引  
ALTER TABLE table_name ADD INDEX index_name ON (column_name)  
–创建表的时候同时创建索引  
CREATE TABLE table_name (  
    id int(11) NOT NULL AUTO_INCREMENT ,  
    title char(255) NOT NULL ,  
    PRIMARY KEY (id),  
    INDEX index_name (title)  
) ENGINE=InnoDB  DEFAULT CHARSET=utf8mb4;  
–删除索引  
DROP INDEX index_name ON table_name;  
  
建立复合索引 。  
CREATE INDEX mytable_categoryid_userid ON mytable (category_id,user_id); 

2.唯一索引

–创建唯一索引  
CREATE UNIQUE INDEX index_name ON table_name(column_name)  
–修改表结构  
ALTER TABLE table_name ADD UNIQUE index_name ON (column_name)  
–创建表的时候直接指定  
CREATE TABLE table_name (  
    id int(11) NOT NULL AUTO_INCREMENT ,  
    title char(255) NOT NULL ,  
    PRIMARY KEY (id),  
    UNIQUE index_name (title)  
);  

........

5.索引的使用策略及优化

MySQL的优化主要分为结构优化(Scheme optimization)和查询优化(Query optimization)。(索引是结构优化!)

字段取值范围很广,属于高选择性,几乎没有重复,使用索引最合适。

6.InnoDB和MyISam引擎的索引以及memory引擎的索引介绍

InnoDB的索引是通过聚集索引(主键索引)和辅助索引+自适应哈希索引+全文索引来实现的!

MyISAM与InnoDB的区别:聚集索引和辅助索引一个存的是真实的数据(InnoDB),一个存的是具体的数据索引地址!(MyISAM)

Memory(heap) 是内存型引擎,索引使用了哈希索引来快速获取数据。对于每一行数据,存储引擎都会对所有的引擎列计算一个哈希码,在哈希表对应位置存放该行数据的指针或地址。为了解决多个hash冲突问题,哈希索引采用了链地址法来解决冲突问题。所以采用链表数组作为存储结构 。

六、切分的选择

出现问题:

随着时间和业务的发展,数据库中的表会越来越多,并且表中的数据量也会越来越大,那么读写操作的开销也会随着增大

垂直切分

将表按功能模块关系密切程度划分出来,部署到不同种类的数据库上。例如,我们会建立商品数据库 pay数据库、用户数据库 user数据库 等,分别用来存储项目商品有关的表和与用户有关的表

水平切分

把表中的数据按照某种规则存储到多个结构相同的表中,例如按 id 的散列值性别等进行划分。

切分的选择:

如果数据库中的表太多,并且项目各项业务逻辑清晰数据分散不是特别严重比较好,那么垂直切分是首选。(划分数据库和表

如果数据库的表不多,但是单表的数据量很大,应该选择水平切分。(划分多个相同的表

存在的问题:

1.事务问题

在执行分数据库分表之后,由于数据存储到了不同的库上,数据库事务管理出现了困难。

2.跨库跨表连接问题

跨库跨表连接,我们无法连接不同库的表(连接不了!),也无法连接不同粒度之间的表连接不了!),这就导致原本一次可以完成的事务需要多次才能完成

3.额外的运算负担

数据的定位和数据的增删改查,引起了额外的逻辑运算

七、故障转移和故障恢复

定义:

故障转移也叫做切换,当主库出现故障时就切换到备库,使备库成为主库。故障恢复顾名思义就是从故障中恢复过来,并且保证数据的正确性

八、存储引擎的区别

OLTP:事务性非常高的系统)(电商,银行,web开发等...),

OLAP:(考核的标准往往是磁盘子系统的吞吐量(带宽))(数据挖掘/分析/算法建模等.....)

InnoDB 是支持事务的存储引擎,主要面向OLTP数据库应用。对并发的支持特别好,通过MVCC来支持高并发,支持行级锁,表级锁,以及带来的问题,实现四个标准的隔离级别并且默认是可重复读,通过聚簇索引和辅助索引+自适应哈希索引+全文检索构建出了高效的索引。

MyISAM 引擎不支持事务和行级锁,只支持表锁设计,支持全文索引,主要是面向OLAP数据库应用。

NDB是集群存储引擎,其数据全部放在内存中,因此主键查找的速度极快。

Memory将表中的数据存放在内存中,如果数据库重启或者发生奔溃,表中的数据都将消失。它使用于存储临时数据的临时表。默认采用哈希索引

九、数据库范式

第一范式(1NF):

属性不可分。如果分了,那么就不是关系型数据库

问题:会存在数据冗余过大,插入异常,删除异常,修改异常的问题

非主属性:包含任何一个码中的属性称主属性。并且除了主属性以外的就是非主属性

一个码可以包含多个主属性

码:假如当 K 确定的情况下(无重复),该表除 K 之外的所有属性的值也就随之确定,那么 K 就是码。(属性/属性组)

第二范式(2NF):

符合1NF,并且,非主属性完全依赖于码。(可以看成:非主键完全依赖主键这个关系!!!!)

(2NF在1NF的基础之上消除了非主属性对于码部分函数依赖

(设X,Y是关系R的两个属性集合,存在X→Y,若X’是X的真子集,存在X’→Y,则称Y部分函数依赖于X。)

每个表必须有一个(而且仅有一个)数据元素为主关键字(Primary key),其他数据元素与主关键字一一对应。通常称这种关系为函数依赖。

2NF要求数据表里的所有非主属性都要和该数据表的主键完全依赖关系;如果有哪些非主属性只和主键的一部份有关的话,它就不符合第二范式。

比如:一个学生上一门课,一定是特定某个教材。所以有(学生,课程)->教材,因此(学生,课程)是一个码。(学生,课程)是个码,课程却决定了教材,这就叫做不完全依赖出现这样的情况,就不满足第二范式

解决:处理了非主属性对码的部分函数依赖关系!

问题:仍然存在非主属性系主任对于码学号的传递函数依赖。

第三范式(3NF):

符合2NF,并且,消除了非主属性对于码的传递函数依赖。

对于一个满足2nd NF 的数据结构来说,表中有可能存在某些非主属性依赖于其他非主属性的现象,必须消除。

比如:如果存在"A → B → C"的决定关系,则码C通过传递还依赖于A,就有非主属性对于码的传递函数依赖!

解决:处理了非主属性对于码的传递函数依赖关系!

问题:存在着主属性对于码的部分函数依赖与传递函数依赖。

BCNF:

符合3NF, 并且,没有任何主属性对于码的部分函数依赖与传递函数依赖。

解决:消除了主属性对于码的部分函数依赖与传递函数依赖。

是好的数据库设计!

猜你喜欢

转载自blog.csdn.net/taka_is_beauty/article/details/89850421