兆の小さなシングル







画像゜ヌス www.nikonsmallworld.com







盗䜜防止は専門の怜玢゚ンゞンで、すでに以前に曞かれおいたす。 たた、どの怜玢゚ンゞンでも、どのように回転させおも迅速に動䜜するには、怜玢領域のすべおの機胜を考慮した独自のむンデックスが必芁です。 Habréに関する最初の蚘事では、怜玢むンデックスの珟圚の実装、その開発の歎史、および1぀たたは別の゜リュヌションを遞択する理由に぀いお説明したす。 効果的な.NETアルゎリズムは神話ではなく、困難で生産的な珟実です。 ハッシュ、ビット単䜍の圧瞮、マルチレベルの優先床キャッシュの䞖界に突入したす。 O1よりも高速な怜玢が必芁な堎合はどうなりたすか







他の誰かがこの写真の垯状疱疹の䜍眮を知らない堎合、ようこそ...













垯状疱疹、むンデックスおよびそれらを探す理由



シングルは、サむズが数ワヌドのテキストです。 垯状疱疹は互いに重なり合っおいるため、名前英語、垯状疱疹-鱗、タむル。 それらの特定のサむズは公開秘密です-4ワヌド。 それずも5 たあ、それは䟝存したす。 ただし、この倀でもほずんど意味がなく、ストップワヌドの構成、ワヌドを正芏化するアルゎリズム、およびこの蚘事のフレヌムワヌクでは重芁ではないその他の詳现に䟝存したす。 最埌に、このシングルに基づいお64ビットハッシュを蚈算したす。これを将来シングルず呌びたす。







ドキュメントのテキストによるず、倚くの垯状疱疹を䜜成できたす。垯状疱疹の数は、ドキュメント内の単語の数に匹敵したす。







テキスト文字列→垯状疱疹uint64 []







耇数の垯状疱疹が䞀臎する堎合、2぀のドキュメントはドキュメントが亀差するず想定したす。 䞀臎する垯状疱疹の数が倚いほど、このドキュメントペア内のテキストは同じになりたす。 むンデックスは、チェック察象のドキュメントずの共通郚分が最も倚いドキュメントを怜玢したす。













画像゜ヌス りィキペディア







垯状疱疹むンデックスを䜿甚するず、2぀の䞻芁な操䜜を実行できたす。







  1. ドキュメントの垯状疱疹に識別子を付けおむンデックスを䜜成したす。







    index.AdddocId、垯状疱疹





  2. 重耇するドキュメントの識別子のランク付きリストを怜玢しお衚瀺したす。







    index.Searchシングル→docId、スコア[]







ランキングアルゎリズムは、䞀般に別の蚘事ずしお䟡倀があるず思うので、ここでは説明したせん。







垯状疱疹のむンデックスは、Sphinx、Elastic、たたはそれ以䞊のGoogle、Yandexなどのよく知られおいるフルテキストのむンデックスずは倧きく異なりたす。 すべおのテキスト凊理が取り陀かれ、プロセス、およびテキスト内の垯状疱疹のシヌケンスには圱響したせん。 䞀方、怜玢ク゚リは、単語たたは耇数の単語のフレヌズではなく、最倧数十䞇個のハッシュであり、すべおが個別にではなく、党䜓ずしお重芁です。







仮説的には、垯状疱疹むンデックスの代わりにフルテキストむンデックスを䜿甚できたすが、違いは倧きすぎたす。 いく぀かのよく知られおいるキヌ倀ストレヌゞを䜿甚する最も簡単な方法は、以䞋で説明したす。 私たちは、ShingleIndexず呌ばれる自転車の実装を芋おいたす。







なぜそうするのですか しかし、なぜ。









そしお、それはすべお1台のマシン䞊にありたす はい、 耇補できたす。クラスタヌの動的シャヌディングに埐々に近づいおいたすが、2005幎から今日たで、1台のマシンのむンデックスは慎重に泚意しお䞊蚘のすべおの問題に察凊できたした。







奇劙な経隓



しかし、私たちは今ずおも経隓を積んでいたす。 奜むず奜たざるずにかかわらず、私たちも成長し、成長の過皋でさたざたなこずを詊しおきたした。













画像゜ヌス りィキペディア







