使用视图的大部分情况是为了保障数据安全性,提高查询效率
什么是视图

视图是从一个或多个表中导出来的表,是一种虚拟存在的表。

视图就像一个窗口,通过这个窗口可以看到系统专门提供的数据。

这样,用户可以不用看到整个数据库中的数据,而之关心对自己有用的数据。

数据库中只存放了视图的定义,而没有存放视图中的数据,这些数据存放在原来的表中。

使用视图查询数据时,数据库系统会从原来的表中取出对应的数据。

视图中的数据依赖于原来表中的数据,一旦表中数据发生改变,显示在视图中的数据也会发生改变。



视图的作用

1.使操作简单化,可以对经常使用的查询定义一个视图,使用户不必为同样的查询操作指定条件

2.增加数据的安全性,通过视图,用户只能查询和修改指定的数据。

3.提高表的逻辑独立性,视图可以屏蔽原有表结构变化带来的影响。



总而言之,使用视图的大部分情况是为了保障数据安全性,提高查询效率



参考表:





创建视图的语法


复制代码 代码如下:
CREATE [ALGORITHM]={UNDEFINED|MERGE|TEMPTABLE}]
      VIEW 视图名 [(属性清单)]
      AS SELECT 语句
      [WITH [CASCADED|LOCAL] CHECK OPTION];

ALGORITHM表示视图选择的算法(可选参数)

     UNDEFINED:MySQL将自动选择所要使用的算法
     MERGE:将视图的语句与视图定义合并起来,使得视图定义的某一部分取代语句的对应部分
     TEMPTABLE:将视图的结果存入临时表,然后使用临时表执行语句

视图名表示要创建的视图的名称

属性清单表示视图中的列名,默认与SELECT查询结果中的列名相同(可选参数)

WITH CHECK OPTION表示更新视图时要保证在该试图的权限范围之内(可选参数)

     CASCADED:更新视图时要满足所有相关视图和表的条件
     LOCAL:更新视图时,要满足该视图本身定义的条件即可



tips:创建试图时最好加上WITH CASCADED CHECK OPTION参数,这种方式比较严格

     可以保证数据的安全性


视图操作
在单表上创建视图


复制代码 代码如下:
mysql> CREATE VIEW work_view(ID,NAME,ADDR) AS SELECT id,name,address FROM work;  
Query OK, 0 rows affected (0.05 sec)

此处work_view为视图名,后面括号内的参数代表视图中的列

AS表示将后面SELECT 语句中的查询结果赋给前面的视图中

在多表上创建视图


复制代码 代码如下:
mysql> CREATE ALGORITHM=MERGE VIEW work_view2(ID,NAME,SALARY)
   -> AS SELECT work.id,name,salary FROM work,salary
   -> WHERE work.id=salary.id
   -> WITH LOCAL CHECK OPTION;
Query OK, 0 rows affected (0.02 sec)

在多表中创建视图需要两表有指定联系,如上面的work.id=salary.id


SELECT查询视图


复制代码 代码如下:
mysql> SELECT * FROM work_view;
+----+--------+--------+
| ID | NAME   | ADDR   |
+----+--------+--------+
|  1 | 张三   | 北京   |
|  2 | 李四   | 上海   |
|  3 | 王五   | 湖南   |
|  4 | 赵六   | 重庆   |
+----+--------+--------+
rows in set (0.00 sec)

此处的SELECT语句用法和其他表中的用法一样

别忘了,视图也是一张表,只不过它是虚拟的


DESCRIBE查看视图基本信息


复制代码 代码如下:
mysql> DESCRIBE work_view;
+-------+-------------+------+-----+---------+-------+
| Field | Type        | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| ID    | int(10)     | NO   |     | NULL    |       |
| NAME  | varchar(20) | NO   |     | NULL    |       |
| ADDR  | varchar(50) | YES  |     | NULL    |       |
+-------+-------------+------+-----+---------+-------+
rows in set (0.00 sec)

与以往一样,此处的DESCRIBE可以简写为DESC


SHOW TABLE STATUS查看视图基本信息


复制代码 代码如下:
mysql> SHOW TABLE STATUS LIKE 'work_view'\G
*************************** 1. row ***************************
          Name: work_view
        Engine: NULL
       Version: NULL
    Row_format: NULL
          Rows: NULL
Avg_row_length: NULL
   Data_length: NULL
Max_data_length: NULL
  Index_length: NULL
     Data_free: NULL
Auto_increment: NULL
   Create_time: NULL
   Update_time: NULL
    Check_time: NULL
     Collation: NULL
      Checksum: NULL
Create_options: NULL
       Comment: VIEW
row in set (0.00 sec)

此处大部分信息显示为NULL,更加说明了视图只是一张虚拟表

如果使用SHOW TABLE STATUS查看一张真实表,结果就不会如此

SHOW CREATE VIEW查看视图详细信息


