sql读写文件的函数有哪些?

该项目记录了Oracle相关的速查知识汇总,主要涉及了oracle基础使用、SQL基础、oracle函数、oracle触发器、oracle高级查询、PL/SQL编程基础、PL/SQL存储过程等。若有新增,还将不断添加中。

(7)设置某字段的默认值

在创建表以后添加默认值:

只能以行为单位来删除数据

约束的作用是定义规则(最重要),确保完整性。

在创建表时设置非空约束:
在修改表时添加非空约束:
在修改表时去除非空约束:

必不可少,确定每一行数据的唯一性。

一张表只能设计一个主键约束。

主键约束可以由多个字段构成,称为联合主键或者复合主键。

在创建表时设置主键约束:

如果没有用约束来创建主键,则系统会自动命名约束的名称,可以看这个:

在修改表时添加主键约束:
更改约束的名称,可以修改任何约束的名字
drop primary key[cascade]; --删除主键约束,如果存在外键约束,填写cascade,可以把其他表中引用该主键约束的一起删掉

两个表之中字段关系的约束。

在创建表的时候设置外键约束:
--table2为主表,table1为从表,也叫主从表。主表当中的字段必须是主表中的主键字段,主从表的字段要设置成同一个数据类型。在向设置了外键约束的表输入值的时候,从表中外键字段的值必须来自主表中的相应字段的值,或者为null值。
如果这样给从表插入数据:

则2在主表中没有找到,会报错。需要填写

才可以,或者那个部分留空值:

在创建表的时候设置外键约束:
--定义完所有的字段之后设置的约束
--后面的中括号是级联删除,表示主表当中的一条数据被删除的时候,从表当中使用了这条数据的字段所在的行也会被一起删除掉,这样确保了主从表数据的完整性。
在修改表时添加外键约束:

作用是保证字段的唯一性,和主键约束的区别是,主键约束必须是非空的,而唯一约束允许有一个空值。主键约束在一张表中只能有一个,唯一约束可以有多个。

在创建表时设置唯一约束:
在修改表时添加唯一约束:

检查约束,让表当中的值更具有实际意义,能够满足一定的条件,具有实际意义。

在创建表时设置检查约束:
在修改表时添加检查约束:
  • 主键约束:每张表只能有一个,可以由多个字段构成
  • 外键约束:涉及两个表之间的关系

在创建表时设置约束: 只有非空约束只能在列级设置约束,不能在表级设置约束,其他的都是两者都可以的。非空约束是没有名字的。

在修改表时添加约束,也是只有非空约束不同,修改表时用的语句是

更改约束的名称:数据字典(user_constraints查看名称)

删除约束,非空约束较特殊

其他的如果是禁用的话使用

--column可以简写成col,设置新的字段名(别名),使用select语句来查询的时候就可以看到变化了,但使用desc看结构还依然不变化。

注意:字符类型只能设置它的长度。 --字符格式用a开头,后面跟它要的长度。 如

如果是数值类型用,9表示一位数字,比如

可以保留4位数和一位小数。 如果

但如果数据中有四位的数,超过这个长度的就用#####表示了,与excel一致。

清除之前设置过的格式:

(3)查询表中的所有字段

不会更改字段的名字,可以为多个字段设置别名

运算符大家都比较熟悉了,而表达式=操作数+运算符组成。

oracle中的操作数可以有变量、常量、字段。

运算符有算术运算符(+、-、*、/),比较运算符(>,>=,<,<=,=,<>都是用在where条件里面的,两个数进行比较得到的结果是布尔类型的,真或者假),逻辑运算符(and,or,not)

在select语句中使用运算符

在查询结果中,给每个员工的工资加上200元,但数据本身没变。 如

查询工资高于800元的员工的姓名; 如

逻辑运算符的优先级顺序:not,and,or

比较运算符优先级高于逻辑运算符

like关键字,也可以归入比较运算符当中。

通配符的使用(_表示一个字符,%表示0到多个任意字符) 如

between...and --表示从什么到什么之间。查询结果是含头又含尾的区间。

如果不在这个之间的,在它们前面加上not 如

in/not in 后面跟着小括号,里面是一个列表的值,一个具体的值。 如

10.其他一些实用命令

  • 使用上下箭头可以选择历史输入记录来使用。
substr(char,[m[,n]]) --获取子字符,分别是从哪取,从哪个位置开始取以及取出多少位,n省略时,从m的位置截取到结束,m从1开始如果m写0也是从第一个字符开始。如果m为负数时,从字符串的尾部开始截取
trim(c2 from c1) --代表从c1中去除c2字符串,就是子文本替换,要求c2中只能是一个字符
ltrim(c1[,c2]) --从c1中去除c2,从左边开始去除,要求第一个就是要去除的字符,有多少个重复的该字符就会去除多少次
rtrim(c1[,c2]) --从c1中去除c2,要求右侧第一个就是要去除的字符,有多少个重复的该字符就会去除多少次
trim(c1) --代表去除首尾的空格,删首尾空,同理ltrim和rtrim只有一个参数时。
add_months(date,i) --用于添加指定的月份,返回在指定的日期上添加的月份,i可以是任意整数,如果i是负数,则是在原有的值上减去该月份了
next_day(date,char) --第二个参数指定星期几,在中文环境下输入星期X即可,返回下一个周几是哪一天。

用于截取日期时间的trunc函数

用法:trunc(字段名,精度)

1、截取时间到年时,sql语句如下:

2、截取时间到月时,sql语句:

3、截取时间到日时,sql语句:

4、截取时间到小时时,sql语句:

5、截取时间到分钟时,sql语句:

6、截取时间到秒暂时不知道怎么操作

8.如果不填写第二个参数,则默认到DD,包含年月日,不包含时分秒。

to_char(date[,fmt[,params]]) --date为需要转换的日期,fmt为转换的格式,params为转换的语言(通常默认会自动选择,可以省略,与安装语言一致)
  • 9:显示数字并忽略前面的0
  • 0:显示数字,位数不足,用0补齐
  • S:加正负号(前后都可以) 如

fmt是转换的格式,可以省略 如

  • 在员工信息表中查询员工的生日
  • 将员工信息表中的年龄字段与10取余数
  • 查询出5月份入职的员工信息

本部分需要有如下两个部分的基础

  • 《oracle数据库开发必备利器之SQL基础》
  • 《oracle数据库开发利器之函数》

分组函数作用于一组数据,并对一组数据返回一个值。 结构:

  • 求出员工的平均工资和工资的总和
  • 求出员工工资的最大值和最小值
  • 举例1:统计员工的平均工资 如
  • 举例二:统计员工的平均奖金 如

二和三结果一样,一不一样,因为在奖金列里面含有空值,count的时候数数不一样

所以分组函数会自动忽略空值,可以在分组函数中使用nvl函数来使分组函数无法忽略空值 如

  • 求出员工表中各个部门的平均工资 注意:在select列表中所有未包含在组函数(就是汇总计算xxx的列)中的列都应该包含在group by子句中,但包含在group by子句中的列不必包含在select列表中 如

