分區是把雙刃劍,用得好效率高,用不好被坑爹。

來源:互聯網
上載者:User

650) this.width=650;" border="0" src="http://img1.51cto.com/attachment/201212/102038943.jpg" alt="" />

                                                                                      ——《MySQL INNODB技術內幕》薑承堯

這是我的表結構:

 
  1. mysql> show create table p1\G; 
  2. *************************** 1. row *************************** 
  3.        Table: p1 
  4. Create Table: CREATE TABLE `p1` ( 
  5.   `id` int(11) NOT NULL, 
  6.   `date` datetime NOT NULL, 
  7.   PRIMARY KEY (`id`) 
  8. ) ENGINE=InnoDB DEFAULT CHARSET=latin1 
  9. 1 row in set (0.00 sec) 

我如果對`date`欄位進行分區,你說,會成功嗎?呵呵,很遺憾,不會的。

 
  1. mysql> alter table p1 partition by range columns(date)( 
  2. partition p0 values less than ('2010-01-01'),  
  3. partition p1 values less than ('2011-01-01'),  
  4. partition p2 values less than ('2012-01-01'),  
  5. PARTITION p3 VALUES LESS THAN MAXVALUE);     
  6. ERROR 1503 (HY000): A PRIMARY KEY must include all columns in the table's partitioning function 

答案已經告訴你了,這個欄位必須是主鍵。

 
  1. mysql> alter table p1 drop primary key,add primary key(`id`,`date`); 
  2. Query OK, 0 rows affected (0.03 sec) 
  3. Records: 0  Duplicates: 0  Warnings: 0 
  4.  
  5. mysql> alter table p1 partition by range columns(date)( 
  6. partition p0 values less than ('2010-01-01'),  
  7. partition p1 values less than ('2011-01-01'),  
  8. partition p2 values less than ('2012-01-01'),  
  9. PARTITION p3 VALUES LESS THAN MAXVALUE); 
  10. Query OK, 0 rows affected (0.05 sec) 
  11. Records: 0  Duplicates: 0  Warnings: 0 
 
  1. mysql> show create table p1\G; 
  2. *************************** 1. row *************************** 
  3.        Table: p1 
  4. Create Table: CREATE TABLE `p1` ( 
  5.   `id` int(11) NOT NULL, 
  6.   `date` datetime NOT NULL, 
  7.   PRIMARY KEY (`id`,`date`)QFVW 
  8. ) ENGINE=InnoDB DEFAULT CHARSET=latin1 
  9. /*!50500 PARTITION BY RANGE  COLUMNS(`date`) 
  10. (PARTITION p0 VALUES LESS THAN ('2010-01-01') ENGINE = InnoDB, 
  11.  PARTITION p1 VALUES LESS THAN ('2011-01-01') ENGINE = InnoDB, 
  12.  PARTITION p2 VALUES LESS THAN ('2012-01-01') ENGINE = InnoDB, 
  13.  PARTITION p3 VALUES LESS THAN (MAXVALUE) ENGINE = InnoDB) */ 
  14. 1 row in set (0.01 sec) 

