解析在OceanBase創建分區的常見問題|OceanBase 用戶問題精粹

在《分區策略和管理分區計劃的實踐方案》這篇文章中,我們介紹了在ODC中制定分區策略及有效管理分區計劃的經驗。有不少用戶在該帖下提出了使用中的問題,其中一個關于創建分區的限制條件的問題,也是很多用戶遭遇的老問題。因此本文以其為切入,將創建分區的幾個問題進行解析,與大家共同探討分享。

為什么主鍵必須包含全部分區鍵?

用戶問:“有一張訂單流水表,數據很大,想考慮按年份對數據進行分區。現在只有 ID 列是主鍵。嘗試了一下好像無法按日期進行分區。是必須要把日期做成和 ID 的聯合主鍵才可以分區么?”

答案是對的,主鍵必須包含所有分區鍵。因為主鍵的唯一性檢查是在各個分區內部進行的,如果主鍵不包含全部分區鍵,這個檢查就會失效,所以 MySQL 及其他數據庫,也一樣會有這個要求。

-- 如果主鍵不包含全部分區鍵,建表就會失敗報錯,報錯信息也挺明確的。
create table t1(c1 int, c2 int,c3 int,primary key (c1))
partition by range (c2) (partition p1 values less than(3),partition p1 values less than(6));ERROR 1503 (HY000): A PRIMARY KEY must include all columns in the table's partitioning function

下面舉個例子:

create table t1(c1 int, c2 int,c3 int,primary key (c1, c2))
partition by range (c2) (partition p0 values less than(3),partition p1 values less than(6));
Query OK, 0 rows affected (0.146 sec)obclient [test]> insert into t1 values(1, 2, 3);
Query OK, 1 row affected (0.032 sec)obclient [test]> insert into t1 values(1, 5, 3);
Query OK, 1 row affected (0.032 sec)obclient [test]> select * from t1;
+----+----+------+
| c1 | c2 | c3   |
+----+----+------+
|  1 |  2 |    3 |
|  1 |  5 |    3 |
+----+----+------+
2 rows in set (0.032 sec)

我們創建了一張表,主鍵是 c1 和 c2,分區鍵是 c2,小于 3 的值在 p0 分區,大于等于 3 且小于 6 的值在 p1 分區。然后插入了兩個行,第一行在 p0 分區,第二行在 p1 分區。

obclient [test]> select * from t1 PARTITION(p0);
+----+----+------+
| c1 | c2 | c3   |
+----+----+------+
|  1 |  2 |    3 |
+----+----+------+
1 row in set (0.033 sec)obclient [test]> select * from t1 PARTITION(p1);
+----+----+------+
| c1 | c2 | c3   |
+----+----+------+
|  1 |  5 |    3 |
+----+----+------+
1 row in set (0.034 sec)

如果主鍵只有 c1 而沒有 c2,那么在 p0 和 p1 分區內對 c1 列的唯一性檢測都會成功,因為在各個分區內 c1 列的值都不重復,然后就會判定插入的數據符合主鍵約束。但實際上在分區間會有重復值,數據并不符合主鍵約束,所以所有數據庫在分區時,都要求主鍵包含全部分區鍵。

為什么分區能讓查詢變快?

用戶另外一個問題:“按日期分區是否能達到讓查詢變快的目的?”

個人理解,分區除了可以讓一張超級大表的數據比較被均衡地被負載在不同的數據庫節點上,另外一個目的就是加速查詢。因為查詢時會利用過濾條件里面的分區鍵進行分區裁剪。例如下面這兩個例子:

如果過濾條件里有分區鍵,計劃中可以看到 partitions(p0),說明只掃描了 p0 這一個分區的數據。