要求所用包含于select列表中,而未包含于组函数中的列都必须包含于group by子句中。

这里的deptno没有包含在group by子句中,所以会报错。

注意不能在where子句中使用组函数(注意)。

可以在having子句中使用组函数。

如果在能使用where的场景下,从SQL优化的角度来看,尽量使用where效率更高,因为having是在分组的基础上过滤分组的结果,而where是先过滤,再分组。要处理的记录数不同。所以where能使分组记录数大大降低,从而提高效率。

(7)在分组查询中使用order by子句

  • 示例:求每个部门的平均工资,要求显示:部门号,部门的平均工资,并且按照工资升序排列 可以按照:列、别名、表达式、序号进行排序
  • 示例:求部门平均工资的最大值 如
  • 按部门、不同的职位显示工资的总额;同时按部门,统计工资总额;统计所有员工的工资总额。 如

rollup就可以实现上述的效果。小计、总计的效果,可以用在报表里面。

再运行上面的代码即可。

部门号 职位 工资总额 部门号 职位 工资总额

按数据库设计原则,员工表中只有部门的编号信息,部门的详细信息会存放在部门表中。

什么是多表查询:就是从多个表中获取数据。

前提是有一个外键约束来表示员工是哪个部门的,有个一个部门号来联结。

有了它才有多表查询的存在。笛卡尔集的列数等于每张表列数的相加,行数等于每张表的行数相乘。比如emp*dept有六列六行。里面的每一条记录不一定都是对的。多表查询就是要从笛卡尔集中选择出正确的记录。需要一个连接条件,比如部门号相等。有了连接条件,就能避免使用笛卡尔全集。在实际运行环境下,应提供where连接条件,避免使用笛卡尔全集。连接条件至少有要连接表数-1个。

创建笛卡尔集可以使用全连接: FULL JOIN

核心:通过外连接,把对于连接条件不成立的记录,仍然包含在最后的结果中。

左外连接(LEFT [OUTER] JOIN):当连接条件不成立的时候,等号左边的表仍然被包含

右外连接(RIGHT [OUTER] JOIN):当连接条件不成立的时候,等号右边的表仍然被包含

改为右外连接 方法是在相反的方向的等值连接结尾加上(+),比如右外连接就是加在左边的最后。

部门号 部门名称 人数
 
  • 作用:通过别名,将同一张表视为多张表(核心) INNER JOIN

尽管是查询一张表,但本质上仍然是多表查询,会产生笛卡尔集。

可以通过这个看笛卡尔集有多少条记录select count(*) from emp e,emp b;表越多,次方越多。比如员工表中有一亿条记录,如果看成三张表,就有一亿的立方的笛卡尔集,所以自连接不适合查询大表。

  • 所以要使用解决方法: 层次查询 (单表查询,只有在一张表时才不会查询笛卡尔集,在某些情况下可以取代自连接)。

  • 层次查询的原理:可以把前面的结果变成分level的一棵树。这棵树的根是没有上司的king,也就是mgr就是NULL。 如:

  • 自连接的优点:结果直观。缺点:不适合操作大表。

  • 层次查询的优点:适合单表查询,不会产生笛卡尔集。缺点:并没有自连接那么直观。

为什么要学习子查询:子查询可以解决不能一步求解的问题

  • 示例:查询工资比scott高的员工信息

子查询的语法:其实也就是select语句的嵌套

(2)子查询注意的十个问题

语法中一定要有小括号,不然是错的。

该换行的换行,该缩进的索引,可以便于阅读。

select后面使用,要求一定要只返回一条记录,要是单行子查询才行,多行子查询不行。 如

非常的重要,很多问题都是在from后面方式子查询来解决的 如

  • 不可以使用子查询的位置:group by
  • 强调:from后面的子查询,比较特殊,比较重要
  • 主查询和子查询可以不是同一张表

哪种查询方式好呢?从理论上来讲,尽量使用多表查询比较好,因为子查询需要对数据库访问两次,而多表查询只需要对数据库访问一次。但实际情况下有可能不一样,因为多表查询的笛卡尔集可能很大所以慢了。

  • 一般不在子查询中,使用排序;但在Top-N分析问题中,必须对子查询排序

比如找到员工表中工资最高的前三名。

rownum行号,是一个伪列,表上没有这一列,当做一些特殊操作的时候,oracle自动加上。行号需要注意的问题:行号永远按照默认的顺序生成;行号只能使用<,<=,不能使用>或者>=这样的符号。 如

  • 一般先执行子查询,再执行主查询;但相关子查询例外

相关子查询的表必须设定一个别名,然后把主查询的内容传入到子查询中进行查询。 如

这里就把主查询e表中的部门号传入子查询中进行查询了。

  • 单行子查询只能使用单行操作符;多行子查询只能使用多行操作符

非法使用单行子查询: 如

group by deptno); --因为子查询返回了不止一行,所以是非法使用单行子查询。
多行操作符:in(等于列表中的任意一个)、any(和子查询返回的任意一个值比较)、all(和子查询返回的所有值比较)
  • 注意:子查询中是null值的问题

单行子查询中返回空值,要使用in之类的关键字,等于号的话永远为空。

多行子查询中,如查询不是老板的员工 如:

  • 分页查询显示员工信息:显示员工号,姓名,月薪
  • 注意:rownum只能使用<,<=不能使用>,>=,因为oracle数据库是一个行式数据库,取了第一行才能取第二行,所以行号永远从1开始,所以比如rownum>=5这样的条件永远为假。
  • 找到员工表中薪水大于本部门平均薪水的员工

如果需要查询执行计划看性能的话,则在语句前面加上EXPLAIN PLAN FOR

  • 按部门统计员工人数,按照规定格式输入,已知员工的入职年份在80,81,82,87年之中。 如

新建两个表,然后按要求查到相关的内容

1.需要进行两个表的连接查询,为两个表都取别名

2.使用instr(a,b)函数,该函数的含义为:如果字符串b在字符串a的里面,则返回的是b在a中的位置,及返回值大于0

1 张三,赵六,王五,李四

同时学会了一个,如果在oracle中,需要实现如果表已经存在则先删除表的操作,写法为:

--如果已经存在表则先删除表
 

其中查询的表名和drop的表名变成你要检测的表名即可。

使用PLSQL语言操作Oracle数据库的效率最高。

之前用sql语句是命令式的语言,但如果案例是复杂的,比如需要分条件来做不同的事情的,就需要PL/SQL效率会更高,不需要用其他的编程语言。

指在SQL命令语言中增加了过程处理语句(如分支、循环等),使SQL语言具有过程处理能力。

(1)是sql的扩展,支持sql语句。

(2)是面向过程的语言。

--说明部分(变量说明、光标申明、例外说明) --程序体(DML语句)
/ --这个正斜杠用来退出前面的代码编写并且执行语句

4.不同数据库中SQL扩展

举例:名字在片面,变量是在后面,:=为赋值符号不是单=号

这里的into就可以赋值,是一一对应的。

--取表中一行的类型,作为变量的类型,可以理解为数组,如果需要取用到列里面的某一行,就像如下写法:
--在控制光标的时候比较简单
 