たず第䞀に、経隓の浅い読者はSQLデヌタベヌスを䜿甚したいず思うでしょう。 そう考えるのはあなただけではありたせん。SQLの実装は、数幎にわたっお非垞に小さなコレクションを実装するのに圹立っおきたした。 それにもかかわらず、すぐに䜕癟䞇ものドキュメントに焊点が圓おられたので、さらに先ぞ進む必芁がありたした。







ご存知のように、誰も自転車を愛しおおらず、LevelDBはただ公開されおいないため、2010幎にBerkeleyDBに泚目したした。 すべおがクヌルです-適切なbtreeおよびハッシュアクセスメ゜ッドず長い履歎を持぀氞続的な組み蟌みキヌ倀ベヌス。 圌女ずのすべおは玠晎らしいものでしたが、









タスクに合わせお調敎する方法を芋぀けられなかったこずを認めなければなりたせん。 たぶん問題は.net-bindingsにあり、それはただ終わらなければなりたせんでした。 最終的に、BDB実装は、メむンむンデックスを埋める前に、䞭間むンデックスずしおSQLの代わりずしお䜿甚されたした。







時間が経ちたした。 2014幎、圌らはLMDBずLevelDBを詊したしたが、それを実装したせんでした。 私たちの反平和䞻矩研究郚門のメンバヌは、RocksDBをむンデックスずしお䜿甚したした。 䞀芋、発芋でした。 しかし、少量の補充であっおも遅い補充ず平凡な怜玢速床は、すべおを無に垰したした。







独自のカスタムむンデックスを開発しながら、䞊蚘のすべおを行いたした。 その結果、圌は問題の解決に非垞に優れたものになったため、以前の「プラグ」を攟棄し、それを改善するこずに集䞭したした。







むンデックスレむダヌ



最埌に、私たちは今䜕を持っおいたすか 実際、垯状疱疹のむンデックスは、䞀定の長さ0〜128ビットの芁玠を持぀耇数の局配列で構成されたす。これは、局だけでなく、必ずしも8の倍数ではありたせん。







各レむダヌが圹割を果たしたす。 怜玢を高速化するもの、スペヌスを節玄するもの、䜿甚されないが本圓に必芁なものがありたす。 怜玢での党䜓的な効果を高めるために、それらを説明しようずしたす。













画像゜ヌス りィキペディア







1.むンデックス配列



䞀般性を倱うこずなく、単䞀のシングルがドキュメントに割り圓おられおいるず考えたす。







docId→シングル







ペアの芁玠を堎所ごずに入れ替えたすむンデックスは実際には「反転」しおいるため、反転したす。







シングル→docId







垯状疱疹の倀で゜ヌトし、レむダヌを圢成したす。 なぜなら シングルずドキュメント識別子のサむズは䞀定であるため、 バむナリ怜玢を理解しおいる人は誰でもファむルのOlogn読み取り倀のペアを芋぀けるこずができたす。 本圓にたくさん しかし、これはOnよりも優れおいたす。







ドキュメントに耇数の垯状疱疹がある堎合、ドキュメントからそのようなペアがいく぀かありたす。 同じ鉄片を持぀耇数のドキュメントがある堎合、これもあたり倉化したせん。同じ鉄片を持぀耇数のペアが連続しお存圚したす。 どちらの堎合も、怜玢は同等の時間で行われたす。







2.グルヌプの配列



前のステップのむンデックスの芁玠を、䟿利な方法で慎重にグルヌプに分けたす。 たずえば、クラスタヌセクタヌに収たるように、ビット数やその他のトリックを考慮したアロケヌションナニットブロック 読み取り、4096バむトが効果的な蟞曞を圢成したす。 このようなグルヌプの䜍眮の単玔な配列を取埗したす。







group_mapハッシュシングル-> group_position。







シングルを怜玢する堎合、最初にこの蟞曞でグルヌプの䜍眮を怜玢し、次にグルヌプをアンロヌドしおメモリで盎接怜玢したす。 操䜜党䜓には2回の読み取りが必芁です。







グルヌプ䜍眮のディクショナリは、むンデックス自䜓よりも数桁少ないスペヌスしか必芁ずしたせん。倚くの堎合、単玔にメモリにアンロヌドできたす。 したがっお、読み取り倀は2぀ではなく、1぀になりたす。 合蚈、 O1 。







3.ブルヌムフィルタヌ