obclient [test]> explain select * from t1 where c2 = 1;
+------------------------------------------------------------------------------------+
| Query Plan                                                                         |
+------------------------------------------------------------------------------------+
| ===============================================                                    |
| |ID|OPERATOR       |NAME|EST.ROWS|EST.TIME(us)|                                    |
| -----------------------------------------------                                    |
| |0 |TABLE FULL SCAN|t1  |1       |3           |                                    |
| ===============================================                                    |
| Outputs & filters:                                                                 |
| -------------------------------------                                              |
|   0 - output([t1.c1], [t1.c2], [t1.c3]), filter([t1.c2 = 1]), rowset=16            |
|       access([t1.c1], [t1.c2], [t1.c3]), partitions(p0)                            |
|       is_index_back=false, is_global_index=false, filter_before_indexback[false],  |
|       range_key([t1.c1], [t1.c2]), range(MIN,MIN ; MAX,MAX)always true             |
+------------------------------------------------------------------------------------+
11 rows in set (0.034 sec)

如果過濾條件里沒有分區鍵,計劃中可以看到 partitions(p[0-1]),說明掃描了 p0 和 p1 全部所有分區的數據。其中 PX PARTITION ITERATOR 算子就是用來循環掃描所有分區的迭代器。

obclient [test]> explain select * from t1 where c3 = 1;
+------------------------------------------------------------------------------------+
| Query Plan                                                                         |
+------------------------------------------------------------------------------------+
| =============================================================                      |
| |ID|OPERATOR                 |NAME    |EST.ROWS|EST.TIME(us)|                      |
| -------------------------------------------------------------                      |
| |0 |PX COORDINATOR           |        |1       |6           |                      |
| |1 |└─EXCHANGE OUT DISTR     |:EX10000|1       |6           |                      |
| |2 |  └─PX PARTITION ITERATOR|        |1       |5           |                      |
| |3 |    └─TABLE FULL SCAN    |t1      |1       |5           |                      |
| =============================================================                      |
| Outputs & filters:                                                                 |
| -------------------------------------                                              |
|   0 - output([INTERNAL_FUNCTION(t1.c1, t1.c2, t1.c3)]), filter(nil), rowset=16     |
|   1 - output([INTERNAL_FUNCTION(t1.c1, t1.c2, t1.c3)]), filter(nil), rowset=16     |
|       dop=1                                                                        |
|   2 - output([t1.c1], [t1.c2], [t1.c3]), filter(nil), rowset=16                    |
|       force partition granule                                                      |
|   3 - output([t1.c1], [t1.c2], [t1.c3]), filter([t1.c3 = 1]), rowset=16            |
|       access([t1.c1], [t1.c2], [t1.c3]), partitions(p[0-1])                        |
|       is_index_back=false, is_global_index=false, filter_before_indexback[false],  |
|       range_key([t1.c1], [t1.c2]), range(MIN,MIN ; MAX,MAX)always true             |
+------------------------------------------------------------------------------------+
19 rows in set (0.038 sec)

range 分區不支持 datetime 類型咋辦?

用戶的另另外一個問題:“range 分區不支持 datetime 類型咋辦?”。

CREATE TABLE ff01 (a datetime , b timestamp)
PARTITION BY RANGE(UNIX_TIMESTAMP(a))(PARTITION p0 VALUES less than (UNIX_TIMESTAMP('2000-2-3 00:00:00')),PARTITION p1 VALUES less than (UNIX_TIMESTAMP('2001-2-3 00:00:00')),PARTITION pn VALUES less than MAXVALUE);ERROR 1486 (HY000): Constant or random or timezone-dependent expressions in (sub)partitioning function are not allowed

試了下,OB 的 MySQL 模式,為了兼容 MySQL 行為,會和 MySQL 對 random expressions 進行一些限制。我第一時間想到的是用生成列繞過,不過很快發現,為了兼容 MySQL 行為,OB 對生成列的使用也進行了限制,生成列里也不允許出現 UNIX_TIMESTAMP 這個特殊的表達式,所以并沒什么卵用:

CREATE TABLE ff01 (a datetime , b timestamp as (UNIX_TIMESTAMP(a)))
PARTITION BY RANGE(b)(PARTITION p0 VALUES less than (UNIX_TIMESTAMP('2000-2-3 00:00:00')),PARTITION p1 VALUES less than (UNIX_TIMESTAMP('2001-2-3 00:00:00')),PARTITION pn VALUES less than MAXVALUE);ERROR 3102 (HY000): Expression of generated column contains a disallowed function