复制代码 代码如下:
mysql> SHOW CREATE VIEW work_view\G
*************************** 1. row ***************************
               View: work_view
        Create View: CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `work_view` AS select `work`.`id` AS `ID`,`work`.`name` AS `NAME`,`work`.`address` AS `ADDR` from `work`
character_set_client: utf8
collation_connection: utf8_general_ci
row in set (0.00 sec)

尼玛好复杂,这里包含了视图的各个属性

在views表中查看视图详细信息
复制代码 代码如下:
mysql> SELECT * FROM information_schema.views\G
*************************** 1. row ***************************
      TABLE_CATALOG: def
       TABLE_SCHEMA: person
         TABLE_NAME: work_view
    VIEW_DEFINITION: select `person`.`work`.`id` AS `ID`,`person`.`work`.`name` AS `NAME`,`person`.`work`.`address` AS `ADDR` from `person`.`work`
       CHECK_OPTION: NONE
       IS_UPDATABLE: YES
            DEFINER: root@localhost
      SECURITY_TYPE: DEFINER
CHARACTER_SET_CLIENT: utf8
COLLATION_CONNECTION: utf8_general_ci
*************************** 2. row ***************************
      TABLE_CATALOG: def
       TABLE_SCHEMA: person
         TABLE_NAME: work_view2

information_schema.views表内包含了所有的视图定义信息

不过,通常使用SHOW CREATE VIEW 更加方便

这里信息太长,没有完全列举……


修改视图

修改视图是指修改数据库中已存在的表的定义,当基本表的某些字段发生改变时,可以通过修改视图来保持视图和基本表之间一致
CREATE OR REPLACE VIEW语句修改视图


复制代码 代码如下:
mysql> CREATE OR REPLACE ALGORITHM=TEMPTABLE
   -> VIEW work_view(ID,NAME)
   -> AS SELECT id,name FROM work;
Query OK, 0 rows affected (0.03 sec)

话说,CREATE OR REPLACE语句非常灵活

在视图存在的情况下可对视图进行修改,视图不在的情况下可创建视图

其基本用法和CREATE VIEW 几乎一致


ALTER语句修改视图


复制代码 代码如下:
mysql> ALTER VIEW work_view2(NAME,SALARY,ADDR)
   -> AS SELECT name,salary,address FROM work,salary
   -> WHERE work.id=salary.id;
Query OK, 0 rows affected (0.03 sec)

我这把名字、工资和地址当做字段修改了视图

如果是真实的话,对小偷来说极为方便

更新视图

更新视图是指通过视图来插入、更新和删除表中的数据,以为视图是一个虚拟表,其中木有数据

通过视图更新时,都是转换到基本表来更新


复制代码 代码如下:
mysql> UPDATE work_view2 SET SALARY=5899.00 WHERE NAME='张三';
Query OK, 1 row affected (0.03 sec)
Rows matched: 1  Changed: 1  Warnings: 0

此处语句等价于
复制代码 代码如下:
mysql> UPDATE salary SET salary=5899.00 WHERE id=1;

tips:视图中虽然可以更新数据,但是有很多限制

   一般情况下,最好将视图作为查询数据的虚拟表,而不要通过视图更新数据


删除视图

删除视图是指删除数据库中已存在的视图,删除视图时,只能删除视图的定义,不会删除数据


复制代码 代码如下:
mysql> DROP VIEW IF EXISTS work_view;
Query OK, 0 rows affected (0.00 sec)

mysql> DROP VIEW work_view2;
Query OK, 0 rows affected (0.01 sec)


这里的IF EXIST参数用来判断视图是否存在,也可以不写
Tags:
触发器是由事件来触发某个操作,这些事件包括INSERT语句,UPDATE语句和DELETE语句
创建触发器

创建只有一个执行语句的触发器


复制代码 代码如下:
CREATE TRIGGER 触发器名 BEFORE|AFTER 触发事件
ON 表名 FOR EACH ROW 执行语句

其中,触发器名参数指要创建的触发器的名字

BEFORE和AFTER参数指定了触发执行的时间,在事件之前或是之后

FOR EACH ROW表示任何一条记录上的操作满足触发事件都会触发该触发器


复制代码 代码如下:
mysql> CREATE TRIGGER trig1 AFTER INSERT
   -> ON work FOR EACH ROW
   -> INSERT INTO time VALUES(NOW());
Query OK, 0 rows affected (0.09 sec)

上面创建了一个名为trig1的触发器,一旦在work中有插入动作,就会自动往time表里插入当前时间


创建有多个执行语句的触发器


复制代码 代码如下:
CREATE TRIGGER 触发器名 BEFORE|AFTER 触发事件
ON 表名 FOR EACH ROW
BEGIN
   执行语句列表
END

其中,BEGIN与END之间的执行语句列表参数表示需要执行的多个语句,不同语句用分号隔开

tips:一般情况下,mysql默认是以 ; 作为结束执行语句,与触发器中需要的分行起冲突

     为解决此问题可用DELIMITER,如:DELIMITER ||,可以将结束符号变成||

     当触发器创建完成后,可以用DELIMITER ;来将结束符号变成;