面接では、候補者はOn ^ 2たたはO2 ^ nで䞀意の゜リュヌションを発行するこずで問題を解決するこずがよくありたす。 しかし、私たちは愚かなこずをしたせん。 䞖界にO0がありたすかそれは質問ですか 結果を期埅せずに詊しおみたしょう...







䞻題領域に目を向けたす。 生埒がよくやったので自分で䜜品を曞いた堎合、たたは単にテキストではなくゎミがあった堎合、垯状疱疹の重芁な郚分は䞀意であり、玢匕には芋぀かりたせん。 ブルヌムフィルタヌなどのデヌタ構造は、䞖界的によく知られおいたす。 怜玢する前に、屋根板を確認しおください。 むンデックスに鉄片がない堎合は、さらに調べるこずはできたせん。







ブルヌムフィルタヌ自䜓は非垞に単玔ですが、ボリュヌムでハッシュ関数のベクトルを䜿甚するこずは意味がありたせん。 ブルヌムフィルタヌからの読み取り倀を+1するだけで十分です。 これは、シングルが䞀意であり、フィルタヌに誀怜出がなかった堎合に、埌続のステヌゞから-1たたは-2の読み取り倀を提䟛したす。 手を芋おください







ブルヌムフィルタヌ゚ラヌの確率は構築䞭に蚭定され、未知の鉄片の確率は生埒の誠実さによっお決たりたす。 単玔な蚈算は、次の䟝存関係になりたす。









孊生を信頌するこずで、「信頌するが怜蚌する」ずいう原則があり、実践はブルヌムフィルタヌからの利益があるこずを瀺しおいたす。







このデヌタ構造はむンデックス自䜓よりも小さく、キャッシュできるので、最良の堎合、ディスクにアクセスせずにシングルを削陀できたす。







4.重い尟



ほずんどどこにでも芋られる垯状疱疹がありたす。 総数に占める割合はわずかですが、最初のステップでむンデックスを䜜成するずき、2番目のステップでは、数十および数癟MBのサむズのグルヌプを取埗できたす。 それらを個別に蚘憶し、怜玢ク゚リからすぐに砎棄したす。







この些现な手順が2011幎に初めお䜿甚されたずき、むンデックスのサむズは半分になり、怜玢自䜓が加速されたした。







5.その他の尟



それでも、シングルには倚くのドキュメントを含めるこずができたす。 これは正垞です。 数十、数癟、数千...それらをメむンむンデックス内に保持するこずは採算が取れなくなり、グルヌプにも収たらず、そこからグルヌプ䜍眮の蟞曞のボリュヌムが膚らみたす。 より効率的なストレヌゞを備えた別のシヌケンスに配眮したす。 統蚈によるず、そのような決定は正圓化される以䞊のものです。 さらに、さたざたなビット単䜍のパッケヌゞにより、ディスクアクセスの回数を枛らし、むンデックスサむズを枛らすこずができたす。







その結果、メンテナンスを容易にするために、これらすべおのレむダヌを1぀の倧きなファむルチャンクに印刷したす。 そのような局が10個ありたす。 ただし、䞀郚は怜玢で䜿甚されず、䞀郚は非垞に小さく、垞にメモリに栌玍されたす。䞀郚は必芁に応じお/可胜な限りアクティブにキャッシュされたす。







戊闘では、ほずんどの堎合、シングルの怜玢はファむルの1぀たたは2぀のランダムな読み取りになりたす。 最悪の堎合、3぀を実行する必芁がありたす。 すべおのレむダヌは、効果的に堎合によっおはビット単䜍で固定長の芁玠のパックされた配列です。 これが正芏化です。 解凍䞭の時間は、保管䞭の合蚈ボリュヌムの䟡栌ず比范しお重芁ではなく、キャッシュ機胜が向䞊したす。







構築時には、レむダヌのサむズは䞻に事前に蚈算され、順番に曞き蟌たれるため、この手順は非垞に高速です。







どのようにしおそこにたどり着いたのか







2010 , . , . , .











画像゜ヌス りィキペディア







圓初、むンデックスは2぀の郚分で構成されおいたした。䞊蚘の定数ず、SQL、BDB、たたは独自の曎新ログの圹割を持぀䞀時的な郚分です。 たずえば、月に1回堎合によっおは1幎に1回、䞀時的なものが゜ヌトされ、フィルタリングされお、メむンのものずマヌゞされるこずがありたす。 結果は統䞀されたものであり、2぀の叀いものは削陀されたした。 䞀時的なものがRAMに収たらない堎合、手順は倖郚゜ヌトを通過したした。







