Mysql按天自動表分區教程


 

前言

在使用mysql時,往往用一張表來存放數據,不同的業務可能產生的數據量也不同,有的業務可能一天需要插入幾萬條數據,也有的則更多,即使量很小日積月累數據庫表的數據堆積也會越來越多,需要人工去刪除數據,當數據達到百萬或千萬級別時,mysql查詢速度明顯下降,性能也隨之下降,解決該問題的辦法有很多,比如添加索引、優化SQL,但這都只是治標不治本的做法,無法從根本上提高Mysql的性能和查詢速度。

什么是表分區?

mysql數據庫中的數據是以文件的形勢存在磁盤上的,默認放在/mysql/data下面(可以通過my.cnf中的datadir來查看),一張表主要對應着三個文件,一個是frm存放表結構的,一個是myd存放表數據的,一個是myi存表索引的。如果一張表的數據量太大的話,那么myd,myi就會變的很大,查找數據就會變的很慢,這個時候我們可以利用mysql的分區功能,在物理上將這一張表對應的三個文件,分割成許多個小塊,這樣呢,我們查找一條數據時,就不用全部查找了,只要知道這條數據在哪一塊,然后在那一塊找就行了。如果表的數據太大,可能一個磁盤放不下,這個時候,我們可以把數據分配到不同的磁盤里面去。

表分區,是指根據一定規則,將數據庫中的一張表分解成多個更小的,容易管理的部分。從邏輯上看,只有一張表,但是底層卻是由多個物理分區組成。

創建測試數據庫

create database test charset=utf8;
  • 1

創建測試表

use test;		// 先切換到test數據庫
create table test_log
(
	time datetime,
	msg varchar(2000)
)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

手動進行分區

對自動分區的表必須是在該表有手動分區的前提之下才能進行;對以下代碼稍做解釋,less than 的意思是小於的意思,所以p20191001這個分區里面存放的數據都是比2019年10月1日之前的數據,以此類推,p20191002存放的是10月1日的數據,p20191003存放的是10月2日的數據。

批量進行分區

alter table test_log partition by range columns(time)(
	partition p20191001 values less than('2019-10-01'),
	partition p20191002 values less than('2019-10-02'),
	partition p20191003 values less than('2019-10-03'),
	partition p20191003 values less than('2019-10-04')
);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

單條增加分區

alter table test_log add partition (partition p20191003 values less than('2019-10-03'));
  • 1

刪除分區命令

因為數據都是存放在一個一個的分區當中,所以當分區刪除的時間,對應的數據也會刪除,例如以下命令會把10月3日的數據刪除,可自行驗證!

alter table test_log drop partition p20191004;
  • 1

插入數據

insert into test_log values('2019-10-01 10:11:13', 'hi');
insert into test_log values('2019-10-02 10:12:10', 'ni');
insert into test_log values('2019-10-03 10:12:10', 'hao');
  • 1
  • 2
  • 3

查看表分區

select partition_name, partition_description as val from information_schema.partitions
where table_name='test_log' and table_schema='test';
  • 1
  • 2

在這里插入圖片描述

創建增加分區和刪除分區代碼

注意:
1.以下代碼可以手動mysql -u root -p登錄到mysql執行
2.以下代碼有table_name和table_schema是表和數據庫名,一共6處,另外每次新增幾個分區,刪除幾個舊分區,找到相應位置,根據需要自行修改,程序員多多少少大致能看懂的。
3.執行到delimiter ;繼續按回車執行完畢,否則會出現無法執行命令的情況。

delimiter $$
DROP PROCEDURE IF EXISTS pro_test_log
$$
CREATE PROCEDURE pro_test_log()
BEGIN
  DECLARE v_sysdate date;
  DECLARE v_mindate date;
  DECLARE v_maxdate date;
  DECLARE v_pt varchar(20);
  DECLARE v_maxval varchar(20);
  DECLARE i int;
  
  /*增加新分區代碼,執行時,不要復制此行*/
  SELECT max(cast(replace(partition_description, '''', '') AS date)) AS val
  INTO   v_maxdate
  FROM   INFORMATION_SCHEMA.PARTITIONS
  WHERE  TABLE_NAME = 'test_log' AND TABLE_SCHEMA = 'test';
  
  set v_sysdate = sysdate();
  
  WHILE v_maxdate <= (v_sysdate + INTERVAL 3 DAY) DO
    SET v_pt = date_format(v_maxdate+ INTERVAL 1 DAY ,'%Y%m%d');
    SET v_maxval = date_format(v_maxdate + INTERVAL 1 DAY, '%Y-%m-%d');
    SET @sql = concat('alter table test_log add partition (partition p', v_pt, ' values less than(''', v_maxval, '''))');
    -- SELECT @sql;
    PREPARE stmt FROM @sql;
    EXECUTE stmt;
    DEALLOCATE PREPARE stmt;
    SET v_maxdate = v_maxdate + INTERVAL 1 DAY;
  END WHILE;
  
  /*刪除舊分區,執行時,不要復制此行*/
  SELECT min(cast(replace(partition_description, '''', '') AS date)) AS val
  INTO   v_mindate
  FROM   INFORMATION_SCHEMA.PARTITIONS
  WHERE  TABLE_NAME = 'test_log ' AND TABLE_SCHEMA = 'test';
    
  WHILE v_mindate <= (v_sysdate - INTERVAL 6 DAY) DO
    SET v_pt = date_format(v_mindate - INTERVAL 1 DAY,'%Y%m%d');
    SET @sql = concat('alter table test_log drop partition p', v_pt);
    -- SELECT @sql;
    PREPARE stmt FROM @sql;
    EXECUTE stmt;
    DEALLOCATE PREPARE stmt;
    SET v_mindate = v_mindate + INTERVAL 1 DAY;
  END WHILE;
 
END$$
delimiter ;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49

手動調用存儲程序命令

每次新增分區和刪除舊分區需要手動執行以下命令執行,一般一天執行一次,或都一小時都可以,但是我們人不能每天上班都去執行一次,接下來我們會使用事件,讓mysql自動每天執行。

call proc_test_log;
  • 1

開啟事件

使用mysql的事件實現定時分區,mysql默認是不會開啟事件例程的,需要手動打開,查看是否打開。
在這里插入圖片描述

新建event事件

為了測試方便,間隔設置為分鍾, 也可設置成小時 24 hour

DELIMITER $$
drop event if exists auto_pt $$
create event auto_pt
on schedule
every 1 minute
starts '2019-10-01 13:19:02'
do
BEGIN
    call proc_test_log();
END$$
delimiter ;


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM