数据库

mysql引擎:

执行查询时,若要查询的数据很多,假设要查询1000 万条,用什么方法提升效率?答案:1)从数据库方面:建立索引、分区、尽量使用固定长度的字段、限制字段长度2)从数据库IO 方面:增加缓冲区3)在sql 语句方面:优化sql 语句,减少比较次数、限制返回的条目数4)在java 方面,如果是反复使用的查询,使用preparedStatement。

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

1.innodb:更新密集型,支持事务,自动灾难恢复,行级锁,外键约束。

2.Mylsam:选择密集型,插入密集型,不支持事务。

3.memory:存储介质是内存。

4.merge:一组Mylsam表组合。

mysq 索引使用的是B+的数据结构

索引:用于提高数据访问速度的数据库对象。

优点:1)索引可以避免全表扫描;2)对于非聚集索引,有些查询甚至可以不访问数据项;3)聚集索引可以避免数据插入操作集中于表的最后一个数据页;4)一些情况下,索引还可以避免排序。

虽然索引可以提高查询速度,但是他们也会导致数据库更新数据的性能下降,因为大部分数据更新时需要同时更新索引。

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

非聚集索引与聚集索引的区别:

1)叶子节点并非数据节点

2)叶子节点为每一个真正的数据行存储一个“键-指针”对

3)叶子节点中还存储了一个指针偏移量,根据页指针及指针偏移可以定位到具体的数据行。

4)在除叶节点外的其他索引节点,存储的是类似内容,只不过是指向下一级索引页。

数据库事务ACID。


聚集索引的叶节点是数据节点,而非聚集索引的叶节点仍然是索引节点,只不过有一个指针指向对应数据块。

有索引就一定快?NO


Mysql 使用B+树。


索引:1)可以避免全表扫描。2)若一个表没有聚集索引,则这样表中的数据没有特定的顺序,all 新行将被添加到表的末尾。3)聚集索引是一种稀疏索引,数据页上一页的索引

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


定义一个对象的过程:加载类,分配对象大小,默认初始化(方法),把对象按程序员的意愿进行初始化。Myisam:不支持事务行级锁和外键约束。所以当执行insert 和update 时,执行写操作时,要锁定整个表,所以效率低。但是它保存了表的行数,执行select count(*) from table 时,不需要全表扫描,而是直接读取保存的值。所以若读操作远远多于写操作,并且不需要事务,myisam 是首选。

Innodb:支持事务、行级锁和外键,mysql  运行时,Innodb  会在内存中建立缓冲池,用于缓冲数据和索引。不保存表的行数,执行select count(*) from table 时要全表扫描。写不锁定全表,高效并发时效率高。

联合索引:两个或多个列上的索引被称为联合索引。复合索引的结构与电话薄类似,人名由姓和名构成,电话薄首先按姓氏进行排序,对于同一个姓氏按名字来排序,若您知道姓,电话薄将非常有用,若您知道姓和名,则电话薄更为有用,但若你不知道姓,只知道名字,电话薄将没有用处。所以创建复合索引时,要仔细考虑列的顺序。对索引中所有列执行搜索,

or 仅对前几列执行搜索,复合索引十分有效;但若仅对后面的列进行搜索时,复合索引则没用。

mysql 每次查询,只能用一个索引。

若我们创建了(A,B,C)的复合索引,那么其实相当于创建了(A,B,C)、(A,B)、

(A)三个索引,这被称为最佳左前缀特性。因此,我们在创建复合索引时,应将最常用的放在最左边。


怎么判断一个mysql 中select 语句是否使用了索引,可以在select 语句前加上explain,比如explain select * from tablename;返回的一列中,若列名为key 的那列为null,则没有使用索引,若不为null,则返回实际使用的索引名。让select 强制使用索引的语法:select * from tablename from index(index_name);

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

唯一索引:不允许其中任何两行有相同的值。

主键索引:为表定义主键自动创建主键索引,是唯一索引的特定类型:

聚集索引:b-树中一次检索最多需要h-1 次io(根节点常驻内存,h 为树的高度),一般用磁盘io 来评价索引的优劣,b 树中一个节点对应一页,所以一个node 只要一次io。

下列事件索引会失效:1)条件中有or,即使其中有条件带索引也不会使用(要想使用

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


Group by:使用Group by 的两个要素。1)出现在select 后面的字段,要么是聚集函数中的,要么是Group by 中的;2)要筛选结果,可以先用where,再用Group by 或先用Group

by 再用where

sql 优化:1)对查询进行优化,要尽量避免全表扫描。在where 或order by 的列上加索引。2)尽量避免在where 子语句中有where num is null,这样不用索引,要全表扫描,可用0 代替null。3)避免在where 中用<>or!=,因为要全表扫描。4)尽量避免在where 中用

or,因为若一个字段有索引,一个没有,则要全表扫描。5)like”%abc%”,全表扫描。6)避免在where 子语句中对字段进行函数操作,因为要全表扫描。7)使用复合索引时,必须用到该索引的第一个字段,否则索引不被使用。

Select * from tablename orderby liename limit m,n (从m+1 条开始,取n 条数据)。

a 表



b 表



A 的id 和b 的parent_id 关联

1)内连接

Select a.*,b.*from a inner join b on a.id=b. parent_id;

结果为: 1 张三 1 23 1

