すべてのプロダクト
Search
ドキュメントセンター

Lindorm:予期しないクエリ結果の一般的な原因

最終更新日:Jan 14, 2025

LindormTable を不適切な方法で使用すると、期待に沿わないクエリ結果が返される可能性があります。このトピックでは、予期しないクエリ結果の一般的な原因について説明し、クエリの問題のトラブルシューティングとクエリ条件の最適化に役立てます。

問題

LindormTable は、Apache HBase と互換性のある NoSQL データエンジンです。 LindormTable のストレージモデルは、Log-Structured Merge Tree(LSM-Tree)に基づいて実装されています。 LindormTable に対して書き込み操作を実行すると、データはデータベースにコミットされる前に、まず Write-Ahead Log(WAL)ログに書き込まれます。書き込み操作中にエラーが報告されない場合、データは正常に書き込まれます。この場合、サーバー障害などのシナリオでは、WAL ログに基づいてデータを復元できます。これにより、データの耐久性が確保され、書き込まれたデータが予期せず不可視になるのを防ぎます。ただし、LindormTable は、データのバージョン、タイムスタンプ、TTL など、さまざまな複雑な機能を提供します。これらの機能が適切に構成されていない場合、予期される問題が発生する可能性があります。たとえば、書き込まれたデータが期待どおりに上書きされない、有効期限が切れてデータが削除される、書き込まれたデータがクエリできない、返されたクエリ結果が期待に沿わないなどです。これらの問題は、次の一般的な原因によって発生します。

一般的な原因

データが正常に書き込まれていないか、データが書き込まれる前にクエリが実行されています

LindormTable では、データは書き込み直後は不可視です。

Lindorm ワイドテーブルは、ビッグデータシナリオに関連するデータリンクでよく使用されます。データ書き込みリンクに障害が発生した場合、ワイドテーブルへのデータの書き込みに失敗するか、書き込み操作が遅延する可能性があります。この場合、クエリするデータがテーブルに書き込まれていないため、見つからない可能性があります。

データがテーブルに書き込まれてから一定期間が経過するまでクエリできない場合は、クエリ条件にヒントを追加して、結果にクエリ対象データのタイムスタンプを取得することをお勧めします。次に、タイムスタンプに基づいて、データが書き込まれる前にクエリが実行されているかどうかを確認できます。クエリ結果でタイムスタンプを取得する方法の詳細については、「ヒントを使用してデータバージョニングを実装する」をご参照ください。

説明

テーブルにデータが書き込まれるときにデータ行にタイムスタンプが指定されていない場合、返されるタイムスタンプは、データ行がテーブルに書き込まれた時刻を示します。

STRING フィールドにストップ文字または不可視文字が含まれています

STRING データ型のフィールドをクエリするときに、フィールドに不可視文字が含まれていると、予期しないクエリ結果が返される可能性があります。たとえば、テーブルの orderID 列に STRING 型のデータが含まれており、プログラムのバグにより、列のフィールドの値 1000 に不可視文字が誤って追加されたとします。フィールドの実際の値は 1000(不可視文字) になります。

この場合、クエリで where oderID="1000" 条件を指定すると、値が条件と一致しないため、フィールドをクエリできません。クエリで where orderID > "1000" limit 1 条件を指定して、この種の問題が発生しているかどうかを確認できます。

さらに、Lindorm は STRING 値の途中のストップ文字をサポートしていません。文字列「1000\stop character\1000」をテーブルに書き込むと、エンコード例外が発生し、文字列をクエリできない可能性があります。

クエリ条件に正しくない列名が指定されています

列名の大文字と小文字が間違っている場合、またはクエリ条件で列ファミリが指定されていない場合、予期しないクエリ結果が返される可能性があります。

  • 指定された列名の大文字と小文字が正しくありません: Lindorm の列名は大文字と小文字が区別されます。したがって、クエリ条件で指定された列が実際の列名と一致していることを確認してください。

  • 列ファミリが指定されていません: Lindorm ワイドテーブルは複数の列ファミリをサポートしています。テーブルを作成するときに列ファミリを指定しないと、テーブルの列はデフォルトで f という名前の列ファミリに自動的に追加されます。この場合、クエリ条件で列ファミリを指定する必要はありません。ただし、テーブルに複数の列ファミリを構成する場合は、テーブル内のデータをクエリするときに、クエリ条件で列ファミリを指定する必要があります。条件で列ファミリを指定しないと、デフォルトの列ファミリ f のデータのみがクエリされます。この場合、返される結果が期待に沿わない可能性があります。たとえば、meta という名前の列ファミリを作成し、column1 という名前の列を列ファミリに追加するとします。 column1 のデータをクエリするときは、where meta:column1=xxx の形式でクエリ条件に列ファミリ meta を指定する必要があります。クエリ条件で列ファミリ meta を指定しない場合(where column1=xxx など)、Lindorm はデフォルトの列ファミリ f 内でのみ column1 を検索します。この場合、返される結果が期待に沿わない可能性があります。

