应届生面试要点总结(6)数据库相关

mysql引擎和区别

MyISAM存储引擎:不支持事务、也不支持外键,优势是访问速度快,对事务完整性没有要求,或者以select,insert为主的应用基本上可以用这个引擎来创建表。当执行insert和update时,执行写操作时,要锁定整个表,所以效率低。但它保存了表的行数,执行select count * from table时,不需全表扫描,而是直接读取保存的值。若读操作多于写操作,并且不需要事务,myisam是首选。非聚集索引。B+树

innodb该存储引擎提供了具有提交、回滚和崩溃恢复能力的事务安全。但是对比MyISAM引擎,写的处理效率会差一些,并且会占用更多的磁盘空间以保留数据和索引。InnoDB存储引擎的特点:支持自动增长列,支持外键约束。支持事务,行级锁,mysql运行时,innodb会在内存中建立缓冲池,用于缓冲数据和索引。不保存表的行数,执行select count * from table时要全表扫描。写不锁定全表,高并发时效率高。聚集索引。

Memory存储引擎使用存在于内存中的内容来创建表。

Merge存储引擎是一组MyISAM表的组合,这些MyISAM表必须结构完全相同,merge表本身并没有数据,对merge类型的表可以进行查询,更新,删除操作,这些操作实际上是对内部的MyISAM表进行的。

b-tree索引可以用于使用<<==>=>或者between运算符比较。如果like的参数是一个没有以通配符起始的常量字符串也可以使用这种索引。

Hash索引:只能用于使用=或<=>运算符的比较,不能用于有范围的运算符,因为键经过hash以后的值没有意义;优化器不能使用hash索引来加速order by操作,这种类型的索引不能用于按顺序查找下个条目;mysql无法使用hash索引来估计两个值之间有多少行;查找某行记录必须全键匹配,而且b-tree索引,任何该键的左前缀都可以用于查找记录;若一张myisam或innodb表换为hash索引的内存表,一些查询可能受影响。

mysql索引使用b+树数据结构。

索引:提高数据库访问速度的数据库对象,但有索引也不一定就会快。优点:索引可避免扫描全表;对于非聚集索引,有些查询甚至可以不访问数据项;聚集索引可以避免数据插入操作集中于表的最后一个数据页;一些情况下,索引还可以避免排序,适用于某范围内的数据。

扫描二维码关注公众号,回复: 5017271 查看本文章

虽然索引可以提高查询速度,但是他们会导致数据库更新性能下降,因为大部分数据更新时需要同时更新索引。索引要占用物理空间,除了数据表外每个索引还有占物理空间。

非聚集索引:数据库索引顺序存储,叶子节点存储真实数据行,不再有另外单独的数据页,有一个指针指向数据块。在一张表上只能创建一个聚集索引,因为真实数据的物理顺序只能用一种,若一张表没有聚集索引,则它被成为堆集,这样的表的数据行无特定的顺序,所有新行将被添加到表的末尾。

聚集索引:叶子节点并非数据节点;叶子节点为每一个真正的数据行存储一个“键-指针”对;叶子节点中还存储一个指针偏移量,根据页指针和指针偏移量可以定位到具体的数据行;在除叶节点外的其它索引节点,存储的是类似内容,只不过指向下一级索引页。

聚集索引是一种稀疏索引,数据页上一页的索引页存储的是页指针,不是行指针。对于非聚集索引,是密集索引,数据页的上一级索引为每一个数据行存储一条索引记录。

mysql分页查询:客户端通过传递start(页码),limit(每页显示的条数)两个参数去分页查询数据库中的数据。limit m,n从m+1条开始,取n条。查询第一条到第十条的是:select * from table limit 0, 10; 对应的就是第一页的数据。查询第10条到20条的是:select * from table limit 10, 10; 对应第二页。第三页:select * from table limit 20 ,10。总结select * from table limit (页数-1) * 每页条数,每页条数。

truncate 、delete与drop区别

1、truncate 和 delete 只删除数据不删除表的结构(定义)。drop 语句将删除表的结构被依赖的约束(constrain)、触发器(trigger)、索引(index);依赖于该表的存储过程/函数将保留,但是变为 invalid 状态。

