フェニックスの二次インデックスの調査



Phoenix Secondary Index Exploration



バージョン情報:

  • HDP-> 3.0.0
  • Hadoop-> 3.0.1
  • HBase-> 2.0.0
  • フェニックス-> 5.0.0

HBASE Google-Bigtableのオープンソース実装です。これは、HDFS上に構築された分散型の列指向ストレージシステムです。 HBaseは非リレーショナルデータベースであり、SQLをサポートしていないため、 フェニックス 。 PhoenixはHBa​​se上に構築されたSQLレイヤーであり、HBaseクライアントAPIの代わりに標準のJDBC APIを使用して、テーブルの作成、データの挿入、HBaseデータのクエリを行うことができます。 -行キークエリ。



二次インデックス

フェニックスは行キーを並べ替えるので、行キーに基づいてクエリを実行すると、速度が非常に速くなります。行キーを設計する場合、ハッシュと一意性を保証するという原則の下で、一般的に使用されるクエリ条件は通常行キーに設計されますが、行キーには一定の長さ制限があり、すべてのクエリ条件を行キーに入れることは不可能です。したがって、セカンダリインデックスを使用できます。ビジネステーブルのインデックスが作成された後、インデックスフィールドはHBaseの行キーの場所に冗長的に格納されるため、スコープをインデックスでスキャンして、テーブル全体のスキャンを回避できます。これにより、クエリ速度が大幅に向上します。ビジネステーブルは、デフォルトで最大10個のインデックスを作成できます。フェニックスの10個のインデックステーブルにマップされます。 10を超えるインデックスがある場合、作成すると例外がスローされます。java.sql.SQLException: ERROR 1047 (43A04): Too many indexes have already been created on the physical table. tableName=DMP.DMP_INDEX_TEST 。実行プランは、クエリの実行時に使用するすべてのインデックスから最適なインデックスを選択します。つまり、クエリごとに1つのインデックスのみが使用されます。インデックスはmutableに分けることができますimmutableで、デフォルトはmutableですビジネステーブルを作成することで宣言できますIMMUTABLE_ROWS=true不変のテーブルを作成するために、この不変のテーブルによって作成されたインデックスも不変であり、ターゲットになりますonly written once and never updatedシーン、会社の現在のシーンは関係していません、もはや詳細に議論されていません、以下はmutableのためですお問い合わせをするため。可変インデックスは、カバレッジインデックス、ローカルインデックス、グローバルインデックスなどに分割できます。可変インデックスをサポートするには、次のことを行う必要がありますhbase-site.xml構成を増やします。

構成hbase-site.xmlサポートするにはmutableインデックス

<property> <name>hbase.regionserver.wal.codecname> <value>org.apache.hadoop.hbase.regionserver.wal.IndexedWALEditCodecvalue> property>

ローカルインデックス

ローカルインデックスターゲットは、スペースに制約のある重いユースケースを記述します。グローバルインデックスの場合と同様に、Phoenixはクエリ時にローカルインデックスを使用するかどうかを自動的に選択します。ローカルインデックスを使用すると、インデックスデータとテーブルデータが同じサーバー上に共存し、書き込み中のネットワークオーバーヘッドを防ぎます。ローカルインデックスは、クエリが完全にカバーされていない場合でも使用できます(つまり、Phoenixは、データテーブルに対するポイント取得を通じてインデックスにない列を自動的に取得します)。グローバルインデックスとは異なり、テーブルのすべてのローカルインデックスは、4.8.0バージョンより前の単一の個別の共有テーブルに格納されます。 4.8.0以降、すべてのローカルインデックスデータを同じデータテーブルの個別のシャドウ列ファミリに格納しています。ローカルインデックスを使用する読み取り時に、インデックスデータの正確な領域の場所を事前に決定できないため、すべての領域でデータを調べる必要があります。したがって、読み取り時にいくらかのオーバーヘッドが発生します。