复制代码 代码如下:
mysql> DELIMITER ||
mysql> CREATE TRIGGER trig2 BEFORE DELETE
   -> ON work FOR EACH ROW
   -> BEGIN
   -> INSERT INTO time VALUES(NOW());
   -> INSERT INTO time VALUES(NOW());
   -> END
   -> ||
Query OK, 0 rows affected (0.06 sec)

mysql> DELIMITER ;


上面的语句中,开头将结束符号定义为||,中间定义一个触发器,一旦有满足条件的删除操作

就会执行BEGIN和END中的语句,接着使用||结束

最后使用DELIMITER ; 将结束符号还原


查看触发器
SHOW TRIGGERS语句查看触发器信息


复制代码 代码如下:
mysql> SHOW TRIGGERS\G;
*************************** 1. row ***************************
            Trigger: trig1
              Event: INSERT
              Table: work
          Statement: INSERT INTO time VALUES(NOW())
             Timing: AFTER
            Created: NULL
           sql_mode:
            Definer: root@localhost
character_set_client: utf8
collation_connection: utf8_general_ci
 Database Collation: latin1_swedish_ci

结果会显示所有触发器的基本信息

tips:SHOW TRIGGERS语句无法查询指定的触发器


在triggers表中查看触发器信息


复制代码 代码如下:
mysql> SELECT * FROM information_schema.triggers\G
*************************** 1. row ***************************
          TRIGGER_CATALOG: def
           TRIGGER_SCHEMA: person
             TRIGGER_NAME: trig1
       EVENT_MANIPULATION: INSERT
     EVENT_OBJECT_CATALOG: def
      EVENT_OBJECT_SCHEMA: person
       EVENT_OBJECT_TABLE: work
             ACTION_ORDER: 0
         ACTION_CONDITION: NULL
         ACTION_STATEMENT: INSERT INTO time VALUES(NOW())

结果显示了所有触发器的详细信息,同时,该方法可以查询制定触发器的详细信息
复制代码 代码如下:
mysql> SELECT * FROM information_schema.triggers WHERE TRIGGER_NAME='trig1'\G
*************************** 1. row ***************************
          TRIGGER_CATALOG: def
           TRIGGER_SCHEMA: person
             TRIGGER_NAME: trig1
       EVENT_MANIPULATION: INSERT
     EVENT_OBJECT_CATALOG: def
      EVENT_OBJECT_SCHEMA: person
       EVENT_OBJECT_TABLE: work

tips:所有触发器信息都存储在information_schema数据库下的triggers表中

     可以使用SELECT语句查询,如果触发器信息过多,最好通过TRIGGER_NAME字段指定查询


删除触发器


复制代码 代码如下:
mysql> DROP TRIGGER trig1;
Query OK, 0 rows affected (0.04 sec)

删除触发器之后最好使用上面的方法查看一遍

同时,也可以使用database.trig来指定某个数据库中的触发器

tips:如果不需要某个触发器时一定要将这个触发器删除,以免造成意外操作
Tags: ,
上海网务网络信息有限公司,2004年6月成立于上海,是上海市科委认证的高新技术企业。上海网务网络信息有限公司有着非凡的技术设计能力,自主研发了 ArthurXF  PHP开发框架,并在ArthurXF开发框架之上研发了BIWEB商务智能网站系统,BIWEB是经过不断的在各种大型项目中实践、总结、开发设计出来 的一个快速开发、简单易用的面向对象的企业应用级PHP MVC建站系统。BIWEB自2005年开源推出后,BIWEB网站系统在经历了多次重大版本升级之后,至2013年8月BIWEB推出webapp版 本,标志着BIWEB从电脑网站系统正式步入移动端应用系统时代。

上海网务公司在行业中发展多年,发现目前行业人才奇缺,招聘来的人员都需要再培训不能直接上岗,遂在上海、桂林、东莞等多地设立实习训练基地,为本公司及行业培养大量直接跟行业接轨的人才。上海网务公司设置的实训课程,直接按照工作岗位设立,完成实训课程即可就业。上海网务公司在行业内积累了大量人脉和口 碑,同行前来招聘络绎不绝,实训人员供不应求。如您有朋友想加入IT行业,请推荐来上海网务公司实训,上海网务公司对实训完成的学生可以解决上海就业。





BIWEB上海实训基地
1.上海市徐汇区漕溪路165号华谊党校1203室
2.上海黄浦区打浦路8号海华商厦2楼225室

BIWEB东莞实训基地
东莞市南城区西平二路弥珍道3栋306室
电话:0769-23889935

BIWEB桂林实训基地
桂林市雁山区果园村委旁二楼
电话:13367735767

实训基地加盟联系方式
联系人:肖飞
电话:13124812420
Tags:
一,什么是mysql分表,分区

什么是分表,从表面意思上看呢,就是把一张表分成N多个小表,具体请看mysql分表的3种方法

什么是分区,分区呢就是把一张表的数据分成N多个区块,这些区块可以在同一个磁盘上,也可以在不同的磁盘上,具体请参考mysql分区功能详细介绍,以及实例