テーブルに構成された TTL に基づいてクエリ対象のデータが期限切れになっています

LindormTable では、テーブルのデータの有効期間(TTL)を秒単位で指定できます。また、テーブルにデータを書き込むときに、タイムスタンプをミリ秒単位で指定することもできます。

テーブルにデータを書き込むときにタイムスタンプを指定しないと、指定された TTL より長い期間保存されたデータは期限切れになります。たとえば、テーブルの TTL を 86400 秒(1 日に相当)に設定すると、今日テーブルに書き込まれたデータは明日期限切れになり、クエリできなくなります。

データを書き込むときに以前のタイムスタンプを指定し、タイムスタンプと現在の時刻の差が指定された TTL パラメータより大きい場合、データはテーブルに書き込まれた直後に削除される可能性があります。その結果、データをクエリできません。

重要

LindormTable では、キーと値のペアのバージョン番号はタイムスタンプに相当します。カスタムバージョン番号として小さい値(1、2、3 など)を指定すると、指定された TTL に基づいてデータがクリアされる可能性が高くなります。同様に、ミリ秒ではなくマイクロ秒またはナノ秒単位のタイムスタンプなどの大きな値をカスタムタイムスタンプまたはバージョン番号として指定すると、指定された TTL に基づいてデータが期待どおりにクリアされません。

クラスター管理システムで次の手順を実行することで、テーブルの TTL を確認できます。クラスター管理システムにログオンします。 [概要] ページで、TTL を確認するテーブルの名前をクリックします。 [現在のテーブルの詳細] セクションで、[テーブルのプロパティを表示] をクリックします。表示されるページで、[TTL] の値を確認します。クラスター管理システムへのログオン方法の詳細については、「クラスター管理システムにログオンする」をご参照ください。

Lindorm Shell を使用するか、ALTER TABLE ステートメントを実行して TTL 値を変更できます。詳細については、次のドキュメントを参照してください。

構成されたセルの TTL に基づいてクエリ対象のデータが期限切れになっています

LindormTable では、キーと値のペアの TTL をミリ秒単位で構成できます。 TTL はセルの TTL とも呼ばれます。

キーと値のペアにセルの TTL を構成する場合、キーと値のペアの有効期限は、次の式に基づいて計算できます。 min{セルの TTL に基づく有効期限、テーブルの TTL に基づく有効期限}。キーと値のペアの有効期限は、キーと値のペアのタイムスタンプまたはバージョン番号に基づいて計算されます。タイムスタンプまたはバージョン番号が小さすぎるか大きすぎる場合、キーと値のペアが予想よりも早くクリアされるか、期待どおりにクリアできない可能性があります。この場合、返されるクエリ結果が期待に沿わない可能性があります。

たとえば、列に KV1 と KV2 という名前の 2 つのキーと値のペアが含まれているとします。 KV1 にはセルの TTL が構成されており、KV2 にはセルの TTL が構成されていません。 KV1 と KV2 が期限切れになる前に列のデータをクエリすると、タイムスタンプが更新された KV1 が返される可能性があります。 KV1 がセルの TTL に基づいて期限切れになった後に列のデータをクエリすると、KV1 はクリアされ、KV2 が返されます。これは期待に沿いません。

説明

KV2 をクエリできるかどうかは、テーブルの VERSIONS 属性、KV1 と KV2 が異なるファイルに格納されているかどうか、KV1 と KV2 がメジャーコンパクション操作によってマージされているかどうかによって異なります。たとえば、テーブルの VERSIONS 属性を 1 に設定すると、VERSIONS 属性に基づいて 1 つのバージョンのデータのみが保持されるため、メジャーコンパクション操作後に KV2 が削除されます。この場合、KV1 が期限切れ後にクリアされても、KV2 をクエリできません。