ローカルインデックスは、書き込みが頻繁でストレージスペースが限られているシナリオに適しています。グローバルインデックスと同様に、Phoenixはクエリ時にローカルインデックスを使用するかどうかを自動的に選択します。ローカルインデックスを使用して、インデックスデータとテーブルデータが同じに書き込まれますRegion Serversこれにより、書き込み中のネットワークオーバーヘッドを回避できます。ローカルインデックスがビジネステーブルのすべてのフィールドを完全にカバーしていなくても、クエリ時にインデックスが使用されます(Phoenixはインデックス外のフィールドを自動的に取得し、ビジネステーブルをクエリしてデータを取得します)。グローバルインデックスとは異なり、バージョン4.8.0より前では、ビジネステーブルのすべてのローカルインデックスは個別の共有テーブルに格納されていました。バージョン4.8.0以降、すべてのローカルインデックスデータは、同じビジネステーブルの個別の列ファミリに格納されます。ローカルインデックスを使用してデータを読み取る場合、インデックスデータの正確な領域位置を事前に決定することはできません。これは、読み取り速度に一定の影響を及ぼします。

ローカルにインデックス付けされたデータストア

作成dmp.dmp_index_testビジネステーブル

テーブルdmp.dmp_index_testを作成します(id varchar not nullプライマリキー、name varchar、age varchar、sex varchar、addr varchar)



データを挿入

dmp.dmp_index_test値にアップサートします(「id01」、「name01」、「age01」、「sex01」、「addr01」)

ローカルインデックスを作成する

dmp.dmp_index_test(name)にローカルインデックスindex_local_test_nameを作成します

HBaseでデータを表示する

4.8以降、ローカルインデックスのデータは、同じビジネステーブルの特定の列ファミリに格納されます。デフォルトはL#0です。 。場合によっては、Phoenixコマンドを使用してローカルインデックスを削除するとタイムアウトになることがあります。hbase shellを選択できます。実行alter 'DMP.DMP_INDEX_TEST', {NAME => 'L#0', METHOD => 'delete'}インデックスを強制的に削除するコマンド。このプロセスは、最初にビジネステーブルで実行する必要があります。disable操作、操作が完了してから実行されますenableオペレーティング。

ローカルインデックスがヒットするかどうか

インデックスがヒットするかどうかを確認します。使用できますexplain実行プランを確認するために、実行プランの説明を次に示します。

  • CLIENT —操作がクライアント側で実行されるかサーバー側で実行されるかを示します。クライアントはより少ないデータを返そうとします。 If SERVERサーバー側での実行を示します。

  • FILTER BY式—フィルター基準に一致する結果を返します。

  • FULL SCAN OVERtableName-フルテーブルがビジネステーブルをスキャンすることを示します。

  • RANGE SCAN OVER tableName [...]-代表的な範囲が、行キーの開始と終了を表す括弧付きのテーブルをスキャンすることを示します。

  • ROUND ROBIN — ORDER BY操作がない場合、ROUNDROBINは最大化されたクライアントの並列化を表します。

  • x-CHUNK —これを行うスレッドの数。

  • PARALLEL x-WAY —マージされる並列スキャンの数を示します。

  • EST_BYTES_READ-クエリの実行時にスキャンされると予想される合計バイト数。

  • EST_ROWS_READ-クエリの実行時にスキャンされると予想される行数。

  • EST_INFO_TS-クエリ情報を収集するepoch time

ローカルインデックスクエリフィールドはインデックス列になく、インデックスも使用します

カバレッジインデックスを作成する

dmp.dmp_index_testにローカルインデックスindex_local_include_test_oneを作成します(年齢)include(性別)

この時点でHBaseを表示します。インデックス列ファミリーを確認できます。L#0冗長ストレージincludeフィールド

インデックスをオーバーライドすると、インデックスを使用せずにクエリ条件が列にインデックス付けされるのを防ぐことができます。クエリ条件がインデックス列またはオーバーレイ列にない場合にのみ、全表スキャンが実行されます。

複合インデックスを作成して、複数の条件付きクエリインデックスヒットを解決できます。複合インデックスの最初のフィールドは、クエリ条件に含まれている必要があります。