2 李四 2 34 2

2)左外链接(左表all 元素都有)

Select a.*,b.*from a left join b on a.id=b. parent_id;

结果为: 1 张三 1 23 1

2 李四 2 34 2

3 王五 null

3)右外链接(右表all 元素都有)

Select a.*,b.*from a right join b on a.id=b. parent_id;


结果为: 1 张三1231

2 李四2342

Null3342

4)完全链接(返回左边和右表中所有行,若某行在另外一个表中无匹配,则另一表的选择列表列包含空值)

Select a.*,b.*from a full join b on a.id=b. parent_id;


结果为: 1 张三1 23 1

2 李四2 34 2

Null3 34 2

3 王五null


Not in 的例子:

Select emp_no from emplyees where emp_no not in (select emp_no from dept_manager).


Sql 的不等为<>


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

事务隔离级别就是对事物并发控制的等级。串行化:所有事务一个接一个的串行执行。可重复读:所有被select 获取的数据都不能被修改,这样就可以避免一个事务前后读取数据不一致的情况。读已提交:被读取的数据可以被其他事务修改。读未提交:允许其他事务看到没提交的数据。脏读:事务没提交,提前读取,就是当一个事务正在访问数据,并且对数据进行了修改,而这种修改还没提交到数据库,这时,另外一个事务也访问这个数据,然后使用了这个数据。

数据库要复习的地方:1)隔离级别;2)索引;3)范式[1NF:属性不可分;2NF:非主键属性完全依赖于主键属性;3NF:非主键属性之间无传递依赖;4NF:主键属性之间无传递依赖];4)引擎。 

左连接on 和where——on and 是在生成临时表时使用的条件,不管on 中条件是否为真,都会返回左表中的记录。2)where 是临时表生成好后,再对临时表进行过滤的条件,这时已经没有了left join 的含义(必须返回左表记录),条件不为真的就全部过滤掉。on 后的条件用来生成临时表,where 条件用来对临时表关联。

Inner join:不管对左表或右表进行筛选,on and 和on where 都会对生成的临时表进行过滤。

索引的缺点:1)创建和维护索引要耗费时间。2)索引需要占用物理空间,除了数据表占数据空间以外,每一个索引还要占物理空间。3)当对表中数据进行增加、删除和修改时,索引也要动态维护,这样就降低了数据的维护速度。

Hibernate 1+N 问题:1)一对多():在1 的这方,通过一条sql 查到1 个对象,由于关联的存在,那么又需要将这n 个对象关联的集合取出。因为集合数量为n,还要发n 条sql,于是本来的一条sql 变为n+1 条。2)多对一(many-to-one),在多的这方通过一条sql 查到了n 个对象,由于关联的存在,也会将这n 个对象对应的一方的对象取出,所以本来一条sql 变为n+1 条。3)iterator 查询时,一定先去缓存中找(1 条sql 查集合,只查

id),在没命中时,会再按id 到库中逐一查找,产生1+n 条sql。解决办法:1)lazy-true:懒加载,不立即查询关联对象,只有当需要关联对象(访问其属性,非id 字段)时才会发生查询动作。2)使用二级缓存:二级缓存的应用不怕1+n 问题,因为即使第一次查询很慢

(未命中),以后查询直接缓存命中也是很快的,刚好利用了1+n。

Load() VS get()  1 )若找不到符合条件的记录,get  返回null ,而load  抛

ObjectNotFoundException。2)load 返回实体的代理类,get 返回实体类。3)load 可利用二级缓存和内部缓存的现有数据。Get 只用内部缓存,若没有发现对应数据,将跳过二级缓存,直接调用sql 进行查找。4)当我们使用session.load 方法来加载一个对象时,此时不会发sql 语句,当前得到的只是一个代理对象。这个代理对象只保存了实体对象的id 值。当我们要使用这个对象,得到其他属性时,这时才发sql 语句,从数据库中去查我们的对象。对于get:当我们使用session.get 方法来得到一个对象时,不管我们使不使用这个对象,此时都会发

sql 语句去数据库里查。5)Load 可能抛出LazyInitializationException,在还没有发出sql 语句去数据库查实体对象时,当前对象为代理对象(只有id),但关了session,再使用该对象就报异常。

范式1NF:第一范式:强调列的原子性,列不能再分为其他几列,属性不可分。2NF:首先是1NF,另外包含两个部分,1)一个表必须有主键2)没有包含在主键中的列必须完全依赖于主键,而不能只依赖于主键的一部分3NF:首先是2NF,非主键列必须直接依赖于主键,不能存在传递依赖,即不能存在非主键A 依赖于非主键b,非主键b 依赖于主键的情况,消除传递依赖。

存储过程 VS 函数 都是为了重复执行 sql 语句的集合 他们的区别:1)写法上:存储过程的参数列表可以有输入参数,输出参数,输入输出参数,函数的参数列表只有输入参数。

2)返回值:存储过程的返回值,可以有多个值,函数只能有1 个。3)调用方式:存储过程

1.exec<过程名> 2.execute<过程名> 3.在sql 语句中直接调用函数:在sql 语句中直接调用。

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

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


Select e.last_name,e.first_name ,d.dept_no from employees e,dept_emp d where e.emp_no=d.enp_no and dept_no is not null.(给列取别名)。

你可能感兴趣的:(数据库)