mysql内置
1、视图、使用场景
视图是一种虚拟的表,具有和物理表相同的功能。可以对视图进行增,改,查,操作,
视图通常是有一个表或者多个表的行或列的子集。
对视图的修改会影响基本表。
它使得我们获取数据更容易,相比多表查询。
视图的优缺点
优点:
1)对数据库的访问,因为视图可以有选择性的选取数据库里的一部分。
2 )用户通过简单的查询可以从复杂查询中得到结果。
3 )维护数据的独立性,试图可从多个表检索数据。
4 )对于相同的数据可产生不同的视图。
缺点:
1)性能:查询视图时,必须把视图的查询转化成对基本表的查询,
如果这个视图是由一个复杂的多表查询所定义,那么,那么就无法更改数据
2)强耦合 :我们程序中使用的sql过分依赖数据库中的视图
如下两种场景一般会使用到视图:
(1)不希望访问者获取整个表的信息,只暴露部分字段给访问者,所以就建一个虚表,就是视图。
(2)查询的数据来源于不同的表,而查询者希望以统一的方式查询,这样也可以建立一个视图,把多个表查询结果联合起来,查询者只需要直接从视图中获取数据,不必考虑数据来源于不同表所带来的差异。
注:这个视图是在数据库中创建的 而不是用代码创建的。
SQL语句
#语法: CREATE VIEW 视图名称 AS SQL语句
create view course_view as select * from course; #创建表course的视图
2、游标
游标实际上是一种能从包括多条数据记录的结果集中每次提取一条记录进行处理的机制。
游标是对查询出来的结果集作为一个单元来有效的处理。
游标可以定在该单元中的特定行,从结果集的当前行检索一行或多行。
可以对结果集当前行做修改。
一般不使用游标,但是需要逐条处理数据的时候,游标显得十分重要。
3、什么是存储过程?有哪些优缺点?
存储过程包含了一系列预编译可执行的sql语句,
存储过程存放于MySQL中,通过调用它的名字可以执行其内部的一堆sql
更加直白的理解:
存储过程可以说是一个记录集,它是由一些T-SQL语句组成的代码块,
这些T-SQL语句代码像一个方法一样实现一些功能(对单表或多表的增删改查),
然后再给这个代码块取一个名字,在用到这个功能的时候调用他就行了。
使用存储过程的优点:
- 一个存储过程替代大量T_SQL语句 ,实现程序与sql解耦
- 存储过程是预编译过的一个代码块,执行效率高。
- 基于网络传输,传别名的数据量小,而直接传sql数据量大
- 一定程度上确保数据安全,执行存储过程需要有一定权限的用户。
缺点
- 程序员扩展功能不方便
- 移植性差
程序与数据库结合使用的三种方式
#方式一:
MySQL:存储过程
程序:调用存储过程
#方式二:
MySQL:
程序:纯SQL语句
#方式三:
MySQL:
程序:类和对象,即ORM(本质还是纯SQL语句)
使用存储过程
# 创建存储过程
delimiter //
create procedure p3(
in n1 int,
out res int
)
BEGIN
select * from blog where id > n1;
set res = 1;
END //
delimiter ;
#在mysql中调用
set @res=0; #0代表假(执行失败),1代表真(执行成功)
call p3(3,@res);
select @res;
#在python中基于pymysql调用
cursor.callproc('p3',(3,0)) #0相当于set @res=0
print(cursor.fetchall()) #查询select的查询结果
cursor.execute('select @_p3_0,@_p3_1;') #@p3_0代表第一个参数,@p3_1代表第二个参数,即返回值
print(cursor.fetchall())
4、什么是触发器?
触发器是一中特殊的存储过程,主要是通过事件来触发而被执行的。
它可以强化约束,来维护数据的完整性和一致性,可以跟踪数据库内的操作从而不允许未经许可的更新和变化。
可以联级运算。如,某表上的触发器上包含对另一个表的数据操作,而该操作又会导致该表触发器被触发。
使用触发器可以定制用户对表进行【增、删、改】操作时前后的行为,注意:没有查询
触发器无法由用户直接调用,而知由于对表的【增/删/改】操作被动引发的。
#创建触发器
delimiter //
CREATE TRIGGER tri_after_insert_cmd AFTER INSERT ON cmd FOR EACH ROW
BEGIN
IF NEW.success = 'no' THEN #等值判断只有一个等号
INSERT INTO errlog(err_cmd, err_time) VALUES(NEW.cmd, NEW.sub_time) ; #必须加分号
END IF ; #必须加分号
END//
delimiter ;
触发器的作用?
触发器是一中特殊的存储过程,主要是通过事件来触发而被执行的。
它可以强化约束,来维护数据的完整性和一致性,可以跟踪数据库内的操作从而不允许未经许可的更新和变化。可以联级运算。
如,某表上的触发器上包含对另一个表的数据操作,而该操作又会导致该表触发器被触发。
5、事务:存储过程实现
事务(Transaction)是并发控制的基本单位。
所谓的事务,将某些操作的多个SQL作为原子性操作,这些操作要么都执行,要么都不执行,它是一个不可分割的工作单位。一旦有某一个出现错误,即可回滚到原来的状态,从而保证数据库数据完整性。
比如银行转账就是事务的典型场景。
四大特性
- 原子性是指事务包含的所有操作要么全部成功,要么全部失败回滚,
- 一致性是指一个事务执行之前和执行之后都必须处于一致性状态。 事务前后,数据总额一致
- 隔离性是当多个用户并发访问数据库时,比如操作同一张表时,数据库为每一个用户开启的事务,不能被其他事务的操作所干扰,多个并发事务之间要相互隔离。
- 持久性是指一个事务一旦被提交了,那么对数据库中的数据的改变就是永久性的,即便是在数据库系统遇到故障的情况下也不会丢失提交事务的操作。
据库事务的三个常用命令
Begin Transaction、Commit Transaction、RollBack Transaction。
6、锁:
在DBMS中,锁是实现事务的关键,锁可以保证事务的完整性和并发性。与现实生活中锁一样,它可以使某些数据的拥有者,在某段时间内不能使用某些数据或数据结构。当然锁还分级别的。
乐观锁,自己实现,通过版本号
悲观锁:共享锁,多个事务,只能读不能写,加 lock in share mode
排它锁,一个事务,只能写,for update
行锁
数据库的乐观锁和悲观锁是什么?
数据库管理系统(DBMS)中的并发控制的任务是确保在多个事务同时存取数据库中同一数据时不破坏事务的隔离性和统一性以及数据库的统一性。
乐观并发控制(乐观锁)和悲观并发控制(悲观锁)是并发控制主要采用的技术手段。
- 悲观锁:假定会发生并发冲突,屏蔽一切可能违反数据完整性的操作
- 乐观锁:假设不会发生并发冲突,只在提交操作时检查是否违反数据完整性。
7、索引
索引是什么??
数据库索引,是数据库管理系统中一个排序的数据结构,以协助快速查询、更新数据库表中数据。
索引相当于字典的音序表,如果要查某个字,如果不使用音序表,则需要从几百页中逐页去查。
在数据之外,数据库系统还维护着满足特定查找算法的数据结构,这些数据结构以某种方式引用(指向)数据,这样就可以在这些数据结构上实现高级查找算法。这种数据结构,就是索引。
**索引有B+索引和hash索引,各自的区别 **
hash索引,等值查询效率高,
不能排序
不能进行范围查询
B+索引
数据有序
范围查询
索引的实现通常使用B树及其变种B+树。
B+树是通过二叉查找树,再由平衡二叉树,B树演化而来。
为表设置索引要付出代价的:
一是增加了数据库的存储空间,
二是在插入和修改数据时要花费较多的时间(因为索引也要随之变动)。
创建索引可以大大提高系统的性能(优点):
- 通过创建唯一性索引,可以保证数据库表中每一行数据的唯一性。
- 可以大大加快数据的检索速度,这也是创建索引的最主要的原因。
- 可以加速表和表之间的连接,特别是在实现数据的参考完整性方面特别有意义。
- 在使用分组和排序子句进行数据检索时,同样可以显著减少查询中分组和排序的时间。
- 通过使用索引,可以在查询的过程中,使用优化隐藏器,提高系统的性能。
增加索引也有许多不利的方面:
- 创建索引和维护索引要耗费时间,这种时间随着数据量的增加而增加。
- 索引需要占物理空间,除了数据表占数据空间之外,每一个索引还要占一定的物理空间,如果要建立聚簇索引,那么需要的空间就会更大。
- 当对表中的数据进行增加、删除和修改的时候,索引也要动态的维护,这样就降低了数据的维护速度。
什么时候【要】创建索引
-(1)表经常进行 SELECT 操作
- (2)表很大(记录超多),记录内容分布范围很广
- (3)列名经常在 WHERE 子句或连接条件中出现
什么时候【不要】创建索引
- (1)表经常进行 INSERT/UPDATE/DELETE 操作
- (2)表很小(记录超少)
- (3)列名不经常作为连接条件或出现在 WHERE 子句中
一般来说,应该在这些列上创建索引:
(1)在经常需要搜索的列上,可以加快搜索的速度;
(2)在作为主键的列上,强制该列的唯一性和组织表中数据的排列结构;
(3)在经常用在连接的列上,这些列主要是一些外键,可以加快连接的速度;
(4)在经常需要根据范围进行搜索的列上创建索引,因为索引已经排序,其指定的范围是连续的;
(5)在经常需要排序的列上创建索引,因为索引已经排序,这样查询可以利用索引的排序,加快排序查询时间;
(6)在经常使用在WHERE子句中的列上面创建索引,加快条件的判断速度。
有些列不应该创建索引:
- 对于那些在查询中很少使用或者参考的列不应该创建索引。
- 对于那些只有很少数据值的列也不应该增加索引。
- 对于那些定义为text, image和bit数据类型的列不应该增加索引
- 当修改性能远远大于检索性能时,不应该创建索引。
使用索引查询一定能提高查询的性能吗?为什么
通常,通过索引查询数据比全表扫描要快.但是我们也必须注意到它的代价.
索引需要空间来存储,也需要定期维护, 每当有记录在表中增减或索引列被修改时,索引本身也会被修改.
这意味着每条记录的INSERT,DELETE,UPDATE将为此多付出4,5 次的磁盘I/O.
因为索引需要额外的存储空间和处理,那些不必要的索引反而会使查询反应时间变慢.
使用索引查询不一定能提高查询性能,
索引范围查询(INDEX RANGE SCAN)适用于两种情况:
- 基于一个范围的检索,一般查询返回结果集小于表中记录数的30%
- 基于非唯一性索引的检索
#方式一
create table t1(
id int,
name char,
age int,
sex enum('male','female'),
unique key uni_id(id),
index ix_name(name) #index没有key
);
#方式二
create index ix_age on t1(age);
#方式三
alter table t1 add index ix_sex(sex);
sql语句
1、说一说三个范式。
第一范式(1NF):数据库表中的字段都是单一属性的,不可再分。
学生信息表,有姓名、年龄、性别、学号等信息组成
第二范式(2NF):满足第一范式,表中的字段必须完全依赖于全部主键而非部分主键。
要有主键,要求其他字段都依赖于主键。
第三范式(3NF):满足第二范式,非主键外的所有字段必须互不依赖
就是数据只在一个地方存储,不重复出现在多张表中,可以认为就是消除传递依赖
消除传递依赖,方便理解,可以看做是“消除冗余”。
所谓传递函数依赖,指的是如 果存在"A → B → C"的决定关系,则C传递函数依赖于A。
2、drop、delete与truncate
简单说一说区别
SQL中的drop、delete、truncate都表示删除,但是三者有一些差别
- delete和truncate只删除表的数据不删除表的结构
- 速度,一般来说: drop> truncate >delete
- delete语句是dml,这个操作会放到rollback segement中,事务提交之后才生效;如果有相应的trigger,执行的时候将被触发.
- truncate,drop是ddl, 操作立即生效,原数据不放到rollback segment中,不能回滚. 操作不触发trigger.
- 安全性:小心使用drop 和truncate,尤其没有备份的时候 ,不可回滚
分别在什么场景之下使用?
- 不再需要一张表的时候,用drop
- 想删除部分数据行时候,用delete,并且带上where子句
- 保留表而删除所有数据的时候用truncate
3、列举几种表连接方式,有什么区别?
- 内联接(Inner Join):匹配2张表中相关联的记录。
- 左外联接(Left Outer Join):除了匹配2张表中相关联的记录外,还会匹配左表中剩余的记录,右表中未匹配到的字段用NULL表示。
- 右外联接(Right Outer Join):除了匹配2张表中相关联的记录外,还会匹配右表中剩余的记录,左表中未匹配到的字段用NULL表示。
- 全外连接:连接的表中不匹配的数据全部会显示出来。
- 交叉连接: 笛卡尔效应,显示的结果是链接表数的乘积。
4. 什么是数据库约束,常见的约束有哪几种?
数据库约束用于保证数据库表数据的完整性(正确性和一致性)。可以通过定义约束索引触发器来保证数据的完整性。
主键约束:primary key;
外键约束:foreign key;
唯一约束:unique;
检查约束:check;
空值约束:not null;
默认值约束:default;
5、如何描述多对多的关系?
在关系型数据库中描述多对多的关系,需要建立第三张数据表。
比如学生选课,需要在学生信息表和课程信息表的基础上,再建立选课信息表,该表中存放学生Id和课程Id。
6、 列举几种常用的聚合函数?
Sum:求和 Avg:求平均数 Max:求最大值 Min:求最小值 Count:求记录数
7、 超键、候选键、主键、外键分别是什么?
超键:在关系中能唯一标识元组的属性集称为关系模式的超键。
一个属性可以为作为一个超键,多个属性组合在一起也可以作为一个超键。
超键包含候选键和主键。
候选键:是最小超键,即没有冗余元素的超键。
主键:数据库表中对储存数据对象予以唯一和完整标识的数据列或属性的组合。
一个数据列只能有一个主键,且主键的取值不能缺失,即不能为空值(Null)。
外键:在一个表中存在的另一个表的主键称此表的外键。
8、 SELECT语句关键字顺序
定义顺序
SELECT DISTINCT <select_list>
FROM <left_table>
<join_type> JOIN <right_table>
ON <join_condition>
WHERE <where_condition>
GROUP BY <group_by_list>
HAVING <having_condition>
ORDER BY <order_by_condition>
LIMIT <limit_number>
执行顺序
(7) SELECT
(8) DISTINCT <select_list>
(1) FROM <left_table>
(3) <join_type> JOIN <right_table>
(2) ON <join_condition>
(4) WHERE <where_condition>
(5) GROUP BY <group_by_list>
(6) HAVING <having_condition>
(9) ORDER BY <order_by_condition>
(10) LIMIT <limit_number>
查询来自杭州,并且订单数少于2的客户。
select a.customer_id, count(b.order_id) as total_orders
from table1 as a left join table2 as b
on a.customer_id = b.customer_id
where a.city = 'hangzhou'
group by a.customer_id
having count(b.order_id) < 2
order by total_orders desc
limit 1;
数据库优化的思路
1、在数据库中查询语句速度很慢,如何优化?
1.建索引
2.减少表之间的关联
3.优化sql,尽量让sql很快定位数据,不要让sql做全表查询,应该走索引,把数据 量大的表排在前面
4.简化查询字段,没用的字段不要,尽量返回少量数据
5.尽量用PreparedStatement来查询,不要用Statement
2、数据库优化的思路
1.SQL语句优化
1)应尽量避免在 where 子句中使用!=或<>操作符,否则将引擎放弃使用索引而进行全表扫描。
2)应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索引而进行全表扫描, 如:select id from t where num is null
可以在num上设置默认值0,确保表中num列没有null值,然后这样查询:
select id from t where num=0
3)很多时候用 exists 代替 in 是一个好的选择
4)用Where子句替换HAVING 子句 因为HAVING 只会在检索出所有记录之后才对结果集进行过滤
2.索引优化
看上文索引
3.数据库结构优化
1)范式优化: 比如消除冗余(节省空间。。)
2)反范式优化:比如适当加冗余等(减少join)
3)拆分表: 分区将数据在物理上分隔开,不同分区的数据可以制定保存在处于不同磁盘上的数据文件里。这样,当对这个表进行查询时,只需要在表分区中进行扫描,而不必进行全表扫描,明显缩短了查询时间,另外处于不同磁盘的分区也将对这个表的数据传输分散在不同的磁盘I/O,一个精心设置的分区可以将数据传输对磁盘I/O竞争均匀地分散开。对数据量大的时时表可采取此方法。可按月自动建表分区。
4)拆分其实又分垂直拆分和水平拆分:
4.服务器硬件优化
3、面试回答数据库优化问题从以下几个层面入手
(1)、根据服务层面:配置mysql性能优化参数;
(2)、从系统层面增强mysql的性能:优化数据表结构、字段类型、字段索引、分表,分库、读写分离等等。
(3)、从数据库层面增强性能:优化SQL语句,合理使用字段索引。
(4)、从代码层面增强性能:使用缓存和NoSQL数据库方式存储,如MongoDB/Memcached/Redis来缓解高并发下数据库查询的压力。
(5)、减少数据库操作次数,尽量使用数据库访问驱动的批处理方法。
(6)、不常使用的数据迁移备份,避免每次都在海量数据中去检索。
(7)、提升数据库服务器硬件配置,或者搭建数据库集群。
(8)、编程手段防止SQL注入:使用JDBC PreparedStatement按位插入或查询;正则表达式过滤(非法字符串过滤);
4、SQL常用命令:
CREATE TABLE Student(
ID NUMBER PRIMARY KEY,
NAME VARCHAR2(50) NOT NULL); //建表
CREATE VIEW view_name AS Select * FROM Table_name; //建视图
Create UNIQUE INDEX index_name ON TableName(col_name); //建索引
INSERT INTO tablename {column1,column2,…} values(exp1,exp2,…); //插入
INSERT INTO Viewname {column1,column2,…} values(exp1,exp2,…); //插入视图实际影响表
UPDATE tablename SET name='zang 3' condition; //更新数据
DELETE FROM Tablename WHERE condition; //删除
GRANT (Select,delete,…) ON (对象) TO USER_NAME [WITH GRANT OPTION]; //授权
REVOKE (权限表) ON(对象) FROM USER_NAME [WITH REVOKE OPTION] //撤权
5、关系型非关系型
比如 有一个学生的数据:
姓名:张三,性别:男,学号:12345,班级:二年级一班
还有一个班级的数据:
班级:二年级一班,班主任:李四
数据库 类型 | 特性 | 优点 | 缺点 |
---|---|---|---|
关系型数据库 SQLite、Oracle、mysql | 1、关系型数据库,是指采用了关系模型来组织 数据的数据库; 2、关系型数据库的最大特点就是事务的一致性; 3、简单来说,关系模型指的就是二维表格模型, 而一个关系型数据库就是由二维表及其之间的联系所组成的一个数据组织。 | 1、容易理解:二维表结构是非常贴近逻辑世界一个概念,关系模型相对网状、层次等其他模型来说更容易理解; 2、使用方便:通用的SQL语言使得操作关系型数据库非常方便; 3、易于维护:丰富的完整性(实体完整性、参照完整性和用户定义的完整性)大大减低了数据冗余和数据不一致的概率; 4、支持SQL,可用于复杂的查询。 | 1、为了维护一致性所付出的巨大代价就是其读写性能比较差; 2、固定的表结构; 3、高并发读写需求; 4、海量数据的高效率读写; |
非关系型数据库 MongoDb、redis、HBase | 1、使用键值对存储数据; 2、分布式; 3、一般不支持ACID特性; 4、非关系型数据库严格上不是一种数据库,应该是一种数据结构化存储方法的集合。 | 1、无需经过sql层的解析,读写性能很高; 2、基于键值对,数据没有耦合性,容易扩展; 3、存储数据的格式:nosql的存储格式是key,value形式、文档形式、图片形式等等,文档形式、图片形式等等,而关系型数据库则只支持基础类型。 | 1、不提供sql支持,学习和使用成本较高; 2、无事务处理,附加功能bi和报表等支持也不好; |
6、MYSQL的两种存储引擎区别(事务、锁级别等等),各自的适用场景
MYISAM 不支持事务,不支持外键,表锁,插入数据时,锁定整个表,查表总行数时,不需要全表扫描
INNODB 支持事务,支持外键,行锁,查表总行数时,全表扫描