select如果返回的结果有多行的话就会出错,所以需要引入光标,光标cursor就是一个结果集。也叫游标。

此外,光标是可以带参数的。

(1)把当前指针指向的记录返回;

(2)将指针指向下一条记录。

  • %isopen:判断光标是否打开
  • %rowcount:影响的行数,不是总行数,比如光标取走了10行的数据,那么这个值就是10

默认情况下,oracle数据库只允许在同一个会话中打开300个光标

scope是范围,取值有三个:both, memory(只更改当前实例), spfile(只更改参数文件,数据库需要重启)

例外是程序设计语言提供的一种功能,用来增强程序的健壮性和容错性。

  • timeout_on_resource 在等待资源时发生超时(分布式数据库的访问会用到)

使用raise关键字抛出自定义例外

设计1.概要设计2.详细设计

以上步骤就像水流一下,最忌讳一上来就编码。

想明白SQL语句、变量。

变量:1.初始值是多少2.最终值如何得到

  • 使用||符号来连接文本字符串。
  • --表示单行注释,/* */表示多行输入
  • plsql中大小写不敏感。
  • then语句相当于一个大括号,后面的语句可以一起被处理,比如如下写法:

这里两句话都会被打印出来。

  • 把握一个原则:能不操作数据库就不操作数据库,比单单加减乘除的计算慢。

触发器是一个特殊的存储过程。是一个与表相关联的、存储的PL/SQL程序。

作用:每当一个特定的数据操作语句(insert、update、delete,注意没有select)在指定的表上发出时,oracle自动地执行触发器中定义的语句序列。

在指定的操作语句操作之前或之后执行一次,不管这条语句影响了多少行。

语句级触发器针对表,只会触发一次

触发语句作用的每一条记录都被触发。在行级触发器中使用:old和:new伪记录变量,识别值的状态。如果有for each row就表示行级触发器。 如

行级触发器针对行,有多少条记录就触发多少次。

每当成功插入新员工后,自动打印一句话,"成功插入新员工"。单词trigger

4.触发器的具体应用场景

(1)复杂的安全性检查 --比如周末不允许操作数据库

(2)数据的确认 --涨后的工资大于涨前的工资

(3)数据库审计 --跟踪表上所做的数据操作,什么时间什么人操作了什么数据,操作的人是什么。基于值的审计

(4)数据的备份和同步 --异地备份,把主数据的数据自动同步到备数据库中

  • 触发器案例一:禁止在非工作时间插入数据
  • 触发器案例二:涨工资不能越涨越少 :old:new的使用要注意。
  • 触发器案例三:创建基于值的触发器
PLSQL子程序体; (关键字可以小写)(如果不传参,则参数列表的小括号也可以省略)

这个PLSQL子程序体;一般为:

如果写的是存储函数,那么这里的PROCEDURE需要改成FUNCTION,而且必须在参数列表和AS之间添加一句:RETURN 函数值类型。而且需要在子程序体需要返回的时候写return 返回值

写好之后先编译,然后调用、运行。

as后面跟的是说明部分,相当于declare。

在参数列表中,如果是输入参数,可以写入eno in number,in是关键,in前面是变量名,后面是变量类型。

如果是输出参数,写eno out number,out是关键,out前面是变量名,后面是变量类型。

存储过程和存储函数都可以有out参数。

他们都可以有多个out参数。

存储过程可以通过out参数来实现返回值。

查询某个员工姓名、月薪和职位

--得到该员工的姓名、月薪和职位

5.在out参数中使用光标案例

案例:查询某个部门中所有员工的所有信息。

包头(负责声明包中的结构):

注意:包头中也可以不定义存储过程,只定义光标那一行。

包体(负责写需要实现包头中声明的所有方法):

--打开光标类型(是一个集合,意味着可以返回许多信息的集合)

注意:包体里面的存储过程也可以不写在包体内部也可以一样调用包头中定义的光标。

  • 参数列表可以换行,也可以在关键字之间多加空格。
  • 如果是没有参数的就是存储过程,如果有参数就是存储函数。存储函数可以有一个返回值,可以用return子句进行返回。
  • 我们的原则是,如果只需要一个返回值,则用存储函数。如果没有返回值,用存储过程,如果需要有多个返回值,则使用存储过程,在参数中使用out参数。
  • 单行注释使用“--注释内容”,多行注释使用“/* 注释内容 */”。

哪个权限没有就到sqlplus输入如下代码:

grant 要调的权限(中间用逗号分隔) to 用户名;

一些不知道插进过去的哪些笔记的笔记就放在这里吧~

为例, exists表示,对于A中的每一个记录,如果,在表B中有记录,其属性a的值与表A这个记录的属性a的值相同,则表A的这个记录是符合条件的记录,

如果是NOT exists,则表示如果表B中没有记录能与表A这个记录连接,则表A的这个记录是符合条件的记录。

问题描述 当应用程序频繁读写某个表或者资源时,容易出现死锁现象。出现死锁时,SQL Server会选择终止其中一个事务...适用于 云数据库 RDS SQL Server 版&如果您的问题仍未解决,您可以在阿里云社区免费咨询,或提交工单联系阿里云技术支持。

在Windows操作系统中查询阿里云SQL Server数据库空间时,可使用查询SQL Server数据库空间工具。以下是适用工具的注意事项和下载地址。使用注意事项 录入的用户必须具有所有数据库的读写权限,否则只能查看有权限的数据库空间大小。总空间=...

问题描述 在RDS SQL Server实例中删除数据库时,会出现以下场景的报错:如果数据库没有会话,对于RDS SQL Server 2008、2012和2016版,是用镜像做的主备同步,直接使用drop databaseSQL语句删除数据库会存在以下报错。The

关于将PostgreSQL数据库迁移到RDS,请参见以下文档:从自...

数据库服务器上执行如执行以下SQL语句(以下几条可以一起执行),数据库名称需要进行替换,具体SQL处理步骤如下:注意:如果日志已满只能截断日志链收缩,所以会影响备份恢复到这个时间点,但不影响业务,处理前请先备份数据库,如果没有...

方法二 通过SQL语句查看所有数据库的数据文件(mdf和ndf文件)和日志文件(ldf文件)的大小,详情请参见RDS for SQL Server如何查看实例、数据库及表占用的空间大小。方法三 可是用相关工具查看空间使用状况,具体使用方法可参见SQL Server...

要收缩一个SQL Server的数据文件,必须用DBCC SHRINKDATABASE语句收缩指定数据库的指定数据或日志文件大小,或者用DBCC SHRINKFILE语句收缩当前数据库的指定数据或日志文件大小。MySQL表的空间是独立的一个文件,所以收缩MySQL的大表,可以...

概述 本文要介绍RDS SQL Server在日常使用和维护时,常用的系统视图及相关查询语句。详细信息 阿里云提醒您:如果您对实例或数据有修改、变更等风险操作,务必注意实例的容灾、容错能力,确保数据安全。...适用于 云数据库 RDS SQL Server 版