二,mysql分表和分区有什么区别呢

1,实现方式上

a),mysql的分表是真正的分表,一张表分成很多表后,每一个小表都是完正的一张表,都对应三个文件,一个.MYD数据文件,.MYI索引文件,.frm表结构文件。

view sourceprint?1 [root@BlackGhost test]# ls |grep user    

2 alluser.MRG    

3 alluser.frm    

4 user1.MYD    

5 user1.MYI    

6 user1.frm    

7 user2.MYD    

8 user2.MYI    

9 user2.frm

简单说明一下,上面的分表呢是利用了merge存储引擎(分表的一种),alluser是总表,下面有二个分表,user1,user2。他们二个都是独立的表,取数据的时候,我们可以通过总表来取。这里总表是没有.MYD,.MYI这二个文件的,也就是说,总表他不是一张表,没有数据,数据都放在分表里面。我们来看看.MRG到底是什么东西

view sourceprint?1 [root@BlackGhost test]# cat alluser.MRG |more    

2 user1    

3 user2    

4 #INSERT_METHOD=LAST

从上面我们可以看出,alluser.MRG里面就存了一些分表的关系,以及插入数据的方式。可以把总表理解成一个外壳,或者是联接池。

b),分区不一样,一张大表进行分区后,他还是一张表,不会变成二张表,但是他存放数据的区块变多了。

view sourceprint?1 [root@BlackGhost test]# ls |grep aa    

2 aa#P#p1.MYD    

3 aa#P#p1.MYI    

4 aa#P#p3.MYD    

5 aa#P#p3.MYI    

6 aa.frm    

7 aa.par

从上面我们可以看出,aa这张表,分为二个区,p1和p3,本来是三个区,被我删了一个区。我们都知道一张表对应三个文件.MYD,.MYI,.frm。分区呢根据一定的规则把数据文件和索引文件进行了分割,还多出了一个.par文件,打开.par文件后你可以看出他记录了,这张表的分区信息,根分表中的.MRG有点像。分区后,还是一张,而不是多张表。

2,数据处理上

a),分表后,数据都是存放在分表里,总表只是一个外壳,存取数据发生在一个一个的分表里面。看下面的例子:

select * from alluser where id=’12′表面上看,是对表alluser进行操作的,其实不是的。是对alluser里面的分表进行了操作。

b),分区呢,不存在分表的概念,分区只不过把存放数据的文件分成了许多小块,分区后的表呢,还是一张表。数据处理还是由自己来完成。

3,提高性能上

a),分表后,单表的并发能力提高了,磁盘I/O性能也提高了。并发能力为什么提高了呢,因为查寻一次所花的时间变短了,如果出现高并发的话,总表可以根据不同的查询,将并发压力分到不同的小表里面。磁盘I/O性能怎么搞高了呢,本来一个非常大的.MYD文件现在也分摊到各个小表的.MYD中去了。

b),mysql提出了分区的概念,我觉得就想突破磁盘I/O瓶颈,想提高磁盘的读写能力,来增加mysql性能。

在这一点上,分区和分表的测重点不同,分表重点是存取数据时,如何提高mysql并发能力上;而分区呢,如何突破磁盘的读写能力,从而达到提高mysql性能的目的。

4),实现的难易度上

a),分表的方法有很多,用merge来分表,是最简单的一种方式。这种方式根分区难易度差不多,并且对程序代码来说可以做到透明的。如果是用其他分表方式就比分区麻烦了。

b),分区实现是比较简单的,建立分区表,根建平常的表没什么区别,并且对开代码端来说是透明的。

三,mysql分表和分区有什么联系呢

1,都能提高mysql的性高,在高并发状态下都有一个良好的表面。

2,分表和分区不矛盾,可以相互配合的,对于那些大访问量,并且表数据比较多的表,我们可以采取分表和分区结合的方式(如果merge这种分表方式,不能和分区配合的话,可以用其他的分表试),访问量不大,但是表数据很多的表,我们可以采取分区的方式等。

另附一段评价:
在以前,一种解决方案就是使用 MERGE

类型,这是一个非常方便的做饭。架构和程序基本上不用做改动,不过,它的缺点是显见的:

只能在相同结构的 MyISAM 表上使用
无法享受到 MyISAM 的全部功能,例如无法在 MERGE 类型上执行 FULLTEXT 搜索
它需要使用更多的文件描述符
读取索引更慢
这个时候,MySQL 5.1 中新增的分区(Partition)功能的优势也就很明显了:

与单个磁盘或文件系统分区相比,可以存储更多的数据
很容易就能删除不用或者过时的数据
一些查询可以得到极大的优化
涉及到 SUM()/COUNT() 等聚合函数时,可以并行进行
IO吞吐量更大
分区允许可以设置为任意大小的规则,跨文件系统分配单个表的多个部分。实际上,表的不同部分在不同的位置被存储为单独的表。