2、delete 语句是数据库操作语言(dml),这个操作会放到 rollback segement 中,事务提交之后才生效;如果有相应的 trigger,执行的时候将被触发。truncate、drop 是数据库定义语言(ddl),操作立即生效,原数据不放到 rollback segment 中,不能回滚,操作不触发 trigger。

3、delete 语句不影响表所占用的 extent,高水线(high watermark)保持原位置不动,drop 语句将表所占用的空间全部释放。truncate 语句缺省情况下见空间释放到 minextents个 extent,除非使用reuse storage;truncate 会将高水线复位(回到最开始)。

4、速度,一般来说:drop> truncate > delete。

5、安全性,小心使用 drop 和 truncate,尤其没有备份的时候,否则哭都来不及。使用上,想删除部分数据行用 delete,注意带上where子句。回滚段要足够大。想删除表,当然用 drop,想保留表而将所有数据删除,如果和事务无关,用truncate即可。如果和事务有关,或者想触发trigger,还是用delete。如果是整理表内部的碎片,可以用truncate跟上reuse stroage,再重新导入/插入数据。

6、TRUNCATE TABLE在功能上与不带 WHERE 子句的 DELETE 语句相同:二者均删除表中的全部行。但 TRUNCATE TABLE 比 DELETE 速度快,且使用的系统和事务日志资源少。DELETE 语句每次删除一行,并在事务日志中为所删除的每行记录一项。TRUNCATE TABLE 通过释放存储表数据所用的数据页来删除数据,并且只在事务日志中记录页的释放。

7、TRUNCATE TABLE 删除表中的所有行,但表结构及其列、约束、索引等保持不变。新行标识所用的计数值重置为该列的种子。如果想保留标识计数值,请改用 DELETE。如果要删除表定义及其数据,请使用 DROP TABLE 语句。

8、对于由 FOREIGN KEY 约束引用的表,不能使用 TRUNCATE TABLE,而应使用不带 WHERE 子句的 DELETE 语句。由于 TRUNCATE TABLE 不记录在日志中,所以它不能激活触发器。

9、TRUNCATE TABLE 不能用于参与了索引视图的表。

事务(Transaction)是由一系列对系统中数据进行访问与更新的操作所组成的一个程序执行逻辑单元。数据库事务特性:A原子,C一致(如果两个以上数据表有关联,那么更新一个表同时另外一个表也要一起更新,否则两个表的数据记录就发生不一致了),I隔离(数据库允许多个并发事务同时对其数据进行读写和修改的能力,隔离性可以防止多个事务并发执行时由于交叉执行而导致数据的不一致),D持久。

在考虑事务的隔离级别之前,需要认识到如果不考虑事务的隔离性,会发生的异常情况:

脏读:一个事务读取了另外一个事务未提交的数据。(会对系统的并发处理带来很大的隐患)。

不可重复读:在同一个事务内,多次读同一个数据时,发现该数据已经被另一个已经提交的事务修改。(在一个事务内两次读到的数据时是不一样的)。

幻读:一个事务根据相同的查询条件,重新执行查询,返回的记录中包含与前一次执行查询返回的记录不同的行。

以上这三种情况都是同时进行的几个事务对相同的数据进行读取时造成的。

Read Uncommitted:最低等级的事务隔离,仅仅保证读取过程中不会读到非法数据。(三种异常情况均可能发生)。

Read Committed:避免了“脏读”。一个select查询只能查看到查询开始之前提交的数据。在查询执行时,其他事务修改或者提交的数据它看不到(数据库默认的事务隔离级别)。

Repeatable Read:避免了“脏读”和“不可重复读”。一个事务不可能更新由另一个事务读取但是没有提交的数据。应用并不广泛。因为它可能出现幻读。同时带来更多性能损失。

Serializable:ORACLE数据库只支持Read Committed 和Serializable两种隔离级别。另外自定义了一个Read Only的隔离级别,只允许读,不允许改。避免不可重复读和幻读。三种都能避免。所有事务串行,而不是并行。