至于為啥 UNIX_TIMESTAMP 在生成列里屬于 disallowed function,猜測大概率是因為它是個非 deterministic 的系統函數。非 deterministic 簡單來說就是這個 UNIX_TIMESTAMP() 函數在前一秒執行,和在后一秒執行,可能會返回不同的結果。像分區表達式、生成列表達式、check 約束里面的表達式,都不允許出現這種非確定性的函數。

下面舉個簡單的例子,解釋一下上面 ERROR 1486 這個報錯里 random 一詞,以及非 deterministic 的含義:

obclient [test]> select UNIX_TIMESTAMP();
+------------------+
| UNIX_TIMESTAMP() |
+------------------+
|       1725008180 |
+------------------+
1 row in set (0.042 sec)obclient [test]> select UNIX_TIMESTAMP();
+------------------+
| UNIX_TIMESTAMP() |
+------------------+
|       1725008419 |
+------------------+
1 row in set (0.041 sec)-- 是不是一下子就明白,為啥 UNIX_TIMESTAMP 這么特殊,在哪里都不受待見了吧?

不過不得不說,OB 的 MySQL 兼容性做的還挺好的,不僅是兼容了 MySQL 各種使用上的限制,甚至是一些 MySQL 的 bug 都給兼容了,雖然給使用帶來了一些不便,不過遷移 MySQL 大概會變得比較輕松。

扯遠了,回歸正題,后面查了下?OB 官網,發現有一種分區方式叫?Range Columns,和 Range 分區十分類似,優點是相比 Range 分區可以支持更多的數據類型,例如用戶需要的 datetime 類型,缺點是分區定義不支持表達式。

因為 Range 不支持?UNIX_TIMESTAMP?這類特殊的非 deterministic?表達式,所以個人理解這里可以通過 Range Columns 解決用戶的問題。例如:

CREATE TABLE ff01 (a datetime , b timestamp)
PARTITION BY RANGE COLUMNS(a)(PARTITION p0 VALUES less than ('2023-01-01'),PARTITION p1 VALUES less than ('2023-01-02'),PARTITION pn VALUES less than MAXVALUE);Query OK, 0 rows affected (0.101 sec)

說來慚愧,我之前也一直沒注意過?Range 分區和 Range Columns 分區的區別,一直是把他們等價的,今天也算是學習到了,哈哈~

最后附上一個?MySQL 的官網文檔鏈接,感覺它對 RANGE COLUMNS partitioning 的介紹比 OB 的官網要更清楚些,在這里推薦給對分區方式感興趣的朋友閱讀~

1725007840

What else?

? ?有同學提出還可以通過利用 to_days 函數代替 UNIX_TIMESTAMP 函數的方式解決第三個問題,這樣就不需要更改 range 分區為 range columns 分區了。例如:

##創建range分區表
-- 分區字段是start_time,類型datetime
CREATE TABLE dba_test_range_1 (id bigint unsigned NOT NULL AUTO_INCREMENT COMMENT '主鍵',`name` varchar(50) NOT NULL COMMENT 'name',start_time datetime NOT NULL COMMENT '開始時間',
PRIMARY KEY (id,start_time)
)AUTO_INCREMENT = 1 DEFAULT CHARSET = utf8mb4 COMMENT = 'test range' 
PARTITION BY RANGE(to_days(start_time))(PARTITION M202301 VALUES LESS THAN(to_days('2023-02-01')),PARTITION M202302 VALUES LESS THAN(to_days('2023-03-01')),PARTITION M202303 VALUES LESS THAN(to_days('2023-04-01')));

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/63653.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/63653.shtml
英文地址,請注明出處:http://en.pswp.cn/web/63653.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

有哪些免費的 ERP 軟件可供選擇?哪些 ERP 軟件使用體驗較好?

