如下是对面试常见面试题整理,来自知乎大神分享的pdf,引用部分连接已给出,若是有没有标注的,纯属意外,但愿提醒。这篇主要整理出来给本身看的
B/B+树html
B/B+java
B树中的每一个结点根据实际状况能够包含大量的关键字信息和分支(固然是不能超过磁盘块的大小,根据磁盘驱动(disk drives)的不一样,通常块的大小在1k~4k左右);这样树的深度下降了,这就意味着查找一个元素只要不多结点从外存磁盘中读入内存,很快访问到要查找的数据mysql
代码定义:
web
B树优点
高度比平衡树低,因此IO磁盘操做次数少,查找更快面试
当B树包含N个关键字时,B树的最大高度为l-1(由于计算B树高度时,叶结点所在层不计算在内),即:l - 1 = log┌m/2┐((N+1)/2 )+1。sql
B+-tree的磁盘读写代价更低:
B+-tree的内部结点并无指向关键字具体信息的指针。所以其内部结点相对B 树更小。若是把全部同一内部结点的关键字存放在同一盘块中,那么盘块所能容纳的关键字数量也越多。一次性读入内存中的须要查找的关键字也就越多。相对来讲IO读写次数也就下降了。数据库
举个例子,假设磁盘中的一个盘块容纳16bytes,而一个关键字2bytes,一个关键字具体信息指针2bytes。一棵9阶B-tree(一个结点最多8个关键字)的内部结点须要2个盘快。而B+ 树内部结点只须要1个盘快。当须要把内部结点读入内存中的时候,B 树就比B+ 树多一次盘块查找时间(在磁盘中就是盘片旋转的时间)。设计模式
B+-tree的查询效率更加稳定:
因为非终结点并非最终指向文件内容的结点,而只是叶子结点中关键字的索引。因此任何关键字的查找必须走一条从根结点到叶子结点的路。全部关键字查询的路径长度相同,致使每个数据的查询效率至关。数组
在MySQL中,索引属于存储引擎级别的概念,不一样存储引擎对索引的实现方式是不一样的,这里主要讨论MyISAM和InnoDB两个存储引擎的索引实现方式
索引服务器
MyISAM引擎使用B+Tree做为索引结构,叶节点的data域存放的是数据记录的地址。下图是MyISAM索引的原理图
假设咱们以Col1为主键,则图8是一个MyISAM表的主索引(Primary key)示意。能够看出MyISAM的索引文件仅仅保存数据记录的地址。在MyISAM中,主索引和辅助索引(Secondary key)在结构上没有任何区别,只是主索引要求key是惟一的,而辅助索引的key能够重复
MyISAM的索引方式也叫作“非汇集”的,之因此这么称呼是为了与InnoDB的汇集索引区分。
虽然InnoDB也使用B+Tree做为索引结构,但具体实现方式却与MyISAM大相径庭。
了解不一样存储引擎的索引实现方式对于正确使用和优化索引都很是有帮助,例如知道了InnoDB的索引实现后,就很容易明白为何不建议使用过长的字段做为主键,由于全部辅助索引都引用主索引,过长的主索引会令辅助索引变得过大。再例如,用非单调的字段做为主键在InnoDB中不是个好主意,由于InnoDB数据文件自己是一颗B+Tree,非单调的主键会形成在插入新记录时数据文件为了维持B+Tree的特性而频繁的分裂调整,十分低效,而使用自增字段做为主键则是一个很好的选择。
//普通索引 alter table table_name add index index_name (column_list) ; //惟一索引 alter table table_name add unique (column_list) ; //主键索引 alter table table_name add primary key (column_list) ;
//CREATE INDEX可用于对表增长普通索引或UNIQUE索引,可用于建表时建立索引。 CREATE INDEX index_name ON table_name(username(length)); //若是是CHAR,VARCHAR类型,length能够小于字段实际长度;若是是BLOB和TEXT类型,必须指定 length。 //create只能添加这两种索引; CREATE INDEX index_name ON table_name (column_list) CREATE UNIQUE INDEX index_name ON table_name (column_list)
drop index index_name on table_name ; alter table table_name drop index index_name ; alter table table_name drop primary key ;
一致性(Consistency):从一个一致性状态到另外一个一致性状
态。
例如现有完整性约束 a+b=10,若是一个事务改变了a,那么必须
得改变b,使得事务结束后依然知足 a+b=10,不然事务失败。
隔离性(Isolation):一个事务所作的修改在最终提交之前,对其它事务不可见。
好比现有有个交易是从A 帐户转100 元至 B 帐户,在这个交易还
未完成的状况下,若是此时 B 查询本身的帐户,是看不到新增长的
100元的。
(Durability) 持久性
持久性是指一旦事务提交后,它所作的修改将会永久的保存在数据库
上,即便出现宕机也不会丢失。
尽可能使用数字字段而不是字符字段
尽可能使用timestamp而不是datetime
Public void FindAllUsers(){ //一、装载sqlserver驱动对象 DriverManager.registerDriver(new SQLServerDriver()); //二、经过JDBC创建数据库链接 Connection con =DriverManager.getConnection("jdbc:sqlserver://192.168.2.6:1433;DatabaseName=customer", "sa", "123"); //三、建立状态 Statement state =con.createStatement(); //四、查询数据库并返回结果 ResultSet result =state.executeQuery("select * from users"); //五、输出查询结果 while(result.next()){ System.out.println(result.getString("email")); } //六、断开数据库链接 result.close(); state.close(); con.close(); }
程序开发过程当中,存在不少问题:首先,每一次web请求都要创建一次数据库链接。创建链接是一个费时的活动,每次都得花费0.05s~1s的时间,并且系统还要分配内存资源。这个时间对于一次或几回数据库操做,或许感受不出系统有多大的开销。但是对于如今的web应用,尤为是大型电子商务网站,同时有几百人甚至几千人在线是很正常的事。在这种状况下,频繁的进行数据库链接操做势必占用不少的系统资源,网站的响应速度一定降低,严重的甚至会形成服务器的崩溃。不是危言耸听,这就是制约某些电子商务网站发展的技术瓶颈问题。其次,对于每一次数据库链接,使用完后都得断开。不然,若是程序出现异常而未能关闭,将会致使数据库系统中的内存泄漏,最终将不得不重启数据库。还有,这种开发不能控制被建立的链接对象数,系统资源会被毫无顾及的分配出去,如链接过多,也可能致使内存泄漏,服务器崩溃。
public class MyDataSource implements DataSource { //链表 --- 实现栈结构 privateLinkedList<Connection> dataSources = new LinkedList<Connection>(); //初始化链接数量 publicMyDataSource() { //一次性建立10个链接 for(int i = 0; i < 10; i++) { try { //一、装载sqlserver驱动对象 DriverManager.registerDriver(new SQLServerDriver()); //二、经过JDBC创建数据库链接 Connection con =DriverManager.getConnection( "jdbc:sqlserver://192.168.2.6:1433;DatabaseName=customer", "sa", "123"); //三、将链接加入链接池中 dataSources.add(con); } catch (Exception e) { e.printStackTrace(); } } } @Override publicConnection getConnection() throws SQLException { //取出链接池中一个链接 finalConnection conn = dataSources.removeFirst(); // 删除第一个链接返回 returnconn; } //将链接放回链接池 publicvoid releaseConnection(Connection conn) { dataSources.add(conn); } }
//查询全部用户 Public void FindAllUsers(){ //一、使用链接池创建数据库链接 MyDataSource dataSource = new MyDataSource(); Connection conn =dataSource.getConnection(); //二、建立状态 Statement state =con.createStatement(); //三、查询数据库并返回结果 ResultSet result =state.executeQuery("select * from users"); //四、输出查询结果 while(result.next()){ System.out.println(result.getString("email")); } //五、断开数据库链接 result.close(); state.close(); //六、归还数据库链接给链接池 dataSource.releaseConnection(conn); }
前缀查询,例如“abc%”,仍是索
引策略的问题
对于共享资源,有一个很著名的设计模式:资源池(resource pool)。该模式正是为了解决资源的频繁分配﹑释放所形成的问题。为解决上述问题,能够采用数据库链接池技术。数据库链接池的基本思想就是为数据库链接创建一个“缓冲池”。预先在缓冲池中放入必定数量的链接,当须要创建数据库链接时,只需从“缓冲池”中取出一个,使用完毕以后再放回去。咱们能够经过设定链接池最大链接数来防止系统无尽的与数据库链接。更为重要的是咱们能够经过链接池的管理机制监视数据库的链接的数量﹑使用状况,为系统开发﹑测试及性能调整提供依据。线程池也是如此,由于频繁开启关闭线程会下降系统资源,因此能够用线程池达到资源共享,统一管理线程资源的目的。初始化一个比较大的线程池,每当程序须要开启新的线程时,会到线程池中申请。一样的咱们能够初始化适当的线程数来达到最大的资源利用率
我的认为是第三范式,此时数据冗余较小,范式级别太高对查询效率也不利
序。
select id from table group by id having avg(score) > 80 order by avg(score) desc
/找出第K大的数 int find_k_big(int A[], int low, int high, int k) { if(low < high) { int pivot_pos = partion2(A, low, high); if(pivot_pos + 1 == k) return A[pivot_pos]; else if(pivot_pos + 1 > k) find_k_big(A, low, pivot_pos - 1, k); else find_k_big(A, pivot_pos + 1, high, k); } else return -1;