概述 云数据库RDS SQL Server版如何统计连接数。详细信息 阿里云提醒您:如果您对实例或数据有修改、变更等风险操作,务必注意实例的容灾、容错能力,确保数据安全。如果您对实例(包括但不限于 ECS、RDS)等进行配置与数据修改,建议提前...

Server实例的连接数已满。进程数量存在阻塞的情况。解决方案...

问题描述 云数据库 RDS SQL Server 版出现阻塞问题。问题原因 当应用程序频繁读写某个表或者资源时,很容易出现阻塞情况。当阻塞问题严重时,应用程序端的语句执行会变得缓慢。解决方法 阿里云提醒您:如果您对实例或数据有修改、变更等...

问题描述 在云数据库RDS SQL Server中出现阻塞情况。问题原因 事务之间锁资源争抢导致出现阻塞情况。解决方案 阿里云提醒您:如果您对实例或数据有修改、变更等风险操作,务必注意实例的容灾、容错能力,确保数据安全。如果您对实例(包括...

概述 云数据库SQL Server版如何查看当前运行的SQL语句,类似于MySQL的show processlist语句。详细信息 阿里云提醒您:如果您对实例或数据有修改、变更等风险操作,务必注意实例的容灾、容错能力,确保数据安全。如果您对实例(包括但不限于...

概述 本文主要介绍MSSQL中如何查看行锁等待。详细信息 阿里云提醒您:如果您对实例或数据有修改、变更等风险操作,务必注意实例的容灾、容错能力,确保数据安全。如果您对实例(包括但不限于ECS、RDS)...适用于 云数据库 RDS SQL Server 版&

PHP可以通过MySQL和MySQLi两种函数操作MySQL数据库函数的具体说明和示例代码如下所示:MySQL函数 在PHP 5.0之前,一般使用PHP的MySQL函数操作MySQL数据库,属于面向过程的方式。例如,函数mysql_query()。MySQL是非持久连接函数,每次...

通过SQL命令删除数据库 说明 删除数据库后,系统将自动回收数据库使用空间。您可以通过监控与告警查看磁盘使用量,查看方法请参见查看资源和引擎监控。登录实例。具体操作,请参见连接实例。执行如下命令,删除数据库。drop database;

数据库审计服务支持对阿里云原生数据库(例如RDS云数据库)及自建数据库(例如ECS自建数据库)进行适配审计,满足您对数据审计及日志数据留存的要求。RDS云数据库审计 通过在用户PC(该PC通过数据库运维工具直接连接RDS数据库)或访问数据...

关于创建数据库实例的具体操作,请参见创建RDS MySQL实例、创建RDS PostgreSQL实例、创建RDS SQL Server实例和创建RDS MariaDB实例。说明 只有您将资产类型配置为RDS时,该参数才会显示。资产组 是 选择要审计的数据库归属的资产组,默认为...

数据库审计服务将数据库监控、审计技术与公共云环境相结合,针对数据库SQL注入、风险操作数据库风险行为进行记录与告警,形成对核心数据的安全防护,为您的云端数据库提供完善的安全诊断、维护、管理功能。数据库审计服务符合等级保护...

使用场景 云数据库HBase全面提供海量半结构/非结构化数据下的实时存储、高并发吞吐、轻SQL分析(参见云原生多模数据库Lindorm)、全文检索(参见Lindorm产品)等能力,结合完备的工具服务,丰富的生态融合,一站式高效满足企业在大数据量...

SQL审计功能可以实时记录数据库DML和DDL操作信息,并提供数据库操作信息的检索功能,提高云原生数据仓库AnalyticDB MySQL版的安全性。功能 SQL审计日志 记录对数据库执行的所有操作。通过审计日志记录,您可以对数据库进行故障分析、行为...

拥有实例下所有数据库操作的所有权限。普通账号只能通过控制台创建和管理。一个实例可以创建多个普通账号。不能创建和管理其他账号。需要通过控制台给普通账号授予特定数据库的权限。可以对已授权的数据库进行读写操作管理用户账号创建用户...

前提条件 自建SQL Server数据库的版本为SQL Server 2008 R2。专属集群MyBase具有足够的存储空间。若空间不足,请提前升级集群空间,详情请参见变更实例配置。完成OSS Bucket的创建,并确保OSS Bucket与专属集群MyBase SQL

DBS支持3种Oracle的恢复方式:异机恢复、原机异位置恢复、原机原位置恢复,本文档介绍如何恢复物理备份的Oracle数据...可选:进入数据库,执行如下SQL语句,启动数据库。ALTER database OPEN

本页面为您介绍云数据库 OceanBase 支持的数据库版本,您可跳转至 OceanBase 官网查看对应版本的数据库信息。数据库版本当前支持的 OceanBase 数据库版本:V2.2.77参考文档模式文档简介通用PL 参考PL 是一种过程化程序语言(Procedural

关于 MySQL 系列面试知识点程序员小吴总结了一个思维导图,分享给大家。

你可以通过这个链接下载这份PDF:

Q1:MySQL 的逻辑架构了解吗?

第一层是服务器层,主要提供连接处理、授权认证、安全等功能。

第二层实现了 MySQL 核心服务功能,包括查询解析、分析、优化、缓存以及日期和时间等所有内置函数,所有跨存储引擎的功能都在这一层实现,例如存储过程、触发器、视图等。

第三层是存储引擎层,存储引擎负责 MySQL 中数据的存储和提取。服务器通过 API 与存储引擎通信,这些接口屏蔽了不同存储引擎的差异,使得差异对上层查询过程透明。除了会解析外键定义的 InnoDB 外,存储引擎不会解析 SQL,不同存储引擎之间也不会相互通信,只是简单响应上层服务器请求。


在处理并发读或写时,可以通过实现一个由两种类型组成的锁系统来解决问题。这两种类型的锁通常被称为共享锁和排它锁,也叫读锁和写锁。读锁是共享的,相互不阻塞,多个客户在同一时刻可以同时读取同一个资源而不相互干扰。写锁则是排他的,也就是说一个写锁会阻塞其他的写锁和读锁,确保在给定时间内只有一个用户能执行写入并防止其他用户读取正在写入的同一资源。

在实际的数据库系统中,每时每刻都在发生锁定,当某个用户在修改某一部分数据时,MySQL 会通过锁定防止其他用户读取同一数据。写锁比读锁有更高的优先级,一个写锁请求可能会被插入到读锁队列的前面,但是读锁不能插入到写锁前面。


Q3:MySQL 的锁策略有什么?

表锁是MySQL中最基本的锁策略,并且是开销最小的策略。表锁会锁定整张表,一个用户在对表进行写操作前需要先获得写锁,这会阻塞其他用户对该表的所有读写操作。只有没有写锁时,其他读取的用户才能获取读锁,读锁之间不相互阻塞。

行锁可以最大程度地支持并发,同时也带来了最大开销。InnoDB 和 XtraDB 以及一些其他存储引擎实现了行锁。行锁只在存储引擎层实现,而服务器层没有实现。


Q4:数据库死锁如何解决?

死锁是指多个事务在同一资源上相互占用并请求锁定对方占用的资源而导致恶性循环的现象。当多个事务试图以不同顺序锁定资源时就可能会产生死锁,多个事务同时锁定同一个资源时也会产生死锁。

为了解决死锁问题,数据库系统实现了各种死锁检测和死锁超时机制。越复杂的系统,例如InnoDB 存储引擎,越能检测到死锁的循环依赖,并立即返回一个错误。这种解决方式很有效,否则死锁会导致出现非常慢的查询。还有一种解决方法,就是当查询的时间达到锁等待超时的设定后放弃锁请求,这种方式通常来说不太好。InnoDB 目前处理死锁的方法是将持有最少行级排它锁的事务进行回滚。

死锁发生之后,只有部分或者完全回滚其中一个事务,才能打破死锁。对于事务型系统这是无法避免的,所以应用程序在设计时必须考虑如何处理死锁。大多数情况下只需要重新执行因死锁回滚的事务即可。


事务是一组原子性的 SQL 查询,或者说一个独立的工作单元。如果数据库引擎能够成功地对数据库应用该组查询的全部语句,那么就执行该组查询。如果其中有任何一条语句因为崩溃或其他原因无法执行,那么所有的语句都不会执行。也就是说事务内的语句要么全部执行成功,要么全部执行失败。


Q6:事务有什么特性?

一个事务在逻辑上是必须不可分割的最小工作单元,整个事务中的所有操作要么全部提交成功,要么全部失败回滚,对于一个事务来说不可能只执行其中的一部分。

数据库总是从一个一致性的状态转换到另一个一致性的状态。

针对并发事务而言,隔离性就是要隔离并发运行的多个事务之间的相互影响,一般来说一个事务所做的修改在最终提交以前,对其他事务是不可见的。

一旦事务提交成功,其修改就会永久保存到数据库中,此时即使系统崩溃,修改的数据也不会丢失。


Q7:MySQL 的隔离级别有哪些?

在该级别事务中的修改即使没有被提交,对其他事务也是可见的。事务可以读取其他事务修改完但未提交的数据,这种问题称为脏读。这个级别还会导致不可重复读和幻读,性能没有比其他级别好很多,很少使用。

多数数据库系统默认的隔离级别。提交读满足了隔离性的简单定义:一个事务开始时只能"看见"已经提交的事务所做的修改。换句话说,一个事务从开始直到提交之前的任何修改对其他事务都是不可见的。也叫不可重复读,因为两次执行同样的查询可能会得到不同结果。

可重复读解决了不可重复读的问题,保证了在同一个事务中多次读取同样的记录结果一致。但还是无法解决幻读,所谓幻读指的是当某个事务在读取某个范围内的记录时,会产生幻行。InnoDB 存储引擎通过多版本并发控制MVCC 解决幻读的问题。

最高的隔离级别,通过强制事务串行执行,避免幻读。可串行化会在读取的每一行数据上都加锁,可能导致大量的超时和锁争用的问题。实际应用中很少用到这个隔离级别,只有非常需要确保数据一致性且可以接受没有并发的情况下才考虑该级别。


MVCC 是多版本并发控制,在很多情况下避免加锁,大都实现了非阻塞的读操作,写操作也只锁定必要的行。

InnoDB 的MVCC 通过在每行记录后面保存两个隐藏的列来实现,这两个列一个保存了行的创建时间,一个保存行的过期时间间。不过存储的不是实际的时间值而是系统版本号,每开始一个新的事务系统版本号都会自动递增,事务开始时刻的系统版本号会作为事务的版本号,用来和查询到的每行记录的版本号进行比较。


InnoDB 是 MySQL 的默认事务型引擎,用来处理大量短期事务。InnoDB 的性能和自动崩溃恢复特性使得它在非事务型存储需求中也很流行,除非有特别原因否则应该优先考虑 InnoDB。

InnoDB 的数据存储在表空间中,表空间由一系列数据文件组成。MySQL4.1 后 InnoDB 可以将每个表的数据和索引放在单独的文件中。

InnoDB 采用 MVCC 来支持高并发,并且实现了四个标准的隔离级别。其默认级别是 REPEATABLE READ,并通过间隙锁策略防止幻读,间隙锁使 InnoDB 不仅仅锁定查询涉及的行,还会对索引中的间隙进行锁定防止幻行的插入。

InnoDB 表是基于聚簇索引建立的,InnoDB 的索引结构和其他存储引擎有很大不同,聚簇索引对主键查询有很高的性能,不过它的二级索引中必须包含主键列,所以如果主键很大的话其他所有索引都会很大,因此如果表上索引较多的话主键应当尽可能小。

InnoDB 的存储格式是平***立的,可以将数据和索引文件从一个平台复制到另一个平台。

InnoDB 内部做了很多优化,包括从磁盘读取数据时采用的可预测性预读,能够自动在内存中创建加速读操作的自适应哈希索引,以及能够加速插入操作的插入缓冲区等。


MySQL5.1及之前,MyISAM 是默认存储引擎,MyISAM 提供了大量的特性,包括全文索引、压缩、空间函数等,但不支持事务和行锁,最大的缺陷就是崩溃后无法安全恢复。对于只读的数据或者表比较小、可以忍受修复操作的情况仍然可以使用 MyISAM。

MyISAM 将表存储在数据文件和索引文件中,分别以 .MYD.MYI 作为扩展名。MyISAM 表可以包含动态或者静态行,MySQL 会根据表的定义决定行格式。MyISAM 表可以存储的行记录数一般受限于可用磁盘空间或者操作系统中单个文件的最大尺寸。

MyISAM 对整张表进行加锁,读取时会对需要读到的所有表加共享锁,写入时则对表加排它锁。但是在表有读取查询的同时,也支持并发往表中插入新的记录。

对于MyISAM 表,MySQL 可以手动或自动执行检查和修复操作,这里的修复和事务恢复以及崩溃恢复的概念不同。执行表的修复可能导致一些数据丢失,而且修复操作很慢。

对于 MyISAM 表,即使是 BLOB 和 TEXT 等长字段,也可以基于其前 500 个字符创建索引。MyISAM 也支持全文索引,这是一种基于分词创建的索引,可以支持复杂的查询。

MyISAM 设计简单,数据以紧密格式存储,所以在某些场景下性能很好。MyISAM 最典型的性能问题还是表锁问题,如果所有的查询长期处于 Locked 状态,那么原因毫无疑问就是表锁。


如果需要快速访问数据且这些数据不会被修改,重启以后丢失也没有关系,那么使用 Memory 表是非常有用的。Memory 表至少要比 MyISAM 表快一个数量级,因为所有数据都保存在内存,不需要磁盘 IO,Memory 表的结构在重启后会保留,但数据会丢失。

Memory 表适合的场景:查找或者映射表、缓存周期性聚合数据的结果、保存数据分析中产生的中间数据。

Memory 表支持哈希索引,因此查找速度极快。虽然速度很快但还是无法取代传统的基于磁盘的表,Memory 表使用表级锁,因此并发写入的性能较低。它不支持 BLOB 和 TEXT 类型的列,并且每行的长度是固定的,所以即使指定了 VARCHAR 列,实际存储时也会转换成CHAR,这可能导致部分内存的浪费。

如果 MySQL 在执行查询的过程中需要使用临时表来保持中间结果,内部使用的临时表就是 Memory 表。如果中间结果太大超出了Memory 表的限制,或者含有 BLOB 或 TEXT 字段,临时表会转换成 MyISAM 表。


Q12:查询执行流程是什么?

简单来说分为五步:① 客户端发送一条查询给服务器。② 服务器先检查查询缓存,如果命中了缓存则立刻返回存储在缓存中的结果,否则进入下一阶段。③ 服务器端进行 SQL 解析、预处理,再由优化器生成对应的执行计划。④ MySQL 根据优化器生成的执行计划,调用存储引擎的 API 来执行查询。⑤ 将结果返回给客户端。


VARCHAR 用于存储可变字符串,是最常见的字符串数据类型。它比 CHAR 更节省空间,因为它仅使用必要的空间。VARCHAR 需要 1 或 2 个额外字节记录字符串长度,如果列的最大长度不大于 255 字节则只需要 1 字节。VARCHAR 不会删除末尾空格。

VARCHAR 适用场景:字符串列的最大长度比平均长度大很多、列的更新很少、使用了 UTF8 这种复杂字符集,每个字符都使用不同的字节数存储。

CHAR 是定长的,根据定义的字符串长度分配足够的空间。CHAR 会删除末尾空格。

CHAR 适合存储很短的字符串,或所有值都接近同一个长度,例如存储密码的 MD5 值。对于经常变更的数据,CHAR 也比 VARCHAR更好,因为定长的 CHAR 不容易产生碎片。对于非常短的列,CHAR 在存储空间上也更有效率,例如用 CHAR 来存储只有 Y 和 N 的值只需要一个字节,但是 VARCHAR 需要两个字节,因为还有一个记录长度的额外字节。


DATETIME 能保存大范围的值,从 年,精度为秒。把日期和时间封装到了一个整数中,与时区无关,使用 8 字节存储空间。

TIMESTAMP 和 UNIX 时间戳相同,只使用 4 字节的存储空间,范围比 DATETIME 小得多,只能表示 年,并且依赖于时区。

Q15:数据类型有哪些优化策略?

一般情况下尽量使用可以正确存储数据的最小数据类型,更小的数据类型通常也更快,因为它们占用更少的磁盘、内存和 CPU 缓存。

简单数据类型的操作通常需要更少的 CPU 周期,例如整数比字符操作代价更低,因为字符集和校对规则使字符相比整形更复杂。应该使用 MySQL 的内建类型 date、time 和 datetime 而不是字符串来存储日期和时间,另一点是应该使用整形存储 IP 地址。

通常情况下最好指定列为 NOT NULL,除非需要存储 NULL值。因为如果查询中包含可为 NULL 的列对 MySQL 来说更难优化,可为 NULL 的列使索引、索引统计和值比较都更复杂,并且会使用更多存储空间。当可为 NULL 的列被索引时,每个索引记录需要一个额外字节,在MyISAM 中还可能导致固定大小的索引变成可变大小的索引。

如果计划在列上建索引,就应该尽量避免设计成可为 NULL 的列。


Q16:索引有什么作用?

索引也叫键,是存储引擎用于快速找到记录的一种数据结构。索引对于良好的性能很关键,尤其是当表中数据量越来越大时,索引对性能的影响愈发重要。在数据量较小且负载较低时,不恰当的索引对性能的影响可能还不明显,但数据量逐渐增大时,性能会急剧下降。

索引大大减少了服务器需要扫描的数据量、可以帮助服务器避免排序和临时表、可以将随机 IO 变成顺序 IO。但索引并不总是最好的工具,对于非常小的表,大部分情况下会采用全表扫描。对于中到大型的表,索引就非常有效。但对于特大型的表,建立和使用索引的代价也随之增长,这种情况下应该使用分区技术。

在MySQL中,首先在索引中找到对应的值,然后根据匹配的索引记录找到对应的数据行。索引可以包括一个或多个列的值,如果索引包含多个列,那么列的顺序也十分重要,因为 MySQL 只能使用索引的最左前缀。


大多数 MySQL 引擎都支持这种索引,但底层的存储引擎可能使用不同的存储结构,例如 NDB 使用 T-Tree,而 InnoDB 使用 B+ Tree。

B-Tree 通常意味着所有的值都是按顺序存储的,并且每个叶子页到根的距离相同。B-Tree 索引能够加快访问数据的速度,因为存储引擎不再需要进行全表扫描来获取需要的数据,取而代之的是从索引的根节点开始进行搜索。根节点的槽中存放了指向子节点的指针,存储引擎根据这些指针向下层查找。通过比较节点页的值和要查找的值可以找到合适的指针进入下层子节点,这些指针实际上定义了子节点页中值的上限和下限。最终存储引擎要么找到对应的值,要么该记录不存在。叶子节点的指针指向的是被索引的数据,而不是其他的节点页。

  • 如果不是按照索引的最左列开始查找,则无法使用索引。
  • 如果查询中有某个列的范围查询,则其右边的所有列都无法使用索引。

哈希索引基于实现,只有精确匹配索引所有列的查询才有效。对于每一行数据,存储引擎都会对所有的索引列计算一个哈希码,哈希码是一个较小的值,并且不同键值的行计算出的哈希码也不一样。哈希索引将所有的哈希码存储在索引中,同时在中保存指向每个数据行的指针。

只有 Memory 引擎显式支持哈希索引,这也是 Memory 引擎的默认索引类型。

因为索引自身只需存储对应的哈希值,所以索引的结构十分紧凑,这让哈希索引的速度非常快,但它也有一些限制:

  • 哈希索引数据不是按照索引值顺序存储的,无法用于排序。
  • 哈希索引不支持部分索引列匹配查找,因为哈希索引始终是使用索引列的全部内容来计算哈希值的。例如在数据列(a,b)上建立哈希索引,如果查询的列只有a就无法使用该索引。
  • 哈希索引只支持等值比较查询,不支持任何范围查询。

Q19:什么是自适应哈希索引?

自适应哈希索引是 InnoDB 引擎的一个特殊功能,当它注意到某些索引值被使用的非常频繁时,会在内存中基于 B-Tree 索引之上再创键一个哈希索引,这样就让 B-Tree 索引也具有哈希索引的一些优点,比如快速哈希查找。这是一个完全自动的内部行为,用户无法控制或配置,但如果有必要可以关闭该功能。


Q20 :什么是空间索引?

MyISAM 表支持空间索引,可以用作地理数据存储。和 B-Tree 索引不同,这类索引无需前缀查询。空间索引会从所有维度来索引数据,查询时可以有效地使用任意维度来组合查询。必须使用 MySQL 的 GIS 即地理信息系统的相关函数来维护数据,但 MySQL 对 GIS 的支持并不完善,因此大部分人都不会使用这个特性。


Q21:什么是全文索引?

通过数值比较、范围过滤等就可以完成绝大多数需要的查询,但如果希望通过关键字匹配进行查询,就需要基于相似度的查询,而不是精确的数值比较,全文索引就是为这种场景设计的。

MyISAM 的全文索引是一种特殊的 B-Tree 索引,一共有两层。第一层是所有关键字,然后对于每一个关键字的第二层,包含的是一组相关的"文档指针"。全文索引不会索引文档对象中的所有词语,它会根据规则过滤掉一些词语,例如停用词列表中的词都不会被索引。


Q22:什么是聚簇索引?

聚簇索引不是一种索引类型,而是一种数据存储方式。InnoDB 的聚簇索引实际上在同一个结构中保存了 B-Tree 索引和数据行。当表有聚餐索引时,它的行数据实际上存放在索引的叶子页中,因为无法同时把数据行存放在两个不同的地方,所以一个表只能有一个聚簇索引。

优点:① 可以把相关数据保存在一起。② 数据访问更快,聚簇索引将索引和数据保存在同一个 B-Tree 中,因此获取数据比非聚簇索引要更快。③ 使用覆盖索引扫描的查询可以直接使用页节点中的主键值。

缺点:① 聚簇索引最大限度提高了 IO 密集型应用的性能,如果数据全部在内存中将会失去优势。② 更新聚簇索引列的代价很高,因为会强制每个被更新的行移动到新位置。③ 基于聚簇索引的表插入新行或主键被更新导致行移动时,可能导致页分裂,表会占用更多磁盘空间。④ 当行稀疏或由于页分裂导致数据存储不连续时,全表扫描可能很慢。


Q23:什么是覆盖索引?

覆盖索引指一个索引包含或覆盖了所有需要查询的字段的值,不再需要根据索引回表查询数据。覆盖索引必须要存储索引列的值,因此 MySQL 只能使用 B-Tree 索引做覆盖索引。

优点:① 索引条目通常远小于数据行大小,可以极大减少数据访问量。② 因为索引按照列值顺序存储,所以对于 IO 密集型防伪查询回避随机从磁盘读取每一行数据的 IO 少得多。③ 由于 InnoDB 使用聚簇索引,覆盖索引对 InnoDB 很有帮助。InnoDB 的二级索引在叶子节点保存了行的主键值,如果二级主键能覆盖查询那么可以避免对主键索引的二次查询。


Q24:你知道哪些索引使用原则?

对查询频次较高且数据量比较大的表建立索引。索引字段的选择,最佳候选列应当从 WHERE 子句的条件中提取,如果 WHERE 子句中的组合比较多,应当挑选最常用、过滤效果最好的列的组合。业务上具有唯一特性的字段,即使是多个字段的组合,也必须建成唯一索引。

索引列开始的部分字符,索引创建后也是使用硬盘来存储的,因此短索引可以提升索引访问的 IO 效率。对于 BLOB、TEXT 或很长的 VARCHAR 列必须使用前缀索引,MySQL 不允许索引这些列的完整长度。前缀索引是一种能使索引更小更快的有效方法,但缺点是 MySQL 无法使用前缀索引做 ORDER BY 和 GROUP BY,也无法使用前缀索引做覆盖扫描。

当不需要考虑排序和分组时,将选择性最高的列放在前面。索引的选择性是指不重复的索引值和数据表的记录总数之比,索引的选择性越高则查询效率越高,唯一索引的选择性是 1,因此也可以使用唯一索引提升查询效率。

MySQL 允许在相同列上创建多个索引,重复的索引需要单独维护,并且优化器在优化查询时也需要逐个考虑,这会影响性能。重复索引是指在相同的列上按照相同的顺序创建的相同类型的索引,应该避免创建重复索引。如果创建了索引 (A,B) 再创建索引 (A) 就是冗余索引,因为这只是前一个索引的前缀索引,对于 B-Tree 索引来说是冗余的。解决重复索引和冗余索引的方法就是删除这些索引。除了重复索引和冗余索引,可能还会有一些服务器永远不用的索引,也应该考虑删除。


Q25:索引失效的情况有哪些?

如果索引列出现了隐式类型转换,则 MySQL 不会使用索引。常见的情况是在 SQL 的 WHERE 条件中字段类型为字符串,其值为数值,如果没有加引号那么 MySQL 不会使用索引。

如果 WHERE 条件中含有 OR,除非 OR 前使用了索引列而 OR 之后是非索引列,索引会失效。

MySQL 不能在索引中执行 LIKE 操作,这是底层存储引擎 API 的限制,最左匹配的 LIKE 比较会被转换为简单的比较操作,但如果是以通配符开头的 LIKE 查询,存储引擎就无法做比较。这种情况下 MySQL 只能提取数据行的值而不是索引值来做比较。

如果查询中的列不是独立的,则 MySQL 不会使用索引。独立的列是指索引列不能是表达式的一部分,也不能是函数的参数。

对于多个范围条件查询,MySQL 无法使用第一个范围列后面的其他索引列,对于多个等值查询则没有这种限制。

如果 MySQL 判断全表扫描比使用索引查询更快,则不会使用索引。

索引文件具有 B-Tree 的最左前缀匹配特性,如果左边的值未确定,那么无法使用此索引。


Q26:如何定位低效 SQL?

可以通过两种方式来定位执行效率较低的 SQL 语句。一种是通过慢查询日志定位,可以通过慢查询日志定位那些已经执行完毕的 SQL 语句。另一种是使用 SHOW PROCESSLIST 查询,慢查询日志在查询结束以后才记录,所以在应用反应执行效率出现问题的时候查询慢查询日志不能定位问题,此时可以使用 SHOW PROCESSLIST 命令查看当前 MySQL 正在进行的线程,包括线程的状态、是否锁表等,可以实时查看 SQL 的执行情况,同时对一些锁表操作进行优化。找到执行效率低的 SQL 语句后,就可以通过 SHOW PROFILE、EXPLAIN 或 trace 等丰富来继续优化语句。



从 MySQL5.6 开始,可以通过 trace 文件进一步获取优化器是是如何选择执行计划的,在使用时需要先打开设置,然后执行一次 SQL,最后查看 information_schema.optimizer_trace 表而都内容,该表为联合i表,只能在当前会话进行查询,每次查询后返回的都是最近一次执行的 SQL 语句。


Q29:EXPLAIN 的字段有哪些,具有什么含义?

执行计划是 SQL 调优的一个重要依据,可以通过 EXPLAIN 命令查看 SQL 语句的执行计划,如果作用在表上,那么该命令相当于 DESC。EXPLAIN 的指标及含义如下:

表示 SELECT 子句或操作表的顺序,执行顺序从大到小执行,当 id 一样时,执行顺序从上往下。
表示查询中每个 SELECT 子句的类型,例如 SIMPLE 表示不包含子查询、表连接或其他复杂语法的简单查询,PRIMARY 表示复杂查询的最外层查询,SUBQUERY 表示在 SELECT 或 WHERE 列表中包含了子查询。
表示访问类型,性能由差到好为:ALL 全表扫描、index 索引全扫描、range 索引范围扫描、ref 返回匹配某个单独值得所有行,常见于使用非唯一索引或唯一索引的非唯一前缀进行的查找,也经常出现在 join 操作中、eq_ref 唯一性索引扫描,对于每个索引键只有一条记录与之匹配、const 当 MySQL 对查询某部分进行优化,并转为一个常量时,使用这些访问类型,例如将主键或唯一索引置于 WHERE 列表就能将该查询转为一个 const、system 表中只有一行数据或空表,只能用于 MyISAM 和 Memory 表、NULL 执行时不用访问表或索引就能得到结果。SQL 性能优化的目标:至少要达到 range 级别,要求是 ref 级别,如果可以是consts 最好。
表示查询时可能用到的索引,但不一定使用。列出大量可能索引时意味着备选索引数量太多了。
显示 MySQL 在查询时实际使用的索引,如果没有使用则显示为 NULL。
表示使用到索引字段的长度,可通过该列计算查询中使用的索引的长度,对于确认索引有效性以及多列索引中用到的列数目很重要。
表示上述表的连接匹配条件,即哪些列或常量被用于查找索引列上的值。
表示 MySQL 根据表统计信息及索引选用情况,估算找到所需记录所需要读取的行数。
表示额外信息,例如 Using temporary 表示需要使用临时表存储结果集,常见于排序和分组查询。Using filesort 表示无法利用索引完成的文件排序,这是 ORDER BY 的结果,可以通过合适的索引改进性能。Using index 表示只需要使用索引就可以满足查询表得要求,说明表正在使用覆盖索引。

Q30:有哪些优化 SQL 的策略?

COUNT 是一个特殊的函数,它可以统计某个列值的数量,在统计列值时要求列值是非空的,不会统计 NULL 值。如果在 COUNT 中指定了列或列的表达式,则统计的就是这个表达式有值的结果数,而不是 NULL。

COUNT 的另一个作用是统计结果集的行数,当 MySQL 确定括号内的表达式不可能为 NULL 时,实际上就是在统计行数。当使用 COUNT() 时,\ 不会扩展成所有列,它会忽略所有的列而直接统计所有的行数。

某些业务场景并不要求完全精确的 COUNT 值,此时可以使用近似值来代替,EXPLAIN 出来的优化器估算的行数就是一个不错的近似值,因为执行 EXPLAIN 并不需要真正地执行查询。

通常来说 COUNT 都需要扫描大量的行才能获取精确的结果,因此很难优化。在 MySQL 层还能做的就只有覆盖扫描了,如果还不够就需要修改应用的架构,可以增加汇总表或者外部缓存系统。

确保 ON 或 USING 子句中的列上有索引,在创建索引时就要考虑到关联的顺序。

确保任何 GROUP BY 和 ORDER BY 的表达式只涉及到一个表中的列,这样 MySQL 才有可能使用索引来优化这个过程。

在 MySQL 5.5 及以下版本尽量避免子查询,可以用关联查询代替,因为执行器会先执行外部的 SQL 再执行内部的 SQL。

如果没有通过 ORDER BY 子句显式指定要的列,当查询使用 GROUP BY 时,结果***自动按照分组的字段进行,如果不关心结果集的顺序,可以使用 ORDER BY

在偏移量非常大的时候,需要查询很多条数据再舍弃,这样的代价非常高。要优化这种查询,要么是在页面中限制分页的数量,要么是优化大偏移量的性能。最简单的办法是尽可能地使用覆盖索引扫描,而不是查询所有的列,然后根据需要做一次关联操作再返回所需的列。

还有一种方法是从上一次取数据的位置开始扫描,这样就可以避免使用 OFFSET。其他优化方法还包括使用预先计算的汇总表,或者关联到一个冗余表,冗余表只包含主键列和需要做的数据列。

MySQL 通过创建并填充临时表的方式来执行 UNION 查询,除非确实需要服务器消除重复的行,否则一定要使用 UNION ALL,如果没有 ALL 关键字,MySQL 会给临时表加上 DISTINCT 选项,这会导致对整个临时表的数据做唯一性检查,这样做的代价非常高。

在查询中混合使用过程化和关系化逻辑的时候,自定义变量可能会非常有用。用户自定义变量是一个用来存储内容的临时容器,在连接 MySQL 的整个过程中都存在,可以在任何可以使用表达式的地方使用自定义变量。例如可以使用变量来避免重复查询刚刚更新过的数据、统计更新和插入的数量等。

需要对一张表插入很多行数据时,应该尽量使用一次性插入多个值的 INSERT 语句,这种方式将缩减客户端与数据库之间的连接、关闭等消耗,效率比多条插入单个值的 INSERT 语句高。也可以关闭事务的自动提交,在插入完数据后提交。当插入的数据是按主键的顺序插入时,效率更高。


复制解决的基本问题是让一台服务器的数据与其他服务器保持同步,一台主库的数据可以同步到多台备库上,备库本身也可以被配置成另外一台服务器的主库。主库和备库之间可以有多种不同的组合方式。

MySQL 支持两种复制方式:基于行的复制和基于语句的复制,基于语句的复制也称为逻辑复制,从 MySQL 3.23 版本就已存在,基于行的复制方式在 5.1 版本才被加进来。这两种方式都是通过在主库上记录二进制日志、在备库重放日志的方式来实现异步的数据复制。因此同一时刻备库的数据可能与主库存在不一致,并且无法包装主备之间的延迟。

MySQL 复制大部分是向后兼容的,新版本的服务器可以作为老版本服务器的备库,但是老版本不能作为新版本服务器的备库,因为它可能无法解析新版本所用的新特性或语法,另外所使用的二进制文件格式也可能不同。

复制解决的问题:数据分布、负载均衡、备份、高可用性和故障切换、MySQL 升级测试。


① 在主库上把数据更改记录到二进制日志中。
② 备库将主库的日志复制到自己的中继日志中。
③ 备库读取中继日志中的事件,将其重放到备库数据之上。

第一步是在主库上记录二进制日志,每次准备提交事务完成数据更新前,主库将数据更新的事件记录到二进制日志中。MySQL 会按事务提交的顺序而非每条语句的执行顺序来记录二进制日志,在记录二进制日志后,主库会告诉存储引擎可以提交事务了。

下一步,备库将主库的二进制日志复制到其本地的中继日志中。备库首先会启动一个工作的 IO 线程,IO 线程跟主库建立一个普通的客户端连接,然后在主库上启动一个特殊的二进制转储线程,这个线程会读取主库上二进制日志中的事件。它不会对事件进行轮询。如果该线程追赶上了主库将进入睡眠状态,直到主库发送信号量通知其有新的事件产生时才会被唤醒,备库 IO 线程会将接收到的事件记录到中继日志中。

备库的 SQL 线程执行最后一步,该线程从中继日志中读取事件并在备库执行,从而实现备库数据的更新。当 SQL 线程追赶上 IO 线程时,中继日志通常已经在系统缓存中,所以中继日志的开销很低。SQL 线程执行的时间也可以通过配置选项来决定是否写入其自己的二进制日志中。

我要回帖

更多关于 sql是什么文件格式 的文章

 

随机推荐