介绍几个MySQL存储引擎
答:MySQL将数据用各种不同的技术存储在文件中,这些技术中的每一种技术都使用不同的存储机制、索引技巧、锁定水平并且最终提供广泛的不同的功能和能力。这些不同的技术以及配套的相关功能在 mysql中被称作存储引擎(也称作表类型)。
- MyISAM引擎:MyISAM引擎是MySQL默认的存储引擎,MyISAM不支持事务和行级锁,所以MyISAM引擎速度很快,性能优秀。MyISAM可以对整张表加锁,支持并发插入,支持全文索引。
缺点:不支持事务和行级锁,也不支持外键
优点:访问速度快,对事务的完整性没有要求或者以select、insert为主的应用基本上都可以使用这个引擎来创建,MyISAM再磁盘上存储成三个文件,其文件名都和表名相同,但扩展名分别是:.frm(存储表定义),.MYD(存储数据),.MYI(存储索引) - InnoDB引擎:InnoDB是专为事务设计的存储引擎,支持事务,支持外键,拥有高并发处理能力。但是,InnoDB在创建索引和加载数据时,比MyISAM慢。-->InnoDB有两种模式的行锁:(面试就问的这里,GG了,如何对表中的一条记录加锁?)
1)共享锁:允许一个事务去读一行,阻止其他事务获得相同数据集的排他锁。
( Select * from table_name where ......lock in share mode)
2)排他锁:允许获得排他锁的事务更新数据,阻止其他事务取得相同数据集的共享读锁和 排他写锁。(select * from table_name where.....for update) - Memory引擎(采用哈希索引):内存表,Memory引擎将数据存储在内存中,表结构不是存储在内存中的,查询时不需要执行磁盘I/O操作,所以要比MyISAM和InnoDB快很多倍,但是数据库断电或是重启后,表中的数据将会丢失,表结构不会丢失.
简单的介绍索引
答:索引是存储引擎用于快速找到记录的一种数据结构。索引本身很大,不可能全部存储在内存中,因此索引以索引表的形式存储在磁盘中。
索引是在存储引擎中实现的,而不是在服务器层中实现的。所以,每种存储引擎的索引都不一定完全相同,并不是所有的存储引擎都支持所有的索引类型。
(滴滴、宜信、广联达面试GG了,B+、B-区别?)
★ B-树索引:每一个叶子节点都包含指向下一个叶子节点的指针,从而方便叶子节点的范围遍历。B-Tree通常意味着所有的值都是按顺序存储的,并且每一个叶子页到根的距离相同,很适合查找范围数据。
★ B+树索引:并不能找到一个给定健值的具体行,B+树索引只能找到被查找数据行所在的页,然后从数据库将页读入内存,在内存中查找。B+树索引可以分为聚集索引和辅助索引。聚簇索引是按照数据存放的逻辑地址为顺序的,而非聚簇索引就不一样了;聚簇索引能提高多行检索的速度,而非聚簇索引对于单行的检索很快。
○ 聚集索引 :聚集索引是一种索引组织形式,索引的键值逻辑顺序决定了表数据行的物理存储顺序。 聚集索引对于那些经常要搜索范围值的列特别有效。使用聚集索引找到包含第一个值的行后,便可以确保包含后续索引值的行在物理相邻。
InnoDB的数据文件本身要按主键聚集,所以InnoDB要求表必须有主键(MyISAM可以没有主键),如果没有显式指定,则MySQL系统会自动选择一个可以唯一标识数据记录的列作为主键,如果不存在这种列,则MySQL自动为InnoDB表生成一个隐含字段作为主键,这个字段长度为6个字节,类型为长整形。
○ 辅助索引:叶结点的data域存放的是对应记录的主键的key。 对于建立辅助索引的表需要先根据辅助索引找到相应的主键,再根据主键在聚集索引中找到相应的记录集。
○ 非聚集索引
非聚集索引则就是普通索引了,仅仅只是对数据列创建相应的索引,不影响整个表的物理存储顺序。主键索引中,叶节点的data域存放的是数据记录的地址,如果指定的Key存在,则取出其data域的值,然后以data域的值为地址,读取相应数据记录。(MYISAM采用此种索引方式)。
区别:
聚集索引表里数据物理存储顺序和主键索引的顺序一致,所以如果新增数据是离散的,会导致数据块趋于离散,而不是趋于顺序。而非聚集索引表数据写入的顺序是按写入时间顺序存储的。聚簇索引索引的叶节点就是数据节点;而非聚簇索引的叶节点仍然是索引节点,只不过有一个指针指向对应的数据块。
适用情景
★ Hash索引:哈希索引基于哈希表实现,只有精确索引所有列的查询才有效。对于每一行数据,存储引擎都会对所有的索引列计算一个哈希码,哈希码是一个较小的值,并且不同键值的行计算出来的哈希码也不一样。哈希索引将所有的哈希存储在索引中,同时在哈希表中保存指向每个数据的指针。
哈希索引中存储的是:哈希值+数据行指针
MySQL中,只有Memory存储引擎显示支持hash索引,是Memory表的默认索引类型,尽管Memory表也可以使用B-Tree索引。Memory存储引擎支持非唯一hash索引,这在数据库领域是罕见的,如果多个值有相同的hash code,索引把它们的行指针用链表保存到同一个hash表项中。
索引有如下优点与缺点:
★ 优点
1.可以通过建立唯一索引或者主键索引,保证数据库表中每一行数据的唯一性
2.建立索引可以大大提高检索的数据,以及减少表的检索行数
3.在表连接的连接条件,可以加速表与表直接的相连
4.在分组和排序字句进行数据检索,可以减少查询时间中分组和 排序时所消耗的时间(数据库的记录会重新排序)
5.建立索引,在查询中使用索引,可以提高性能
--索引大大减小了服务器需要扫描的数据量
--索引可以帮助服务器避免排序和临时表
--索引可以将随机IO变成顺序IO
△ 缺点
1.创建索引和维护索引会耗费时间,随着数据量的增加而增加
2.索引文件会占用物理空间,除了数据表需要占用物理空间之外,每一个索引还会占用一定的物理空间
3.当对表的数据进行 INSERT,UPDATE,DELETE 的时候,索引也要动态的维护,这样就会降低数据的维护速度,(建立索引会占用磁盘空间的索引文件。一般情况这个问题不太严重,但如果你在一个大表上创建了多种组合索引,索引文件的会膨胀很快)。
索引的使用:最好的做法是创建表的时候创建索引,如果创建表之后再修改新建索引的话,对于聚集索引,会根据原来的表,创建一个新的表带有索引数据结构,再把原来的表删去,新创建的表改成原来的表的名字。而非聚集索引则是通过修改索引文件来完成。所以都是需要占用额外的资源来修改或新建索引的。
什么是事务?有哪些属性?以及属性的意义。
答:事务是并发操作的单位,是用户定义的一个操作序列。
事务的四个特性:原子性(事务必须是一个不可分割的整体)、一致性(执行完数据库操作后,数据不会被破坏,A给B充Q币,A充了之后B能看见自己的Q币多了)、隔离性(写写之间隔离)、持久性(数据库必须要保证有一条数据永久地存放在磁盘)。
详细的关于事务的学习,推荐看这篇文章:http://blog.csdn.net/u014079773/article/details/52808193
SQL语句常用优化技巧
答:要提高SQL语句的执行效率,最常见的方法就是建立索引,以及尽量避免全表扫描。一个简单的优化,也许能让你的SQL执行效率提高几倍,甚至几十倍。
①.避免在where子句中使用 is null 或 is not null 对字段进行判断。
如:select id from table where name is null
在这个查询中,就算我们为 name 字段设置了索引,查询分析器也不会使用,因此查询效率底下。为了避免这样的查询,在数据库设计的时候,尽量将可能会出现 null 值的字段设置默认值,这里如果我们将 name 字段的默认值设置为0,那么我们就可以这样查询:
select id from table where name = 0
②.避免在 where 子句中使用 != 或 <> 操作符。
如:select name from table where id <> 0
数据库在查询时,对 != 或 <> 操作符不会使用索引,而对于 < 、 <= 、 = 、 > 、 >= 、 BETWEEN AND,数据库才会使用索引。因此对于上面的查询,正确写法应该是:
select name from table where id < 0
union all
select name from table where id > 0
这里我们为什么没有使用 or 来链接 where 后的两个条件呢?这就是我们下面要说的第3个优化技巧。
③.避免在 where 子句中使用 or来链接条件。
如:select id from tabel where name = 'UncleToo' or name = 'PHP'
这种情况,我们可以这样写:
select id from tabel where name = 'UncleToo'
union all
select id from tabel where name = 'PHP'
④.少用 in 或 not in。
虽然对于 in 的条件会使用索引,不会全表扫描,但是在某些特定的情况,使用其他方法也许效果更好。如:
select name from tabel where id in(1,2,3,4,5)
像这种连续的数值,我们可以使用 BETWEEN AND,如:
select name from tabel where id between 1 and 5
⑤.注意 like 中通配符的使用
下面的语句会导致全表扫描,尽量少用。如:
select id from tabel where name like'%UncleToo%'
或者
select id from tabel where name like'%UncleToo'
而下面的语句执行效率要快的多,因为它使用了索引:
select id from tabel where name like'UncleToo%'
⑥.避免在 where 子句中对字段进行表达式操作。
如:select name from table where id/2 = 100
正确的写法应该是:
select name from table where id = 100*2
⑦.避免在 where 子句中对字段进行函数操作。
如:select id from table where substring(name,1,8) = 'UncleToo'
或 select id from table where datediff(day,datefield,'2014-07-17') >= 0
这两条语句中都对字段进行了函数处理,这样就是的查询分析器放弃了索引的使用。正确的写法是这样的:
select id from table where name like'UncleToo%'
或 select id from table where datefield <= '2014-07-17'
也就是说,不要在 where 子句中的 = 左边进行函数、算术运算或其他表达式运算。
⑧.在子查询中,用 exists 代替 in 是一个好的选择。
如:select name from a where id in(select id from b)
如果我们将这条语句换成下面的写法:select name from a where id exists(select 1 from b where id = a.id)
这样,查询出来的结果一样,但是下面这条语句查询的速度要快的多。
⑨.对查询进行优化,要尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引。
⑩.不要在 where 子句中的“=”左边进行函数、算术运算或其他表达式运算,否则系统将可能无法正确使用索引。
如果使用到了临时表,在存储过程的最后务必将所有的临时表显式删除,先 truncate table ,然后 drop table ,这样可以避免系统表的较长时间锁定。
尽量避免大事务操作,提高系统并发能力。
简要说NoSQL 数据库的分布式模型
答:分片 -- 特点:数据的各个部分存放在集群的不同服务器中;比如按字母来划分:以a-g 开头的键值都存放到第一台,服务器上,以h-n 开头的存放到第二台.
需要考虑的问题 -- 如何存放数据,让用户基本上只需从一台服务器上获取数据?如果经常需要与多个结点交互才能取到需要数据,可能分片策略不合适,或者该场景中分片不是一个理想的方案;
数据节点的分布 -- 地理位置与访问用户的关系 数据结点分布在全球各地,让北京的用户只需要访问北京的结点就能取到所需数据;
保持负载均衡 -- 优点:同时提升读取和写入性能、由于分片是将数据分散到多个结点存储,这样在写入时,压力同样分散;横向扩展写入能力 缺点:降低数据库的错误恢复能力,分片后,集群中结点的故障将导致部分数据丢失;
解决方案 -- 每个分片数据不只存放在一个结点上,冗余存放,增加数据安全性(通过后面讲到的与主从复制的结合使用,是常用的手段)
主从复制 -- 特点:主节点存放权威数据,负责数据更新操作;主节点将更新的数据复制到从节点;优点:有助于提升数据读取性能,从结点只负责查询,增加从结点提升数据读取性能,增强“读取操作的故障恢复能力”,主节点损坏,依然可处理读取请求;从结点升级为主结点后可以处理更新请求;
“一拖一” 即时备份的单存储方案 -- 即使不需要分布式部署,主从复制也可以用来做为单机服务器备份的部署方案;缺点:数据的不一致性(未及时更新),主节点更新后,同步到各个从结点的数据不能保证及时,可能导致各个结点上查询的数据不一致(只具有最终一致性)、对提升写入操作性能帮助不大、所有的更新操作都通过主结点处理,对于更新频繁的业务,使用主从复制模型优势不大;
主节点是系统的瓶颈和弱点
对等复制 -- 特点:所有节点地位相同,都可接收查询和写入请求;各节点将自己的更新的数据复制到其他节点;优点:从容处理出错节点,不必担心数据请求的丢失增加节点,轻易提升查询和写入性能;缺点:数据不一致性、写入和读取都有可能发生冲突;
结合使用 -- 分片和主从复制中的一拖一方案结合使用、分片的作用在于数据的分布式存储;主从复制的作用在于为各个分片结点提供备份,增加数据安全;