このトピックでは、SelectDB と Elasticsearch データソースを統合して、Elasticsearch データソースに対してフェデレーテッド分析を実行する方法について説明します。
概要
ApsaraDB for SelectDB の Elasticsearch カタログは、Elasticsearch データソースからのメタデータの自動マッピングをサポートしています。 ApsaraDB for SelectDB の分散クエリ計画機能と Elasticsearch の全文検索機能に基づいて、Elasticsearch カタログを使用して、以下のクエリのための包括的なオンライン分析処理 (OLAP) ソリューションを提供できます。
Elasticsearch でのマルチインデックス分散結合クエリ
全文検索とフィルタリングのための ApsaraDB for SelectDB と Elasticsearch にまたがるマルチテーブル結合クエリ
ApsaraDB for SelectDB は、Elasticsearch 5.X 以降をサポートしています。
前提条件
Elasticsearch クラスタ内のすべてのノードが SelectDB インスタンスに接続されていること。
Elasticsearch クラスタ内のすべてのノードが、SelectDB インスタンスと同じ VPC 内にあること。 データソースクラスタ内のノードが異なる VPC に存在する場合は、ノードを SelectDB インスタンスに接続する必要があります。 詳細については、「ApsaraDB for SelectDB インスタンスとデータソース間の接続の確立に失敗した場合の対処方法」をご参照ください。
Elasticsearch クラスタ内のすべてのノードの IP アドレスが、SelectDB インスタンスの IP アドレスホワイトリストに追加されていること。 詳細については、「IP アドレスホワイトリストの構成」をご参照ください。
SelectDB インスタンスが存在する VPC 内の IP アドレスが、Elasticsearch クラスタの IP アドレスホワイトリストに追加されていること (ホワイトリストメカニズムが Elasticsearch クラスタでサポートされている場合)。
SelectDB インスタンスが属する VPC 内の SelectDB インスタンスの IP アドレスを取得するには、「ApsaraDB SelectDB インスタンスが属する VPC 内の IP アドレスを確認するにはどうすればよいですか。」で説明されている操作を実行できます。
SelectDB インスタンスのパブリック IP アドレスを取得するには、ping コマンドを実行して SelectDB インスタンスのパブリック IP アドレスに ping を実行できます。
カタログに関する基本的な知識があり、カタログで実行できる操作を理解していること。 詳細については、「データレイクハウス」をご参照ください。
Elasticsearch カタログの作成
CREATE CATALOG test_es PROPERTIES (
"type"="es",
"hosts"="http://127.0.0.1:9200",
"user"="test_user",
"password"="test_passwd",
"nodes_discovery"="false"
);Elasticsearch にはデータベースの概念がありません。 したがって、Elasticsearch データソースを ApsaraDB for SelectDB に接続すると、ApsaraDB for SelectDB は default_db という名前の固有のデータベースを自動的に作成します。 スイッチdefault_dbUSE default_db 文を実行して Elasticsearch カタログに切り替えると、ApsaraDB for SelectDB は 文を実行する必要なく、自動的に データベースに切り替えます。
次の表にパラメータを示します。
パラメータ | 必須 | デフォルト値 | 説明 |
hosts | はい | 該当なし | Elasticsearch データソースにアクセスするために使用される URL。 1 つ以上の URL を指定するか、このパラメータを Elasticsearch データソースの Server Load Balancer (SLB) インスタンスの URL に設定できます。 |
user | いいえ | 該当なし | Elasticsearch データソースにアクセスするために使用されるアカウント。 |
password | いいえ | 該当なし | Elasticsearch データソースにアクセスするために使用されるアカウントのパスワード。 |
doc_value_scan | いいえ | true | フィールド値をクエリするために Elasticsearch または Apache Lucene の列指向ストレージ機能を有効にするかどうかを指定します。 |
keyword_sniff | いいえ | true | Elasticsearch で TEXT タイプのフィールドを検出し、対応する KEYWORD フィールドを使用してクエリを実行するかどうかを指定します。 このパラメータを false に設定すると、システムは TEXT フィールドが term に分割された後にデータを照合します。 |
nodes_discovery | いいえ | true | Elasticsearch のノード検出機能を有効にするかどうかを指定します。 デフォルト値: true。 説明 Alibaba Cloud Elasticsearch は、受信リクエストを処理するためのエントリとして SLB インスタンスを使用します。 これにより、Elasticsearch クラスタのノードへの直接アクセスが防止されます。 したがって、このパラメータを false に設定する必要があります。 |
ssl | いいえ | false | Elasticsearch データソースへの HTTPS アクセスを有効にするかどうかを指定します。 ApsaraDB for SelectDB は、SSL 証明書の有効性に関係なく、フロントエンド (FE) およびバックエンド (BE) からのすべての HTTPS リクエストを信頼するように構成されています。 |
mapping_es_id | いいえ | false | Elasticsearch インデックスの |
like_push_down | いいえ | true | LIKE 条件をワイルドカードに変換し、LIKE 条件を Elasticsearch データソースにプッシュダウンするかどうかを指定します。 これにより、Elasticsearch データソースの CPU 消費量が増加します。 |
include_hidden_index | いいえ | false | 非表示のインデックスを含めるかどうかを指定します。 デフォルト値: false。 |
HTTP ベーシック認証のみがサポートされています。 Elasticsearch データソースにアクセスするために使用されるアカウントに、
/_cluster/state/や_nodes/httpなどのパスにアクセスし、インデックスを読み取る権限があることを確認してください。 Elasticsearch クラスタへの HTTPS アクセスを有効にしない場合は、アカウントまたはパスワードを指定する必要はありません。デフォルトでは、Elasticsearch 5.x または 6.x のインデックスに複数のタイプが含まれている場合、ApsaraDB for SelectDB は最初のタイプからデータを読み取ります。
Elasticsearch データソースからのデータのクエリ
ApsaraDB for SelectDB で Elasticsearch カタログを作成した後、ApsaraDB for SelectDB の内部テーブルをクエリするのと同じ方法で、ApsaraDB for SelectDB の外部 Elasticsearch テーブルをクエリできます。 ただし、ApsaraDB for SelectDB では、ロールアップ、事前集計、マテリアライズドビューなどのデータモデルを使用することはできません。
基本的なクエリ
SELECT * FROM es_table WHERE k1 > 1000 AND k3 ='term' OR k4 LIKE 'fu*z_';拡張 esquery
match_phrase や geoshape など、SQL で表現できないクエリをフィルタリングのために Elasticsearch にプッシュダウンするには、esquery(field, QueryDSL) 関数を使用できます。 esquery(field, QueryDSL) 関数では、field パラメータはインデックスの関連付けに使用され、QueryDSL パラメータは Elasticsearch の基本クエリドメイン固有言語 (DSL) の JSON 式を指定します。 QueryDSL パラメータは中かっこ ({}) で囲みます。 JSON 式には、match_phrase、geo_shape、bool など、ルートキーが 1 つだけ含まれている必要があります。 例:bool
match_phrase クエリ:
SELECT * FROM es_table WHERE esquery(k4, '{ "match_phrase": { "k4": "selectdb on es" } }');geo_shape クエリ:
SELECT * FROM es_table WHERE esquery(k4, '{ "geo_shape": { "location": { "shape": { "type": "envelope", "coordinates": [ [ 13, 53 ], [ 14, 52 ] ] }, "relation": "within" } } }');bool クエリ:
SELECT * FROM es_table WHERE esquery(k4, ' { "bool": { "must": [ { "terms": { "k1": [ 11, 12 ] } }, { "terms": { "k2": [ 100 ] } } ] } }');列タイプのマッピング
Elasticsearch のデータ型 | ApsaraDB for SelectDB のデータ型 | 備考 |
NULL | NULL | 該当なし |
BOOLEAN | BOOLEAN | 該当なし |
BYTE | TINYINT | 該当なし |
SHORT | SMALLINT | 該当なし |
INTEGER | INT | 該当なし |
LONG | BIGINT | 該当なし |
UNSIGNED_LONG | LARGEINT | 該当なし |
FLOAT | FLOAT | 該当なし |
HALF_FLOAT | FLOAT | 該当なし |
DOUBLE | DOUBLE | 該当なし |
SCALED_FLOAT | DOUBLE | 該当なし |
DATE | DATE | デフォルトの yyyy-MM-dd HH:mm:ss、yyyy-MM-dd、および epoch_millis 形式のみがサポートされています。 |
KEYWORD | STRING | 該当なし |
TEXT | STRING | 該当なし |
IP | STRING | 該当なし |
NESTED | STRING | 該当なし |
OBJECT | STRING | 該当なし |
OTHER | UNSUPPORTED | 該当なし |
ARRAY タイプ
Elasticsearch は明示的な ARRAY タイプをサポートしていませんが、Elasticsearch のフィールドには ゼロ個以上の値を含めることができます。 フィールドを ARRAY タイプとして示すには、ApsaraDB for SelectDB のインデックスマッピングの _meta フィールドに特定の構造アノテーションを追加します。 Elasticsearch 6.x 以前の _meta フィールドの詳細については、「_meta field」をご参照ください。
たとえば、doc インデックスは次のデータ構造を使用します。
{
"array_int_field": [1, 2, 3, 4],
"array_string_field": ["selectdb", "is", "the", "best"],
"id_field": "id-xxx-xxx",
"timestamp_field": "2022-11-12T12:08:56Z",
"array_object_field": [
{
"name": "xxx",
"age": 18
}
]
}上記のデータ構造で ARRAY フィールドを定義するには、次のコマンドを実行して、インデックスマッピングの _meta.selectdb プロパティの下にプロパティ構成を追加します。
# ES 7.x 以降
curl -X PUT "localhost:9200/doc/_mapping?pretty" -H 'Content-Type:application/json' -d '
{
"_meta": {
"selectdb":{
"array_fields":[
"array_int_field",
"array_string_field",
"array_object_field"
]
}
}
}'
# ES 6.x 以前
curl -X PUT "localhost:9200/doc/_mapping?pretty" -H 'Content-Type: application/json' -d '
{
"_doc": {
"_meta": {
"selectdb":{
"array_fields":[
"array_int_field",
"array_string_field",
"array_object_field"
]
}
}
}
}array_fields パラメータは、ARRAY タイプのフィールドを指定します。
ベストプラクティス
フィルタ条件のプッシュダウン
Elasticsearch カタログは、Elasticsearch へのフィルタ条件のプッシュダウンをサポートしています。 フィルタ条件を満たすデータのみが返されます。 これにより、クエリのパフォーマンスが向上し、ApsaraDB for SelectDB と Elasticsearch の両方で CPU、メモリ、および I/O リソースの使用量が削減されます。
演算子は次の Elasticsearch クエリに変換されます。
SQL 構文 | Elasticsearch 5.x 以降の構文 |
= | 複数値完全一致検索 |
in | 複数値完全一致検索 |
>、<、>=、および <= | 範囲クエリ |
and | bool.filter |
or | bool.should |
not | bool.must_not |
not in | bool.must_not + 複数値完全一致検索 |
is_not_null | exists クエリ |
is_null | bool.must_not + exists クエリ |
esquery | Elasticsearch のネイティブ JSON 形式のクエリ DSL |
列スキャン機能を有効にしてクエリを高速化する
クエリを高速化するには、enable_docvalue_scan パラメータを true に設定して、列スキャン機能を有効にします。
この機能を有効にすると、ApsaraDB for SelectDB は Elasticsearch からデータをクエリするときに次の 2 つの原則を適用します。
ベストエフォート: ApsaraDB for SelectDB は、クエリ対象のフィールドに対して列指向ストレージが有効になっているかどうかを自動的にチェックします。
doc_valueパラメータが true に設定されている場合、すべてのフィールドに対して列指向ストレージが有効になります。 この場合、ApsaraDB for SelectDB は列指向ストレージからすべてのフィールド値をクエリします。自動スペックダウン: クエリ対象のフィールドのいずれかで列指向ストレージが無効になっている場合、ApsaraDB for SelectDB は、行指向ストレージが有効になっている
_sourceフィールドからすべてのフィールド値を解析してクエリします。
デフォルトでは、ApsaraDB on Elasticsearch は、行指向ストレージを使用し、データを JSON 形式で格納する _source フィールドからすべての列をクエリします。 列指向ストレージと比較して、行指向アプローチは、一度に複数のデータレコードを読み取る効率が低くなります。特に、少数の列のみをクエリする必要がある場合に顕著です。 少数の列のみがクエリされる場合、列指向ストレージが有効になっているフィールドからデータをクエリするパフォーマンスは、_source フィールドからクエリするよりも 10 倍以上高速になります。
Elasticsearch の
TEXTフィールドに対しては、列指向ストレージを有効にすることはできません。 したがって、TEXTフィールドがクエリの一部である場合、ApsaraDB for SelectDB は_sourceフィールドからのデータのクエリに戻ります。クエリ対象のフィールド数が 25 以上の場合、列指向ストレージが有効になっているフィールドからデータをクエリするパフォーマンスは、基本的に
_sourceフィールドからクエリするパフォーマンスと同等です。
KEYWORD フィールドの検出
enable_keyword_sniff パラメータを true に設定することにより、KEYWORD タイプのフィールドの検出を有効にできます。
Elasticsearch では、インデックスを作成せずにデータを直接インポートできます。 データがインポートされると、Elasticsearch は自動的にインデックスを作成します。 STRING フィールドの場合、Elasticsearch はマルチフィールド機能を使用して、TEXT フィールドと KEYWORD フィールドの両方を作成します。
次のサンプルコードは、フィールドを TEXT タイプと KEYWORD タイプの両方にマッピングする方法の例を示しています。
"k4": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
}たとえば、k4 フィールドで = 演算子によって指定されたフィルタ条件を含むクエリを実行する場合、ApsaraDB on Elasticsearch はクエリを Elasticsearch の複数値完全一致検索に変換します。 SQL フィルタ条件:
k4 = "SelectDB On ES"Elasticsearch で変換されたクエリ DSL:
"term" : { "k4": "SelectDB On ES"}k4 フィールドの最初のタイプは TEXT であるため、k4 フィールドの値は、k4 フィールドに指定されたトークナイザに基づいて、SelectDB、On、および ES という term にトークン化されます。 フィールドにトークナイザを指定しない場合は、標準のトークナイザが使用されます。 次の API リクエストを送信して、K4 フィールドの値をトークン化します。
POST /_analyze{ "analyzer": "standard", "text": "SelectDB On ES"}次の結果が返されます。
{
"tokens": [
{
"token": "selectdb",
"start_offset": 0,
"end_offset": 8,
"type": "<ALPHANUM>",
"position": 0
},
{
"token": "on",
"start_offset": 9,
"end_offset": 11,
"type": "<ALPHANUM>",
"position": 1
},
{
"token": "es",
"start_offset": 12,
"end_offset": 15,
"type": "<ALPHANUM>",
"position": 2
}
]
}次の複数値完全一致検索を実行します。
"term" : { "k4": "SelectDB On ES"}辞書の term は SelectDB On ES term と一致しません。 したがって、結果は返されません。 ただし、enable_keyword_sniff パラメータを true に設定すると、システムは SQL セマンティクスと一致するように k4 = "SelectDB On ES" を k4.keyword = "SelectDB On ES" に自動的に変換します。 Elasticsearch で変換されたクエリ DSL:
"term" : { "k4.keyword": "SelectDB On ES"}k4.keyword フィールドは KEYWORD タイプであり、Elasticsearch に書き込まれたデータは完全な term です。 したがって、SelectDB On ES term を照合できます。
自動ノード検出機能を有効にする
nodes_discovery パラメータを true に設定することにより、自動ノード検出機能を有効にできます。
この機能を有効にすると、ApsaraDB for SelectDB は、Elasticsearch でシャードが割り当てられているすべての使用可能なデータノードを検出します。 ApsaraDB for SelectDB の BE が Elasticsearch のデータノードの URL にアクセスできない場合は、nodes_discovery パラメータを false に設定します。
Alibaba Cloud Elasticsearch は、受信リクエストを処理するためのエントリとして SLB インスタンスを使用します。 これにより、Elasticsearch クラスタのノードへの直接アクセスが防止されます。 したがって、nodes_discovery パラメータを false に設定する必要があります。
Elasticsearch クラスタへの HTTPS アクセスを有効にする
ssl パラメータを true に設定することにより、Elasticsearch クラスタへの HTTPS アクセスを有効にできます。
ApsaraDB for SelectDB は、SSL 証明書の有効性に関係なく、FE および BE からのすべての HTTPS リクエストを信頼するように構成されています。
時間フィールドに関する推奨事項
これらの推奨事項は、外部 Elasticsearch テーブルにのみ適用されます。 時間フィールドは、Elasticsearch カタログの DATE または DATETIME タイプに自動的にマッピングされます。
Elasticsearch では、時間フィールドは柔軟です。 ただし、外部 Elasticsearch テーブルで時間フィールドのタイプが正しく指定されていない場合、フィルタ条件をプッシュダウンできません。
インデックスを作成するときは、最大限の互換性を確保するために、幅広い形式に対応するように日付フィールドを構成します。
"dt": {
"type": "date",
"format": "yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis"
}ApsaraDB for SelectDB でフィールドを作成するときは、type パラメータを date または datetime に設定することをお勧めします。 type パラメータを varchar に設定することもできます。 次の SQL 文を実行して、フィルタ条件を Elasticsearch にプッシュダウンできます。
SELECT * FROM doe WHERE k2 > '2020-06-21';
SELECT * FROM doe WHERE k2 < '2020-06-21 12:00:00';
SELECT * FROM doe WHERE k2 < 1593497011;
SELECT * FROM doe WHERE k2 < now();
SELECT * FROM doe WHERE k2 < date_format(now(), '%Y-%m-%d');Elasticsearch では、時間フィールドに
formatパラメータを設定しない場合、時間フィールドのデフォルト形式はstrict_date_optional_time||epoch_millisです。Elasticsearch にインポートされる DATE フィールドの値がタイムスタンプである場合、タイムスタンプを
ミリ秒に変換する必要があります。 Elasticsearch では、内部処理のためにタイムスタンプがミリ秒単位である必要があります。 そうしないと、外部 Elasticsearch テーブルを含む操作でエラーが発生する可能性があります。
_idElasticsearch で
_id フィールドを指定せずに Elasticsearch にドキュメントをインポートする場合、Elasticsearch は各ドキュメントにグローバルに一意な _id フィールドを自動的に割り当てます。このフィールドはプライマリキーとして機能します。ドキュメントのインポート時に、ドキュメントの特定のビジネス上の意味を示す _id フィールドを指定することもできます。外部 Elasticsearch テーブルから _id フィールドの値をクエリするには、テーブルの作成時に VARCHAR 型の _id フィールドを追加できます。
CREATE EXTERNAL TABLE `doe` (
`_id` varchar COMMENT "",
`city` varchar COMMENT ""
) ENGINE=ELASTICSEARCH
PROPERTIES (
"hosts" = "http://127.0.0.1:8200",
"user" = "root",
"password" = "root",
"index" = "doe"
}Elasticsearch カタログから _id フィールドの値をクエリするには、mapping_es_id パラメータを true に設定します。
_idフィールドの値は、=またはIN演算子を使用してのみフィルタリングできます。_idフィールドは、VARCHAR型である必要があります。
付録
次の図は、ApsaraDB for SelectDB が Elasticsearch からデータをクエリする際の原則を示しています。
+----------------------------------------------+
| |
| SelectDB +------------------+ |
| | FE +--------------+-------+
| | | リクエストシャードの場所
| +--+-------------+-+ | |
| ^ ^ | |
| | | | |
| +-------------------+ +------------------+ | |
| | | | | | | | |
| | +----------+----+ | | +--+-----------+ | | |
| | | BE | | | | BE | | | |
| | +---------------+ | | +--------------+ | | |
+----------------------------------------------+ |
| | | | | | |
| | | | | | |
| HTTP スクロール | | HTTP スクロール | |
+-----------+---------------------+------------+ |
| | v | | v | | |
| | +------+--------+ | | +------+-------+ | | |
| | | | | | | | | | |
| | | データノード | | | | データノード +<-----------+
| | | | | | | | | | |
| | | +<--------------------------------+
| | +---------------+ | | |--------------| | | |
| +-------------------+ +------------------+ | |
| 同じ物理ノード | |
| | |
| +-----------------------+ | |
| | | | |
| | マスターノード +<-----------------+
| ES | | |
| +-----------------------+ |
+----------------------------------------------+FE は、テーブルの作成時に指定されたホストにリクエストを送信し、すべてのノードの HTTP ポートとインデックスのシャード分散に関する情報を取得します。 リクエストが失敗した場合、FE は成功または完全な失敗までホストリストを順番に走査します。
クエリが開始されると、FE は取得したノードとインデックスのメタデータに関する情報に基づいてクエリ実行計画を生成し、実行計画を対応する BE に送信します。
BE は、
HTTP スクロールメソッドを使用して、_sourceフィールドのデータ、または列指向ストレージが有効になっているフィールドのデータを、各 Elasticsearch インデックスシャードからストリーミングモードで同時に取得します。ApsaraDB for SelectDB は、結果を計算した後、結果を返します。