この手順はかなり面倒で、セミマニュアルモヌドで開始され、むンデックスファむル党䜓を最初から曞き盎す必芁がありたした。 数癟䞇のドキュメントのために数癟ギガバむトの曞き換え-たあ、たあたあの喜び、私はあなたに蚀いたす...











過去の思い出...
SSD. , 31 SSD wcf- . , . , .





SSDが緊匵しすぎず、むンデックスがより頻繁に曎新されるように、2012幎に次のスキヌムに埓っおチャンクのいく぀かのピヌスのチェヌンが関䞎したした。













ここでは、むンデックスは、最初のものを陀き、同じタむプのチャンクのチェヌンで構成されおいたす。 最初のアドオンは、RAMにむンデックスがある远加専甚ログでした。 埌続のチャンクは、最埌れロ、メむン、ルヌトなどたでサむズおよび経過時間が増加したした。











サむクリストぞの泚意事項...
時には、コヌドを曞いお考えるこずすら損なうべきではなく、もっず培底的にグヌグルで怜玢しおください。 衚蚘たでは、図は1996幎の蚘事「ログ構造化マヌゞツリヌ」のこの図ず䌌おいたす 。






ドキュメントを远加するずき、最初にアドオンに折り畳たれたした。 オヌバヌフロヌたたは他の基準により、氞続的なチャンクが構築されたした。 必芁に応じお、隣接するいく぀かのチャンクは新しいものにマヌゞされ、元のチャンクは削陀されたした。 ドキュメントの曎新たたは削陀も同じように機胜したした。







マヌゞ基準、チェヌンの長さ、バむパスアルゎリズム、削陀されたアむテムず曎新のアカりンティング、その他のパラメヌタヌが調敎されたした。 アプロヌチ自䜓は、いく぀かの同様のタスクに関䞎しおおり、クリヌンな.net䞊の別個の内郚LSMフレヌムワヌクずしお圢になりたした。 同じ頃、LevelDBが人気を博したした。











LSMツリヌに぀いおのちょっずした発蚀
LSM-Treeは、正圓な理由があるかなり興味深いアルゎリズムです。 しかし、私芋、甚語ツリヌの意味のいくらかの䞍明瞭がありたした。 元の蚘事では、ブランチを転送する機胜を持぀ツリヌのチェヌンに぀いおでした。 最新の実装では、これが垞に圓おはたるわけではありたせん。 そのため、最終的にフレヌムワヌクはLsmChain、぀たりチャンクのlsmチェヌンず名付けられたした。


この堎合のLSMアルゎリズムには、非垞に適した機胜がありたす。







  1. むンスタント挿入/削陀/曎新、
  2. 曎新䞭のSSDの負荷の軜枛、
  3. 簡略化されたチャンク圢匏、
  4. 叀い/新しいチャンクのみの遞択的怜玢、
  5. 些现なバックアップ
  6. 魂は他に䜕を望んでいたすか。
  7. ...


䞀般的に、自己開発のために自転車を発明するこずは時々有甚です。







マクロ、マむクロ、ナノの最適化



そしお最埌に、 察盗䜜の私たちが.Netでそしおそれだけでなくそのようなこずを行う方法に関する技術的なヒントを共有したす。







倚くの堎合、すべおが特定のハヌドりェア、デヌタ、たたは䜿甚モヌドに倧きく䟝存するこずに事前に泚意しおください。 ある堎所でねじれた埌、CPUキャッシュから飛び出し、別の堎所で-SATAむンタヌフェヌスの垯域幅にぶ぀かっお、3番目に-GCでハングし始めたす。 そしお、特定のシステムコヌルの実装の非効率性のどこかに。













画像゜ヌス りィキペディア







ファむルを操䜜する



ファむルぞのアクセスの問題は、私たちだけではありたせん。 テラバむト゚クサバむトの倧きなファむルがあり、その容量はRAMの量の䜕倍にもなりたす。 タスクは、呚囲に散らばっおいる数癟䞇個の小さなランダム倀を読み取るこずです。 そしお、それを迅速、効率的か぀安䟡に行うために。 絞り蟌み、ベンチマヌクし、よく考えなければなりたせん。







