1.sql优化有哪些?如何创建索引?创建索引的原则是什么?索引的优缺点?(索引失效的几种情况)
1、在表中建立索引,优先考虑where、group by使用到的字段(较频繁地作为查询条件且唯一性不太差),不会在where中用到的字段不建立索引,因为建立索引也需要系统的开销。
2、减少使用 * ,用列名代替
select * from user;
要写成 select userID, userName, userSalary from user;
因为在使用 * 的时候,数据库还得查询数据字典,进而解析得到列名,而直接写出列名效率会更高些。
3、避免在开头使用模糊查询(%),该查询数据库引擎会放弃索引进行全表扫描。
4、需要删除所有记录的时候,用truncate而不用detele
因为delete删除表的时候,会扫描整个表再一条一条删除;
而truncate会一次性删除整个表的所有内容,不进行扫描,效率高。
5、避免使用in和not in,会导致全表扫描
优化方式:如果是连续数值,用between代替;如果是子查询,用exists代替。
6、如果表名或列名过长,就使用别名,因为长的表名和列名也会消耗扫描时间。
如何创建索引?
建表时创建:
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 索引方法];
创建索引的原则是什么?
在mysql中使用索引的原则有以下几点:
1、 对于查询频率高的字段创建索引;
2、 索引的数目不宜太多
原因:a、每创建一个索引都会占用相应的物理空间;
b、过多的索引会导致insert、update、delete语句的执行效率降低;
3. 对于经常存取的列避免建立索引;
因为,修改性能和检索性能是互相矛盾的。当增加索引时,会提高检索性能,但是会降低修改性能。当减少索引时,会提高修改性能,降低检索性能.因为更新表时,MySQL不仅要保存数据,还要保存一下索引文件。因此,当修改性能远远大于检索性能时,不应该创建索引。
MySQL中索引的优点和缺点和使用原则
优点:
加快数据的查询速度
缺点:
创建索引会耗费时间和占用磁盘空间,并且随着数据量的增加所耗费的时间也会增加
2.sql如何去重?
mysql去除重复查询的方法:1、使用distinct,代码为【select distinct name from a where statesign=0】;2、使用group by,代码为【statesign=0 group by .】。
mysql去除重复查询的方法:
1:使用distinct
select distinct name from a where statesign=0
查询表a中的name字段,去除重复记录
2:使用group by
select name from a where statesign=0 group by name
查询表a中的name字段,分组,去除重复记录
内连接和外连接的区别?
内连接:指连接结果仅包含符合连接条件的行,参与连接的两个表都应该符合连接条件。
外连接:连接结果不仅包含符合连接条件的行同时也包含自身不符合条件的行。包括左外连接、右外连接和全外连接。
左外连接:左边表数据行全部保留,右边表保留符合连接条件的行。
右外连接:右边表数据行全部保留,左边表保留符合连接条件的行。
4.Java中何使用 Redis? Redis支持的数据类型及各数据类型的使用场景? redis如何解决数据过期?
1.在pom.xml引入redis依赖包
<!--SpringBoot在pom.xml中引入redis依赖包 重要!!!! --><!--redis --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency>
2.在application.properties中配置redis
##redis settings##本地连接spring.redis.host=127.0.0.1##使用默认端口spring.redis.port=6379##未设密码,默认pwd为空spring.redis.password=
配置RestTemplate 的序列化方式
Redis支持的数据类型及各数据类型的使用场景?
string
此类型和memcache相似,作为常规的key-value缓存应用。
例如微博数、粉丝数等
注:一个键最大能存储512MB
list
list列表是简单的字符串列表,按照插入顺序排序(内部实现为LinkedList),可以选择将一个链表插入到头部或尾部
常用命令 :lpush(添加左边元素),rpush,lpop(移除左边第一个元素),rpop,lrange(获取列表片段,LRANGE key start stop)等。
应用场景:Redis list的应用场景非常多,也是Redis最重要的数据结构之一,比如twitter的关注列表,粉丝列表等都可以用Redis的list结构来实现。
zset
常用命令:zadd,zrange
实现方式:Redis sorted set的内部使用HashMap和跳跃表(SkipList)来保证数据的存储和有序,HashMap里放的是成员到score的映射,跳跃表按score从小到大保存所有集合元素。使用跳跃表的结构可以获得比较高的查找效率,并且在实现上比较简单。时间复杂度与红黑树相同,增加、删除的操作较为简单。
输入方式
应用场景:排行榜
redis如何解决数据过期?(如何持久化到硬盘)
在 Redis 中,是可以设置过期数据的,Redis 提供了两种的方式,用于删除过期的数据!
定期删除
惰性删除
Redis 默认 100ms 随即抽取部分设置过期时间的 key,过期了就删除。优点是避免长时间的在扫描过期 key,缺点是有些过期 key 无法被删除。
不扫描全部 key 的原因是,当设置了过期时间的 key 太多的情况下,会很耗时间,O(n) 的时间复杂度。
如果查询了某个过期 key,但定期删除没有删除掉,那就将其删除了。key 没过期就正常返回
如何持久化到硬盘
redis提供两种方式进行持久化,一种是RDB持久化
RDB持久化是指在指定的时间间隔内将内存中的数据集快照写入磁盘
AOF持久化以日志的形式记录服务器所处理的每一个写、删除操作,查询操作不会记录,以文本的方式记录,可以打开文件看到详细的操作记录。
5.数据库表的设计注意事项有哪些?三大范式的了解?
表设计:
1、 数据库表命名,将业务和基础表区分,采用驼峰表示法等。
2、 排序字段,按照某种类型来排序(sortcode)最好不依赖id排序,这样方便我们查询记录时按照某种方式排序,而不依赖id。
3、 增加备注字段,虽然我们考虑了很多用户需要输入信息的需求,但是无论何时我们都不可能考虑全,因此可以定义一个备注字段,允许用户将其它的信息填写在这里。无论表设计的再神奇,那么还是加一个备注字段。
4、 添加时间,有添加时间可以明确知道记录什么时候添加的。
5、 修改时间,可以知道记录什么时候被修改了,一旦数据出现问题,可以根据修改时间来定位问题。比如某人在这个时间做了哪些事。
数据库的三范式是什么?
第一范式:强调的是列的原子性,即数据库表的每一列都是不可分割的原子数据项。
第二范式:要求实体的属性完全依赖于主关键字。所谓完全依赖是指不能存在仅依赖主关键字一部分的属性。
第三范式:任何非主属性不依赖于其它非主属性。
6.存储过程的了解和使用?
存储过程的概念
存储过程(Stored Procedure)是一组为了完成特定功能的SQL语句集。经编译后存储在数据库中。
存储过程是数据库中的一个重要对象,用户通过指定存储过程的名字并给出参数(如果该存储过程带有参数)来执行它。
可由应用程序通过一个调用来执行,而且允许用户声明变量。
存储过程的使用
1、创建一个存储过程
create procedure GetUsers()
begin
select * from user;
end;12345
2、调用存储过程
call GetUsers();12
3、删除存储过程
drop procedure if exists GetUsers;
7.数据库如何实现分页?百万级量的数据分页查询如何优化?
Mysql:limit
Oracle:rownum
百万级量的数据分页查询如何优化?
利用表的覆盖索引来加速分页查询
我们都知道,利用了索引查询的语句中如果只包含了那个索引列(覆盖索引),那么这种情况会查询很快。
因为利用索引查找有优化算法,且数据就在查询索引上面,不用再去找相关的数据地址了,这样节省了很多时间。另外Mysql中也有相关的索引缓存,在并发高的时候利用缓存就效果更好了。
8.数据库的乐观锁和悲观锁的理解和使用?
乐观锁:每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在提交更新的时候会判断一下在此期间别人有没有去更新这个数据。
悲观锁:每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会阻止,直到这个锁被释放。
数据库的乐观锁需要自己实现,在表里面添加一个 version 字段,每次修改成功值加 1,这样每次修改的时候先对比一下,自己拥有的 version 和数据库现在的 version 是否一致,如果不一致就不修改,这样就实现了乐观锁。
使用悲观锁来实现:
在上面的场景中,商品信息从查询出来到修改,中间有一个处理订单的过程,使用悲观锁的原理就是,当我们在查询出goods信息后就把当前的数据锁定,直到我们修改完毕后再解锁。那么在这个过程中,因为goods被锁定了,就不会出现有第三者来对其进行修改了。
注:要使用悲观锁,我们必须关闭mysql数据库的自动提交属性,因为MySQL默认使用autocommit模式,也就是说,当你执行一个更新操作后,MySQL会立刻将结果进行提交。
我们可以使用命令设置MySQL为非autocommit模式:
set autocommit=0;
9.数据库中字符串和日期的相互转换?(oracle和mysql的日期如何转换,oracle如何分页)
1、使用date_format
select * from day where date_format(dateTime,'%Y-%m-%d') > '2016-03-15'
2、日期转换还可以使用str_to_date()
select str_to_date(dateTime,'%Y-%m-%d %H:%i:%s')
3、oracle是to_date
10. union和 unionall区别?
UNION 会做去重和排序处理,UNION ALL只是简单地将两个结果集合并;因此UNION 效率比UNION ALL慢很多,
11. mysql的存储引擎有哪些?
12.事务的隔离级别有哪些?mysql和 oracle默认的隔离级别是什么?
事务隔离级别
(1)read uncommitted 未提交读
所有事务都可以看到没有提交事务的数据。
(2)read committed 提交读
事务成功提交后才可以被查询到。
(3)repeatable 重复读
同一个事务多个实例读取数据时,可能将未提交的记录查询出来,而出现幻读。mysql默认级别
mysql和 oracle默认的隔离级别是什么?
MySQL
mysql默认的事务处理级别是'REPEATABLE-READ',也就是可重复读
Oracle
默认系统事务隔离级别是READ COMMITTED,也就是读已提交
13.mysql如何行转列和列转行
行转列:
1.使用case...when....then 进行行转列
CASE <单值表达式>
WHEN <表达式值> THEN <SQL语句或者返回值>
列转行:
本质是将一列数据分散成一条记录显示出来
用UNION ALL将结果集加起来
14.如何查看mysql的sql的执行计划?
可以通过(explain+执行sql)查看sql的执行计划
查看心法:
1.首先从查询类型type列开始查看,如果出现all关键字,那么不用继续看了,全表扫描了
2.查看key列,看是否使用了索引,null代表没有使用索引
3.查看rows列,该列代表在SQL执行过程中被扫描的行数,该数值越大,意味着需要扫描的行数越多,相应的耗时就更长
15. oracle中的分析函数有哪些?
--------------聚合函数
SUM :该函数计算组中表达式的累积和
MIN :在一个组中的数据窗口中查找表达式的最小值
MAX :在一个组中的数据窗口中查找表达式的最大值
AVG :用于计算一个组和数据窗口内表达式的平均值。
COUNT :对一组内发生的事情进行累积计数
16.数据库中除了聚合函数之外还有哪些常用的函数?
oracle数据库 merge()函数的作用和使用?
除了聚合函数之外还有哪些常用的函数
destinct(去除重复行)
to_char(转换自符串)
to_date(日期格式函数)
substr(截取自符串)
lower(将字母转换为小写)
upper(将字母转换为小写)
oracle数据库 merge()函数的作用和使用?
能够在一个SQL语句中对一个表同时执行inserts和updates操作. MERGE命令从一个或多个数据源中选择行来updating或inserting到一个或多个表
比如向数据库插入一条数据 如果ID和name都相同 就更新AGE的数据,否则就插入
17.sql中drop、 truncate、 delete的区别?
drop:drop table 表名
删除内容和定义,并释放空间。执行drop语句,将使此表的结构一起删除。
truncate (清空表中的数据):truncate table 表名
删除内容、释放空间但不删除定义(也就是保留表的数据结构)。与drop不同的是,只是清空表数据而已。
truncate不能删除行数据,虽然只删除数据,但是比delete彻底,它只删除表数据。
delete:delete from 表名 (where 列名 = 值)
与truncate类似,delete也只删除内容、释放空间但不删除定义;但是delete即可以对行数据进行删除,也可以对整表数据进行删除。
都删除整张表的话
TRUNCATE TABLE 速度更快,占用的日志更少,这是因为 TRUNCATE TABLE 直接释放数据页并且在事务日志中也只记录数据页的释放,而 DELETE 是一行一行地删除,在事务日志中要记录每一条记录的删除
18.mysql如何忽略表名的大小写?
找到你mysql的配置文件my.ini(linux下是my.cnf),打开后找到“[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;
21.如何使用数据库中的定时器、触发器、定时任务?
如何使用数据库中的定时器
create一个event on schedule 后跟时间
整体流程简介:
1.开启mysql数据库的event功能
2.创建一个类似于要执行的代码块。
3.创建一个事件,这个事件中有诸多属性,可以设置执行时间间隔以及指定执行的代码块
4.因为创建的事件的执行属性默认是关闭的,所以我们要去修改这个事件的属性为开启。
触发器
CREATE TRIGGER trigger_name trigger_time trigger_event
ON tbl_name FOR EACH ROW trigger_stmt
其中trigger_name标识触发器名称,用户自行指定;
trigger_time标识触发时机,用before和after替换;
trigger_event标识触发事件,用insert,update和delete替换;
tbl_name标识建立触发器的表名,即在哪张表上建立触发器;
trigger_stmt是触发器程序体;触发器程序可以使用begin和end作为开始和结束,中间包含多条语句;
定时任务
#创建计划任务
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没有”auto_increment”属性,所以它没法像MySQL般在表内定义自增主键。
但是Oracle里的序列(SEQUENCE),可间接实现自增主键的作用
25. delete误删数据没有备份怎么恢复?
可以使用数据库闪回
--得到一个当前序列号.
select dbms_flashback.get_system_change_number scn from dual;
--7827319是序列号
select * from table as of scn 7827319;
你可以慢慢减序列号,直到你能查询到数据.
例如, 我删除数据提交, Oracle会给这个操作一个序列号. 然后每一次操作都会生成序列号.
你用 as of scn 序列 查询时, 查询当时那个操作的数据情况.
26. oracle死锁如何处理?
--1.查看数据库中那些用户产生了锁
--2.杀掉ORACLE进程:
--3.查找并杀死死锁的进程