mysql高级特性之数据分区



mysql高级特性
  1 以存储引擎的角度分析,分区表和物理表没有区别。是按照一定的规则将数据分别存储的逻辑设计。器底层是由多个物理字表组成。
  
  2 分区的原理
     分区表由多个相关的底层表实现,这些底层表也是由句柄对象表示,所以我们可以直接访问各个分区。存储引擎管理分区的各个底层
	 表和管理普通表一样(所有底层表都必须使用相同的存储引擎),分区表的索引只是在各个底层表上各自加上一个完全相同的索引。
	 从存储引擎角度来看,底层表和一个普通表没有任何的不同,存储引擎也无需知道这是一个普通表还是一个分区表。
	 在分区表中 索引已经失去作用,添加索引只会增加服务器的负担。如果发现某一些索引仍会起作用那也只是短暂的
	 回光返照。随着数据规模的增加,这些索引必然会成为负担。
	 
  3 分区表的类型
    1 根据范围进行分区
	2 根据实践间隔分区
	3 	mysql还支持键值、哈希、列表分区,这其中还支持子分区。
	4 还可以根据数学模函数来进行分区。
	

  4 如何使用分区表
    在分区表中,索引在空间和维护上的消耗巨大,尤其是当表非常大的时候,特别不希望使用索引,即使真的使用索引,你会
	发现数据并不是按照想要的方式聚集的,而且会有大量的碎片产生,最终会导致一个查询产生成千上万的随机IO,应用
	程序也随之僵死。有时候也可以通过一两个索引解决一些问题,不过多数情况下,索引不会有任何作用,这时候有两条路可选:
	让所有的查询都只在数据表上做顺序扫描,或者将数据表和索引全部都缓存在内存中。
	
	这里需要再陈述一遍,在数据量超大的时候,B-Tree索引就无法起作用了。除非是索引覆盖查询,否则数据库服务器
	需要根据索引扫描的结果回表查询所有符合条件的记录,如果数据量巨大,这将产生大量随机IO,随之,数据库的响应时间
	将大到不可接受。另外,索引维护(磁盘空间、IO操作)的代价也非常高。
	
	这正是分区所要做的事情。理解分区时还可以将其当做索引的最初形态,以待价非常小的方式定位到需要的数据在那一片区域。
	在这片区域中,你可以做顺序扫描,可以建索引,还可以将数据都缓存到内存等。因为分区无需额外的数据结构记录每个
	分区有哪些数据,分区不需要精确定位每条数据的位置,也就无需额外的数据结构,只需要一个简单的表达式就可以表达每个分区
	存放的是什么数据。
	
	为了保证大数据量的可扩展性,一般有下面两个策略:
	
	全量扫描数据,不需要任何索引。
	 可以使用简单的分区方式存放表,不需要任何索引,根据分区的规则大致定位需要的数据位置。只要能够使用where条件,将需要的数据限制在少数分区
	 中,则效率是非常高的。使用该策略假设不用将数据完全放入到内存中,同时还假设需要的数据全都在磁盘上,因为内存相对很小
	 数据很快会被挤出内存,所以缓存起不了任何作用。这个策略适用于以正常的方式访问大量数据的时候。
	 
	索引数据,并分离热点。
	  如果某部分数据有明显的热点,而且除了这部分数据,其他数据很少被访问到,那么可以将这部分热点数据单独放在一个分区中,
	  让这个分区的数据能够有机会都缓存在内存中。这样查询就可以只访问一个很小的分区表,能够使用索引,也能够有效的使用缓存。
	  
   5 分区的陷阱
     前面介绍的分区策略都基于两个非常重要的假设:查询都能够过滤掉很多额外的分区、分区本身不会带来很多额外的代价。
    事实是这两个假设在某些场景下会有问题。
	
	1)null值会使分区过滤无效
	  mysql分区时会创建第一个分区,用于存放分区列为null 或非法的记录。
	  例如 按照 partition by year(order_date) 来分区,那么order_date为null 或者是一个非法的值得时候,
	  记录都会被放入第一个分区。假设存在下面的查询 where order_date between 2012-09-08 and 2012-08-07
	  那么这个查询会检查2012这个分区,同时他还会检查第一个分区,检查第一个分区是因为year接受的参数
	  可能是null或者非法数值,如果是Null或者非法的话就会被放入第一个分区。
	  
	  同时,如果第一个分区非常大,特别是使用 全量扫描数据,不使用索引的策略时,代价会非常大。
	  
	  为了避免这种情况,我们可以创建一个无用的第一个分区,例如上面的例子可以使用
	  partition p_nulls values less than (0) 来创建第一个分区,如果插入的数据都是有效的,那么
	  第一个分区就是空的,即使需要检测第一个分区,代价也会非常小。
	  
	  在mysql 5.5就不需要这个技巧了,因为可以直接使用列本身而不是基于列的函数进行分区。
	  partition by range columns(order_date).
	  
	 2) 分区列和索引列不匹配
	    如果定义的索引咧和分区列不匹配,会导致查询无法进行分区过滤。假如在b列上建立索引	,在a列上进行分区。
		因为每个分区都有其独立的索引,所以扫描列a上的索引就需要扫描每一个分区内对应的索引。要避免这种情况,就要避免建立和分区不匹配的索引,除非查询中还同时包含了可以过滤分区的条件。
	  
	 3) 选择分区的成本可能很高
	    对于使用范围来分区的情况来说,查询的成本可能会非常高。这一行属于哪个分区,这些符合查询条件的行分布在那些区
		找到这样的回答的代价可能会非常高。随着分区数的增长,成本会越来越高。
		在按行写入大量数据的时候,每写入一行数据到范围分区的表时,都需要扫描分区定义列表来找到合适的分区。
		
		可以通过限制分区的数量来缓解这类问题,对于大多数系统来说100个分区是没有问题的。
		其他的分区类型,比如键分区和哈希分区,则没有这样的问题。
		
	 4) 打开并锁住所有底层表的成本可能很高
	    当查询访问分区表的时候,mysql需要打开并锁住所有的底层表,这是分区表的另一个开销。这个操作在分区过滤之前发生,所以无法通过分区过滤
		降低此开销,并且该开销也和分区类型无关,会影响所有的查询。这一点对于一些本身操作非常快的查询,比如根据主键查找
		单行,会带来明显的额外开销。
		
		我们可以通过使用批量操作的方式来降低这个操作带来的开销。同时还需要限制分区的个数。
		
	 5) 维护分区的成本可能很高	  
	  
	  
	  
	  
	  
	  
	  
	  

你可能感兴趣的:(java,数据结构,mongodb,分区,mysql)