概要

ローカルインデックスはバケットテーブルをサポートしていません。 HBaseには個別のテーブルメンテナンスはありません。フェニックスでは、インデックステーブルのマッピングがあります。書き込み操作が実行されると、データはローカルに保存され、読み取り操作が実行されるときに追加のネットワークIOは実行されず、インデックスはインデックス条件範囲に従ってスキャンされ、スペースが許せば高速クエリが実装されます。インデックスは、インデックス条件が変更されないように作成できます。逃した。該当するシナリオは頻繁な書き込みです。

グローバルインデックス

グローバルインデックスターゲットは、重いユースケースを読み取ります。グローバルインデックスでは、インデックスのすべてのパフォーマンスペナルティは書き込み時に発生します。書き込み時にデータテーブルの更新をインターセプトし(DELETE、UPSERT VALUES、UPSERT SELECT)、インデックスの更新を作成してから、必要な更新をすべての関心のあるインデックステーブルに送信します。読み取り時に、Phoenixは使用するインデックステーブルを選択します。これにより、クエリ時間が最速になり、他のHBaseテーブルと同じように直接スキャンされます。デフォルトでは、ヒントがない限り、インデックスは、インデックスの一部ではない列を参照するクエリには使用されません。

グローバルインデックスは、頻繁に読み取られるシーンに適しています。グローバルインデックスの場合、書き込み時にすべてのパフォーマンス消費が発生し、ビジネステーブルに対するすべての更新操作(DELETE、UPSERT VALUES、およびUPSERT SELECT)によってインデックスが更新され、インデックスが異なるノード、クロスノードに分散されます。データ送信パフォーマンスが大幅に消費されます。データを読み取るとき、Phoenixは最速のインデックスを選択し、ビジネステーブルをスキャンする代わりに、通常のHBaseテーブルとしてスキャンします。デフォルトでは、必須のインデックスは指定されていません。クエリのフィールドがインデックス付きの列にない場合、この場合、インデックスは使用されません。

グローバルインデックス付きデータストレージ

作成dmp.dmp_index_testビジネステーブル

テーブルdmp.dmp_index_testを作成します(id varchar not nullプライマリキー、name varchar、age varchar、sex varchar、addr varchar)

データを挿入

dmp.dmp_index_test値にアップサートします(「id01」、「name01」、「age01」、「sex01」、「addr01」)

グローバルインデックスを作成する

  • dmp.dmp_index_test(name)にインデックスindex_global_test_nameを作成します

  • dmp.dmp_index_testにインデックスindex_global_test_include_nameを作成します(name)include(age)

HBaseでデータを表示する

グローバルインデックスの場合、インデックスを維持するためにHBaseに別のテーブルがあることがわかります。したがって、クエリがインデックスにヒットすると、範囲はクエリ条件に従ってインデックステーブルをスキャンし、サービスデータテーブルはスキャンしません。 。

グローバルインデックスがヒットするかどうか

グローバルインデックスクエリフィールドはインデックスを作成しませんでしたが、使用されましたincludeキーワードはこのフィールドの値を格納し、インデックスがヒットする可能性があります。

グローバルインデックスクエリフィールドはインデックスを作成せず、使用されませんでしたincludeキーワードはこのフィールドをカバーし、合格できます/* + INDEX(TableName MyIndexName)*/このコマンドはインデックスの使用を強制しますが、フィルター条件がフィルター処理された後、結果セットが大きくないことは明らかです。そうでない場合、全表スキャンが発生します。

複数条件クエリを使用すると、複合インデックスを作成できます。結合インデックスの最初のフィールドはクエリ条件である必要があります。そうしないと、全表スキャンが発生する可能性があります。

dmp.dmp_index_test(name、age、sex)にインデックスindex_global_test_mutilを作成しますinclude(addr)

概要

