稱為分割區修剪的最佳化是基於一個相對簡單的概念,可以描述為「不要掃描不可能有符合值的分割區」。假設一個分割資料表 t1
是由此陳述式所建立
CREATE TABLE t1 (
fname VARCHAR(50) NOT NULL,
lname VARCHAR(50) NOT NULL,
region_code TINYINT UNSIGNED NOT NULL,
dob DATE NOT NULL
)
PARTITION BY RANGE( region_code ) (
PARTITION p0 VALUES LESS THAN (64),
PARTITION p1 VALUES LESS THAN (128),
PARTITION p2 VALUES LESS THAN (192),
PARTITION p3 VALUES LESS THAN MAXVALUE
);
假設您想要從SELECT
陳述式中取得結果,例如這個
SELECT fname, lname, region_code, dob
FROM t1
WHERE region_code > 125 AND region_code < 130;
很容易看出,應該傳回的列都不在分割區 p0
或 p3
中;也就是說,我們只需要搜尋分割區 p1
和 p2
即可找到符合的列。透過限制搜尋,與掃描資料表中的所有分割區相比,可以花費更少的時間和精力來尋找符合的列。這種「切除」不需要的分割區稱為修剪。當最佳化工具可以在執行此查詢時使用分割區修剪時,查詢的執行速度可能會比針對包含相同欄定義和資料的非分割資料表執行相同的查詢快一個數量級。
當 WHERE
條件可以簡化為以下兩種情況之一時,最佳化工具可以執行修剪
分割區欄位
=常數
分割區欄位
IN (常數1
,常數2
, ...,常數N
)
在第一種情況下,最佳化工具只會評估指定值的分割區運算式,判斷哪個分割區包含該值,並且只掃描這個分割區。在許多情況下,等號可以替換為其他算術比較,包括 <
、>
、<=
、>=
和 <>
。某些在 WHERE
子句中使用 BETWEEN
的查詢也可以利用分割區修剪。請參閱本節稍後的範例。
在第二種情況下,最佳化工具會評估清單中每個值的分割區運算式,建立符合分割區的清單,然後只掃描這個分割區清單中的分割區。
SELECT
、DELETE
和 UPDATE
陳述式支援分割區修剪。即使資料表是透過 HASH
或 KEY
分割的,INSERT
陳述式也只會存取每個插入列的一個分割區;儘管目前 EXPLAIN
的輸出中未顯示,但這是正確的。
修剪也可以應用於短範圍,最佳化工具可以將其轉換為等效的值清單。例如,在先前的範例中,WHERE
子句可以轉換為 WHERE region_code IN (126, 127, 128, 129)
。然後,最佳化工具可以判斷清單中的前兩個值位於分割區 p1
中,其餘兩個值位於分割區 p2
中,而其他分割區不包含任何相關值,因此不需要搜尋符合的列。
最佳化工具也可以對使用 RANGE COLUMNS
或 LIST COLUMNS
分割的資料表,在包含多個欄位的先前類型的比較之 WHERE
條件執行修剪。
每當分割區運算式包含等式或可以簡化為一組等式的範圍時,或當分割區運算式表示遞增或遞減的關係時,都可以應用這種最佳化。當分割區運算式使用 YEAR()
或 TO_DAYS()
函式時,也可以對分割在 DATE
或 DATETIME
欄位上的資料表應用修剪。當分割區運算式使用 TO_SECONDS()
函式時,也可以對這類資料表應用修剪。
假設使用此處所示的陳述式建立一個以 DATE
欄位分割的資料表 t2
CREATE TABLE t2 (
fname VARCHAR(50) NOT NULL,
lname VARCHAR(50) NOT NULL,
region_code TINYINT UNSIGNED NOT NULL,
dob DATE NOT NULL
)
PARTITION BY RANGE( YEAR(dob) ) (
PARTITION d0 VALUES LESS THAN (1970),
PARTITION d1 VALUES LESS THAN (1975),
PARTITION d2 VALUES LESS THAN (1980),
PARTITION d3 VALUES LESS THAN (1985),
PARTITION d4 VALUES LESS THAN (1990),
PARTITION d5 VALUES LESS THAN (2000),
PARTITION d6 VALUES LESS THAN (2005),
PARTITION d7 VALUES LESS THAN MAXVALUE
);
以下使用 t2
的陳述式可以利用分割區修剪
SELECT * FROM t2 WHERE dob = '1982-06-23';
UPDATE t2 SET region_code = 8 WHERE dob BETWEEN '1991-02-15' AND '1997-04-25';
DELETE FROM t2 WHERE dob >= '1984-06-21' AND dob <= '1999-06-21'
對於最後一個陳述式,最佳化工具也可以執行以下動作
尋找包含範圍下限的分割區.
YEAR('1984-06-21')
產生值1984
,該值位於分割區d3
中。尋找包含範圍上限的分割區.
YEAR('1999-06-21')
評估為1999
,該值位於分割區d5
中。只掃描這兩個分割區以及可能介於它們之間的任何分割區.
在這種情況下,這表示只會掃描分割區
d3
、d4
和d5
。其餘分割區可以安全地忽略(並且會被忽略)。
在針對分割資料表的陳述式的 WHERE
條件中參考的無效 DATE
和 DATETIME
值會被視為 NULL
。這表示諸如 SELECT * FROM
之類的查詢不會傳回任何值(請參閱錯誤 #40972)。分割資料表
WHERE 日期欄位
< '2008-12-00'
到目前為止,我們只看過使用 RANGE
分割的範例,但修剪也可以應用於其他分割類型。
考慮一個依 LIST
分割的資料表,其中分割區運算式是遞增或遞減的,例如此處顯示的資料表 t3
。(在此範例中,為了簡潔起見,我們假設 region_code
欄位僅限於 1 到 10(含)之間的值。)
CREATE TABLE t3 (
fname VARCHAR(50) NOT NULL,
lname VARCHAR(50) NOT NULL,
region_code TINYINT UNSIGNED NOT NULL,
dob DATE NOT NULL
)
PARTITION BY LIST(region_code) (
PARTITION r0 VALUES IN (1, 3),
PARTITION r1 VALUES IN (2, 5, 8),
PARTITION r2 VALUES IN (4, 9),
PARTITION r3 VALUES IN (6, 7, 10)
);
對於像 SELECT * FROM t3 WHERE region_code BETWEEN 1 AND 3
這樣的語句,最佳化器會判斷值 1、2 和 3 存在於哪些分割區(r0
和 r1
),並跳過其餘的分割區(r2
和 r3
)。
對於使用 HASH
或 [LINEAR] KEY
分割的表格,當 WHERE
子句針對分割運算式中使用的欄位使用簡單的 =
關係時,也可以進行分割區修剪。考慮一個像這樣建立的表格:
CREATE TABLE t4 (
fname VARCHAR(50) NOT NULL,
lname VARCHAR(50) NOT NULL,
region_code TINYINT UNSIGNED NOT NULL,
dob DATE NOT NULL
)
PARTITION BY KEY(region_code)
PARTITIONS 8;
比較欄位值與常數的語句可以被修剪。
UPDATE t4 WHERE region_code = 7;
修剪也可以用於短範圍,因為最佳化器可以將這些條件轉換為 IN
關係。例如,使用與先前定義的相同表格 t4
,可以修剪像這樣的查詢:
SELECT * FROM t4 WHERE region_code > 2 AND region_code < 6;
SELECT * FROM t4 WHERE region_code BETWEEN 3 AND 5;
在這兩種情況下,最佳化器都會將 WHERE
子句轉換為 WHERE region_code IN (3, 4, 5)
。
只有當範圍大小小於分割區數量時,才會使用此最佳化。考慮以下語句:
DELETE FROM t4 WHERE region_code BETWEEN 4 AND 12;
WHERE
子句中的範圍涵蓋 9 個值(4、5、6、7、8、9、10、11、12),但 t4
只有 8 個分割區。這表示 DELETE
無法進行修剪。
當表格使用 HASH
或 [LINEAR] KEY
分割時,只能對整數欄位使用修剪。例如,此語句無法使用修剪,因為 dob
是 DATE
欄位。
SELECT * FROM t4 WHERE dob >= '2001-04-14' AND dob <= '2005-10-15';
但是,如果表格在 INT
欄位中儲存年份值,則具有 WHERE year_col >= 2001 AND year_col <= 2005
的查詢可以進行修剪。
如果明確分割,則使用提供自動分割的儲存引擎(例如 MySQL Cluster 使用的 NDB
儲存引擎)的表格可以進行修剪。