想找個 “免費” 的 ERP 軟件? 咱得知道,ERP 那可是涉及財務、人力、供應鏈、采購、銷售等好多方面的重要企業軟件。功能這么全,能免費才怪呢!真要是有免費的,早就火遍大江南北,說不定把市場都壟斷了&…

centos-stream9系統安裝docker

如果之前安裝過docker需要刪除之前的。 sudo dnf -y remove docker docker-client docker-client-latest docker-common docker-latest docker-latest-logrotate docker-logrotate docker-engine 安裝yum-utils工具: dnf -y install yum-utils dnf-plugin…

了解cuda的統一內存

1. CUDA 6中的統一內存 在CUDA 6中,從Kepler GPU架構(計算能力3.0或更高)開始,在64位Windows 7、8和Linux操作系統(內核2.6.18)上開始支持統一內存. 從CUDA 6開始,NVIDIA推出了CUDA平臺歷史上…

unity 最小后監聽鍵盤輸入

當Untiy最小化后,游戲窗口不會立刻失去焦點,此時依然可以使用Input來獲取按鍵,但是點擊其他窗口后,就會失去焦點,此時系統會把按鍵輸入分配到其他窗口里,此時要用windowsAPI獲取按鍵輸入,應對兩…

Pytorch | 從零構建MobileNet對CIFAR10進行分類

Pytorch | 從零構建MobileNet對CIFAR10進行分類 CIFAR10數據集MobileNet設計理念網絡結構技術優勢應用領域 MobileNet結構代碼詳解結構代碼代碼詳解DepthwiseSeparableConv 類初始化方法前向傳播 forward 方法 MobileNet 類初始化方法前向傳播 forward 方法 訓練過程和測試結果…

Electronjs+Vue如何開發PC桌面客戶端(Windows,Mac,Linux)

electronjs官網 https://www.electronjs.org/zh/ Electron開發PC桌面客戶端的技術選型非常適合已經有web前端開發人員的團隊。能夠很絲滑的過渡。 Electron是什么? Electron是一個使用 JavaScript、HTML 和 CSS 構建桌面應用程序的框架。 嵌入 Chromium 和 Node.…

【1.排序】

排序 筆記記錄 1.排序的基本概念1.1 排序的定義 2. 插入排序2.1 直接插入排序2.2 折半插入排序2.3 希爾排序 3. 交換排序3.1 冒泡排序3.2 快速排序 4. 選擇排序4.1 簡單選擇排序4.2 堆排序 5. 歸并排序、基數排序和計數排序5.1 歸并排序4.2 基數排序4.3 計數排序 6. 各種內部排…

Linux Swap: 深入解析 mkswap, mkfs.swap, 和 swapon

文章目錄 Linux Swap: 深入解析 mkswap, mkfs.swap, 和 swapon什么是 Swap?主要命令介紹1. mkswap2. mkfs.swap3. swapon 創建和管理 Swap 的步驟1. 創建 Swap 分區2. 初始化 Swap3. 激活 Swap4. 持久化配置5. 查看 Swap 狀態 刪除 Swap 分區或文件1. 停用 Swap2. 刪…

取子串(指針)

#include <stdio.h> #include <string.h>char* substr(char *s, int startloc, int len) {static char result[51]; // 定義一個足夠大的靜態數組來存儲結果static char result1[] {N,U,L,L,\0};int i, j;// 檢查startloc是否在字符串的范圍內if (startloc < 1…

「Mac暢玩鴻蒙與硬件45」UI互動應用篇22 - 評分統計工具

本篇將帶你實現一個評分統計工具&#xff0c;用戶可以對多個選項進行評分。應用會實時更新每個選項的評分結果&#xff0c;并統計平均分。這一功能適合用于問卷調查或評分統計的場景。 關鍵詞 UI互動應用評分統計狀態管理數據處理多目標評分 一、功能說明 評分統計工具允許用…

類與對象的理解

面向對象中兩個重要的概念&#xff1a;類與對象 類 簡單理解&#xff0c;它指的是類型或者分類或某個模塊 比如&#xff1a;人類、動物類……&#xff1b;入公司的入職單&#xff0c;沒寫上任何人的情況下 對象 簡單理解&#xff0c;它指的具體的個體 備注&#xff1a;對…

