Accumulo 連接器¶
概觀¶
Accumulo 連接器支援從 Apache Accumulo 讀取和寫入資料。請詳閱此頁面,以了解連接器的功能和特性。
安裝迭代器相依性¶
Accumulo 連接器使用自訂的 Accumulo 迭代器,以便將 SQL 述詞子句中的各種資訊推送至 Accumulo 以進行伺服器端篩選,稱為「述詞下推」。為了使伺服器端迭代器正常運作,您需要將 presto-accumulo
jar 檔案新增至每個 TabletServer 節點上的 Accumulo lib/ext
目錄。
# For each TabletServer node:
scp $PRESTO_HOME/plugins/accumulo/presto-accumulo-*.jar [tabletserver_address]:$ACCUMULO_HOME/lib/ext
# TabletServer should pick up new JAR files in ext directory, but may require restart
請注意,此處使用 Java 8。如果您的 Accumulo 叢集使用 Java 7,當您嘗試建立索引資料表時,您會在 TabletServer 記錄中收到 Unsupported major.minor version 52.0
錯誤。您需要改用位於 https://github.com/bloomberg/presto-accumulo 的 *presto-accumulo-iterators* jar 檔案。
連接器組態¶
建立 etc/catalog/accumulo.properties
以將 accumulo
連接器掛載為 accumulo
目錄,並根據需要替換 accumulo.xxx
屬性
connector.name=accumulo
accumulo.instance=xxx
accumulo.zookeepers=xxx
accumulo.username=username
accumulo.password=password
組態變數¶
屬性名稱 |
預設值 |
必要 |
描述 |
---|---|---|---|
|
(無) |
是 |
Accumulo 執行個體的名稱 |
|
(無) |
是 |
ZooKeeper 連接字串 |
|
(無) |
是 |
Presto 的 Accumulo 使用者 |
|
(無) |
是 |
使用者的 Accumulo 密碼 |
|
|
否 |
用於儲存中繼資料的根 znode。僅在使用預設中繼資料管理員時相關 |
|
|
否 |
設定索引基數快取的大小 |
|
|
否 |
設定基數快取的到期時間。 |
不支援的功能¶
不支援下列功能
透過
ALTER TABLE
新增欄:雖然您無法透過 SQL 新增欄,但您可以使用工具。如需更多詳細資訊,請參閱下方關於新增欄的章節。DELETE
:連接器尚未實作刪除列的功能。
用法¶
只需開始使用 SQL 在 Accumulo 中建立新資料表,即可開始處理資料。依預設,資料表定義的第一欄會設定為 Accumulo 列 ID。這應該是您資料表的主索引鍵,請記住,任何包含相同列 ID 的 INSERT
陳述式實際上都相當於 Accumulo 的 UPDATE,因為儲存格中的任何先前資料都會被覆寫。列 ID 可以是任何有效的 Presto 資料類型。如果第一欄不是您的主索引鍵,您可以使用資料表定義的 WITH
子句中的 row_id
資料表屬性來設定列 ID 欄。
只需發出 CREATE TABLE
陳述式即可建立新的 Presto/Accumulo 資料表
CREATE TABLE myschema.scientists (
recordkey VARCHAR,
name VARCHAR,
age BIGINT,
birthday DATE
);
DESCRIBE myschema.scientists;
Column | Type | Extra | Comment
-----------+---------+-------+---------------------------------------------------
recordkey | varchar | | Accumulo row ID
name | varchar | | Accumulo column name:name. Indexed: false
age | bigint | | Accumulo column age:age. Indexed: false
birthday | date | | Accumulo column birthday:birthday. Indexed: false
此命令將建立一個新的 Accumulo 資料表,其中 recordkey
欄為 Accumulo 列 ID。name、age 和 birthday 欄會對應至自動產生的欄系列和限定詞值 (實際上,這兩者都與 Presto 欄名稱相同)。
當使用 SQL 建立資料表時,您可以選擇性地指定 column_mapping
資料表屬性。此屬性的值是以逗號分隔的三元組清單,即 Presto 欄: Accumulo 欄系列: Accumulo 欄限定詞,每個非列 ID 欄都有一個三元組。這會設定 Presto 欄名稱與對應的 Accumulo 欄系列和欄限定詞之間的對應。
如果您未指定 column_mapping
資料表屬性,則連接器會自動產生欄名稱 (並遵守任何已設定的局部性群組)。自動產生欄名稱僅適用於內部資料表,因此如果您的資料表是外部的,您必須指定 column_mapping 屬性。
如需資料表屬性的完整清單,請參閱資料表屬性。
例如
CREATE TABLE myschema.scientists (
recordkey VARCHAR,
name VARCHAR,
age BIGINT,
birthday DATE
)
WITH (
column_mapping = 'name:metadata:name,age:metadata:age,birthday:metadata:date'
);
DESCRIBE myschema.scientists;
Column | Type | Extra | Comment
-----------+---------+-------+-----------------------------------------------
recordkey | varchar | | Accumulo row ID
name | varchar | | Accumulo column metadata:name. Indexed: false
age | bigint | | Accumulo column metadata:age. Indexed: false
birthday | date | | Accumulo column metadata:date. Indexed: false
然後,您可以發出 INSERT
陳述式以將資料放入 Accumulo。
注意
雖然發出 INSERT
陳述式很方便,但這種將資料載入 Accumulo 的方法輸送量很低。您應該使用 Accumulo API 將 Mutations
直接寫入資料表。如需更多詳細資訊,請參閱關於載入資料的章節。
INSERT INTO myschema.scientists VALUES
('row1', 'Grace Hopper', 109, DATE '1906-12-09' ),
('row2', 'Alan Turing', 103, DATE '1912-06-23' );
SELECT * FROM myschema.scientists;
recordkey | name | age | birthday
-----------+--------------+-----+------------
row1 | Grace Hopper | 109 | 1906-12-09
row2 | Alan Turing | 103 | 1912-06-23
(2 rows)
如您所預期,透過 Shell 或程式設計方式插入 Accumulo 的列也會在查詢時顯示。(Accumulo Shell 認為「-5321」是一個選項,而不是數字…因此,我們將 TBL 的年紀縮小一點。)
$ accumulo shell -u root -p secret
root@default> table myschema.scientists
root@default myschema.scientists> insert row3 metadata name "Tim Berners-Lee"
root@default myschema.scientists> insert row3 metadata age 60
root@default myschema.scientists> insert row3 metadata date 5321
SELECT * FROM myschema.scientists;
recordkey | name | age | birthday
-----------+-----------------+-----+------------
row1 | Grace Hopper | 109 | 1906-12-09
row2 | Alan Turing | 103 | 1912-06-23
row3 | Tim Berners-Lee | 60 | 1984-07-27
(3 rows)
您也可以使用 DROP TABLE
來刪除資料表。此命令會同時刪除中繼資料和資料表。如需有關內部和外部資料表的更多詳細資訊,請參閱下方關於外部資料表的章節。
DROP TABLE myschema.scientists;
索引欄¶
在內部,連接器會建立一個 Accumulo Range
,並將其打包在分割中。此分割會傳遞至 Presto 工作者,以透過 BatchScanner
從 Range
讀取資料。當發出導致完整資料表掃描的查詢時,每個 Presto 工作者都會取得一個對應至資料表單一平板的單一 Range
。當發出包含述詞的查詢 (亦即,WHERE x = 10
子句) 時,Presto 會將述詞 (10
) 中的值傳遞至連接器,以便使用此資訊來掃描較少的資料。當 Accumulo 列 ID 用作述詞子句的一部分時,這會縮小 Range
查閱範圍,以從 Accumulo 快速擷取資料子集。
但其他欄位呢? 如果您經常查詢非資料列 ID 的欄位,您應該考慮使用 Accumulo 連接器內建的索引功能。當從表格中選擇少量數值時,此功能可以大幅縮短查詢執行時間,而且當您透過 Presto INSERT
陳述式載入資料時,會為您完成繁重的工作 (但請記住,透過 INSERT
將資料寫入 Accumulo 並沒有很高的輸送量)。
若要啟用索引功能,請新增 index_columns
表格屬性,並指定您要建立索引的 Presto 欄位名稱的逗號分隔清單 (在此範例中,我們使用 string
序列化器來協助說明,您應該使用預設的 lexicoder
序列化器)。
CREATE TABLE myschema.scientists (
recordkey VARCHAR,
name VARCHAR,
age BIGINT,
birthday DATE
)
WITH (
serializer = 'string',
index_columns='name,age,birthday'
);
建立表格後,我們會看到額外兩個 Accumulo 表格用於儲存索引和指標。
root@default> tables
accumulo.metadata
accumulo.root
myschema.scientists
myschema.scientists_idx
myschema.scientists_idx_metrics
trace
插入資料後,我們可以查看索引表格,並看到 name、age 和 birthday 欄位有索引值。連接器會查詢這個索引表格
INSERT INTO myschema.scientists VALUES
('row1', 'Grace Hopper', 109, DATE '1906-12-09'),
('row2', 'Alan Turing', 103, DATE '1912-06-23');
root@default> scan -t myschema.scientists_idx
-21011 metadata_date:row2 []
-23034 metadata_date:row1 []
103 metadata_age:row2 []
109 metadata_age:row1 []
Alan Turing metadata_name:row2 []
Grace Hopper metadata_name:row1 []
當針對索引欄位發出帶有 WHERE
子句的查詢時,連接器會搜尋索引表格,找出述詞中包含該值的所有資料列 ID。這些資料列 ID 會被捆綁成 Presto 分割區,作為單一值的 Range
物件 (每個分割區的資料列 ID 數量由 accumulo.index_rows_per_split
的值控制),並傳遞到 Presto 工作節點,以便在掃描資料表格的 BatchScanner
中進行設定。
SELECT * FROM myschema.scientists WHERE age = 109;
recordkey | name | age | birthday
-----------+--------------+-----+------------
row1 | Grace Hopper | 109 | 1906-12-09
(1 row)
載入資料¶
Accumulo 連接器支援透過 INSERT 陳述式載入資料,但這種方法的輸送量往往較低,當考量輸送量時不應依賴此方法。相反地,連接器的使用者應使用 PrestoBatchWriter
工具,該工具作為 presto-accumulo 儲存庫中 presto-accumulo-tools 子專案的一部分提供。
PrestoBatchWriter
是典型 BatchWriter
的包裝類別,它利用 Presto/Accumulo 中繼資料將突變寫入主資料表格。特別是,它會處理在任何索引欄位上針對給定突變建立索引。此工具的使用方法已在 儲存庫的 README 中提供。
外部表格¶
預設情況下,使用 Presto 的 SQL 陳述式建立的表格是內部表格,也就是說,Presto 會管理 Presto 表格中繼資料和 Accumulo 表格。當您建立內部表格時,也會建立 Accumulo 表格。如果 Accumulo 表格已存在,您將會收到錯誤訊息。當透過 Presto 刪除內部表格時,也會刪除 Accumulo 表格 (和任何索引表格)。
若要變更此行為,請在發出 CREATE
陳述式時,將 external
屬性設定為 true
。這會將表格設為外部表格,而 DROP TABLE
命令將只會刪除與表格相關聯的中繼資料。如果 Accumulo 表格還不存在,則會由連接器建立。
建立外部表格將會在索引和指標表格上設定任何已設定的區域性群組以及迭代器 (如果表格已建立索引)。簡而言之,外部表格和內部表格之間的唯一差異在於,當發出 DROP TABLE
命令時,連接器將刪除 Accumulo 表格。
外部表格可能比較難以使用,因為資料是以預期的格式儲存。如果資料未正確儲存,您將會遇到麻煩。使用者在建立表格時必須提供 column_mapping
屬性。這會建立 Presto 欄位名稱到表格資料格的欄位系列/限定詞的對應。資料格的值會儲存在 Accumulo 金鑰/值組的 Value
中。預設情況下,預期此值會使用 Accumulo 的 lexicoder API 進行序列化。如果您將值儲存為字串,可以使用表格的 serializer
屬性指定不同的序列化器。如需更多資訊,請參閱 表格屬性章節。
接下來,我們建立 Presto 外部表格。
CREATE TABLE external_table (
a VARCHAR,
b BIGINT,
c DATE
)
WITH (
column_mapping = 'a:md:a,b:md:b,c:md:c',
external = true,
index_columns = 'b,c',
locality_groups = 'foo:b,c'
);
建立表格後,表格的使用方式照常進行
INSERT INTO external_table VALUES
('1', 1, DATE '2015-03-06'),
('2', 2, DATE '2015-03-07');
SELECT * FROM external_table;
a | b | c
---+---+------------
1 | 1 | 2015-03-06
2 | 2 | 2015-03-06
(2 rows)
DROP TABLE external_table;
刪除表格後,表格仍會存在於 Accumulo 中,因為它是外部表格。
root@default> tables
accumulo.metadata
accumulo.root
external_table
external_table_idx
external_table_idx_metrics
trace
如果我們想要將新的欄位新增到表格中,我們可以再次建立表格,並指定新的欄位。表格中的任何現有資料列都會有 NULL 值。此命令將重新設定 Accumulo 表格,設定區域性群組和迭代器設定。
CREATE TABLE external_table (
a VARCHAR,
b BIGINT,
c DATE,
d INTEGER
)
WITH (
column_mapping = 'a:md:a,b:md:b,c:md:c,d:md:d',
external = true,
index_columns = 'b,c,d',
locality_groups = 'foo:b,c,d'
);
SELECT * FROM external_table;
a | b | c | d
---+---+------------+------
1 | 1 | 2015-03-06 | NULL
2 | 2 | 2015-03-07 | NULL
(2 rows)
表格屬性¶
表格屬性使用範例
CREATE TABLE myschema.scientists (
recordkey VARCHAR,
name VARCHAR,
age BIGINT,
birthday DATE
)
WITH (
column_mapping = 'name:metadata:name,age:metadata:age,birthday:metadata:date',
index_columns = 'name,age'
);
屬性名稱 |
預設值 |
描述 |
---|---|---|
|
(已產生) |
欄位中繼資料的逗號分隔清單: |
|
(無) |
在此表格的對應索引表格中建立索引的 Presto 欄位的逗號分隔清單 |
|
|
如果為 true,Presto 將只會執行表格的中繼資料作業。否則,Presto 將在適當情況下建立和刪除 Accumulo 表格。 |
|
(無) |
要設定在 Accumulo 表格上的區域性群組清單。僅在內部表格上有效。字串格式為區域性群組名稱、冒號、群組中以逗號分隔的欄位系列清單。群組以管道符號分隔。範例: |
|
(第一個欄位) |
對應至 Accumulo 資料列 ID 的 Presto 欄位名稱。 |
|
|
Accumulo 資料編碼的序列化器。可以是 |
|
(使用者授權) |
在批次掃描器上設定的掃描時授權。 |
工作階段屬性¶
您可以使用 SET SESSION 變更工作階段屬性的預設值。請注意,工作階段屬性會加上目錄名稱的前置詞
SET SESSION accumulo.column_filter_optimizations_enabled = false;
屬性名稱 |
預設值 |
描述 |
---|---|---|
|
|
設定為 true 可針對未索引掃描啟用資料區域性 |
|
|
設定為 true 可依平板分割區分割未索引的查詢。一般應為 true。 |
|
|
設定為 true 可啟用查詢的輔助索引使用 |
|
|
封裝到單一 Presto 分割區的 Accumulo 資料列 ID 數量 |
|
|
根據索引掃描的資料列數量與資料列總數的比率。如果比率低於此閾值,將會使用索引。 |
|
|
當最低基數的欄位將被使用,而不是計算索引中範圍的交集時的閾值。必須啟用輔助索引 |
|
|
設定為 true 可啟用指標表格的使用,以最佳化索引的使用 |
|
(設定) |
掃描表格時要模擬的使用者。此屬性會覆蓋 |
|
|
一旦任何欄位小於最低基數閾值,就會縮短擷取索引指標的時間 |
|
|
設定縮短擷取索引指標的基數快取輪詢持續時間 |
新增欄位¶
由於欄位運作所需的額外中繼資料 (欄位系列、限定詞,以及是否已建立索引),目前無法透過 ALTER TABLE [table] ADD COLUMN [name] [type]
將新欄位新增到現有的表格。
相反地,您可以使用 presto-accumulo
儲存庫的 presto-accumulo-tools 子專案中的其中一個公用程式。文件和使用方式可在 README 中找到。
序列化器¶
適用於 Accumulo 的 Presto 連接器具有可外掛的序列化器架構,可處理 Presto 和 Accumulo 之間的 I/O。這讓終端使用者能夠以程式設計方式在 Accumulo 中序列化和還原序列化其特殊的資料格式,同時將連接器本身的複雜性抽象化。
目前有兩種序列化器類型可用;一種 string
序列化器,將值視為 Java String
,以及一種 lexicoder
序列化器,它會利用 Accumulo 的 Lexicoder API 來儲存值。預設序列化器是 lexicoder
序列化器,因為此序列化器不需要在 String
物件和 Presto 類型之間進行昂貴的轉換作業,也就是說,資料格的值會編碼為位元組陣列。
此外,lexicoder
序列化器會對數值類型(如 BIGINT
或 TIMESTAMP
)進行正確的字典排序。這對於連接器在查詢資料時正確利用二級索引至關重要。
您可以透過指定 serializer
表格屬性來變更預設的序列化器。可用的選項包括內建類型 default
(即 lexicoder
)、string
或 lexicoder
。您也可以透過擴展 AccumuloRowSerializer
來提供自己的實作,將其加入 Presto 的 CLASSPATH
,並在連接器配置中指定完整的 Java 類別名稱。
CREATE TABLE myschema.scientists (
recordkey VARCHAR,
name VARCHAR,
age BIGINT,
birthday DATE
)
WITH (
column_mapping = 'name:metadata:name,age:metadata:age,birthday:metadata:date',
serializer = 'default'
);
INSERT INTO myschema.scientists VALUES
('row1', 'Grace Hopper', 109, DATE '1906-12-09' ),
('row2', 'Alan Turing', 103, DATE '1912-06-23' );
root@default> scan -t myschema.scientists
row1 metadata:age [] \x08\x80\x00\x00\x00\x00\x00\x00m
row1 metadata:date [] \x08\x7F\xFF\xFF\xFF\xFF\xFF\xA6\x06
row1 metadata:name [] Grace Hopper
row2 metadata:age [] \x08\x80\x00\x00\x00\x00\x00\x00g
row2 metadata:date [] \x08\x7F\xFF\xFF\xFF\xFF\xFF\xAD\xED
row2 metadata:name [] Alan Turing
CREATE TABLE myschema.stringy_scientists (
recordkey VARCHAR,
name VARCHAR,
age BIGINT,
birthday DATE
)
WITH (
column_mapping = 'name:metadata:name,age:metadata:age,birthday:metadata:date',
serializer = 'string'
);
INSERT INTO myschema.stringy_scientists VALUES
('row1', 'Grace Hopper', 109, DATE '1906-12-09' ),
('row2', 'Alan Turing', 103, DATE '1912-06-23' );
root@default> scan -t myschema.stringy_scientists
row1 metadata:age [] 109
row1 metadata:date [] -23034
row1 metadata:name [] Grace Hopper
row2 metadata:age [] 103
row2 metadata:date [] -21011
row2 metadata:name [] Alan Turing
CREATE TABLE myschema.custom_scientists (
recordkey VARCHAR,
name VARCHAR,
age BIGINT,
birthday DATE
)
WITH (
column_mapping = 'name:metadata:name,age:metadata:age,birthday:metadata:date',
serializer = 'my.serializer.package.MySerializer'
);
中繼資料管理¶
Presto/Accumulo 表格的中繼資料儲存在 ZooKeeper 中。您可以在 Presto 中執行 SQL 語句來建立和刪除表格(建議這樣做)。這是建立連接器運作所需中繼資料最簡單的方法。最好不要隨意更動中繼資料,但以下是關於其儲存方式的詳細資訊,知道這些資訊是有益的。
ZooKeeper 中的一個根節點保存了所有的映射,其格式如下:
/metadata-root/schema/table
其中,metadata-root
是組態檔中 zookeeper.metadata.root
的值(預設值為 /presto-accumulo
),schema
是 Presto schema(與 Accumulo 命名空間名稱相同),而 table
是 Presto 表格名稱(也與 Accumulo 名稱相同)。table
ZooKeeper 節點的資料是一個序列化的 AccumuloTable
Java 物件(位於連接器程式碼中)。此表格包含 schema(命名空間)名稱、表格名稱、欄位定義、表格要使用的序列化器,以及任何其他表格屬性。
如果您需要以程式方式操作 Accumulo 的 ZooKeeper 中繼資料,請參考 com.facebook.presto.accumulo.metadata.ZooKeeperMetadataManager
以獲取簡化此過程的 Java 程式碼。
將表格從內部轉換為外部¶
如果您的表格是內部表格,您可以透過刪除 ZooKeeper 中對應的 znode 將其轉換為外部表格,實際上使該表格在 Presto 中不再存在。然後,使用相同的 DDL 重新建立表格,但新增 external = true
表格屬性。
例如
1. 我們從一個內部表格 foo.bar
開始,該表格是使用以下 DDL 建立的。如果您之前沒有為 column_mapping
定義表格屬性(如本範例),請務必在刪除中繼資料之前描述表格。在建立外部表格時,我們將需要欄位映射。
CREATE TABLE foo.bar (a VARCHAR, b BIGINT, c DATE)
WITH (
index_columns = 'b,c'
);
DESCRIBE foo.bar;
Column | Type | Extra | Comment
--------+---------+-------+-------------------------------------
a | varchar | | Accumulo row ID
b | bigint | | Accumulo column b:b. Indexed: true
c | date | | Accumulo column c:c. Indexed: true
2. 使用 ZooKeeper CLI,刪除對應的 znode。請注意,這裡使用的是預設的 ZooKeeper 中繼資料根目錄 /presto-accumulo
$ zkCli.sh
[zk: localhost:2181(CONNECTED) 1] delete /presto-accumulo/foo/bar
3. 使用與之前相同的 DDL 重新建立表格,但新增 external=true
屬性。請注意,如果您之前沒有定義 column_mapping,則需要在新的 DDL 中新增該屬性(外部表格需要設定此屬性)。欄位映射位於 DESCRIBE
語句的輸出中。
CREATE TABLE foo.bar (
a VARCHAR,
b BIGINT,
c DATE
)
WITH (
column_mapping = 'a:a:a,b:b:b,c:c:c',
index_columns = 'b,c',
external = true
);