我現在要增加一個欄位name並建立索引,然後插入幾條記錄測試

 
  1. mysql> alter table p1 add name varchar(10) not null; 
  2. Query OK, 0 rows affected (0.04 sec) 
  3. Records: 0  Duplicates: 0  Warnings: 0 
  4.  
  5. mysql> alter table p1 add index IX_name(name); 
  6. Query OK, 0 rows affected (0.07 sec) 
  7. Records: 0  Duplicates: 0  Warnings: 0 
  8.  
  9. mysql> insert into p1 values(1,'2009-10-1','zhangsan'); 
  10. Query OK, 1 row affected (0.05 sec) 
  11.  
  12. mysql> insert into p1 values(2,'2010-05-05','lisi');    
  13. Query OK, 1 row affected (0.01 sec) 
  14.  
  15. mysql> insert into p1 values(3,'2011-07-08','wangwu'); 
  16. Query OK, 1 row affected (0.00 sec) 
  17.  
  18. mysql> insert into p1 values(4,'2012-04-27','xuliu');  
  19. Query OK, 1 row affected (0.00 sec) 
  20.  
  21. mysql> insert into p1 values(5,'2013-02-14','zhaoqi'); 
  22. Query OK, 1 row affected (0.01 sec) 
  23.  
  24. mysql> select * from p1; 
  25. +----+---------------------+----------+ 
  26. | id | date                | name     | 
  27. +----+---------------------+----------+ 
  28. |  1 | 2009-10-01 00:00:00 | zhangsan | 
  29. |  2 | 2010-05-05 00:00:00 | lisi     | 
  30. |  3 | 2011-07-08 00:00:00 | wangwu   | 
  31. |  4 | 2012-04-27 00:00:00 | xuliu    | 
  32. |  5 | 2013-02-14 00:00:00 | zhaoqi   | 
  33. +----+---------------------+----------+ 
  34. 5 rows in set (0.01 sec) 
 
  1. mysql> explain partitions select * from p1 where (`date` between '2009-1-1' and '2009-12-31') and name ='zhangsan';      
  2. +----+-------------+-------+------------+------+---------------+---------+---------+-------+------+--------------------------+ 
  3. | id | select_type | table | partitions | type | possible_keys | key     | key_len | ref   | rows | Extra                    | 
  4. +----+-------------+-------+------------+------+---------------+---------+---------+-------+------+--------------------------+ 
  5. |  1 | SIMPLE      | p1    | p0         | ref  | IX_name       | IX_name | 12      | const |    1 | Using where; Using index | 
  6.  
  7. +----+-------------+-------+------------+------+---------------+---------+---------+-------+------+--------------------------+ 
  8. 1 row in set (0.00 sec) 
  9.  
  10. mysql> explain partitions select * from p1 where (`date` between '2010-1-1' and '2010-12-31') and name ='lisi';   
  11. +----+-------------+-------+------------+------+---------------+---------+---------+-------+------+--------------------------+ 
  12. | id | select_type | table | partitions | type | possible_keys | key     | key_len | ref   | rows | Extra                    | 
  13. +----+-------------+-------+------------+------+---------------+---------+---------+-------+------+--------------------------+ 
  14. |  1 | SIMPLE      | p1    | p1         | ref  | IX_name       | IX_name | 12      | const |    1 | Using where; Using index | 
  15. +----+-------------+-------+------------+------+---------------+---------+---------+-------+------+--------------------------+ 
  16. 1 row in set (0.00 sec) 

註:使用分區,where後面的欄位必須是分區欄位,這樣才會使用到分區,這裡09年的使用的是分區p0,10年的使用的是分區p1,

那麼如果我去掉`date`欄位,直接寫name='zhaoqi',看行不行?

 
  1. mysql> explain partitions select * from p1 where name='zhaoqi';                                            
  2. +----+-------------+-------+-------------+------+---------------+---------+---------+-------+------+--------------------------+ 
  3.  
  4. | id | select_type | table | partitions  | type | possible_keys | key     | key_len | ref   | rows | Extra                    | 
  5.  
  6. +----+-------------+-------+-------------+------+---------------+---------+---------+-------+------+--------------------------+ 
  7.  
  8. |  1 | SIMPLE      | p1    | p0,p1,p2,p3 | ref  | IX_name       | IX_name | 12      | const |    2 | Using where; Using index | 
  9.  
  10. +----+-------------+-------+-------------+------+---------------+---------+---------+-------+------+--------------------------+ 
  11. 1 row in set (0.01 sec) 

掃描了全部的分區,分區在這裡沒有一點意義,反而拖累了效能。

原因如下:

650) this.width=650;" border="0" src="http://www.bkjia.com/uploads/allimg/131229/1T94B338-1.jpg" alt="" />

 

本文出自 “賀春暘的技術專欄” 部落格,請務必保留此出處http://hcymysql.blog.51cto.com/5223301/1094699

相關文章

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.