グローバルインデックスはバケットテーブルをサポートします。デフォルトでは、ビジネステーブルと同じバケットルールが使用されます。 HBaseには、個別の一意のインデックステーブルメンテナンスがあります。したがって、書き込み操作中に、各リージョンサーバー間にネットワークIOが存在する可能性があります。より消費しやすいので、複数の読み取りと書き込みがあるシナリオに適しています。グローバルインデックスがクエリに含まれている場合、実際にはインデックステーブルを直接チェックします。クエリフィールドがインデックスを作成せず、インデックスを使用する場合は、includeを使用できます。キーワードはこのフィールドをオーバーライドし、このフィールドの値は冗長に格納されるため、余分なスペースが必要になりますが、ヒットインデックスを保証するか、/* + INDEX(TableName MyIndexName)*/を使用できます。このコマンドは、インデックスの使用を強制します。これは、結果セットが返されることが少なく、全表スキャンを回避する状況に適しています。

非同期インデックス

デフォルトでは、インデックスが作成されると、CREATEINDEX呼び出し中に同期的に入力されます。データテーブルの現在のサイズによっては、これが実行できない場合があります。 4.5以降、インデックスの作成DDLステートメントにASYNCキーワードを含めることで、最初にインデックスの作成を非同期で行うことができます。インデックステーブルに作成するmap reduceジョブは、HBaseコマンドラインから個別に開始する必要があります。

デフォルトでは、インデックスが作成されると、CREATEINDEXの実行中にインデックスデータが同期的に入力されます。小さなテーブルの場合、これを行うことができます。テーブルが大きい場合、インデックスはタイムアウトになります。 4.5以降、インデックスを作成するときに使用できますASYNCキーワードは、インデックスデータの入力を非同期的に完了します。作成完了後のインデックスのステータスはBUILDINGです。 HBaseコマンドラインから個別に起動する必要がありますmap reduceタスクは、インデックスデータの入力作業を完了することです。 MRタスクが正常に実行されると、ビューインデックスのステータスがACTIVEに変わり、インデックスを正常に使用できるようになります。

非同期インデックスを作成する

実際のビジネスシナリオでは、多くの場合、インデックスは要件に応じてビジネステーブル用にカスタマイズされます。現時点では、ビジネステーブルのデータ量が非常に多いため、同期インデックスの作成は確実にタイムアウトになります。このとき、非同期インデックスを作成できます。この問題を解決します。

dmp.dmp_index_test(name)include(age)ASYNCにインデックスindex_global_test_asyncを作成します

MRタスクを開始し、データ入力とインデックスのアクティブ化を完了します

HBaseコマンドを実行する前に、現在のユーザーがHBaseと操作中のテーブルに対する権限を持っていることを確認してください。su - hbaseに切り替えhbaseユーザーは、対応するコマンドを実行します。私たちの環境では、それが有効になっているため Kerberos したがって、コマンドを実行する前に、まずkinitを実行する必要があります。このコマンドはユーザーの認証を完了し、HBaseコマンドを実行してMRタスクを送信します。環境がYARNの権限も管理している場合は、MRタスクを送信する権限を付与するために承認ツールが必要です。hbaseユーザー。

Kerberosユーザー認証

kinit -kt /path/hbase.headless.keytab [メール保護]

HBaseコマンドでMRタスクを開始します

HADOOP_CLASSPATH = '/ etc / hbase / conf' hadoop jar /path/phoenix/phoenix-client.jar org.apache.phoenix.mapreduce.index.IndexTool --schema DMP --data-table DMP_INDEX_TEST --index-tableINDEX_GLOBAL_TEST_ASYNC- -出力パス/ hbase-backup2

MRタスクが完了すると、ビューインデックステーブルのステータスがACTIVEに変更されます。この時点で、インデックステーブルが有効になります。

MRタスクを実行せずに非同期インデックスを作成する

MRタスクは正常に実行され、インデックスステータスはACTIVEです。

フェニックスインデックスツールのピット

フェニックスのWebサイトでは、MRタスクを開始するコマンドは次のとおりです。

