完全にソートされていないデータを検索するためのヒューリスティック


8

ソートされたデータがあれば、検索ソリューションは明白です。並べ替えられていないデータが与えられた場合、適切なオプションは、並べ替えてから検索するか、単なる線形検索です。

この質問は、データがある程度ソートされているが、再編成できない場合の対処方法です(書き込み操作にはセクターの消去が必要であり、セクターがRAMに収まりません)。

詳細:

データレコードは、タイムスタンプとともに順次ログに記録されます。ただし、タイムスタンプクロックは、同期される前にしばらくの間エポックリセットされるか、夏時間調整などにより単純に調整されます。

検索結果は、指定された時刻に最も近いタイムスタンプを持つログレコードである必要があります。特定のタイムスタンプでレコードのバイナリ検索を実行しているときに、不連続なログデータのパッチに到達し、間違った方向にピボットする可能性があります。

ブルート線形法以外に、ここで利用できるヒューリスティックはありますか?例:ローカルミニマの影響を受けないシンプレックス検索?

更新:

レコードの約95%がソートされた順序であると想定できます。約5%(ログ全体に分散)は、汚いしゃっくりです。タイムスタンプが時間的に逆戻りし、ログの先頭よりも前のスタンプがある場合、しゃっくりの始まりを識別できます。


誤ったタイムスタンプに特有の特徴はありますか?「はい」の場合は、「良い」レコードが表示されるまで直線的に進み、その上でピボットします
ラチェットフリーク、

@ratchetfreakの唯一の可能な違いは、それらが古いタイムスタンプである可能性が高く、保証されないことです。パッチを介した線形の問題は、それが長期間続く可能性があることです。
MandoMando 2013

2
並べ替えとスキャンの他に、インデックス作成オプションもあります
CapelliC

ログレコードのサンプルブロックが役立つ場合があります。また、データはどのように整理され、テキストファイル、データベースレコード、固定形式のASCIIデータなどですか?
Jan Doggen 2013

2
多分ばかげている:あなたは時計のリセットの根本的な原因を修正できないのですか?すなわち。if(currentTimeStamp <lastLogTimeStamp){force clock resync} writeToLog(...)
Steven Evers

回答:


3

追加の仮定

この回答は、次の追加の前提に基づいています。

  • ログの先頭のタイムスタンプを簡単に決定できます。
  • しゃっくりの位置を保存することが可能です(オプション)

検索アルゴリズム

検索は実際には2つの異なるアルゴリズムに分割されます。ログの先頭よりのタイムスタンプを持つログを検索する場合、ログがしゃっくりで見つからないことがわかっているので、以下の非しゃっくり検索を使用します。ログの開始前にタイムスタンプを検索する場合は、代わりにしゃっくり検索を使用します。タイムスタンプではなく他の基準で検索する場合、95%のカバレッジのため、最初に非しゃっくり検索を試し、見つからない場合はしゃっくり検索を試します。

必要に応じて、前処理ステップにより、一時的な検索を高速化できます。

前処理(オプション)

可能であれば、線形検索を使用してデータを事前に分析し、しゃっくりデータの位置を見つけます。これは、これらの範囲を保存できる可能性に完全に依存します。これは、ログの5%にすぎない場合に可能である可能性があります(そうでない場合、パフォーマンスが低下します)。

新しいログを書き込むときは常に、対応するデータ構造を更新する必要があります。少なくとも、前処理が実行されたログの時点までを通知できる必要があります。

非しゃっくり検索

非しゃっくりデータの検索は、バイナリ検索と線形検索の組み合わせによって可能です。通常のバイナリ検索を実行しますが、ピボット要素にログの開始前にタイムスタンプが付けられている場合、つまりピボット要素がしゃっくりである場合、ピボット要素の前の最初のログエントリを特定し、それを実際のピボット要素として使用する必要があります。あなたの二分探索の。

ログの開始のタイムスタンプを持つこの最初のログエントリは、hiccupピボット要素から始まる線形検索によって見つかります。関連するピボット要素が配置されているキャッシュされたしゃっくりの前処理または増分更新からわかっている場合は、一定の時間でそこにジャンプできます。完全線形検索を実行する必要があった場合は、データ構造を更新して、これらの位置がしゃっくりデータでカバーされていることを保存します。これにより、次回は正しいピボット要素をすばやく特定できます。

しゃっくり検索

これは、前処理を行ったかどうかによって異なります。そうでない場合は、すべてのデータを線形検索します(この時点で前処理パーツを実行することもできます)。それ以外の場合、前処理されたデータ構造はしゃっくりデータの位置を示すことができ、これらを直接検索できます。つまり、しゃっくりデータの5%のみを使用して線形検索を実行します。

パフォーマンス

完全に前処理されたデータを使用した一時的な検索では、デフォルトのバイナリ検索とほぼ同じパフォーマンスが得られます。各ステップで単純な比較を行う代わりに、しゃっくり要素にヒットしたかどうかを判断するために追加の比較が必要であり、そうであれば実際のピボット要素を見つけるためにデータ構造にアクセスする必要があります。ただし、この追加作業は、データセットの半分だけを除外するだけでなく、しゃっくりデータ部分も除外するという事実によって、少し緩和されます。

もちろん、線形検索に頼らなければならない場合、これはそれに応じて低下します。

既存のしゃっくりに関する情報がなく、すべてのデータを直線的に検索する必要がある場合、しゃっくり検索は悪いケースです。

最後に、タイムスタンプを検索しないが、他の基準があり、そのようなログエントリが存在しない場合、これは最悪のケースです。実際、しゃっくりのデータ構造がない場合、両方の検索実行が同じしゃっくりの位置を線形にスキャンする可能性があるため(それでもO(n)ですが)、線形検索よりも遅くなります。

データ構造が利用可能で完全に前処理されている場合、最悪のケースのランタイムはO(max(log(M)* log(N)、M))になります。ここで、Mは線形検索されるヒカップデータの量です。また、O(log(M))のデータ構造からしゃっくり位置を指定して、しゃっくりデータの終わりを検索できると仮定します。


@Franksこれをありがとう!私はしゃっくりに着地すると、将来の両方のピボットを調べて、データサイズを(1/2ではなく)1/4削減できるかどうかを確認する計画を立てていました。3つすべて(現在のピボットと2つの可能性)がすべてしゃっくりである場合の対処方法がわかりませんでした。提案があれば、ヒカップパッチの端まで直線的に進むことができます。
MandoMando 2013
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.