遞歸實現指數型枚舉(遞歸)

92. 遞歸實現指數型枚舉 - AcWing題庫 每個數有選和不選兩種情況 我們把每個數看成每層&#xff0c;可以畫出一個遞歸搜索樹 葉子節點就是我們的答案 很容易寫出每dfs函數 dfs傳入一個u表示層數 當層數大于我們n時&#xff0c;去判斷每個數字的選擇情況&#xff0c;輸出被選…

Linux相關概念和易錯知識點(25)(信號原理、操作系統的原理、volatile)

目錄 1.信號的產生 &#xff08;1&#xff09;kill &#xff08;2&#xff09;raise、abort 2.對block、pending、handler表的管理 &#xff08;1&#xff09;信號集&#xff08;sigset_t&#xff09; &#xff08;2&#xff09;block表的管理 ①操作相關的函數 ②sigpr…

opencv中的色彩空間及其轉換

在 OpenCV 中&#xff0c;色彩空間&#xff08;Color Space&#xff09;指的是表示顏色的一種方式&#xff0c;或是用數學模型對顏色的表達。不同的色彩空間采用不同的方式來描述顏色的三要素&#xff08;如亮度、飽和度、色調&#xff09;&#xff0c;因此可以在不同的應用場景…

OPPO 數據分析面試題及參考答案

如何設計共享單車數據庫的各個字段? 對于共享單車的數據庫設計,首先考慮用戶相關的字段。用戶表可以包含用戶 ID,這是一個唯一標識符,用于區分不同用戶;姓名,記錄用戶的真實姓名;聯系方式,比如手機號碼,方便在出現問題時聯系用戶;注冊時間,記錄用戶何時開始使用共享…

在Ubuntu下運行QEMU仿真FreeBSD riscv64系統

在Ubuntu下運行QEMU仿真FreeBSD riscv64系統 突發奇想&#xff0c;嘗試在Ubuntu下運行QEMU仿真FreeBSD riscv64系統&#xff0c; 參考這篇文檔&#xff1a;手把手教你在QEMU上運行RISC-V Linux_qemu 運行 .bin-CSDN博客 并參考FreeBSD的Wiki&#xff1a;riscv - FreeBSD Wik…

大模型微調---Prompt-tuning微調

目錄 一、前言二、Prompt-tuning實戰2.1、下載模型到本地2.2、加載模型與數據集2.3、處理數據2.4、Prompt-tuning微調2.5、訓練參數配置2.6、開始訓練 三、模型評估四、完整訓練代碼 一、前言 Prompt-tuning通過修改輸入文本的提示&#xff08;Prompt&#xff09;來引導模型生…

Visual Studio 、 MSBuild 、 Roslyn 、 .NET Runtime、SDK Tools之間的關系

1. Visual Studio Visual Studio 是一個集成開發環境&#xff08;IDE&#xff09;&#xff0c;為開發者提供代碼編寫、調試、測試和發布等功能。它內置了 MSBuild、Roslyn 和 SDK Tools&#xff0c;并提供圖形化界面來方便開發者進行項目管理和構建。與其他組件的關系&#xf…

Winnows基礎(2)

Target 了解常見端口及服務&#xff0c;熟練cmd命令&#xff0c;編寫簡單的 .bat 病毒程序。 Trail 常見服務及端口 80 web 80-89 可能是web 443 ssl心臟滴血漏洞以及一些web漏洞測試 445 smb 1433 mssql 1521 oracle 2082/2083 cpanel主機管理系統登陸&#xff08;國外用的…

Edge Scdn用起來怎么樣?

Edge Scdn&#xff1a;提升網站安全與性能的最佳選擇 在當今互聯網高速發展的時代&#xff0c;各種網絡攻擊層出不窮&#xff0c;特別是針對網站的DDoS攻擊威脅&#xff0c;幾乎每個行業都可能成為目標。為了確保網站的安全性與穩定性&#xff0c;越來越多的企業開始關注Edge …