本文介紹了OSS冷數據的查詢加速功能。
背景信息
隨著OSS應用的日益廣泛,存儲的數據量也迅速增加,查詢性能低下問題日益突出,嚴重影響體驗。盡管冷數據并行查詢可以提供更快的查詢速度,但在掃描OSS表的過程中,冷數據并行查詢的高效需要消耗大量內存、連接數和網絡帶寬資源,業務體驗仍然會受到一定影響。因此,我們急需一種能夠快速過濾OSS表數據的方法,以提升查詢性能。
為了解決這一問題,我們引入了OSS數據塊過濾(OSS File Filter)功能。該功能根據查詢條件排除不需要掃描的OSS數據塊,從而減少需要掃描的數據量,大幅提升查詢性能。這一創新不僅優化了資源使用效率,也顯著增強了使用體驗。
功能說明
查詢加速功能通過收集每個歸檔數據塊的統計信息生成過濾數據(filter data),并將其保存在OSS上。在查詢過程中,系統會根據引擎下推的查詢條件結合過濾數據,排除不需要掃描的數據塊,從而減少數據掃描量并縮短查詢時間。OSS冷數據可以通過OSS_FILE_FILTER對數據進行過濾。針對不同的數據類型OSS_FILE_FILTER采用了不同的過濾方式:數值類型通過比較數據塊最小值和最大值統計信息來進行過濾;字符串類型則通過比較字符映射進行過濾。如果指定了過濾類型為BLOOM類型,則將使用布隆過濾器進行過濾。
對于有序或局部有序的數值類型數據,OSS_FILE_FILTER能夠提供更優異的處理效果。然而,對于全局無序的數據,建議使用布隆過濾器,以實現更有效的過濾。
由于歸檔數據通常具有較好的時間序列,因此使用時間類型的列進行過濾可以顯著提升查詢性能。
前置條件
數據庫引擎版本為MySQL 8.0.2,且內核小版本為8.0.2.2.25及以上。
已開啟冷數據歸檔功能。
已連接數據庫集群。
僅支持CSV格式的OSS冷數據創建 OSS_FILE_FILTER。
要在當前表上支持
OSS_FILE_FILTER
,必須具有OSS META = 1
的選項。通過SHOW CREATE TABLE
命令,可以在CSV格式中查看當前表是否已開啟OSS META
。如果返回結果中包含OSS META=1
,則表示當前表已開啟OSS META
。如需詳細了解請參考冷數據DDL。SHOW CREATE TABLE t; *************************** 1. row *************************** Table: t Create Table: CREATE TABLE `t` ( `id` int(11) DEFAULT NULL ) /*!99990 800020213 STORAGE OSS */ ENGINE=CSV DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci /*!99990 800020204 NULL_MARKER='NULL' */ /*!99990 800020223 OSS META=1 */ 1 row in set (0.00 sec)
使用限制
目前暫不支持在ePQ彈性并行查詢的場景下使用OSS_FILE_FILTER過濾數據。
當前支持的OSS_FILE_FILTER函數:=、<=>、<、<=、>=、>、BETWEEN、LIKE、IS NULL、IS NOT NULL、LIKE只支持右百分號(LIKE 'ABC%')。
當前支持OSS_FILE_FILTER的數據類型:
類別
數據類型
整數
TINYINT
,SMALLINT
,MEDIUMINT
,INT
,BIGINT
,TINYINT UNSIGNED
,SMALLINT UNSIGNED
,MEDIUMINT UNSIGNED
,INT UNSIGNE
,BIGINT UNSIGNED
浮點數
FLOAT
,DOUBLE
定點數
DECIMAL
時間類型
DATE
,DATETIME
,TIME
,TIMESTAMP
字符串類型
CHAR
,VARCHAR
如果使用BLOOM FILTER則不限制列的數據類型。
如果字符串類型保存的是UUID值,建議使用BLOOM FILTER進行過濾。
對于字符串類型的列,只支持大小寫敏感的比較方式。
支持多個條件之間的AND運算,但不支持多個條件之間的OR運算。
如果OSS表里沒有數據,則不能使用OSS_FILE_FILTER查詢加速。
操作步驟
請在控制臺中將集群參數
loose_use_oss_meta
設置為ON,開啟USE_OSS_META
功能,集群參數配置請參考設置集群參數和節點參數。請在控制臺中將集群參數
loose_optimizer_switch
設置為ENGINE_CONDITION_PUSHDOWN=ON
,集群參數配置請參考設置集群參數和節點參數。請在控制臺中將集群參數
loose_csv_oss_file_filter
設置為ON,開啟OSS_FILE_FILTER
功能,集群參數配置請參考設置集群參數和節點參數。請確保數據庫集群已成功連接。如尚未連接,請參考連接數據庫集群相關文檔進行連接操作,驗證當前參數配置是否已成功應用。
-- 檢查oss_file_filter是否設置成功 SHOW VARIABLES LIKE 'oss_file_filter'; -- 檢查use_oss_meta是否設置成功 SHOW VARIABLES LIKE 'use_oss_meta'; -- 檢查engine_condition_pushdown是否設置成功 SHOW VARIABLES LIKE 'optimizer_switch';
OSS_FILE_FILTER格式
通過給CSV格式歸檔表增加OSS_FILE_FILTER的table option來創建表的OSS_FILE_FILTER數據。OSS_FILE_FILTER格式如下:
OSS_FILE_FILTER = 'field_filter[,field_filter]'
field_filter := field_name[:filter_type]
filter_type := bloom
各列類型均有默認的FILE_FILTER類型(數值和時間類型默認使用MIN/MAX統計過濾,字符串類型默認使用CHARACTOR MAP過濾),所有列類型均可通過指定FILE_FILTER為BLOOM類型使用布隆過濾器。
示例
歸檔冷存表時創建OSS_FILE_FITLER
手動歸檔表時創建OSS_FILE_FITLER
-- 表結構
CREATE TABLE `lineitem` (
`L_ORDERKEY` int(11) NOT NULL,
`L_PARTKEY` int(11) NOT NULL,
`L_SUPPKEY` int(11) NOT NULL,
`L_LINENUMBER` int(11) NOT NULL,
`L_QUANTITY` decimal(15,2) NOT NULL,
`L_EXTENDEDPRICE` decimal(15,2) NOT NULL,
`L_DISCOUNT` decimal(15,2) NOT NULL,
`L_TAX` decimal(15,2) NOT NULL,
`L_RETURNFLAG` char(1) COLLATE utf8_bin NOT NULL,
`L_LINESTATUS` char(1) COLLATE utf8_bin NOT NULL,
`L_SHIPDATE` date NOT NULL,
`L_COMMITDATE` date NOT NULL,
`L_RECEIPTDATE` date NOT NULL,
`L_SHIPINSTRUCT` char(25) COLLATE utf8_bin NOT NULL,
`L_SHIPMODE` char(10) COLLATE utf8_bin NOT NULL,
`L_COMMENT` varchar(44) COLLATE utf8_bin NOT NULL
) ENGINE = innodb;
-- 歸檔表同時在L_ORDERKEY、L_LINENUMBER、L_SHIPDATE列創建oss file filter
ALTER TABLE lineitem ENGINE = CSV STORAGE OSS
OSS_FILE_FILTER = 'L_ORDERKEY,L_LINENUMBER,L_SHIPDATE';
已歸檔的表新增OSS_FILE_FITLER
對已經完成歸檔的表創建OSS_FILE_FITLER
-- 表結構
CREATE TABLE `lineitem` (
`L_ORDERKEY` int(11) NOT NULL,
`L_PARTKEY` int(11) NOT NULL,
`L_SUPPKEY` int(11) NOT NULL,
`L_LINENUMBER` int(11) NOT NULL,
`L_QUANTITY` decimal(15,2) NOT NULL,
`L_EXTENDEDPRICE` decimal(15,2) NOT NULL,
`L_DISCOUNT` decimal(15,2) NOT NULL,
`L_TAX` decimal(15,2) NOT NULL,
`L_RETURNFLAG` char(1) COLLATE utf8_bin NOT NULL,
`L_LINESTATUS` char(1) COLLATE utf8_bin NOT NULL,
`L_SHIPDATE` date NOT NULL,
`L_COMMITDATE` date NOT NULL,
`L_RECEIPTDATE` date NOT NULL,
`L_SHIPINSTRUCT` char(25) COLLATE utf8_bin NOT NULL,
`L_SHIPMODE` char(10) COLLATE utf8_bin NOT NULL,
`L_COMMENT` varchar(44) COLLATE utf8_bin NOT NULL
) ENGINE = CSV STORAGE OSS;
-- 在已經歸檔的表的L_ORDERKEY、L_LINENUMBER、L_SHIPDATE、L_SHIPINSTRUCT 列創建oss file filter,其中 L_SHIPINSTRUCT 列上是BLOOM
ALTER TABLE lineitem OSS_FILE_FILTER = 'L_ORDERKEY,L_LINENUMBER,L_SHIPDATE,L_SHIPINSTRUCT:BLOOM';
使用OSS_FILE_FILTER
查詢條件如果使用OSS_FILE_FILTER,將會被下推到CSV格式的OSS冷數據中。通過查詢計劃可以查看被下推到引擎的條件。
-- 表結構
CREATE TABLE `lineitem` (
`L_ORDERKEY` int(11) NOT NULL,
`L_PARTKEY` int(11) NOT NULL,
`L_SUPPKEY` int(11) NOT NULL,
`L_LINENUMBER` int(11) NOT NULL,
`L_QUANTITY` decimal(15,2) NOT NULL,
`L_EXTENDEDPRICE` decimal(15,2) NOT NULL,
`L_DISCOUNT` decimal(15,2) NOT NULL,
`L_TAX` decimal(15,2) NOT NULL,
`L_RETURNFLAG` char(1) COLLATE utf8_bin NOT NULL,
`L_LINESTATUS` char(1) COLLATE utf8_bin NOT NULL,
`L_SHIPDATE` date NOT NULL,
`L_COMMITDATE` date NOT NULL,
`L_RECEIPTDATE` date NOT NULL,
`L_SHIPINSTRUCT` char(25) COLLATE utf8_bin NOT NULL,
`L_SHIPMODE` char(10) COLLATE utf8_bin NOT NULL,
`L_COMMENT` varchar(44) COLLATE utf8_bin NOT NULL
) ENGINE = CSV STORAGE OSS OSS_FILE_FILTER = 'L_ORDERKEY,L_LINENUMBER,L_SHIPDATE';
-- 查詢計劃
explain select * from lineitem where l_orderkey=96;
+----+-------------+----------+------------+------+---------------+------+---------+------+---------+----------+---------------------------------------------------------------------------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+----------+------------+------+---------------+------+---------+------+---------+----------+---------------------------------------------------------------------------------+
| 1 | SIMPLE | lineitem | NULL | ALL | NULL | NULL | NULL | NULL | 6001215 | 10.00 | Using where; With pushed engine condition (`test`.`lineitem`.`L_ORDERKEY` = 96) |
+----+-------------+----------+------------+------+---------------+------+---------+------+---------+----------+---------------------------------------------------------------------------------+
explain format = tree select * from lineitem where l_orderkey=96 \G
*************************** 1. row ***************************
EXPLAIN: -> Filter: (lineitem.L_ORDERKEY = 96) (cost=15010.00 rows=10000)
-> Table scan on lineitem, extra (oss_file_filter conditions: (lineitem.L_ORDERKEY = 96)) (cost=15010.00 rows=100000)
-- 執行SQL
select count(*) from lineitem where l_orderkey=96;