Tags: , ,
一,什么是数据库分区
前段时间写过一篇关于mysql分表的的文章,下面来说一下什么是数据库分区,以mysql为例。mysql数据库中的数据是以文件的形势存在磁盘上的,默认放在/mysql/data下面(可以通过my.cnf中的datadir来查看),一张表主要对应着三个文件,一个是frm存放表结构的,一个是myd存放表数据的,一个是myi存表索引的。如果一张表的数据量太大的话,那么myd,myi就会变的很大,查找数据就会变的很慢,这个时候我们可以利用mysql的分区功能,在物理上将这一张表对应的三个文件,分割成许多个小块,这样呢,我们查找一条数据时,就不用全部查找了,只要知道这条数据在哪一块,然后在那一块找就行了。如果表的数据太大,可能一个磁盘放不下,这个时候,我们可以把数据分配到不同的磁盘里面去。

备注说明:上面是只对myisam存储引擎的,下面是innodb
innodb的数据库的物理文件结构为:

.frm文件

.ibd文件和.ibdata文件:

这两种文件都是存放innodb数据的文件,之所以用两种文件来存放innodb的数据,是因为innodb的数据存储方式能够通过配置来决定是使用共享表空间存放存储数据,还是用独享表空间存放存储数据。

独享表空间存储方式使用.ibd文件,并且每个表一个ibd文件

共享表空间存储方式使用.ibdata文件,所有表共同使用一个ibdata文件


分区的二种方式
1,横向分区
什么是横向分区呢?就是横着来分区了,举例来说明一下,假如有100W条数据,分成十份,前10W条数据放到第一个分区,第二个10W条数据放到第二个分区,依此类推。也就是把表分成了十分,根用merge来分表,有点像哦。取出一条数据的时候,这条数据包含了表结构中的所有字段,也就是说横向分区,并没有改变表的结构。

2,纵向分区
什么是纵向分区呢?就是竖来分区了,举例来说明,在设计用户表的时候,开始的时候没有考虑好,而把个人的所有信息都放到了一张表里面去,这样这个表里面就会有比较大的字段,如个人简介,而这些简介呢,也许不会有好多人去看,所以等到有人要看的时候,在去查找,分表的时候,可以把这样的大字段,分开来。

感觉数据库的分区好像是切苹果,到底是横着切呢,还是竖着切,根据个人喜好了,mysql提供的分区属于第一种,横向分区,并且细分成很多种方式。下面将举例说明一下。

二,mysql的分区
我觉着吧,mysql的分区只有一种方式,只不过运用不同的算法,規则将数据分配到不同的区块中而已。

1,mysql5.1及以上支持分区功能
安装安装的时候,我们就可以查看一下

view sourceprint?1 [root@BlackGhost mysql-5.1.50]# ./configure --help |grep -A 3 Partition  

2  === Partition Support ===  

3  Plugin Name:      partition  

4  Description:      MySQL Partitioning Support  

5  Supports build:   static

6  Configurations:   max, max-no-ndb

查看一下,如果发现有上面这个东西,说明他是支持分区的,默认是打开的。如果你已经安装过了mysql的话

view sourceprint?1 mysql> show variables like "%part%";  

2 +-------------------+-------+  

3 | Variable_name     | Value |  

4 +-------------------+-------+  

5 | have_partitioning | YES   |  

6 +-------------------+-------+  

7 1 row in set (0.00 sec)

查看一下变量,如果支持的话,会有上面的提示的。

2,range分区
按照RANGE分区的表是通过如下一种方式进行分区的,每个分区包含那些分区表达式的值位于一个给定的连续区间内的行

view sourceprint?1 //创建range分区表  