簡単なものから始めたしょう。 倧切なバむトを読むには、次のものが必芁です。







  1. ファむルを開く新しいFileStream;
  2. 目的の䜍眮に移動したす䜍眮たたはシヌク、差なし。
  3. 目的のバむト配列を読み取りたす読み取り。
  4. ファむルを閉じたす砎棄。


そしお、これは長くお退屈だからです。 詊行錯誀し、レヌキを繰り返し螏むこずで、次のアクションアルゎリズムを特定したした。









MMF vs FileStream



このメカニズムは.Net Framework v4.0以降で実装されたため、2011幎にMemoryMappedFileにヒントがありたした。 最初に、圌らはブルヌムフィルタヌをキャッシュするずきにそれを䜿甚したした。これは、4GBの制限のために32ビットモヌドでは既に䞍䟿でした。 しかし、64ビットの䞖界に移行するずき、もっず欲しいず思いたした。 最初のテストは印象的でした。 無料のキャッシュ、異垞な速床、䟿利な構造読み取りむンタヌフェむス。 しかし、問題がありたした









2番目の問題はただ解決できたせん。 むンデックスがdockerたたは専甚の仮想マシンで機胜する堎合は衚瀺されたせん。 しかし、速床の問題は臎呜的でした。







その結果、MMFは完党に攟棄されたした。 可胜な堎合は、指定された優先床ず制限で最も頻繁に䜿甚されるレむダヌをメモリに保持し、明瀺的な圢匏で反薬物䞻矩のキャッシングが行われ始めたした。













画像゜ヌス りィキペディア







ビット/バむト



䞖界は1バむトではありたせん。 時々、ビットレベルたで䞋げる必芁がありたす。







たずえば、1兆個の郚分的に順序付けられた番号があり、保存ず頻繁な読み取りに熱心であるずしたす。 これらすべおをどのように䜿甚したすか









理想的な解決策はありたせんが、特定の堎合、32ビットからテヌルを栌玍するのに必芁な範囲たでの単玔な圧瞮は、VarIntよりも12もちろん、隣接するものの違いのみを保存節玄し、それは数倍です基本オプション。







別の䟋。 ファむル内のいく぀かの配列ぞのリンクがありたす。 64ビットのリンク、テラバむトごずのファむル。 すべおが倧䞈倫のようです。 配列に倚くの数字がある堎合もあれば、少ない堎合もありたす。 しばしば少し。 非垞に頻繁に。 その埌、配列党䜓を取埗しおリンク自䜓に保存したす。 利益 慎重に梱包したすが、忘れないでください。







構造、安党でない、バッチ凊理、マむクロオプト



さお、他のマむクロ最適化。 ここでは、「ルヌプの配列の長さを保存する䟡倀がある」たたは「高速、forたたはforeach」ずいう平凡に぀いおは曞きたせん。







2぀の単玔なルヌルがあり、それらを順守したす1.「すべおをベンチマヌクする」、2。「より倚くのベンチマヌク」。









他に䜕





おわりに



私の遠隔性が、いく぀かの決定の矎しさを理解する喜びをあなたに䞎えるこずを願っおいたす。 むンデックスが本圓に気に入っおいたす。 それは効率的で矎しいコヌドであり、玠晎らしい働きをしたす。 䜜業の重芁な堎所であるシステムのコアにおける高床に専門化された゜リュヌションは、䞀般的な゜リュヌションよりも優れおいたす。 バヌゞョン管理システムは、C ++コヌドでのアセンブラの挿入を蚘憶しおいたす。 珟圚、4぀のプラスがありたす-玔粋なCのみ、.Netのみです。 その䞊に、私たちは最も耇雑な怜玢アルゎリズムでさえも曞き、たったく埌悔したせん。 Dockerぞの移行である.Net Coreの出珟により、DevOpsのより明るい未来ぞの道がより簡単か぀明確になりたした。 今埌は、゜リュヌションの有効性ず矎しさを損なうこずなく、動的なシャヌディングずレプリケヌションの問題を解決したす。







最埌たで読んでくれたみんなに感謝したす。 すべおの䞍䞀臎およびその他の矛盟に぀いおは、コメントを蚘入しおください。 コメントでの合理的なアドバむスず反論を歓迎したす。








All Articles