削除リクエストに不適切なタイムスタンプが指定されています

LindormTable では、削除リクエストでタイムスタンプまたはバージョン番号を構成できます。タイムスタンプまたはバージョン番号で指定された時刻より前に列または行に書き込まれたデータは削除されます。リクエストでタイムスタンプまたはバージョン番号を構成しない場合、現在の時刻またはバージョンより前に列または行に書き込まれたデータは削除されます。たとえば、現在の時刻は 2024 年 1 月 16 日 16:00:00 です。 DELETE FROM sensor WHERE p1 = 10; ステートメントを実行して、現在の時刻より前に書き込まれ、p1 列の値が 10 である行を削除します。

データ行がテーブルに書き込まれた時刻が、削除リクエストのタイムスタンプで指定された時刻より後の場合、行は削除されません。この場合、テーブルのデータをクエリすると、この行はクエリ結果に含まれます。

削除リクエストで指定されたタイムスタンプまたはバージョン番号が大きい場合、削除操作後に書き込まれたデータのタイムスタンプは、リクエストのタイムスタンプまたはバージョン番号よりも小さくなります。この場合、データは書き込み直後に削除され、クエリできません。

説明

SQL ステートメントを使用してタイムスタンプを指定することはできません。

リンクの問題により、書き込み直後にデータが削除されます

一部のビッグデータシナリオに関連するデータリンクでは、書き込み操作と削除操作が異なるプログラムまたはプロセスで実行される場合、書き込み直後にデータが削除される可能性があります。

また、Realtime Compute for Apache Flink によって提供される以前のバージョンの Lindorm コネクタを使用して Lindorm ワイドテーブルを更新する場合は、2 つの操作がほぼ同時に実行された場合に書き込み操作が削除操作によって上書きされる可能性があるという問題に注意してください。この問題は、Flink で ignoreDelete=true を構成することで解決できます。

詳細については、「Lindorm コネクタ」をご参照ください。

テーブルの VERSIONS 属性が 0 に設定されているため、データが削除されます

ワイドテーブルの VERSIONS 属性の値が 0 に設定されている場合、テーブル内のデータは保持されません。テーブルに書き込まれたデータはすぐに削除され、クエリできません。テーブルを作成するときにテーブルの VERSIONS 属性を構成しないと、この属性の値はデフォルトで 1 になります。これは、テーブルに 1 つのバージョンのデータのみが保持されることを示します。詳細については、「ヒントを使用してデータバージョニングを実装する」をご参照ください。

誤って VERSIONS 属性を 0 に設定した場合は、現在のテーブルを削除して新しいテーブルを作成するか、VERSIONS 属性を 1 以上の値に変更することをお勧めします。

クラスター管理システムで次の手順を実行することで、テーブルの VERSIONS 属性の値を確認できます。クラスター管理システムにログオンします。 [概要] ページで、確認するテーブルの名前をクリックします。 [現在のテーブルの詳細] セクションで、[テーブルのプロパティを表示] をクリックします。表示されるページで、[VERSIONS] の値を確認します。クラスター管理システムへのログオン方法の詳細については、「クラスター管理システムにログオンする」をご参照ください。

Lindorm Shell を使用するか、ALTER TABLE ステートメントを実行して VERSIONS 属性の値を変更できます。詳細については、次のドキュメントを参照してください。

説明

MIN_VERSIONS 属性は、テーブルに保持できる最小バージョン数を指定し、デフォルトで 0 に設定されています。この属性は、データがテーブルに書き込まれた後に削除され、クエリできないという問題を引き起こしません。

変更不可のテーブルのデータが更新されます

テーブルの MUTABILITY 属性が IMMUTABLE に設定されている場合、単一の UPSERT ステートメントを実行することによってのみ、データ行をテーブルに書き込むことができます。テーブルに書き込まれたデータは、更新または削除できません。ただし、Lindorm は変更不可のテーブルに対して実行される更新操作と削除操作を厳密に禁止しているわけではありません。したがって、このような操作により、インデックステーブルとベーストテーブル間でデータの不整合が発生する可能性があります。その結果、クエリ条件に一致するデータがインデックステーブルとベーストテーブルで異なります。

この場合は、インデックステーブルを再構築し、変更不可のテーブルのデータの更新または削除を停止することをお勧めします。