2 mysql> CREATE TABLE IF NOT EXISTS `user` (  

3  ->   `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '用户ID',  

4  ->   `name` varchar(50) NOT NULL DEFAULT '' COMMENT '名称',  

5  ->   `sex` int(1) NOT NULL DEFAULT '0' COMMENT '0为男,1为女',  

6  ->   PRIMARY KEY (`id`)  

7  -> ) ENGINE=MyISAM  DEFAULT CHARSET=utf8 AUTO_INCREMENT=1  

8  -> PARTITION BY RANGE (id) (  

9  ->     PARTITION p0 VALUES LESS THAN (3),  

10  ->     PARTITION p1 VALUES LESS THAN (6),  

11  ->     PARTITION p2 VALUES LESS THAN (9),  

12  ->     PARTITION p3 VALUES LESS THAN (12),  

13  ->     PARTITION p4 VALUES LESS THAN MAXVALUE  

14  -> );  

15 Query OK, 0 rows affected (0.13 sec)  

16    

17 //插入一些数据  

18 mysql> INSERT INTO `test`.`user` (`name` ,`sex`)VALUES ('tank', '0')  

19  -> ,('zhang',1),('ying',1),('张',1),('映',0),('test1',1),('tank2',1)  

20  -> ,('tank1',1),('test2',1),('test3',1),('test4',1),('test5',1),('tank3',1)  

21  -> ,('tank4',1),('tank5',1),('tank6',1),('tank7',1),('tank8',1),('tank9',1)  

22  -> ,('tank10',1),('tank11',1),('tank12',1),('tank13',1),('tank21',1),('tank42',1);  

23 Query OK, 25 rows affected (0.05 sec)  

24 Records: 25  Duplicates: 0  Warnings: 0  

25    

26 //到存放数据库表文件的地方看一下,my.cnf里面有配置,datadir后面就是  

27 [root@BlackGhost test]# ls |grep user |xargs du -sh  

28 4.0K    user#P#p0.MYD  

29 4.0K    user#P#p0.MYI  

30 4.0K    user#P#p1.MYD  

31 4.0K    user#P#p1.MYI  

32 4.0K    user#P#p2.MYD  

33 4.0K    user#P#p2.MYI  

34 4.0K    user#P#p3.MYD  

35 4.0K    user#P#p3.MYI  

36 4.0K    user#P#p4.MYD  

37 4.0K    user#P#p4.MYI  

38 12K    user.frm  

39 4.0K    user.par  

40    

41 //取出数据  

42 mysql> select count(id) as count from user;  

43 +-------+  

44 | count |  

45 +-------+  

46 |    25 |  

47 +-------+  

48 1 row in set (0.00 sec)  

49    

50 //删除第四个分区  

51 mysql> alter table user drop partition p4;  

52 Query OK, 0 rows affected (0.11 sec)  

53 Records: 0  Duplicates: 0  Warnings: 0  

54    

55 /**存放在分区里面的数据丢失了,第四个分区里面有14条数据,剩下的3个分区  

56 只有11条数据,但是统计出来的文件大小都是4.0K,从这儿我们可以看出分区的  

57 最小区块是4K  

58 */

59 mysql> select count(id) as count from user;  

60 +-------+  

61 | count |  

62 +-------+  

63 |    11 |  

64 +-------+  

65 1 row in set (0.00 sec)  

66    

67 //第四个区块已删除  

68 [root@BlackGhost test]# ls |grep user |xargs du -sh  

69 4.0K    user#P#p0.MYD  

70 4.0K    user#P#p0.MYI  

71 4.0K    user#P#p1.MYD  

72 4.0K    user#P#p1.MYI  

73 4.0K    user#P#p2.MYD  

74 4.0K    user#P#p2.MYI  

75 4.0K    user#P#p3.MYD  

76 4.0K    user#P#p3.MYI  

77 12K    user.frm  

78 4.0K    user.par  

79    

80 /*可以对现有表进行分区,并且会按規则自动的将表中的数据分配相应的分区  

81 中,这样就比较好了,可以省去很多事情,看下面的操作*/

82 mysql> alter table aa partition by RANGE(id)  

83  -> (PARTITION p1 VALUES less than (1),  

84  -> PARTITION p2 VALUES less than (5),  

85  -> PARTITION p3 VALUES less than MAXVALUE);  

86 Query OK, 15 rows affected (0.21 sec)   //对15数据进行分区  

87 Records: 15  Duplicates: 0  Warnings: 0  

88    

89 //总共有15条  

90 mysql> select count(*) from aa;  

91 +----------+  

92 | count(*) |  

93 +----------+  

94 |       15 |  

95 +----------+  

96 1 row in set (0.00 sec)  

97    

98 //删除一个分区  

99 mysql> alter table aa drop partition p2;  

100 Query OK, 0 rows affected (0.30 sec)  

101 Records: 0  Duplicates: 0  Warnings: 0  

102    

103 //只有11条了,说明对现有的表分区成功了  

104 mysql> select count(*) from aa;  

105 +----------+  

106 | count(*) |  

107 +----------+  

108 |       11 |  

109 +----------+  

110 1 row in set (0.00 sec)

3,list分区
LIST分区中每个分区的定义和选择是基于某列的值从属于一个值列表集中的一个值,而RANGE分 区是从属于一个连续区间值的集合。



view sourceprint?1 //这种方式失败  

2 mysql> CREATE TABLE IF NOT EXISTS `list_part` (  

3  ->   `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '用户ID',  

4  ->   `province_id` int(2) NOT NULL DEFAULT 0 COMMENT '省',  

5  ->   `name` varchar(50) NOT NULL DEFAULT '' COMMENT '名称',  

6  ->   `sex` int(1) NOT NULL DEFAULT '0' COMMENT '0为男,1为女',  

7  ->   PRIMARY KEY (`id`)  

8  -> ) ENGINE=INNODB  DEFAULT CHARSET=utf8 AUTO_INCREMENT=1  

9  -> PARTITION BY LIST (province_id) (  

10  ->     PARTITION p0 VALUES IN (1,2,3,4,5,6,7,8),  

11  ->     PARTITION p1 VALUES IN (9,10,11,12,16,21),  

12  ->     PARTITION p2 VALUES IN (13,14,15,19),  

13  ->     PARTITION p3 VALUES IN (17,18,20,22,23,24)  

14  -> );  