$ {HBASE_HOME} / bin / hbase org.apache.phoenix.mapreduce.index.IndexTool --schema MY_SCHEMA --data-table MY_TABLE --index-table ASYNC_IDX --output-path ASYNC_IDX_HFILES

このコマンドが使用されますphoenix-server.jar 、このパッケージに存在しますcommons-cli依存関係が競合するため、このコマンドを使用してMRタスクを開始すると、エラーが発生します:Exception in thread 'main' java.lang.NoClassDefFoundError: org/apache/commons/cli/DefaultParser 、したがって、MRタスクを開始するときに使用する必要があります。$ hadoop jar $PHOENIX_HOME/phoenix-*client.jar org.apache.phoenix.mapreduce.index.IndexToolコマンド、use phoenix-client.jarを指定しますタスクは正常に送信され、実行されました。この問題は フェニックス-4880HBASE-20201 課題追跡の説明を参照することで解決できる、より詳細な手順もあります。

総括する

フェニックスはさまざまなインデックス技術を提供しています。Covered Indexes値の値の冗長ストレージ。スペースを使用して速度を変更し、クエリが結果を返す時間を節約します。Local Indexes書き込みが頻繁なシーンでの書き込みパフォーマンスの低下が少ないGlobal Indexesインデックステーブルを個別に更新し、インデックステーブルをスキャンして結果セットを直接返します。よく使うシーンに最適です。この記事では、一般的に使用されるいくつかのインデックスと、それらがインデックスにヒットするかどうかを確認する方法について説明します。もちろん、Phoenixにはより複雑な結合があり、単一テーブルのインデックス作成の基本的なルールに従います。フェニックスの柔軟なクエリモードは、インデックスの数の制限であろうと、インデックスメカニズムの影響であろうと、わずかに不十分であり、多数のスキャンタイプのOLAPクエリには適していません。フェニックスのインデックスには、独自の適切なシナリオと長所と短所もあります。実際のビジネスシナリオとクエリ要件、合理的な選択と設計インデックスによれば、Phoenixは十分に満足できます。

Q&A

  • ローカルインデックスを非同期で作成し、カスタムインデックスを使用しますschema 、IndexToolを使用してエラーを報告するError: java.lang.RuntimeException: org.apache.phoenix.schema.TableNotFoundException: ERROR 1012 (42M03)

    カスタムを使用schema非同期インデックスを作成します。現在、グローバルインデックスのみを作成します。デフォルトを使用schemaローカルインデックスとグローバルインデックスをサポートできます。具体的な解決策、コミュニティはまだ答えていません。

  • 実行プランのインデックスヒットを確認します。実行時間が非常に長いのはなぜですか。

    インデックスヒットと実行時間の間に絶対的な比例関係はありません。実際のクエリ条件によって決まります。インデックスがヒットすることもありますが、クエリ条件はほとんどのデータをフィルタリングしません。この時点で範囲スキャンビジネステーブルに移動すると、時間がかかり、全表スキャンよりも遅くなるため、インデックスを設計するときは、インデックスを使用してほとんどのデータを除外するようにしてください。

  • なぜバケットテーブルを使用するのですか?

    HBaseホットスポットの書き込みを回避するために、Phoenixはサーバーの負荷を不均衡にし、バケットをカスタマイズする方法を提供します。salt row keys with a prefix行キーでソルティングキーのプレフィックスを使用して、行キーがハッシュされないようにします。これにより、ビジネステーブルの作成時に宣言できるホットな問題が発生します。SALT_BUCKETS=xテーブルをバケット化する属性。テーブルが作成された後、さまざまなリージョンサーバーでハッシュされたx個のテーブルリージョンがあり、xの値は通常1〜256です。

参照

https://mp.weixin.qq.com/s/7bg1hu7LI9m7KbXAt-SN2Q

https://blog.csdn.net/gaoshui87/article/details/52381927

https://blog.csdn.net/maomaosi2009/article/details/45619679

https://phoenix.apache.org/index.html

https://sematext.com/blog/hbasewd-avoid-regionserver-hotspotting-despite-writing-records-with-sequential-keys/