1. 程式人生 > 其它 >mysql 資料庫表被鎖住了_Mysql資料庫表分割槽

mysql 資料庫表被鎖住了_Mysql資料庫表分割槽

技術標籤:mysql 資料庫表被鎖住了

原因
我們有一張大的資料表5000多萬的資料,查詢時間跨度比較大的資料的時候,比較慢。

解決辦法

解決資料庫效能問題方法是多種多樣,在不動程式碼邏輯的情況下,比較節省開發成本的方式就是表分割槽。

實現

一般分2種方法,第一種是對現有表進行分割槽,第二種新建立同樣欄位的分割槽表,把老表的資料匯入。

需求:按月對錶分割槽

首先,為了方便,採用第一種對現有表進行分割槽。使用 Alter table (更改表)命令。

ALTER TABLE weather_dat PARTITION BY RANGE (unix_timestamp(create_time))
(   
PARTITION p0 VALUES LESS THAN (unix_timestamp('2020-02-01')),
PARTITION p1 VALUES LESS THAN (unix_timestamp('2020-03-01')), 
PARTITION p2 VALUES LESS THAN (unix_timestamp('2020-04-01')), 
PARTITION p3 VALUES LESS THAN (unix_timestamp('2020-05-01')), 
PARTITION p4 VALUES LESS THAN (unix_timestamp('2020-06-01')), 
PARTITION p5 VALUES LESS THAN (unix_timestamp('2020-07-01')), 
PARTITION p6 VALUES LESS THAN (unix_timestamp('2020-08-01')), 
PARTITION p7 VALUES LESS THAN (unix_timestamp('2020-09-01')), 
PARTITION p8 VALUES LESS THAN (unix_timestamp('2020-10-01')), 
PARTITION p9 VALUES LESS THAN (unix_timestamp('2020-11-01')), 
PARTITION p10 VALUES LESS THAN (unix_timestamp('2020-12-01')), 
PARTITION p11 VALUES LESS THAN MAXVALUE );

上面程式碼意思是,根據月份更改weather_da表作為分割槽表。Range表示是按範圍分割槽。我現在是按資料記錄建立時間作為關鍵字,按月進行分割槽。

因為create_time是timestamp型別,我們需要按時間戳進行比對,來劃分資料記錄應該進那個分割槽表。


報錯:

[Err] 1503 - A PRIMARY KEY must include all columns in the table's partitioning function

意思是在表的分割槽函式裡面,主鍵必須包含所有的欄位。現在用到“create_time”這個欄位,但它不是主鍵,所以報錯了。

navicat調整create_time成主鍵。結果又報錯,提示如下:

7edc929ad7067adb5c14600a0a518332.png

並且,反覆幾次不成功。只能決定採用第二種方式進行分割槽。

建立空的分割槽表:

CREATE TABLE `weather_dat1` (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '唯一標識ID,主鍵',
  `road_id` int(11) DEFAULT NULL COMMENT '路段Id',
  `device_id` int(11) NOT NULL,
  `pressure` float(11,1) DEFAULT NULL COMMENT '單位毫巴hPa,1hPa=100帕斯卡',
  `atmospheric_temperature` float(11,1) DEFAULT NULL COMMENT '大氣溫度,單位:℃',
  `relative_humidity` int(3) DEFAULT NULL COMMENT '相對溼度,單位:%,如85表示相對溼度85%',
  `dew_point_temperature` float(11,1) DEFAULT NULL COMMENT '露點溫度,單位:℃,有的有輸出,有的需根據溫溼度計算',
  `wind_speed` float(11,1) DEFAULT NULL COMMENT 'm/s',
  `wind_direction` int(11) DEFAULT NULL COMMENT '風向,360° ',
  `precipitation` float(11,1) DEFAULT NULL COMMENT '降水量,單位:mm/min,表示每分鐘的mm降水量',
  `visibility` int(11) DEFAULT NULL COMMENT '能見度,單位:m',
  `weather_phenomena` varchar(255) DEFAULT NULL COMMENT '天氣現象,取決於天氣現象感測器的輸出',
  `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '精確到分鐘,即每分鐘一條記錄,如“201905202310”',
  PRIMARY KEY (`id`,`create_time`) USING BTREE,
  KEY `idx_weatherDat_deviceIdCreateTime` (`device_id`,`create_time`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=118196010 DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT
PARTITION BY RANGE (unix_timestamp(create_time))
(PARTITION p0 VALUES LESS THAN (1580486400) ENGINE = InnoDB,
 PARTITION p1 VALUES LESS THAN (1582992000) ENGINE = InnoDB,
 PARTITION p2 VALUES LESS THAN (1585670400) ENGINE = InnoDB,
 PARTITION p3 VALUES LESS THAN (1588262400) ENGINE = InnoDB,
 PARTITION p4 VALUES LESS THAN (1590940800) ENGINE = InnoDB,
 PARTITION p5 VALUES LESS THAN (1593532800) ENGINE = InnoDB,
 PARTITION p6 VALUES LESS THAN (1596211200) ENGINE = InnoDB,
 PARTITION p7 VALUES LESS THAN (1598889600) ENGINE = InnoDB,
 PARTITION p8 VALUES LESS THAN (1601481600) ENGINE = InnoDB,
 PARTITION p9 VALUES LESS THAN (1604160000) ENGINE = InnoDB,
 PARTITION p10 VALUES LESS THAN (1606752000) ENGINE = InnoDB,
 PARTITION p11 VALUES LESS THAN MAXVALUE ENGINE = InnoDB);

老表資料匯入到新表SQL語句:

insert into weather_dat1  SELECT * FROM weather_dat

5000萬資料掛機一個晚上匯入成功。匯入成功後,把分割槽表命名weather_dat。

總結:對大資料表直接進行更改為分割槽表失敗的概率很大,可能是因為資料量太大的原因。建議採用新建同欄位的分割槽表,再把資料匯入。

另外,關於現在分割槽表按日期是hardcode了,如果超出分割槽的時間,表又需要重新分割槽。如何自動建立分割槽表是可以探索下一個話題。