数据库几个面试题
1.什么样的场景会产生数据库死锁,如何解决?
第一条:事务之间对资源访问顺序的交替
简单说就是,
用户1访问A表,用户2访问B表。
然后1还要访问B,2还要访问A。
但是1锁住了A,2锁住了B。
死锁了。
解决办法:
调整程序的逻辑,一般操作多张表的话,避免这样交替顺序的表操作。
第二条:并发修改同一记录
用户1和用户2都要对一条记录修改。
先读取记录,获取共享锁。这时候两个事务获得了共享模式锁。
然后试图修改,共享锁要转换为排他锁,
因为一个事务的排他锁和其他事务的共享锁是不兼容的。即:要等待其他事务释放共享锁。
所以这时候发生锁等待,两个事务都在等待另一个事务释放共享锁,发生死锁。
解决办法:
a.乐观锁。
b.悲观锁。
c.sqlserver的更新锁。
第三条:索引不当导致全表扫描
事务在执行一条不满足条件的语句,执行全表扫描,行级锁上升为表级锁。
多个事务执行后,容易发生阻塞和死锁。
数据量大,索引少的时候。应用系统变慢,阻塞发生死锁。
sql语句不要使用太复杂的关联多表查询,建立相关索引优化。
2.sql如何优化
第一条:还是索引问题
索引建立时需要注意的地方
避免对索引字段(
计算
使用not,<>,!=
使用is null 和 is not null
出现数据类型转化
使用函数
使用空值(控制可以用默认值代替)
)
说简单点就是索引要建的合适,如果索引是数字(日期也是)的话,不要以字符格式声明数字,因为会使索引无效,产生全表扫描。
order by 和 where 后面经常写的字段,如果也满足规则,最好索引。
并不是所有索引对查询都有效,如果一个索引有大量重复数据时,sql可能不会利用索引,比如说性别。
索引不是说越多越好,索引提高了select效率,降低了insert和update效率。因为insert和update可能重建索引。一个表索引最好不要超过6个。
能使用数字类型字段就不要用字符型。字符型会一个一个字符比较,数字型只需要比较一次。
第二条:多个update就写成一个好了
第三条:用 exist 和 not exist 替换 in 和 not in,
如果是连续数字也可以用between
第四条:不要写select * ,要把字段写全了
第五条:distinct,union,minus,intersect,order by
需要启动sql引擎,distinct需要一次排序,其他两次。
第六条:在一种情况下可以避免使用or,在or的字段是索引时,宁愿查询两次。
例子:
select id from t where num=10 or num=20;
可以这样查询
select id from t where num=10;
select id from t where num=20;
第七条:海量数据查询避免格式转换
第八条:尽可能使用更小的数据类型,比如mediumint 代替 int
第九条:尽可能使用enum
————————————————
3.oracle 和 mysql 使用分页
oracle:
oracle使用rownum实现。
rownum没有>,>= 因为oracle行式数据库
所以,如果分页的数据不需要排序可以直接
select * from (
select rownum rn,a.* from student a where rownum <= 8
) where rn >= 5
如果需要先排序就是这样
select * from (
select rownum rn,a.* from (
select b.* from student b order by studentId asc
) a where rownum <= 8
) where rn >= 5
mysql:
mysql使用limit实现。
select * from student limit n,m;
n:(currentPage-1)*pageSize
m:pageSize
——————————————————————
4.唯一索引能否插入空
mysql:
唯一索引允许插入空,
创建唯一索引sql举例:
CREATE UNIQUE INDEX index_name
ON table_name(index_column_1,index_column_2,...);
ALTER TABLE table_name
ADD CONSTRAINT constraint_name UNIQUE KEY(column_1,column_2,...);
CREATE TABLE table_name(
...
UNIQUE KEY(index_column_,index_column_2,...)
);
5.SQL怎样判断字段是否为空
sqlserver用isnull函数
oracle用nvl函数
mysql用ifnull函数或者coalesce函数
(如果字段是null就转化成字段后面的内容)
select * from student where colesce(student_name,'')<>'';