数据库的三大范式
第一范式:数据库中每一个属性都不可再分(不可以用多重值);
第二范式:数据库中非主键属性必须完全依赖于全体主键
第三范式:数据库中非主键属性不能传递依赖于主键
触发器的作用?
触发器是一种特殊的存储过程,主要是通过事件来触发而被执行的。它可以强化约束,来维护数据的完整性和一致性,可以跟踪数据库内的操作从而不允许未经许可的更新和变化。可以联级运算。如,某表上的触发器上包含对另一个表的数据操作,而该操作又会导致该表触发器被触发
索引的优缺点?
创建索引可以大大提高系统的性能(优点):
1.通过创建唯一性索引,可以保证数据库表中每一行数据的唯一性。
2.可以大大加快数据的检索速度,这也是创建索引的最主要的原因。
3.可以加速表和表之间的连接,特别是在实现数据的参考完整性方面特别有意义。
4.在使用分组和排序子句进行数据检索时,同样可以显著减少查询中分组和排序的时间。
5.通过使用索引,可以在查询的过程中,使用优化隐藏器,提高系统的性能。
增加索引也有许多不利的方面(缺点):
1.创建索引和维护索引要耗费时间,这种时间随着数据量的增加而增加。
2.索引需要占物理空间,除了数据表占数据空间之外,每一个索引还要占一定的物理空间,如果要建立聚簇索引,那么需要的空间就会更大。
3.当对表中的数据进行增加、删除和修改的时候,索引也要动态的维护,这样就降低了数据的维护速度。
MySQL索引类型
普通索引 。
是最基本的索引,它没有任何限制.
唯一索引
与前面的普通索引类似,不同的就是:索引列的值必须唯一,但允许有空值。如果是组合索引,则列值的组合必须唯一.
主键索引
是一种特殊的唯一索引,一个表只能有一个主键,不允许有空值。
组合索引
指多个字段上创建的索引,只有在查询条件中使用了创建一个字段,索引才会被使用。使用组合索引时遵循最左前缀。
全文索引
主要用来查找文本中的关键字,而不是直接与索引中的值相比较.fulltext索引跟其它索引大不相同,它更像是一个搜索引擎,而不是简单的,其中语句的参数匹配.fulltext索引配合匹配操作使用,而不是一般的where语句加像。它可以在create table,alter table,create index使用,不过目前只有char,varchar,text列上可以创建全文索引。值得一提的是,在数据量较大时候,现将数据放入一个没有全局索引的表中,然后再用CREATE index创建全文索引,要比先为一张表建立全文然后再将数据写入的速度快很多
MySQL无法命中索引的情况
1、如果条件中有or,即使其中有条件带索引也不会使用(这也是为什么尽量少用or的原因
注意:要想使用or,又想让索引生效,只能将or条件中的每个列都加上索引
2、对于多列索引,不是使用的第一部分(第一个),则不会使用索引
3、like查询是以%开头
4、如果列类型是字符串,那一定要在条件中将数据使用引号引用起来,否则不使用索引
5、强制类型转换会导致索引失效
6、如果mysql估计全表查询会比使用索引快,那么则不会使用索引
MySQL B+Tree索引和Hash索引的区别?
Hash索引和B+树索引的特点:
-
Hash索引结构的特殊性,其检索效率非常高,索引的检索可以一次定位;
-
B+树索引需要从根节点到枝节点,最后才能访问到页节点这样多次的IO访问;
为什么不都用Hash索引而使用B+树索引?
-
Hash索引仅仅能满足"=","IN"和""查询,不能使用范围查询,因为经过相应的Hash算法处理之后的Hash值的大小关系,并不能保证和Hash运算前完全一样;
-
Hash索引无法被用来避免数据的排序操作,因为Hash值的大小关系并不一定和Hash运算前的键值完全一样;
-
Hash索引不能利用部分索引键查询,对于组合索引,Hash索引在计算Hash值的时候是组合索引键合并后再一起计算Hash值,而不是单独计算Hash值,所以通过组合索引的前面一个或几个索引键进行查询的时候,Hash索引也无法被利用;
-
Hash索引在任何时候都不能避免表扫描,由于不同索引键存在相同Hash值,所以即使取满足某个Hash键值的数据的记录条数,也无法从Hash索引中直接完成查询,还是要回表查询数据;
-
Hash索引遇到大量Hash值相等的情况后性能并不一定就会比B+树索引高。
B+ Tree索引和Hash索引区别?
哈希索引适合等值查询,但是无法进行范围查询
哈希索引没办法利用索引完成排序
哈希索引不支持多列联合索引的最左匹配规则
如果有大量重复键值的情况下,哈希索引的效率会很低,因为存在哈希碰撞问题
drop、truncate、 delete区别
最基本:
- drop直接删掉表。
- truncate删除表中数据,再插入时自增长id又从1开始。
- delete删除表中数据,可以加where字句。
聚集索引和非聚集索引区别?
聚合索引(clustered index):
聚集索引表记录的排列顺序和索引的排列顺序一致,所以查询效率快,只要找到第一个索引值记录,其余就连续性的记录在物理也一样连续存放。聚集索引对应的缺点就是修改慢,因为为了保证表中记录的物理和索引顺序一致,在记录插入的时候,会对数据页重新排序。
聚集索引类似于新华字典中用拼音去查找汉字,拼音检索表于书记顺序都是按照a~z排列的,就像相同的逻辑顺序于物理顺序一样,当你需要查找a,ai两个读音的字,或是想一次寻找多个傻(sha)的同音字时,也许向后翻几页,或紧接着下一行就得到结果了。非聚合索引(nonclustered index):
非聚集索引指定了表中记录的逻辑顺序,但是记录的物理和索引不一定一致,两种索引都采用B+树结构,非聚集索引的叶子层并不和实际数据页相重叠,而采用叶子层包含一个指向表中的记录在数据页中的指针方式。非聚集索引层次多,不会造成数据重排。
非聚集索引类似在新华字典上通过偏旁部首来查询汉字,检索表也许是按照横、竖、撇来排列的,但是由于正文中是a~z的拼音顺序,所以就类似于逻辑地址于物理地址的不对应。同时适用的情况就在于分组,大数目的不同值,频繁更新的列中,这些情况即不适合聚集索引。根本区别:
聚集索引和非聚集索引的根本区别是表记录的排列顺序和与索引的排列顺序是否一致。
哪些列适合建立索引、哪些不适合建索引?
索引是建立在数据库表中的某些列的上面。在创建索引的时候,应该考虑在哪些列上可以创建索引,在哪些列上不能创建索引。
一般来说,应该在这些列上创建索引:
(1)在经常需要搜索的列上,可以加快搜索的速度;
(2)在作为主键的列上,强制该列的唯一性和组织表中数据的排列结构;
(3)在经常用在连接的列上,这些列主要是一些外键,可以加快连接的速度;
(4)在经常需要根据范围进行搜索的列上创建索引,因为索引已经排序,其指定的范围是连续的;
(5)在经常需要排序的列上创建索引,因为索引已经排序,这样查询可以利用索引的排序,加快排序查询时间;
(6)在经常使用在WHERE子句中的列上面创建索引,加快条件的判断速度。
对于有些列不应该创建索引:
(1)对于那些在查询中很少使用或者参考的列不应该创建索引。
这是因为,既然这些列很少使用到,因此有索引或者无索引,并不能提高查询速度。相反,由于增加了索引,反而降低了系统的维护速度和增大了空间需求。
(2)对于那些只有很少数据值的列也不应该增加索引。
这是因为,由于这些列的取值很少,例如人事表的性别列,在查询的结果中,结果集的数据行占了表中数据行的很大比例,即需要在表中搜索的数据行的比例很大。增加索引,并不能明显加快检索速度。
(3)对于那些定义为text, image和bit数据类型的列不应该增加索引。
这是因为,这些列的数据量要么相当大,要么取值很少。
(4)当修改性能远远大于检索性能时,不应该创建索引。
这是因为,修改性能和检索性能是互相矛盾的。当增加索引时,会提高检索性能,但是会降低修改性能。当减少索引时,会提高修改性能,降低检索性能。因此,当修改性能远远大于检索性能时,不应该创建索引。
MyISAM和InnoDB区别
(1)事务处理:
MyISAM是非事务安全型的,而InnoDB是事务安全型的(支持事务处理等高级处理);
(2)锁机制不同:
MyISAM是表级锁,而InnoDB是行级锁;
(3)select ,update ,insert ,delete 操作:
MyISAM:如果执行大量的SELECT,MyISAM是更好的选择
InnoDB:如果你的数据执行大量的INSERT或UPDATE,出于性能方面的考虑,应该使用InnoDB表
(4)查询表的行数不同:
MyISAM:select count() from table,MyISAM只要简单的读出保存好的行数,注意的是,当count()语句包含 where条件时,两种表的操作是一样的
InnoDB : InnoDB 中不保存表的具体行数,也就是说,执行select count(*) from table时,InnoDB要扫描一遍整个表来计算有多少行
(5)外键支持:
mysiam表不支持外键,而InnoDB支持
为什么MyISAM会比Innodb 的查询速度快。
INNODB在做SELECT的时候,要维护的东西比MYISAM引擎多很多;
1)数据块,INNODB要缓存,MYISAM只缓存索引块, 这中间还有换进换出的减少;
2)innodb寻址要映射到块,再到行,MYISAM 记录的直接是文件的OFFSET,定位比INNODB要快
3)INNODB还需要维护MVCC一致;虽然你的场景没有,但他还是需要去检查和维护
MVCC ( Multi-Version Concurrency Control )多版本并发控制
应用场景
MyISAM适合:(1)做很多count 的计算;(2)插入不频繁,查询非常频繁;(3)没有事务。
InnoDB适合:(1)可靠性要求比较高,或者要求事务;(2)表更新和查询都相当的频繁,并且行锁定的机会比较大的情况。
总结一下就是:
1 innodb支持外键,事务以及行级锁,另外还支持聚簇索引。
2 而mysiam不支持上述特性,但是他在count场景速度快(因为保存了行数)。
3 另外由于innodb需要维护聚簇索引,以及事务的MVCC特性,需要额外的开销。所以在查询方面,innodb可能会稍逊一筹。
4 而插入方面,由于innodb支持行级锁,所以对于行级插入删除速度很快。
说一说你能想到的sql语句优化,至少五种
避免select *,将需要查找的字段列出来;
使用连接(join)来代替子查询;
拆分大的delete或insert语句;
使用limit对查询结果的记录进行限定;
用 exists 代替 in 是一个好的选择;
用Where子句替换HAVING 子句 因为HAVING 只会在检索出所有记录之后才对结果集进行过滤;
不要在 where 子句中的“=”左边进行函数、算术运算或其他表达式运算否则系统将可能无法正确使用索引
尽量避免在where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索引而进行全表扫描;
尽量避免在 where 子句中使用 or 来连接条件,否则将导致引擎放弃使用索引而进行全表扫描;
尽量避免在 where 子句中使用!=或<>操作符,否则将引擎放弃使用索引而进行全表扫描
说一说你能想到的表结构优化
永远为每张表设置一个ID (所有建表的时候不设置主键的程序猿都应该被辞退);
选择正确的存储引擎 ;
使用可存下数据的最小的数据类型,整型 < date,time < char,varchar < blob;
使用简单的数据类型,整型比字符处理开销更小,因为字符串的比较更复杂。
使用合理的字段属性长度,固定长度的表会更尽可能使用not null定义字段(给空字段设置默认值);
尽量少用text;给频繁使用和查询的字段建立合适的索引