15 ERROR 1503 (HY000): A PRIMARY KEY must include all columns in the table's partitioning function

16    

17 //这种方式成功  

18 mysql> CREATE TABLE IF NOT EXISTS `list_part` (  

19  ->   `id` int(11) NOT NULL  COMMENT '用户ID',  

20  ->   `province_id` int(2) NOT NULL DEFAULT 0 COMMENT '省',  

21  ->   `name` varchar(50) NOT NULL DEFAULT '' COMMENT '名称',  

22  ->   `sex` int(1) NOT NULL DEFAULT '0' COMMENT '0为男,1为女'

23  -> ) ENGINE=INNODB  DEFAULT CHARSET=utf8  

24  -> PARTITION BY LIST (province_id) (  

25  ->     PARTITION p0 VALUES IN (1,2,3,4,5,6,7,8),  

26  ->     PARTITION p1 VALUES IN (9,10,11,12,16,21),  

27  ->     PARTITION p2 VALUES IN (13,14,15,19),  

28  ->     PARTITION p3 VALUES IN (17,18,20,22,23,24)  

29  -> );  

30 Query OK, 0 rows affected (0.33 sec)



上面的这个创建list分区时,如果有主銉的话,分区时主键必须在其中,不然就会报错。如果我不用主键,分区就创建成功了,一般情况下,一个张表肯定会有一个主键,这算是一个分区的局限性吧。

如果对数据进行测试,请参考range分区的测试来操作

4,hash分区
HASH分区主要用来确保数据在预先确定数目的分区中平均分布,你所要做的只是基于将要被哈希的列值指定一个列值或表达式,以 及指定被分区的表将要被分割成的分区数量。

