1.sql优化有哪些?如何创建索引?创建索引的原则是什么?索引的优缺点?
1、在表中建立索引,优先考虑where、group by
2、减少使用 * ,用列名代替
3、避免在开头使用模糊查询(%)
该查询数据库引擎会放弃索引进行全表扫描。
4、需要删除所有记录的时候,用truncate
5、避免使用in和not in,会导致全表扫描
6、如果表名或列名过长,就使用别名
索引的数据结构?
非关系型数据库MongoDB使用B树作为数据库索引。
大部分关系型数据库,比如Mysql,则使用B+树作为索引。
B+树是基于B-树的一种变体,有着比B-树更高的查询性能。
B+树和B-树有一些共同点,但是B+树也具备一些新的特征。
在B+树中,只有叶子节点才真正存储数据,非叶子节点不存储数据。
使用B+树做索引的好处主要体现在查询性能上。
B+树和B-树的区别:
B+树中间节点没有存储数据,只有叶节点存放数据,其余节点用来索引,所以同样大小的磁盘页可以容纳更多的节点元素,而B-树是每个索引节点都会有Data域。这就意味着,数据量相同的情况下,B+树的结构比B-树更加“矮胖”,因此查询是IO次数也更少。这就决定了B+树更适合用来存储外部数据,也就是所谓的磁盘数据。
B-树的查询性能并不稳定(最好情况是只查根节点,最坏情况是查到叶子节点)。而B+树每一次查找都是稳定的。
B+树相比B-树的优势有三个:
1.单一节点存储更多的元素,使得查询的IO次数更少。
2.所有查询都要查找到叶子节点,查询性能稳定。
3.所有叶子节点形成有序链表,便于范围查询。
数据库索引为什么用B+树而不用B-树?
数据库索引采用B+树的主要原因是B树在提高了磁盘IO性能的同时并没有解决元素遍历的效率低下的问题。正是为了解决这个问题,B+树应运而生。B+树只要遍历叶子节点就可以实现整棵树的遍历。而且在数据库中基于范围的查询是非常频繁的,而B树不支持这样的操作(或者说效率太低)。
那么MongoDB为什么使用B-树而不是B+树?
至于MongoDB为什么使用B-树而不是B+树,可以从它的设计角度来考虑,它并不是传统的关系性数据库,而是以Json格式作为存储的nosql,目的就是高性能,高可用,易扩展。首先它摆脱了关系模型,上面所述的范围查询的优点就没那么强烈了,其次Mysql由于使用B+树,数据都在叶节点上,每次查询都需要访问到叶节点,而MongoDB使用B-树,所有节点都有Data域,只要找到指定索引就可以进行访问,无疑单次查询平均快于Mysql(但侧面来看Mysql至少平均查询耗时差不多)。
总体来说,Mysql选用B+树和MongoDB选用B-树还是以自己的需求来选择的。
使用B+树而不是用其他结构的原因就是为了减少磁盘IO的次数,减少数的高度,而B+树就很好的做到了这一点。
B+树
每一个结点放到一个page中,一次连续的加载到内存
MyISAM VS Innodb
一个表有三个文件:
.frm 表的定义文件:表结构
.MYD 数据文件
.MYI index文件
Innodb :
.frm
.ibd: 聚集索引
索引失效的情况?
1.随着表的增长,where条件出来的数据太多,大于15%,使得索引失效
2.统计信息失效 需要重新搜集统计信息
3.索引本身失效 需要重建索引
replace()和replaceAll()的区别
相同点
都是全部替换,即把源字符串中的某一字符或字符串全部换成指定的字符或字符串,如果只想替换第一次出现的,可以使用 replaceFirst(),这个方法也是基于规则表达式的替换,但与replaceAll()不同的是,只替换第一次出现的字符串;
另外,如果replaceAll()和replaceFirst()所用的参数据不是基于规则表达式的,则与replace()替换字符串的效果是一样的,即这两者也支持字符串的操作;
还有一点注意:执行了替换操作后,源字符串的内容是没有发生改变的.
区别
replace的参数是char和CharSequence,即可以支持字符的替换,也支持字符串的替换(CharSequence即字符串序列的意思,说白了也就是字符串);
replaceAll的参数是regex,即基于规则表达式的替换,比如,可以通过replaceAll(“\d”, “*”)把一个字符串所有的数字字符都换成星号;
如何创建索引?
建表时创建:
create table 表名(
字段名 数据类型 [完整性约束条件],
.......,
[unique | fulltext | spatial] index | key [索引名] (字段名1 [(长度)] [asc | desc])[using 索引方法]
);
建表后创建:
alter table 表名 add[unique | fulltext | spatial] index | key [索引名] (字段名1[长度][asc|desc])[using 索引方法];
或
create[unique | fulltext | spatial] index 索引名 on 表名(字段名)[using 索引方法];
创建索引的方法
创建索引有多种方法,这些方法包括直接创建索引的方法和间接创建索引的方法。
第一, 直接创建索引,例如使用CREATE INDEX语句或者使用创建索引向导。
第二, 间接创建索引,例如在表中定义主键约束或者唯一性键约束时,同时也创建了索引。
虽然,这两种方法都可以创建索引,但是,它们创建索引的具体内容是有区别的。
使用CREATE INDEX语句或者使用创建索引向导来创建索引,这是最基本的索引创建方式,并且这种方法最具有柔性,可以定制创建出符合自己需要的索引。在使用这种方式创建索引时,可以使用许多选项,例如指定数据页的充满度、进行排序、整理统计信息等,这样可以优化索引。使用这种方法,可以指定索引的类型、唯一性和复合性,也就是说,既可以创建聚簇索引,也可以创建非聚簇索引,既可以在一个列上创建索引,也可以在两个或者两个以上的列上创建索引。
通过定义主键约束或者唯一性键约束,也可以间接创建索引。主键约束是一种保持数据完整性的逻辑,它限制表中的记录有相同的主键记录。在创建主键约束时,系统自动创建了一个唯一性的聚簇索引。虽然,在逻辑上,主键约束是一种重要的结构,但是,在物理结构上,与主键约束相对应的结构是唯一性的聚簇索引。换句话说,在物理实现上,不存在主键约束,而只存在唯一性的聚簇索引。同样,在创建唯一性键约束时,也同时创建了索引,这种索引则是唯一性的非聚簇索引。因此,当使用约束创建索引时,索引的类型和特征基本上都已经确定了,由用户定制的余地比较小。
当在表上定义主键或者唯一性键约束时,如果表中已经有了使用CREATE INDEX语句创建的标准索引时,那么主键约束或者唯一性键约束创建的索引覆盖以前创建的标准索引。也就是说,主键约束或者唯一性键约束创建的索引的优先级高于使用CREATE INDEX语句创建的索引。
创建索引的原则是什么?
1、 对于查询频率高的字段创建索引;
2、 索引的数目不宜太多
3. 对于经常存取的列避免建立索引;
索引的优缺点?
优点:
加快数据的查询速度
缺点:
创建索引会耗费时间和占用磁盘空间,并且随着数据量的增加所耗费的时间也会增加
2.sql如何去重?
1:使用distinct
2:使用group by
3.内连接和外连接的区别?
内连接:指连接结果包含符合连接条件的行,参与连接的两个表都应该符合连接条件。
外连接:连接结果包含符合连接条件的行同时也包含自身不符合条件的行。
包括左外连接、右外连接和全外连接。
左外连接:左边表数据行全部保留,右边表保留符合连接条件的行。
右外连接:右边表数据行全部保留,左边表保留符合连接条件的行。
4.Java中如何使用Redis? redis支持的数据类型及各数据类型的使用场景?reids如何解决数据过期?
1.在pom.xml引入redis依赖包
2.在application.yml中配置redis
redis支持的数据类型及各数据类型的使用场景?
Redis数据类型及使用场景
String:
作为常规的key-value缓存应用,微博数、粉丝数
Hash:
Hash存的是字符串和字符串值之间的映射。存放结构化数据,比如用户信息。
List:
List是一个双向链表。各种列表,比如twitter的关注列表、粉丝列表等,最新消息排行、每篇文章的评论等消息队列,
Set:
是一种无序的集合,集合中的元素没有先后顺序,不重复。交集、并集、差集
zset:
(sorted set 可排序Set) 是string类型的有序集合,也不可重复。排行榜
Redis支持的数据类型
string
list
zset
各数据类型的使用场景
string:微博数、粉丝数
list:应用场景:微博的关注列表,粉丝列表
zset:应用场景:排行榜
如何持久化到硬盘
redis提供两种方式进行持久化,一种是RDB持久化
RDB持久化是指在指定的时间间隔内将内存中的数据集快照写入磁盘
AOF持久化以日志的形式记录服务器所处理的每一个写、删除操作,查询操作不会记录,以文本的方式记录,可以打开文件看到详细的操作记录。
reids如何解决数据过期?
在 Redis 中,是可以设置过期数据的,用于删除过期的数据
1、定期删除
2、惰性删除
5.数据库表的设计注意事项有哪些?三大范式的了解?
1、 数据库表命名,采用驼峰表示法
2、 排序字段,不依赖id排序,
3、 增加备注字段,
4、 添加时间,
5、 修改时间
三大范式的了解?
第一范式:列的原子性
第二范式:实体的属性完全依赖于主关键字
第三范式:任何非主属性不依赖于其它非主属性。
6.存储过程的了解和使用?
存储过程的概念
存储过程(Stored Procedure)是一组为了完成特定功能的SQL语句集。经编译后存储在数据库中。
存储过程是数据库中的一个重要对象,用户通过指定存储过程的名字并给出参数(如果该存储过程带有参数)来执行它。
可由应用程序通过一个调用来执行,而且允许用户声明变量。
存储过程和存储函数(Oracle)
存储过程和函数的区别?
存储过程
1.储存过程可以有返回值也可以无返回值
2.存储过程的实现比较复杂
3.储存过程可以输入输出参数
4.可以在存储过程中调用函数
函数:
1.函数必须有返回值
2.函数的实现比较有针对性
3.函数只可以输入参数
4.不可以在函数中调用存储过程
1.储存过程可以有返回值也可以无返回值。函数必须有返回值。
2.存储过程的实现比较复杂,而函数的实现比较有针对性。
3.储存过程可以输入输出参数,而函数只可以输入参数。
4.过程允许在其中选择以及DML语句,而函数只可以在其中select语句。
5.可以在存储过程中调用函数,不可以在函数中调用存储过程。
2、调用存储过程方法:
1、exec 过程名
2、begin
过程名;
过程名;
end;
存储过程的使用
1、创建一个存储过程
create procedure GetUsers()
begin
select * from user;
end;12345
2、调用存储过程
call GetUsers();12
3、删除存储过程
drop procedure if exists GetUsers;
存储过程:
应用程序通过一个调用来执行
为了完成特定功能的SQL语句。经编译后存储在数据库中
存储过程的使用
1、创建一个存储过程
2、调用存储过程
3、删除存储过程
7.数据库如何实现分页?百万级量的数据分页查询如何优化?
Mysql:limit
Oracle:rownum
百万级量的数据分页查询如何优化?
利用表的覆盖索引来加速分页查询
8.数据库的乐观锁和悲观锁的理解和使用?
乐观锁:每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在提交更新的时候会判断一下在此期间别人有没有去更新这个数据。
悲观锁:每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会阻止,直到这个锁被释放。
使用:
数据库的乐观锁需要自己实现,在表里面添加一个 version 字段,每次修改成功值加 1,这样每次修改的时候先对比一下,自己拥有的 version 和数据库现在的 version 是否一致,如果不一致就不修改,这样就实现了乐观锁。
使用悲观锁来实现:
在上面的场景中,商品信息从查询出来到修改,中间有一个处理订单的过程,使用悲观锁的原理就是,当我们在查询出goods信息后就把当前的数据锁定,直到我们修改完毕后再解锁。那么在这个过程中,因为goods被锁定了,就不会出现有第三者来对其进行修改了。
.悲观锁通常依靠数据库提供的锁机制实现,比如mysql的排他锁,select … for update来实现悲观锁。
数据库的乐观锁需要自己实现,
在表里面添加一个 version 字段,每次修改成功值加 1,这样每次修改的时候先对比一下,自己拥有的version 和数据库现在的 version 是否一致,如果不一致就不修改,这样就实现了乐观锁。
使用悲观锁的原理就是,当我们在查询出goods信息后就把当前的数据锁定,直到我们修改完毕后再解锁。
,因为goods被锁定了,就不会出现有第三者来对其进行修改了
9.数据库中字符串和日期的相互转换?
1、使用date_format
2、日期转换还可以使用str_to_date()
3、oracle是to_date
10.union 和unionAll区别?
UNION 做去重和排序处理
UNION ALL将两个结果集合并;
UNION 效率比UNION ALL慢很多
11.mysql的存储引擎有哪些?
InnoDB
,MyISAM
,Memory
,Merge
,Archive
,Federate
,CSV
,BLACKHOLE
存储引擎
存储引擎对比
-
MyIsam:
-
使用三个文件表示每个表:
- 格式文件 — 存储表的结构(mytable.frm)
- 数据文件 — 存储表的数据(mytable.MYD)
- 索引文件 — 存储表的索引(mytable.MYI)
-
对表文件中数据行查询提速,有很大帮助。
-
灵活的
AUTO_INCREMENT
字段处理 -
可被转换为压缩、只读表来节省空间
-
但是MyIsam不支持事务,因此在进行数据行添加,修改,删除时,无法保证数据安全性
-
-
INNODB:MySQL数据库的默认引擎;
- 每个
InnoDB
表在数据库目录中以.frm
格式文件表示 InnoDB
表空间tablespace
被用于存储表的内容- 提供一组用来记录事务性活动的日志文件
- 支持事务处理
- 提供全
ACID
兼容 - 在
MySQL
服务器崩溃后提供自动恢复- 多版本(
MVCC
)和行级锁定 - 支持外键及引用的完整性,包括级联更新和删除
- 多版本(
-
MEMORY:其数据存储在内存中,且行的长度固定,这两个特点使得MEMORY存储引擎非常快;
- 在数据库目录内,每个表均以
.frm
格式文件表示; - 表数据及索引被存储在内存中;
- 表级锁机制;
- 不能包含TEXT或BLOB字段;
- 在数据库目录内,每个表均以
-
如何选择合适的存储引擎
MyISAM
表最适合于大量的数据读而少量数据更新的混合操作。MyISAM表的另一种适用情形是使用压缩的中读表。- 如果查询中包含较多的数据更新操作,应使用
InnoDB
。其行级锁机制和多版本的支持为数据读取和更新的混合提供了良好的并发机制。 - 可使用
MEMORY
存储引擎存储非永久需要的数据,或者是能够从基于磁盘的表中重新生成的数据。
- 每个
Innodb有哪些特性?
- 插入缓冲
- 二次写
- 自适应哈希
- 预读
ndb:mysql集群专用存储引擎
innodb:具备外键支持功能的事务处理引擎
csv:以逗号作为数据项之间的分隔符
archive :数据库存档引擎
12.事务的隔离级别有哪些?mysql和oracle默认的隔离级别是什么?
(1)read uncommitted 未提交读
(2)read committed 提交读
(3)repeatable 重复读
mysql和oracle默认的隔离级别是什么?
mysql默认的事务处理级别是repeatable-read;可重复读
Oracle
默认系统事务隔离级别是read committed;读已提交
13.sql如何行转列和列转行?
行转列:
1.使用case...when....then 进行行转列
列转行:用UNION ALL将结果集加起来
14.如何查看sql的执行计划?
可以通过(explain+执行sql)查看sql的执行计划
15.oracle中的分析函数有哪些?
---聚合函数
SUM :累积和
MIN:最小值
MAX :最大值
AVG :平均值
COUNT :计数
16.数据库中除了聚合函数之外还有哪些常用的函数?oracle数据库merge()函数的作用和使用?
destinct(去除重复行)
to_char(转换自符串)
to_date(日期格式函数)
substr(截取自符串)
lower(将字母转换为小写)
upper(将字母转换为小写)
oracle数据库merge()函数的作用和使用?
在一个SQL语句中对一个表同时执行inserts和updates操作.
17.sql中drop、truncate、delete的区别?
drop:将使此表的结构一起删除
truncate (清空表中的数据)
删除内容、保留表的数据结构,只删除数据,但是比delete彻底
delete:delete即可以对行数据进行删除,也可以对整表数据进行删除
都删除整张表的话
TRUNCATE 速度更快,占用的日志更少,
DELETE 是一行一行地删除,在事务日志中要记录每一条记录的删除
18.mysql如何忽略表明的大小写?
找到你mysql的配置文件,
找到“[mysqld]”节点,
在下面加上一句话:
lower_case_table_names=1
即可,重启mysql,就不用担心表名的大小写问题了。
19.having和where的区别?
having是在分组后对数据进行过滤,where是在分组前对数据进行过滤,
having后面可以使用聚合函数,where后面不可以使用聚合函数
在查询过程中执行顺序:from>where>group(含聚合)>having>order>select
20.游标的作用和使用?
游标实际上是一种能从包括多条数据记录的结果集中每次提取一条记录的机制。游标充当指针的作用。尽管游标能遍历结果中的所有行,但他一次只指向一行。
游标可以被看作是一个查询结果集和结果集中指向特定记录的游标位置组成的一个临时文件,提供了在查询结果集中向前或向后浏览数据、处理结果集中数据的能力
1 作用: 用来存储查询结果集的
2 使用: 遍历游标中的数据, 相当于有一个指针指向游标中的第一行数据,每获取一行记录,指针向下移一行
3 语法格式
1 声明游标
1 格式
declare cursor_name cursor for select_statement
2 格式介绍
1 cursor_name:游标名称,存储sql语句执行的结果
2 select_statement:sql语句
2 打开游标
1 格式
open cursor_name;
3 遍历游标中的数据
1 介绍
1 相当于有一个指针指向游标中的第一行数据,每获取一行记录,指针向下移一行
2 格式
fetch cursor_name into var_name [, var_name] ...
3 格式介绍
1 一行fetch只能获取游标中的一行记录,并把记录中每一列的值赋值给var_name
2 一个var_name保存一行记录中一个列的值,若有多个列,需要多个变量
3 要输出游标中的所有数据,需要使用循环语句
4 关闭游标
1 格式
close cursor_name;
MS SQL SERVER 支持三种类型的游标:Transact_SQL 游标,API 服务器游标和客户游标。
游标是一段私有的SQL工作区,也就是一段内存区域,用于暂时存放受SQL语句影响到的数据。通俗理解就是将受影响的数据暂时放到了一个内存区域的虚表中,而这个虚表就是游标。 游标是一种能从包括多条数据记录的结果集中每次提取一条记录的机制。即游标用来逐行读取结果集。游标充当指针的作用。尽管游标能遍历结果中的所有行,但他一次只指向一行。概括来讲,SQL的游标是一种临时的数据库对象,即可以用来存放在数据库表中的数据行副本,也可以指向存储在数据库中的数据行的指针。游标的一个常见用途就是保存查询结果,以便以后使用。游标的结果集是由SELECT语句产生,如果处理过程需要重复使用一个记录集,那么创建一次游标而重复使用若干次,比重复查询数据库要快的多。
游标cursor,主要用于循环处理结果集。 存储Select的查询结果,并用来遍历。游标总是与一条SQL 选择语句相关联因为游标由结果集(可以是零条、一条或由相关的选择语句检索出的多条记录)和结果集中指向特定记录的游标位置组成。
游标是系统为用户开设的一个数据缓冲区,存放SQL语句的执行结果
每个游标区都有一个名字
用户可以用SQL语句逐一从游标中获取记录,并赋给主变量,交由主语言进一步处理
主语言是面向记录的,一组主变量一次只能存放一条记录
仅使用主变量并不能完全满足SQL语句向应用程序输出数据的要求
嵌入式SQL引入了游标的概念,用来协调这两种不同的处理方式
PLSQL中显式游标使用的4个步骤 创建-打开-提取-关闭
本例简单介绍一下游标处理的4个过程中涉及到的加锁,一致性读的问题.
显式游标处理需四个 PL/SQL步骤:
1 定义/声明游标:就是定义一个游标名,以及与其相对应的SELECT 语句。
格式:
CURSOR cursor_name
IS
select_statement;
2 打开游标:就是执行游标所对应的SELECT 语句,将其查询结果放入工作区,并且指针指向工作区的首部,标识游标结果集合。如果游标查询语句中带有FOR UPDATE选项,OPEN 语句还将锁定 数据库表中游标结果集合对应的数据行。
格式:
OPEN cursor_name[([parameter =>] value[, [parameter =>] value]…)];
在向游标传递参数时,可以使用与函数参数相同的传值方法,即位置表示法和名称表示法。PL/SQL 程序不能用OPEN 语句重复打开一个游标。
3 提取游标数据:就是检索结果集合中的数据行,放入指定的输出变量中。
FETCH cursor_name INTO {variable_list | record_variable };
执行FETCH语句时,每次返回一个数据行,然后自动将游标移动指向下一个数据行。当检索到最后一行数据时,如果再次执行FETCH语句,将操作失败,并将游标属性%NOTFOUND置为TRUE。所以每次执行完FETCH语句后,检查游标属性%NOTFOUND就可以判断FETCH语句是否执行成功并返回一个数据行,以便确定是否给对应的变量赋了值。
4关闭游标:当提取和处理完游标结果集合数据后,应及时关闭游标,以释放该游标所占用的系统资源,并使该游标的工作区变成无效,不能再使用FETCH 语句取其中数据。关闭后的游标可以使用OPEN 语句重新打开。
格式:
CLOSE cursor_name;
作用: 用来存储查询结果集
使用:
1 声明游标
2 打开游标
3 遍历游标中的数据
4 关闭游标
21.如何使用数据库中的定时器、触发器、定时任务?
如何使用数据库中的定时器
1.开启mysql数据库的event功能
2.创建一个要执行的代码块。
3.创建一个事件,设置执行时间间隔
4.去修改这个事件的属性为开启。
触发器
create trigger trigger_name trigger_time trigger_event on tabl_name for each row trigger_stmt
trigger_name标识触发器名称
trigger_time标识触发时机,
trigger_event标识触发事件
tbl_name标识建立触发器的表名
trigger_stmt是触发器程序体
定时任务
创建计划任务
create event if not exists testinsert
on schedule every 3 second
on completion preserve
do insert into aa('name',sex) values('aa',2),('bb',1);
开启计划任务
alter event testinsert enable;
关闭计划任务
alter event testinsert disable;
22.oracle中如何实现实现递归查询?
在oracle中使用 start with 条件一
connect by prior 条件二
where 条件三
23.高并发下如何保证修改数据库安全?
乐观锁 悲观锁 Synchronized Lock
24.oracle中如何实现主键自增?
Oracle里的序列(sequence),可间接实现自增主键的作用
25.delete误删数据没有备份怎么恢复?
使用数据库闪回
得到一个当前序列号
可以慢慢减序列号,直到你能查询到数据.
26.oracle死锁如何处理?
1.查看数据库中那些用户产生了锁
2.杀掉oracle进程:
3.查找并杀死死锁的进程