public static void main(String[] args) throws SQLException {

Connection conn = null;

PreparedStatement st = null;

ResultSet rs = null;

try {

conn = JdbcUtils.getConnection();

conn.setAutoCommit(false); // 相当于start transaction,开启事务

String sql1 = "update account set money=money-100 where name='aaa'";

String sql2 = "update account set money=money+100 where name='bbb'";

st = conn.prepareStatement(sql1);

st.executeUpdate();

int x = 1/0; // 程序运行到这个地方抛异常,后面的代码就不执行,数据库没有收到commit命令

st = conn.prepareStatement(sql2);

st.executeUpdate();

conn.commit();

} catch (Exception e) {

e.printStackTrace();

conn.rollback(); // 捕获到异常之后手动通知数据库执行回滚事务的操作

} finally {

JdbcUtils.release(conn, st, rs);

}

}

范式:[1NF:原子性,属性不可分;2NF:非主键属性完全依赖于主键属性;3NF:非主键属性之间无传递依赖;4NF:主键属性间无传递依赖]。

JDBC中,链接操作是由driver manager管理,jdbc建立和关闭是及其消耗资源的,connection接口实现链接数据库。jdbc链接数据库分为4步:加载驱动class.forName("com.mysql.jdbc.Driver");创建链接connection con = DriverManager.getConnection(url, username, passwd);创建statement s = con.createStatement();执行sql s.executeQuery(String sql);

prepareStatement是预先编译的语句,statement不是防止sql注入性能提高。callableStatement:存储过程调用DatabaseMetaDate类的很多方法都可以知道数据库中存储过程的详情。

存储过程和函数:都是为了重复执行sql语句的集合,他们的区别:写法上:存储过程的参数列表可以有输入输出参数,函数的列表只能有输入参数。返回值:存储过程的返回值,可以有多个值,函数只能有一个。调用过程:存储过程1.exec<过程名>2.execute<过程名>3.在sql语句中直接调用。函数:在sql语句中直接调用。

游标用于定位结果集的行,通过判断全局变量@FETCH_STATUS,可以判断右表是否到达了最后,通常此变量不等于0表示出错或者到了最后。

事前触发器运行于触发事件之前,事后触发器运行于触发事件之后。语句级触发器:触发器只会在相应的语句执行前或执行后执行一次,行级触发器:该语句影响了几行,就要执行几次触发器。

执行查询时,若要查询的数据很多,假设1000W条,用什么方法提升查询效率。

从数据库方面:建立索引、分区、尽量使用固定长度的字段、限制字段长度。

从数据库io方面:增加缓冲区。在sql语句方面:优化sql语句,减少比较次数、限制返回的条目数。

在java方面:如果是反复使用的查询,使用preparedStatement。

数据库连接池的工作机制:j2ee服务器启动时会建立一定数量的连接,并一直维护不少与此数目的池连接。客户端程序需要连接时,池驱动程序就会返回一个未使用的池连接并将其标记为忙。若当前没有空闲连接,池驱动程序就建立一定数量的连接,新建链接数量由配置参数决定。当使用的池连接调用完成后,池驱动程序将此连接标记为空闲,其他调用就可以使用这个连接。

数据库连接池技术带来的优势:

1. 资源重用:由于数据库连接得到重用,避免了频繁创建、释放连接引起的大量性能开销。在减少系统消耗的基础上,另一方面也增进了系统运行环境的平稳性(减少内存碎片以及数据库临时进程/线程的数量)。

2. 更快的系统响应速度:数据库连接池在初始化过程中,往往已经创建了若干数据库连接置于池中备用。此时连接的初始化工作均已完成。对于业务请求处理而言,直接利用现有可用连接,避免了数据库连接初始化和释放过程的时间开销,从而缩减了系统整体响应时间。

3. 新的资源分配手段:对于多应用共享同一数据库的系统而言,可在应用层通过数据库连接的配置,实现数据库连接池技术,几年钱也许还是个新鲜话题,对于目前的业务系统而言,如果设计中还没有考虑到连接池的应用,那么…….快在设计文档中加上这部分的内容吧。某一应用最大可用数据库连接数的限制,避免某一应用独占所有数据库资源。

