一、为什么用自增列作为主键
1、如果咱们定义了主键 (PRIMARY KEY),那么 InnoDB 会抉择主键作为汇集索引、如果没有显式定义主键,则 InnoDB 会抉择第一个不蕴含有 NULL 值的惟一索引作为主键索引、如果也没有这样的惟一索引,则 InnoDB 会抉择内置 6 字节长的 ROWID 作为隐含的汇集索引 (ROWID 随着行记录的写入而主键递增,这个 ROWID 不像 ORACLE 的 ROWID 那样可援用,是隐含的)。
2、数据记录自身被存于主索引(一颗 B +Tree)的叶子节点上。这就要求同一个叶子节点内(大小为一个内存页或磁盘页)的各条数据记录按主键程序寄存,因而每当有一条新的记录插入时,MySQL 会依据其主键将其插入适当的节点和地位,如果页面达到装载因子(InnoDB 默认为 15/16),则开拓一个新的页(节点)
3、如果表应用自增主键,那么每次插入新的记录,记录就会程序增加到以后索引节点的后续地位,当一页写满,就会主动开拓一个新的页
4、如果应用非自增主键(如果身份证号或学号等),因为每次插入主键的值近似于随机,因而每次新纪录都要被插到现有索引页得两头某个地位,此时 MySQL 不得不为了将新记录插到适合地位而挪动数据,甚至指标页面可能曾经被回写到磁盘上而从缓存中清掉,此时又要从磁盘上读回来,这减少了很多开销,同时频繁的挪动、分页操作造成了大量的碎片,失去了不够紧凑的索引构造,后续不得不通过 OPTIMIZE TABLE 来重建表并优化填充页面。
二、为什么应用数据索引能提高效率
1、数据索引的存储是有序的
2、在有序的状况下,通过索引查问一个数据是无需遍历索引记录的
3、极其状况下,数据索引的查问效率为二分法查问效率,趋近于 log2(N)
三、B+ 树索引和哈希索引的区别
B+ 树是一个均衡的多叉树,从根节点到每个叶子节点的高度差值不超过 1,而且同层级的节点间有指针互相链接,是有序的
哈希索引就是采纳肯定的哈希算法,把键值换算成新的哈希值,检索时不须要相似 B + 树那样从根节点到叶子节点逐级查找,只需一次哈希算法即可, 是无序的
四、哈希索引的劣势:
1、等值查问。哈希索引具备绝对优势(前提是:没有大量反复键值,如果大量反复键值时,哈希索引的效率很低,因为存在所谓的哈希碰撞问题。)
五、哈希索引不实用的场景:
1、不反对范畴查问
2、不反对索引实现排序
3、不反对联结索引的最左前缀匹配规定
通常,B+ 树索引构造实用于绝大多数场景,像上面这种场景用哈希索引才更有劣势:
在 HEAP 表中,如果存储的数据反复度很低(也就是说基数很大),对该列数据以等值查问为主,没有范畴查问、没有排序的时候,特地适宜采纳哈希索引,例如这种 SQL:
select id,name from table where name='李明'; — 仅等值查问
而罕用的 InnoDB 引擎中默认应用的是 B + 树索引,它会实时监控表上索引的应用状况,如果认为建设哈希索引能够进步查问效率,则主动在内存中的“自适应哈希索引缓冲区”建设哈希索引(在 InnoDB 中默认开启自适应哈希索引),通过观察搜寻模式,MySQL 会利用 index key 的前缀建设哈希索引,如果一个表简直大部分都在缓冲池中,那么建设一个哈希索引可能放慢等值查问。
留神:在某些工作负载下,通过哈希索引查找带来的性能晋升远大于额定的监控索引搜寻状况和放弃这个哈希表构造所带来的开销。但某些时候,在负载高的状况下,自适应哈希索引中增加的 read/write 锁也会带来竞争,比方高并发的 join 操作。like 操作和 % 的通配符操作也不适用于自适应哈希索引,可能要敞开自适应哈希索引。
六、B 树和 B + 树的区别
1、B 树,每个节点都存储 key 和 data,所有节点组成这棵树,并且叶子节点指针为 nul,叶子结点不蕴含任何关键字信息。
2、B+ 树,所有的叶子结点中蕴含了全副关键字的信息,及指向含有这些关键字记录的指针,且叶子结点自身依关键字的大小自小而大的程序链接,所有的非终端结点能够看成是索引局部,结点中仅含有其子树根结点中最大(或最小)关键字。(而 B 树的非终节点也蕴含须要查找的无效信息)
七、为什么说 B + 比 B 树更适宜理论利用中操作系统的文件索引和数据库索引?
1、B+ 的磁盘读写代价更低 B + 的外部结点并没有指向关键字具体信息的指针。因而其外部结点绝对 B 树更小。如果把所有同一外部结点的关键字寄存在同一盘块中,那么盘块所能包容的关键字数量也越多。一次性读入内存中的须要查找的关键字也就越多。相对来说 IO 读写次数也就升高了。
2、B+-tree 的查问效率更加稳固因为非终结点并不是最终指向文件内容的结点,而只是叶子结点中关键字的索引。所以任何关键字的查找必须走一条从根结点到叶子结点的路。所有关键字查问的门路长度雷同,导致每一个数据的查问效率相当。
八、MySQL 联结索引
1、联结索引是两个或更多个列上的索引。对于联结索引:Mysql 从左到右的应用索引中的字段,一个查问能够只应用索引中的一部份,但只能是最左侧局部。例如索引是 key index (a,b,c). 能够反对 a、a,b、a,b,c 3 种组合进行查找,但不反对 b,c 进行查找 . 当最左侧字段是常量援用时,索引就非常无效。
2、利用索引中的附加列,您能够放大搜寻的范畴,但应用一个具备两列的索引 不同于应用两个独自的索引。复合索引的构造与电话簿相似,人名由姓和名形成,电话簿首先按姓氏对进行排序,而后按名字对有雷同姓氏的人进行排序。如果您知 道姓,电话簿将十分有用;如果您晓得姓和名,电话簿则更为有用,但如果您只晓得名不姓,电话簿将没有用途。
九、什么状况下应不建或少建索引
1、表记录太少
2、常常插入、删除、批改的表
3、数据反复且散布均匀的表字段,如果一个表有 10 万行记录,有一个字段 A 只有 T 和 F 两种值,且每个值的散布概率大概为 50%,那么对这种表 A 字段建索引个别不会进步数据库的查问速度。
4、常常和主字段一块查问但主字段索引值比拟多的表字段
十、什么是表分区?
表分区,是指依据肯定规定,将数据库中的一张表分解成多个更小的,容易治理的局部。从逻辑上看,只有一张表,然而底层却是由多个物理分区组成。
十一、表分区与分表的区别
分表:指的是通过肯定规定,将一张表分解成多张不同的表。比方将用户订单记录依据工夫成多个表。
分表与分区的区别在于:分区从逻辑上来讲只有一张表,而分表则是将一张表分解成多张表。
十二、表分区有什么益处?
1、分区表的数据能够散布在不同的物理设施上,从而高效地利用多个硬件设施。2. 和单个磁盘或者文件系统相比,能够存储更多数据
2、优化查问。在 where 语句中蕴含分区条件时,能够只扫描一个或多个分区表来进步查问效率;波及 sum 和 count 语句时,也能够在多个分区上并行处理,最初汇总后果。
3、分区表更容易保护。例如:想批量删除大量数据能够革除整个分区。
4、能够应用分区表来防止某些非凡的瓶颈,例如 InnoDB 的单个索引的互斥拜访,ext3 问价你零碎的 inode 锁竞争等。
十三、分区表的限度因素
1、一个表最多只能有 1024 个分区
2、MySQL5.1 中,分区表达式必须是整数,或者返回整数的表达式。在 MySQL5.5 中提供了非整数表达式分区的反对。
3、如果分区字段中有主键或者惟一索引的列,那么多有主键列和惟一索引列都必须蕴含进来。即:分区字段要么不蕴含主键或者索引列,要么蕴含全副主键和索引列。
4、分区表中无奈应用外键束缚
5、MySQL 的分区实用于一个表的所有数据和索引,不能只对表数据分区而不对索引分区,也不能只对索引分区而不对表分区,也不能只对表的一部分数据分区。
十四、如何判断以后 MySQL 是否反对分区?
命令:show variables like ‘%partition%’ 运行后果:
mysql> show variables like '%partition%';
+-------------------+-------+| Variable_name | Value |+-------------------+-------+| have_partitioning | YES |+-------------------+-------+1 row in set (0.00 sec)
have_partintioning 的值为 YES,示意反对分区。
十五、MySQL 反对的分区类型有哪些?
1、RANGE 分区:这种模式容许将数据划分不同范畴。例如能够将一个表通过年份划分成若干个分区
2、LIST 分区:这种模式容许零碎通过预约义的列表的值来对数据进行宰割。依照 List 中的值分区,与 RANGE 的区别是,range 分区的区间范畴值是间断的。
3、HASH 分区:这中模式容许通过对表的一个或多个列的 Hash Key 进行计算,最初通过这个 Hash 码不同数值对应的数据区域进行分区。例如能够建设一个对表主键进行分区的表。
4、KEY 分区:下面 Hash 模式的一种延长,这里的 Hash Key 是 MySQL 零碎产生的。
十六、四种隔离级别
1、Serializable (串行化):可防止脏读、不可反复读、幻读的产生。
2、Repeatable read (可反复读):可防止脏读、不可反复读的产生。
3、Read committed (读已提交):可防止脏读的产生。
4、Read uncommitted (读未提交):最低级别,任何状况都无奈保障。
十七、对于 MVVC
MySQL InnoDB 存储引擎,实现的是基于多版本的并发控制协议——MVCC (Multi-Version Concurrency Control) (注:与 MVCC 绝对的,是基于锁的并发管制,Lock-Based Concurrency Control)。MVCC 最大的益处:读不加锁,读写不抵触。在读多写少的 OLTP 利用中,读写不抵触是十分重要的,极大的减少了零碎的并发性能,现阶段简直所有的 RDBMS,都反对了 MVCC。
1、LBCC:Lock-Based Concurrency Control,基于锁的并发管制。
2、MVCC:Multi-Version Concurrency Control,基于多版本的并发控制协议。纯正基于锁的并发机制并发量低,MVCC 是在基于锁的并发管制上的改良,次要是在读操作上进步了并发量。
十八、在 MVCC 并发管制中,读操作能够分成两类:
1、快照读 (snapshot read):读取的是记录的可见版本 (有可能是历史版本),不必加锁(共享读锁 s 锁也不加,所以不会阻塞其余事务的写)。
2、以后读 (current read):读取的是记录的最新版本,并且,以后读返回的记录,都会加上锁,保障其余事务不会再并发批改这条记录。
十九、行级锁定的长处:
1、当在许多线程中拜访不同的行时只存在大量锁定抵触。
2、回滚时只有大量的更改
3、能够长时间锁定繁多的行。
二十、行级锁定的毛病:
1、比页级或表级锁定占用更多的内存。
2、当在表的大部分中应用时,比页级或表级锁定速度慢,因为你必须获取更多的锁。
3、如果你在大部分数据上常常进行 GROUP BY 操作或者必须常常扫描整个表,比其它锁定显著慢很多。
4、用高级别锁定,通过反对不同的类型锁定,你也能够很容易地调节应用程序,因为其锁老本小于行级锁定。
二十一、MySQL 优化
1、开启查问缓存,优化查问
2、explain 你的 select 查问,这能够帮你剖析你的查问语句或是表构造的性能瓶颈。EXPLAIN 的查问后果还会通知你你的索引主键被如何利用的,你的数据表是如何被搜寻和排序的
3、当只有一行数据时应用 limit 1,MySQL 数据库引擎会在找到一条数据后进行搜寻,而不是持续往后查少下一条合乎记录的数据
4、为搜寻字段建索引
5、应用 ENUM 而不是 VARCHAR,如果你有一个字段,比方“性别”,“国家”,“民族”,“状态”或“部门”,你晓得这些字段的取值是无限而且固定的,那么,你应该应用 ENUM 而不是 VARCHAR。
6、Prepared StatementsPrepared Statements 很像存储过程,是一种运行在后盾的 SQL 语句汇合,咱们能够从应用 prepared statements 取得很多益处,无论是性能问题还是平安问题。Prepared Statements 能够查看一些你绑定好的变量,这样能够爱护你的程序不会受到“SQL 注入式”攻打
7、垂直分表
8、抉择正确的存储引擎
二十二、key 和 index 的区别
1、key 是数据库的物理构造,它蕴含两层意义和作用,一是束缚(偏重于束缚和标准数据库的构造完整性),二是索引(辅助查问用的)。包含 primary key, unique key, foreign key 等
2、index 是数据库的物理构造,它只是辅助查问的,它创立时会在另外的表空间(mysql 中的 innodb 表空间)以一个相似目录的构造存储。索引要分类的话,分为前缀索引、全文本索引等;
二十三、Mysql 中 MyISAM 和 InnoDB 的区别有哪些?
区别:
1、InnoDB 反对事务,MyISAM 不反对,对于 InnoDB 每一条 SQL 语言都默认封装成事务,主动提交,这样会影响速度,所以最好把多条 SQL 语言放在 begin 和 commit 之间,组成一个事务;
2、InnoDB 反对外键,而 MyISAM 不反对。对一个蕴含外键的 InnoDB 表转为 MYISAM 会失败;
3、InnoDB 是汇集索引,数据文件是和索引绑在一起的,必须要有主键,通过主键索引效率很高。然而辅助索引须要两次查问,先查问到主键,而后再通过主键查问到数据。因而,主键不应该过大,因为主键太大,其余索引也都会很大。而 MyISAM 是非汇集索引,数据文件是拆散的,索引保留的是数据文件的指针。主键索引和辅助索引是独立的。
4、InnoDB 不保留表的具体行数,执行 select count(*) from table 时须要全表扫描。而 MyISAM 用一个变量保留了整个表的行数,执行上述语句时只须要读出该变量即可,速度很快;
5、Innodb 不反对全文索引,而 MyISAM 反对全文索引,查问效率上 MyISAM 要高;
如何抉择:
1、是否要反对事务,如果要请抉择 innodb,如果不须要能够思考 MyISAM;
2、如果表中绝大多数都只是读查问,能够思考 MyISAM,如果既有读写也挺频繁,请应用 InnoDB。
3、零碎奔溃后,MyISAM 复原起来更艰难,是否承受;
4、MySQL5.5 版本开始 Innodb 曾经成为 Mysql 的默认引擎 (之前是 MyISAM),阐明其劣势是引人注目的,如果你不晓得用什么,那就用 InnoDB,至多不会差。
二十四、数据库表创立注意事项
1、字段名及字段配制合理性
- 剔除关系不亲密的字段;
- 字段命名要有规定及绝对应的含意(不要一部分英文,一部分拼音,还有相似 a.b.c 这样不明含意的字段);
- 字段命名尽量不要应用缩写(大多数缩写都不能明确字段含意);
- 字段不要大小写混用(想要具备可读性,多个英文单词可应用下划线模式连贯);
- 字段名不要应用保留字或者关键字;
- 放弃字段名和类型的一致性;
- 谨慎抉择数字类型;
- 给文本字段留足余量;
2、零碎非凡字段解决及建成后倡议
- 增加删除标记(例如操作人、删除工夫);
- 建设版本机制;
3、表构造合理性配置
- 多型字段的解决,就是表中是否存在字段可能分解成更小独立的几局部(例如:人能够分为男人和女人);
- 多值字段的解决,能够将表分为三张表,这样使得检索和排序更加有调节,且保证数据的完整性!
4、其它倡议
- 对于大数据字段,独立表进行存储,以便影响性能(例如:简介字段);
- 应用 varchar 类型代替 char,因为 varchar 会动态分配长度,char 指定长度是固定的;
- 给表创立主键,对于没有主键的表,在查问和索引定义上有肯定的影响;
- 防止表字段运行为 null,倡议设置默认值(例如:int 类型设置默认值为 0)在索引查问上,效率立显;
- 建设索引,最好建设在惟一和非空的字段上,建设太多的索引对前期插入、更新都存在肯定的影响(思考理论状况来创立);
对于面试中有哪些经典的数据库,你学废了么?