view sourceprint?1 mysql> CREATE TABLE IF NOT EXISTS `hash_part` (  

2  ->   `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '评论ID',  

3  ->   `comment` varchar(1000) NOT NULL DEFAULT '' COMMENT '评论',  

4  ->   `ip` varchar(25) NOT NULL DEFAULT '' COMMENT '来源IP',  

5  ->   PRIMARY KEY (`id`)  

6  -> ) ENGINE=INNODB  DEFAULT CHARSET=utf8 AUTO_INCREMENT=1  

7  -> PARTITION BY HASH(id)  

8  -> PARTITIONS 3;  

9 Query OK, 0 rows affected (0.06 sec)

测试请参考range分区的操作

5,key分区
按照KEY进行分区类似于按照HASH分区,除了HASH分区使用的用 户定义的表达式,而KEY分区的 哈希函数是由MySQL 服务器提供。

view sourceprint?1 mysql> CREATE TABLE IF NOT EXISTS `key_part` (  

2  ->   `news_id` int(11) NOT NULL  COMMENT '新闻ID',  

3  ->   `content` varchar(1000) NOT NULL DEFAULT '' COMMENT '新闻内容',  

4  ->   `u_id` varchar(25) NOT NULL DEFAULT '' COMMENT '来源IP',  

5  ->   `create_time` DATE NOT NULL DEFAULT '0000-00-00 00:00:00' COMMENT '时间'

6  -> ) ENGINE=INNODB  DEFAULT CHARSET=utf8  

7  -> PARTITION BY LINEAR HASH(YEAR(create_time))  

8  -> PARTITIONS 3;  

9 Query OK, 0 rows affected (0.07 sec)

测试请参考range分区的操作

6,子分区
子分区是分区表中每个分区的再次分割,子分区既可以使用HASH希分区,也可以使用KEY分区。这 也被称为复合分区(composite partitioning)。

1,如果一个分区中创建了子分区,其他分区也要有子分区

2,如果创建了了分区,每个分区中的子分区数必有相同

3,同一分区内的子分区,名字不相同,不同分区内的子分区名子可以相同(5.1.50不适用)

view sourceprint?1 mysql> CREATE TABLE IF NOT EXISTS `sub_part` (  

2  ->   `news_id` int(11) NOT NULL  COMMENT '新闻ID',  

3  ->   `content` varchar(1000) NOT NULL DEFAULT '' COMMENT '新闻内容',  

4  ->   `u_id`  int(11) NOT NULL DEFAULT 0s COMMENT '来源IP',  

5  ->   `create_time` DATE NOT NULL DEFAULT '0000-00-00 00:00:00' COMMENT '时间'

6  -> ) ENGINE=INNODB  DEFAULT CHARSET=utf8  

7  -> PARTITION BY RANGE(YEAR(create_time))  

8  -> SUBPARTITION BY HASH(TO_DAYS(create_time))(  

9  -> PARTITION p0 VALUES LESS THAN (1990)(SUBPARTITION s0,SUBPARTITION s1,SUBPARTITION s2),  

10  -> PARTITION p1 VALUES LESS THAN (2000)(SUBPARTITION s3,SUBPARTITION s4,SUBPARTITION good),  

11  -> PARTITION p2 VALUES LESS THAN MAXVALUE(SUBPARTITION tank0,SUBPARTITION tank1,SUBPARTITION tank3)  

12  -> );  

13 Query OK, 0 rows affected (0.07 sec)

三,分区管理
1,删除分区

mysql> alter table user drop partition p4;  
2,新增分区

view sourceprint?1 //range添加新分区  

2 mysql> alter table user add partition(partition p4 values less than MAXVALUE);  

3 Query OK, 0 rows affected (0.06 sec)  

4 Records: 0  Duplicates: 0  Warnings: 0  

5    

6 //list添加新分区  

7 mysql> alter table list_part add partition(partition p4 values in (25,26,28));  

8 Query OK, 0 rows affected (0.01 sec)  

9 Records: 0  Duplicates: 0  Warnings: 0  

10    

11 //hash重新分区  

12 mysql> alter table hash_part add partition partitions 4;  

13 Query OK, 0 rows affected (0.12 sec)  

14 Records: 0  Duplicates: 0  Warnings: 0  

15    

16 //key重新分区  

17 mysql> alter table key_part add partition partitions 4;  

18 Query OK, 1 row affected (0.06 sec)    //有数据也会被重新分配  

19 Records: 1  Duplicates: 0  Warnings: 0  

20    

21 //子分区添加新分区,虽然我没有指定子分区,但是系统会给子分区命名的  

22 mysql> alter table sub1_part add partition(partition p3 values less than MAXVALUE);  

23 Query OK, 0 rows affected (0.02 sec)  

24 Records: 0  Duplicates: 0  Warnings: 0  

25    

26 mysql> show create table sub1_partG;  

27 *************************** 1. row ***************************  

28  Table: sub1_part  

29 Create Table: CREATE TABLE `sub1_part` (  

30  `news_id` int(11) NOT NULL COMMENT '新闻ID',  

31  `content` varchar(1000) NOT NULL DEFAULT '' COMMENT '新闻内容',  

32  `u_id` varchar(25) NOT NULL DEFAULT '' COMMENT '来源IP',  

33  `create_time` date NOT NULL DEFAULT '0000-00-00' COMMENT '时间'

34 ) ENGINE=InnoDB DEFAULT CHARSET=utf8  

35 !50100 PARTITION BY RANGE (YEAR(create_time))  

36 SUBPARTITION BY HASH (TO_DAYS(create_time))  

37 (PARTITION p0 VALUES LESS THAN (1990)  

38  (SUBPARTITION s0 ENGINE = InnoDB,  

39  SUBPARTITION s1 ENGINE = InnoDB,  

40  SUBPARTITION s2 ENGINE = InnoDB),  

41  PARTITION p1 VALUES LESS THAN (2000)  

42  (SUBPARTITION s3 ENGINE = InnoDB,  

43  SUBPARTITION s4 ENGINE = InnoDB,  

44  SUBPARTITION good ENGINE = InnoDB),  

45  PARTITION p2 VALUES LESS THAN (3000)  

46  (SUBPARTITION tank0 ENGINE = InnoDB,  

47  SUBPARTITION tank1 ENGINE = InnoDB,  

48  SUBPARTITION tank3 ENGINE = InnoDB),  

49  PARTITION p3 VALUES LESS THAN MAXVALUE  

50  (SUBPARTITION p3sp0 ENGINE = InnoDB,    //子分区的名子是自动生成的  

51  SUBPARTITION p3sp1 ENGINE = InnoDB,  

52  SUBPARTITION p3sp2 ENGINE = InnoDB))  

53 1 row in set (0.00 sec)


3,重新分区

view sourceprint?1 //range重新分区  

2 mysql> ALTER TABLE user REORGANIZE PARTITION p0,p1,p2,p3,p4 INTO (PARTITION p0 VALUES LESS THAN MAXVALUE);  

3 Query OK, 11 rows affected (0.08 sec)  

4 Records: 11  Duplicates: 0  Warnings: 0  

5    

6 //list重新分区  

7 mysql> ALTER TABLE list_part REORGANIZE PARTITION p0,p1,p2,p3,p4 INTO (PARTITION p0 VALUES in (1,2,3,4,5));  

8 Query OK, 0 rows affected (0.28 sec)  

9 Records: 0  Duplicates: 0  Warnings: 0  

10    

11 //hash和key分区不能用REORGANIZE,官方网站说的很清楚  

12 mysql> ALTER TABLE key_part REORGANIZE PARTITION COALESCE PARTITION 9;  

13 ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'PARTITION 9' at line 1

四,分区优点
1,分区可以分在多个磁盘,存储更大一点

2,根据查找条件,也就是where后面的条件,查找只查找相应的分区不用全部查找了

3,进行大数据搜索时可以进行并行处理。

4,跨多个磁盘来分散数据查询,来获得更大的查询吞吐量

课外阅读
:http://dev.mysql.com/doc/refman/5.1/zh/partitioning.html

Tags: ,
分页: 4/128 第一页 上页 1 2 3 4 5 6 7 8 9 10 下页 最后页 [ 显示模式: 摘要 | 列表 ]