4. 统一的连接管理,避免数据库连接泄漏:在较为完备的数据库连接池实现中,可根据预先的连接占用超时设定,强制收回被占用连接。从而避免了常规数据库连接操作中可能出现的资源泄漏。

一般来说,应该在这些列上加索引:经常需要搜索的列,加快搜索速度;作为主键的列,强制该列的唯一性;在经常用连接的列上,这些列主要是外键,可以加快连接速度;在经常需要根据范围进行搜索的列上创建索引,因为索引已经排序,指定的范围是连续的;在经常需要排序的列上。

唯一索引:不允许其中任何两行有相同的值。主键索引:为表定义主键自动创建主键索引,是唯一索引的特定类型。聚集索引:b-树中一次检索最多需要h-1次io(根据节点常驻内存,h为树的高度),一般用磁盘io来评价所有的优劣,b树中一个索引对应一页,所以一个node只要一次io。

下列事件索引会失效:条件中有or,即使其中有条件带索引也不会使用(要想使用or又想让索引生效,只能将or条件中每个列加上索引);like查询,以%开头;若列类型为字符串,则一定要在条件中将数据用引号括起来,否则不使用索引;若以mysql估计使用全表扫描要比索引快,则不使用索引;对索引进行运算导致索引列失效;使用内部函数导致索引失效,这样应当创建基于函数的索引;b-树,is null不会用,is not null会用。

可以在select语句前加上explain,比如explain select * from tablename;返回的一列种,若列名为key的那列为null,则没有使用索引,若不为null,则返回实际使用的索引名。

让select强制使用索引的语法:select * from tablename from index(index_name)。

联合索引:两个或多个列上的索引被称为联合索引。联合索引结构与电话簿类似,人名由姓和名组成,首先按姓氏排序,同姓氏按名排序。所以创建联合索引时,要考虑列的顺序。对索引中所有列执行搜索,或者仅对前几列搜索,复合索引很有效;但若只对后面的列搜索,就没用。 创建联合索引的语法:create index 索引名 on 表名(字段名1,字段名2)

mysql每次查询,只能用一个索引。创建了(A,B,C)的复合索引,实际上创建了(A), (A,B) (A,B,C)三个索引,这被称为最佳左前缀特性。因此创建复合索引时,最常用的放最左边。

完全限定名:在引用列的时候可能出现二义性,必须使用完全限定名(用一个点分隔的表名和列名)。如果引用一个没有用表明限制的具有二义性的列名,mysql将返回错误。

sql优化:对查询进行优化,尽量避免全表扫描。在where或order by的列上加索引。尽量避免在where子语句中有where num is null,这样不用索引,且要全表扫描,可用0代替null。避免在where中用<>或!=,因为要全表扫面。尽量避免在where中用or,因为若一个字段有索引,一个没有,则要全表扫描。like“%abc%”,全表扫描。避免在where子语句中对字段进行函数操作,要全表扫描。使用复合索引时,必须用到该索引的第一个字段,否则索引不被使用。

sql内连接(inner join):返回结果是两张表重叠的部分;左右外连接(left/right join):返回重叠加左/右表中未重叠的;完全连接(full join):返回重叠和未未重叠的所有结果。不管对左表和右表进行筛选,on and和on where都会对生成的临时表进行过滤。

主键:唯一标识一条记录,不能有重复的,不允许为空;用来保证数据完整性;主键只能有一个。

外键:表的外键是另一表的主键, 外键可以有重复的, 可以是空值;用来和其他表建立联系用的;一个表可以有多个外键。

视图(子查询):是从一个或多个表导出的虚拟的表,其内容由查询定义。具有普通表的结构,但是不实现数据存储。对视图的修改:单表视图一般用于查询和修改,会改变基本表的数据,多表视图一般用于查询,不会改变基本表的数据。①简化了操作,把经常使用的数据定义为视图。②安全性,用户只能查询和修改能看到的数据。③逻辑上的独立性,屏蔽了真实表的结构带来的影响。

缺点:①性能差。②修改限制。

mysql oracle区别

