Phoenix学習ノート

19397 ワード

HBase Phoenix
[TOC]
概要
Phoenixはアプリケーション層とHBASEの間のミドルウェアとして、次の特性により、ビッグデータ量の単純なクエリーシーンで独自の利点があります.
  • 二次インデックスサポート(global index+local index)
  • SQLをコンパイル元のHBASEとなる並列実行可能なscanはデータ層で計算を完了し、server側のcoprocessorは集約を実行してwhereフィルタ条件をserver側のscan filterに押して統計情報を利用して最適化し、クエリー計画を選択する(5.xバージョンはCBOをサポートする)
  • .
  • skip scan機能スキャン速度
  • 向上
    一般的にPhoenixにアクセスするには、次の3つの方法があります.
  • JDBC API
  • Pythonで作成したコマンドラインツール(sqlline,sqlline-thin,psqlなど)
  • を使用
  • SQuirrel

  • インストール
    Ambariは実はPhoenixを持っているので、インストールが簡単なので、起動して直接インストールをクリックすればいいです.
    でもambari 2.4.2.Phoenixバージョン4.7.0とHBAse 1.1.2ではsqllineを用いる.py接続時にエラーが発生します
    Class org.apache.phoenix.coprocessor.MetaDataEndpointImpl cannot be loaded Set hbase.table.sanity.checks to false at conf or table descriptor if you want to bypass sanity checks

    ヒントに従って配置を増やし、HBAseを再起動すればいいです.
    新しいバージョンambari 2.7.3この問題はありません.Phoenix 5.0.0 HBase2.0.0
    今回は4.7.0バージョンを例に、phoenix-sqlline${zookeeeper}を使用してデモを行います.
    データ型
  • INTEGER Type
  • UNSIGNED_INT Type
  • BIGINT Type
  • UNSIGNED_LONG Type
  • TINYINT Type
  • UNSIGNED_TINYINT Type
  • SMALLINT Type
  • UNSIGNED_SMALLINT Type
  • FLOAT Type
  • UNSIGNED_FLOAT Type
  • DOUBLE Type
  • UNSIGNED_DOUBLE Type
  • DECIMAL Type
  • BOOLEAN Type
  • TIME Type
  • DATE Type
  • TIMESTAMP Type
  • UNSIGNED_TIME Type
  • UNSIGNED_DATE Type
  • UNSIGNED_TIMESTAMP Type
  • VARCHAR Type
  • CHAR Type
  • BINARY Type
  • VARBINARY Type
  • ARRAY

  • データ型詳細は公式サイトを参照
    CRUD操作
    公式サイトPhoenixコマンドの詳細
    以下は一部のプレゼンテーションのみです.
    テーブルの作成
    Phoenixでのテーブルの作成CREATE TABLE IF NOT EXISTS ljktest (ID VARCHAR PRIMARY KEY,NAME VARCHAR,AGE TINYINT) CREATE TABLE IF NOT EXISTS "ljktest" (ID VARCHAR PRIMARY KEY,NAME VARCHAR,AGE TINYINT) CREATE TABLE LJKTEST2 (ID INTEGER NOT NULL,AGE TINYINT NOT NULL,NAME VARCHAR,CONSTRAINT PK PRIMARY KEY(ID, AGE)) TTL = 86400;
    hbase-shellでテーブル生成があるかどうかを確認すると、デフォルトではHBAse側のテーブルが大文字で、大文字と小文字を区別するには引用符を入れればいいことがわかります.その中にはコプロセッサがたくさん入っています.カラムクラスタを指定しない場合、デフォルトのカラムクラスタは0で表されます.
    hbase(main):008:0> desc 'LJKTEST'
    Table LJKTEST is ENABLED                                                                        
    LJKTEST, {TABLE_ATTRIBUTES => {coprocessor$1 => '|org.apache.phoenix.coprocessor.ScanRegionObser
    ver|805306366|', coprocessor$2 => '|org.apache.phoenix.coprocessor.UngroupedAggregateRegionObser
    ver|805306366|', coprocessor$3 => '|org.apache.phoenix.coprocessor.GroupedAggregateRegionObserve
    r|805306366|', coprocessor$4 => '|org.apache.phoenix.coprocessor.ServerCachingEndpointImpl|80530
    6366|', coprocessor$5 => '|org.apache.phoenix.hbase.index.Indexer|805306366|index.builder=org.ap
    ache.phoenix.index.PhoenixIndexBuilder,org.apache.hadoop.hbase.index.codec.class=org.apache.phoe
    nix.index.PhoenixIndexCodec'}                                                                   
    COLUMN FAMILIES DESCRIPTION                                                                     
    {NAME => '0', VERSIONS => '1', EVICT_BLOCKS_ON_CLOSE => 'false', NEW_VERSION_BEHAVIOR => 'false'
    , KEEP_DELETED_CELLS => 'FALSE', CACHE_DATA_ON_WRITE => 'false', DATA_BLOCK_ENCODING => 'FAST_DI
    FF', TTL => 'FOREVER', MIN_VERSIONS => '0', REPLICATION_SCOPE => '0', BLOOMFILTER => 'NONE', CAC
    HE_INDEX_ON_WRITE => 'false', IN_MEMORY => 'false', CACHE_BLOOMS_ON_WRITE => 'false', PREFETCH_B
    LOCKS_ON_OPEN => 'false', COMPRESSION => 'NONE', BLOCKCACHE => 'true', BLOCKSIZE => '65536'}    
    1 row(s)
    Took 0.1066 seconds

    HBAseに既に存在するテーブルのマッピング
  • PhoenixがHBAseのテーブルをマッピングし、読み取り操作としてのみ使用する場合は、ビューグラフで作成することを強くお勧めします.CREATE VIEW LJK_TEST(ROWKEY VARCHAR PRIMARY KEY,"mycf"."name" VARCHAR);
  • はHBAseのテーブルをマッピングし、マッピングされたフィールドが正しく書かれていることを覚えています.

  • `CREATE TABLE LJK_TEST (ROWKEY VARCHAR PRIMARY KEY, "mycf"."name"VARCHAR) COLUMN_ENCODED_BYTES=0;`
    データの挿入
    UPSERT VALUES
  • 単純挿入
    UPSERT INTO LJKTEST VALUES('0001','LINJIKAI',18);
    同期hbase-shellで見た結果は
    hbase(main):010:0> scan 'LJKTEST'
    ROW                       COLUMN+CELL                                                           
     0001                     column=0:\x00\x00\x00\x00, timestamp=1557719617275, value=x           
     0001                     column=0:\x80\x0B, timestamp=1557719617275, value=LINJIKAI            
     0001                     column=0:\x80\x0C, timestamp=1557719617275, value=\x92                
    1 row(s)
    Took 0.0079 seconds                             
  • であった.
  • 特定フィールドUPSERT INTO LJKTEST(ID,NAME) VALUES('0002',' ');
  • を挿入する.
  • KEY挿入ポリシー更新フィールドUPSERT INTO LJKTEST VALUES('0003',' ',19) ON DUPLICATE KEY UPDATE AGE = AGE + 1;を繰り返す効果はvalueが同じ場合に年齢が1歳大きくなることであり、李四の最後の年齢が20歳
    0: jdbc:phoenix:> UPSERT INTO LJKTEST VALUES('0003','  ',19) ON DUPLICATE KEY UPDATE AGE = AGE + 1;
    1 row affected (0.011 seconds)
    0: jdbc:phoenix:>  SELECT * FROM LJKTEST;
    +-------+-----------+-------+
    |  ID   |   NAME    |  AGE  |
    +-------+-----------+-------+
    | 0001  | LINJIKAI  | 18    |
    | 0002  |           | null  |
    | 0003  |           | 20    |
    +-------+-----------+-------+
    3 rows selected (0.026 seconds)
    になってUPSERT INTO LJKTEST VALUES('0003',' ',19) ON DUPLICATE KEY IGNORE;を更新しないという書き方は李四の年齢を変えることはない.このデータのkeyはすでに存在しているからだ.

  • 二次索引
    phoenix 2次インデックス
    インデックスの上書き
    Phoenixは、インデックスを上書きするため、特に強力です.インデックス・エントリが見つかったら、プライマリ・テーブルに戻る必要はありません.逆に、関心のあるデータをインデックス・ラインにバンドルすることで、読み取り時間のオーバーヘッドを節約できます.
    二次インデックスメカニズムをテストするためにテーブルを作成します.次の他の機能インデックスもこのテーブルを使用して対応する二次インデックスを作成します.CREATE TABLE LJKTEST (ID CHAR(4) NOT NULL PRIMARY KEY,AGE UNSIGNED_TINYINT,NAME VARCHAR,COMPANY VARCHAR,SCHOOL VARCHAR)
    いくつかのデータを挿入します
    UPSERT INTO LJKTEST VALUES('0001',18,'  ','    ','    ');
    UPSERT INTO LJKTEST VALUES('0002',19,'  ','    ','    ');
    UPSERT INTO LJKTEST VALUES('0003',20,'  ','    ','    ');
    UPSERT INTO LJKTEST VALUES('0004',21,'  ','    ','    ');

    マルチフィールド上書きインデックスCREATE INDEX COVER_LJK_INDEX ON LJKTEST(COMPANY,SCHOOL) INCLUDE (NAME);の作成
    インデックスロジックの表示
    schoolフィールドを使用してクエリーを行うと、インデックスは表示されず、全テーブルスキャンに移行します.
    0: jdbc:phoenix:> EXPLAIN SELECT NAME FROM LJKTEST WHERE SCHOOL ='    ';
    +---------------------------------------------------------------------------+------------------+
    |                                   PLAN                                    | EST_BYTES_READ   |
    +---------------------------------------------------------------------------+------------------+
    | CLIENT 1-CHUNK PARALLEL 1-WAY ROUND ROBIN FULL SCAN OVER COVER_LJK_INDEX  | null             |
    |     SERVER FILTER BY "SCHOOL" = '    '                                    | null             |
    +---------------------------------------------------------------------------+------------------+

    ただし、companyフィールドを使用してクエリーを行うと、プレフィックスインデックスが付けられrange scanに入ります.
    0: jdbc:phoenix:> EXPLAIN SELECT NAME FROM LJKTEST WHERE COMPANY ='    ';
    +-------------------------------------------------------------------------------------+--------+
    |                                        PLAN                                         | EST_BY |
    +-------------------------------------------------------------------------------------+--------+
    | CLIENT 1-CHUNK PARALLEL 1-WAY ROUND ROBIN RANGE SCAN OVER COVER_LJK_INDEX ['    ']  | null   |
    +-------------------------------------------------------------------------------------+--------+

    次に、単一フィールドオーバーライドインデックスを作成します.CREATE INDEX COVER_LJK_INDEX_COMPANY ON LJKTEST(COMPANY) INCLUDE (NAME);
    0: jdbc:phoenix:> EXPLAIN SELECT NAME FROM LJKTEST WHERE COMPANY ='    ';
    +----------------------------------------------------------------------------------------------+
    |                                            PLAN                                              |
    +----------------------------------------------------------------------------------------------+
    | CLIENT 1-CHUNK PARALLEL 1-WAY ROUND ROBIN RANGE SCAN OVER COVER_LJK_INDEX_COMPANY ['    ']   |
    +----------------------------------------------------------------------------------------------+
    1 row selected (0.028 seconds)

    フィールドとして*番号を使用して検索すると、FULL SCANが表示されます.
    0: jdbc:phoenix:> EXPLAIN SELECT /*+ INDEX(LJKTEST COVER_LJK_INDEX_COMPANY)*/ *  FROM LJKTEST WHERE COMPANY ='    ';
    +----------------------------------------------------------------------------------------------+
    |                                                   PLAN                                       |
    +----------------------------------------------------------------------------------------------+
    | CLIENT 1-CHUNK PARALLEL 1-WAY ROUND ROBIN FULL SCAN OVER LJKTEST                             |
    |     SKIP-SCAN-JOIN TABLE 0                                                                   |
    |         CLIENT 1-CHUNK PARALLEL 1-WAY ROUND ROBIN RANGE SCAN OVER COVER_LJK_INDEX_COMPANY_ON |
    |             SERVER FILTER BY FIRST KEY ONLY                                                  |
    |     DYNAMIC SERVER FILTER BY "LJKTEST.ID" IN ($34.$36)                                       |
    +----------------------------------------------------------------------------------------------+

    この場合hintを使用してインデックスを指定する必要があります
    0: jdbc:phoenix:> EXPLAIN SELECT /*+INDEX(LJKTEST COVER_LJK_INDEX_COMPANY)*/* FROM LJKTEST WHERE COMPANY='    ';
    +-----------------------------------------------------------------------------------------------------+-----------------+----------------+--------------+
    |                                                PLAN                                                 | EST_BYTES_READ  | EST_ROWS_READ  | EST_INFO_TS  |
    +-----------------------------------------------------------------------------------------------------+-----------------+----------------+--------------+
    | CLIENT 1-CHUNK PARALLEL 1-WAY ROUND ROBIN FULL SCAN OVER LJKTEST                                    | null            | null           | null         |
    |     SKIP-SCAN-JOIN TABLE 0                                                                          | null            | null           | null         |
    |         CLIENT 1-CHUNK PARALLEL 1-WAY ROUND ROBIN RANGE SCAN OVER COVER_LJK_INDEX_COMPANY ['    ']  | null            | null           | null         |
    |             SERVER FILTER BY FIRST KEY ONLY                                                         | null            | null           | null         |
    |     DYNAMIC SERVER FILTER BY "LJKTEST.ID" IN ($10.$12)                                              | null            | null           | null         |
    +-----------------------------------------------------------------------------------------------------+-----------------+----------------+--------------+
    5 rows selected (0.046 seconds)

    機能インデックスCREATE INDEX SCHOOL_WITH_COMPANY ON LJKTEST(COMPANY||' '||SCHOOL)
    ローカルインデックスとグローバルインデックス
    ローカルインデックスにはLOCALキーを追加する必要があります.上はグローバルインデックスです.CREATE LOCAL INDEX COVER_LJK_INDEX_COMPANY ON LJKTEST(COMPANY) INCLUDE (NAME);
  • ローカルインデックス
  • 書くことが多く読むことが少ない場合に適しており、データは元のテーブルに格納され、侵入性が強い.
  • グローバルインデックス
  • 読み書きが少ない場合には、データは別のテーブルに格納されます.
    インデックス非同期作成{{いんでっくす:ひどうきさくせい}}
    デフォルトでは、インデックスを作成すると、CREATE INDEX呼び出し中にインデックスが同期して埋め込まれます.ただし、データ・テーブルの現在のサイズでは、実行できない可能性があります.4.5から、インデックス作成DDL文にASYNCキーワードを含めることで、インデックスの埋め込みを非同期で完了できます.CREATE INDEX INDEX_LJKTEST_AGE_ASYNC ON LJKTEST(AGE) INCLUDE(SCHOOL) ASYNC;
    これは最初のステップです.HBAseコマンドラインを使用して、インデックステーブルを埋め込むmap reduceジョブを個別に開始する必要があります. hbase org.apache.phoenix.mapreduce.index.IndexTool --data-table LJKTEST --index-table INDEX_LJKTEST_AGE_ASYNC --output-path ASYNC_IDX_HFILES
    インデックスはmap reduceジョブが完了した場合にのみアクティブ化され、クエリーで使用されます.
    output-pathオプションHFileへの書き込み用HDFSディレクトリの指定
    可変インデックス
    データが1回のみ書き込まれ、その場で更新されていないテーブルの場合、インクリメンタル・メンテナンスの書き込み時間のオーバーヘッドを低減するために、いくつかの最適化を行うことができます.これは、ログやイベントデータなどの時間系列データによく見られ、ローを書き込むと更新されません.これらの最適化を使用するには、DDL文にIMMUTABLE_を追加します.ROWS=trueプロパティテーブルを可変として宣言CREATE TABLE LJKTEST_IMMU (ROWKEY VARCHAR PRIMARY KEY, NAME VARCHAR,AGE VARCHAR) IMMUTABLE_ROWS=true; CREATE INDEX INDEX_LJKTEST_IMMU ON LJKTEST_IMMU(NAME) INCLUDE(AGE);
    下の不変インデックスの特性をテストしました
    rowkeyが同じデータで更新動作をしてもphoenixでは追加動作をします
      UPSERT INTO LJKTEST_IMMU VALUES('1','LILEI','18');
      UPSERT INTO LJKTEST_IMMU VALUES('1','HANGMEIMEI','18');
    0: jdbc:phoenix:dn1> select * from LJKTEST_IMMU;
    +---------+-------------+------+
    | ROWKEY  |    NAME     | AGE  |
    +---------+-------------+------+
    | 1       | HANGMEIMEI  | 18   |
    | 1       | LILEI       | 18   |
    +---------+-------------+------+
    2 rows selected (0.078 seconds)
    0: jdbc:phoenix:dn1> SELECT * FROM INDEX_LJKTEST_IMMU;
    +-------------+----------+--------+
    |   0:NAME    | :ROWKEY  | 0:AGE  |
    +-------------+----------+--------+
    | HANGMEIMEI  | 1        | 18     |
    | LILEI       | 1        | 18     |
    +-------------+----------+--------+
    2 rows selected (0.021 seconds)
    
    0: jdbc:phoenix:dn1> SELECT * FROM LJKTEST_IMMU WHERE ROWKEY='1';
    +---------+-------------+------+
    | ROWKEY  |    NAME     | AGE  |
    +---------+-------------+------+
    | 1       | HANGMEIMEI  | 18   |
    +---------+-------------+------+
    1 row selected (0.017 seconds)
    0: jdbc:phoenix:dn1> SELECT * FROM LJKTEST_IMMU WHERE NAME='LILEI';
    +---------+--------+------+
    | ROWKEY  |  NAME  | AGE  |
    +---------+--------+------+
    | 1       | LILEI  | 18   |
    +---------+--------+------+
    1 row selected (0.024 seconds)
    0: jdbc:phoenix:dn1> SELECT * FROM LJKTEST_IMMU WHERE AGE='18';
    +---------+-------------+------+
    | ROWKEY  |    NAME     | AGE  |
    +---------+-------------+------+
    | 1       | HANGMEIMEI  | 18   |
    | 1       | LILEI       | 18   |
    +---------+-------------+------+
    2 rows selected (0.027 seconds)

    hbaseテーブルでは、元のルールに従ってrowkeyが対応するフィールドを同じに置き換えます.
    hbase(main):002:0> scan 'LJKTEST_IMMU'
    ROW                               COLUMN+CELL                                                                                    
     1                                column=0:AGE, timestamp=1563241706845, value=18                                                
     1                                column=0:NAME, timestamp=1563241706845, value=HANGMEIMEI                                       
     1                                column=0:_0, timestamp=1563241706845, value=x                                                  
    1 row(s) in 0.0590 seconds

    索引チェックツール
    Phoenix 4.12を使用すると、MapReduceジョブを実行して、インデックス・テーブルがデータ・テーブルに対して有効であるかどうかを確認するツールがあります.いずれかのテーブルで孤立したローを検索する唯一の方法は、テーブル内のすべてのローをスキャンし、別のテーブルで対応するローを検索することです.したがって、このツールは、データまたはインデックス・テーブルをソース・テーブルとして実行し、ターゲット・テーブルとして実行できます.このツールは、検出されたすべての無効な行をファイルまたは出力テーブルPHOENIX_に書き込みます.INDEX_SCRUTINY.無効なローは、ターゲット・テーブルに対応するローがないか、ターゲット・テーブルに不正な値(上書きされたカラム値)があるソース・ローです.hbase org.apache.phoenix.mapreduce.index.IndexScrutinyTool -dt my_table -it my_index -o
    またはHADOOP_CLASSPATH=$(hbase mapredcp) hadoop jar phoenix--server.jar org.apache.phoenix.mapreduce.index.IndexScrutinyTool -dt my_table -it my_index -o
    インデックス最適化パラメータ
    開梱してすぐ使用し、インデックスが非常に速い.ただし、特定の環境とワークロードを最適化するには、いくつかのプロパティを調整します.
    属性名
    説明
    デフォルト
    index.builder.threads.max
    プライマリ・テーブルから構築インデックスの更新に使用されるスレッド数
    10
    index.builder.threads.keepalivetime
    コンストラクタスレッドプールのスレッドが期限切れになった後の時間量(秒単位)を指定します.
    60
    index.writer.threads.max
    ターゲットインデックステーブルを書き込むときに使用するスレッドの数.
    10
    index.writer.threads.keepalivetime
    ライタスレッドプールのスレッドが期限切れになった後の時間量(秒単位)を指定します.
    60
    hbase.htable.threads.max
    各インデックスHTableが書き込みに使用できるスレッドの数.
    2,147,483,647
    hbase.htable.threads.keepalivetime
    HTableのスレッドプールのスレッドが期限切れになった後の時間量(秒単位)
    60
    index.tablefactory.cache.size
    キャッシュに保持すべきインデックスHTableの数.
    10
    org.apache.phoenix.regionserver.index.priority.min
    インデックスの優先度が含まれる範囲の下部にある値を指定します.
    1000
    org.apache.phoenix.regionserver.index.priority.max
    インデックスの優先度が含まれない範囲の上部にある値を指定します.
    1050
    org.apache.phoenix.regionserver.index.handler.count
    グローバルインデックス・メンテナンスにインデックス書き込み要求を提供するときに使用するスレッドの数.
    30
    誤報整理
  • Unable find parent table
  • 19/05/14 11:23:40 WARN iterate.BaseResultIterators: Unable to find parent table "LJKTEST" of table "COVER_LJK_INDEX_COMPANY_ONLY" to determine USE_STATS_FOR_PARALLELIZATION
    org.apache.phoenix.schema.TableNotFoundException: ERROR 1012 (42M03): Table undefined. tableName=LJKTEST
  • インデックス作成失敗
  • ここでインデックステーブルを作成してエラーを報告し、エラー情報に基づいてhbase-siteを変更し、hbaseを再起動すればよい.
    Error: ERROR 1029 (42Y88): Mutable secondary indexes must have the hbase.regionserver.wal.codec property set to org.apache.hadoop.hbase.regionserver.wal.IndexedWALEditCodec in the hbase-sites.xml of every region server. tableName=COVER_LJK_INDEX (state=42Y88,code=1029)

    ふろく
  • Phoenixは入門からアリ雲に精通するまで
  • Phoenix公式サイト
  • Phoenixブログ紹介
  • アリ雲のアルバム
  • Phoenix ambari viewテーブル
  • Phoenixローカルインデックスとグローバルインデックスのテストと区別
  • Phoenix簡書学習ノート