并发性:mysql以表级锁为主,对资源锁定的粒度很大,如果一个session对一个表加锁时间过长,会让其他session无法更新此表中的数据。虽然InnoDB引擎的表可以用行级锁,但这个行级锁的机制依赖于表的索引,如果表没有索引,或者sql语句没有使用索引,那么仍然使用表级锁。oracle使用行级锁,对资源锁定的粒度要小很多,只是锁定sql需要的资源,并且加锁是在数据库中的数据行上,不依赖与索引。所以oracle对并发性的支持要好很多。

一致性:oracle支持serializable的隔离级别,可以实现最高级别的读一致性。

事务:oracle很早就完全支持事务。mysql在innodb存储引擎的行级锁的情况下才支持事务。

数据持久性:oracle保证提交的数据均可恢复,因为oracle把提交的sql操作线写入了在线联机日志文件中,保持到了磁盘上,如果出现数据库或主机异常重启,重启后oracle可以靠联机在线日志恢复客户提交的数据。mysql默认提交sql语句,但如果更新过程中出现db或主机重启的问题,也许会丢失数据。

提交方式:oracle默认不自动提交,需要用户手动提交。mysql默认是自动提交。

逻辑备份:oracle逻辑备份时不锁定数据,且备份的数据是一致的。mysql逻辑备份时要锁定数据,才能保证备份的数据是一致的,影响业务正常的dml使用。

热备份:oracle有成熟的热备工具rman,热备时,不影响用户使用数据库。即使备份的数据库不一致,也可以在恢复时通过归档日志和联机重做日志进行一致的回复。mysql的myisam引擎,用mysql自带的mysqlhostcopy热备时,需要给表加读锁,影响dml操作。innodb的引擎,它会备份innodb的表和索引,但是不会备份.frm文件。用ibbackup备份时,会有一个日志文件记录备份期间的数据变化,因此可以不用锁表,不影响其他用户使用数据库。但此工具是收费的。innobackup是结合ibbackup使用的一个脚本,他会协助对.frm文件的备份。

sql语句的扩展和灵活性:mysql对sql语句有很多非常实用而方便的扩展,比如limit功能,insert可以一次插入多行数据,select某些管理数据可以不加from。oracle在这方面感觉更加稳重传统一些。

复制:oracle既有推或拉式的传统数据复制,也有dataguard的双机或多机容灾机制,主库出现问题是,可以自动切换备库到主库,但配置管理较复杂。mysql复制服务器配置简单,但主库出问题时,丛库有可能丢失一定的数据。且需要手工切换丛库到主库。

性能诊断:oracle有各种成熟的性能诊断调优工具,能实现很多自动分析、诊断功能。比如awr、addm、sqltrace、tkproof等。mysql的诊断调优方法较少,主要有慢查询日志。

权限与安全:mysql的用户与主机有关,感觉没有什么意义,另外更容易被仿冒主机及ip有可乘之机。oracle的权限与安全概念比较传统,中规中矩。

分区表和分区索引:oracle的分区表和分区索引功能很成熟,可以提高用户访问db的体验。mysql的分区表还不太成熟稳定。

管理工具:oracle有多种成熟的命令行、图形界面、web管理工具,还有很多第三方的管理工具,管理极其方便高效。mysql管理工具较少,在linux下的管理工具的安装有时要安装额外的包(phpmyadmin, etc),有一定复杂性。

Mysql主从复制的实现原理图大致如下

MySQL之间数据复制的基础是二进制日志文件(binary log file)。一台MySQL数据库一旦启用二进制日志后,其作为master,它的数据库中所有操作都会以“事件”的方式记录在二进制日志中,其他数据库作为slave通过一个I/O线程与主服务器保持通信,并监控master的二进制日志文件的变化,如果发现master二进制日志文件发生变化,则会把变化复制到自己的中继日志中,然后slave的一个SQL线程会把相关的“事件”执行到自己的数据库中,以此实现从数据库和主数据库的一致性,也就实现了主从复制。

实现MySQL主从复制需要进行的配置:

主服务器:开启二进制日志,配置唯一的server-id,获得master二进制日志文件名及位置,创建一个用于slave和master通信的用户账号。

从服务器:配置唯一的server-id,使用master分配的用户账号读取master二进制日志,启用slave服务。

猜你喜欢

转载自blog.csdn.net/SEUSUNJM/article/details/86568630