ビデオ怜玢に぀いお䞀蚀

今日、この玠晎らしい春の日に、ビデオ怜玢だけでなく、技術的なこずに぀いおも曞きたいず思いたす。

ロヌドされたDjangoプロゞェクトでのSphinxsearchの動䜜の実装。







怜玢する







おそらく、ビゞネスタスクを蚭定するこずから始める䟡倀がありたす。









非機胜芁件









Rutubeでsphinxsearchがどのように䜿甚されおいるか、そしおこのストヌリヌはどうなるか







ビデオの関連性ず数孊に぀いお



むンタヌネットでの怜玢に぀いお話す堎合、通垞はテキスト情報を怜玢するこずを意味したす。 ビデオの堎合、すべおがはるかに悪いです。 通垞、人ずは非垞に具䜓的な芖芚的むメヌゞを意味し、リク゚ストのテキストに倉換したす。 サむトに動画をアップロヌドしおいる他の人は、動画の内容を動画のタむトルず説明に翻蚳したした。「test」、「sdfsdf」、たたは「111」でなければ良いでしょう。 いずれにせよ、最小限のテキスト情報のみが存圚し、線集スタッフずパヌトナヌナヌザヌが添付するメタデヌタもありたす。 あなたが怜玢プログラマである堎合、「なぜ怜玢されないのですかRp」ずいう質問は倜にあなたを悩たせたす。特別なテストナヌティリティは、これらの質問に答えるのに圹立ちたす。

これは、怜玢ク゚リによっお、むンデックスにあるすべおのフィヌルドを持぀ビデオだけでなく、各ドキュメントのすべおの特性の倀を持぀ランカヌからの情報も返すペヌゞです。 このために、 PACKEDFACTORS()



、 SNIPPETS()



およびCALL KEYWORDS



芁求されたす。 通垞、このペヌゞのデヌタは、 無関係ず呌ばれるものを数孊的に実蚌するのに十分ですここでは、プログラマだけが数孊的な意味で理解し、残りはすべお霊的な意味で理解できる魔法の蚀葉です...䞊蚘の関連 。







Djangoバック゚ンド怜玢ベヌス



Sphinxsearchはmysqlクラむアントをサポヌトしおいるので、Djangoのバック゚ンドを䜿甚しお必芁な怜玢ク゚リを䜜成し、結果をDjangoモデルずしお返したせんか 誰もがこれを行うこずをお勧めしたせんが、それは本圓にそれほど怖いではありたせん。 そしお、ただ怖い、たたは単に興味がない人のために、次のセクションにすぐに進むこずをお勧めしたす。







い぀ものように、githubには䟿利なものがありたす。 たずえば、同じdjango-sphinx-dbは 、djangoモデルから盎接゚ンゞンを開始するのに圹立ちたした。 Django-1.8では、デヌタベヌスバック゚ンド実装のプラむベヌト郚分が倧幅に倉曎されたため、 django-sphinx-db



移怍が問題になりたした。 その結果、 django-sphinxsearchプロゞェクトが登堎したした。これは、開発偎からの泚意が少し欠けおいたすが、 すでに本番環境で䜿甚されおいたす。 ちなみに、ここにバック゚ンドサポヌトの難しさの䟋がありたす。Djangoの新しいバヌゞョンがリリヌスされ、すべおがバラバラになりたす。なぜなら、「私の内臓は私が望むものを倉える」からです。 ですから、最初から始めなければなりたせん。







次のようになりたす。







  1. PEP-0249互換のデヌタベヌスコネクタを探しおいたす。 MySQL-python、psycopg、python_monetdb-Djangoのねじ蟌み先によっお異なりたす。
  2. 粟神的に最も近いバック゚ンドが取埗され、継承されたす。 sphinxsearchの堎合、これはMySQL、別名django.db.backends.mysql



    です。
  3. 最も難しいのは、バック゚ンドが蚘述されおいるデヌタベヌスず互換性のあるコヌドSQLCompiler



    生成するようにSQLCompiler



    に教えるこずです。 これは、匕甚笊の䜿甚、スキヌマを指定せずにテヌブル名を指定する機胜、LIMIT / OFFSET構文などに適甚されたす。 ここで、 SQLCompiler.as_sql



    から文字列を収集するSQLCompiler.as_sql



    メ゜ッドがほが100行のモノリスであるずいう事実に぀いお、Django開発者に別の「劖粟」を蚀いたいず思いたす。 その結果、 LIMIT OFFSET



    をLIMIT start, end



    に倉曎するには、基本クラスメ゜ッドを呌び出した結果を定期的にLIMIT start, end



    がありたす。
  4. 怜玢固有の機胜を提䟛するQuerySetメ゜ッドが远加されたした。 たずえば、 SphinxQuerySet.match



    はself.match構造をSphinxQuerySet.match



    远加し、SphinxQL匏の構築に必芁なデヌタが含たれたす。 䞀臎フィヌルドは耇補され、 SphinxWhereNode.make_atom



    で倉曎され、最埌にSphinxWhereNode.make_atom



    䜿甚されおク゚リ文字列の䞀郚を生成したす。 耇雑なこずは䜕もありたせん。テストを曞いお、手元に良いデバッガを甚意するだけです。


怜玢結果ランキング



通垞、怜玢結果は、怜玢ク゚リずの関連性によっお゜ヌトされたす。 それを数えるには たずえば、ドキュメントずク゚リに同時に存圚する単語の数を取埗できたす。 亀差点の単語が倚いほど、このク゚リにより正確に結果が適合したす。 䞀臎する単語の数だけでなく、それらの順序も考慮するこずができたす。 そしお、各単語の「垌少性」が考慮される堎合、それは䞀般的にクヌルです。リク゚ストおよびドキュメント内の前眮詞ず接続詞の存圚は、もはや問題に圱響したせん。 そのような特性を発明した倚くの異なる、有甚な、そしおそれほど倚くはないので、䞀般的なケヌスでは、゚ンゞンが考慮するすべおの特性の倀の加重和を䜿甚するのが合理的です。







特定のドキュメントを怜玢ク゚リに関連付ける特性に加えお、ク゚リに関係なく、特定の属性を持぀ドキュメントに重みを远加するこずができたす。 たずえば、高品質でロヌドされたビデオの出力を増やすため。 たたは、最近の動画や芖聎回数の倚い動画に重みを付けたす。







リク゚ストに远加したす







 SELECT weight() + a * view_count + b * age as my_weight, ... OPTION ranker=expr('...') ORDER BY my_weight DESC;
      
      





たた、発行の゜ヌト順は完党に管理されおいたす。







そのため、簡単な方法で次のようになりたす









QuerySet.iterator



c゜ナヌズマルトフィルム

線集者は、これらの「ねじれ」が十分でないこずをほのめかしおいたす







怜玢ク゚リの調敎だけでは䞍十分な堎合は、結果を爪で「釘付け」できたす。 䞀郚のク゚リでは、これは䞀般に重芁な機胜であるため、必芁ではありたせんが、怜玢結果を操䜜するメカニズムを実装する必芁がありたす。







  1. 線集者が怜玢結果に衚瀺したい珟圚のリク゚ストの動画があるかどうかを探しおいたす。 それらが占有されおいる䜍眮を取埗したす。
  2. 「ネむル」結果以倖の怜玢をリク゚ストしたす。
  3. QuerySet.iterator QuerySet.iterator()



    メ゜ッドを倉曎しお、「通垞」状態のsphinxsearchからの結果を返し、䞀郚の堎所で同じ「釘付け」クリップを返すようにしたすたずえば、「Real男の子。「コメントなし」。
  4. 怜玢で無関係な結果が生成される堎合、䞀般的に、たずえば、類䌌のクリップの代わりに、デヌタベヌスから䜕か、たずえば同じシリヌズの゚ピ゜ヌドのリストを衚瀺できたす。 これを行うには、メむンVideoモデルがSearchVideo怜玢結果のモデルずフィヌルドを䞀臎させるだけで十分です。


技術的な制限



sphinxsearchでできないこずに぀いお少し説明したす。 最も奇劙で、同時に説明䞍可胜な「䞍可胜」1぀たたは耇数の文曞を陀いおすべおの発行を発行するこずは䞍可胜です。 フルスキャンだけを実行できたすが、フルスキャンWHERE MATCH('~document_id')



〜document_id WHERE MATCH('~document_id')



は実行できたせん。 ゜フトりェアは、非効率的に犁止しおいたす。







制限には2぀の制限がありたす。最初に、明瀺的にLIMITを指定しないSELECT *



、ほがrepr(queryset)



ような20の結果を返したす。 次に、100500番目の芁玠を芋぀けるには、ク゚リにOPTION max_matches=100500



を远加したす。 ゚ンゞン内には郚分的な䞊べ替えがあり、既定ではりィンドりサむズは1000です。その結果、より倧きなオフセットを芁求するず゚ラヌになりたす。







属性を持぀数倀挔算には倚くの奇劙な制限がありたす。 䟋えば、 SELECT



ではfloat_field <> 3.1415



蚘述できたすが、 WHERE



では蚘述できたせん。 䜕ができるか、特にパヌサヌ。 QuerySet.extra()



を介しお戊いたす。







最も䞍快な「䞍可胜」最も䞍快な瞬間に怜玢がクラッシュしないずいう事実に頌るこずはできたせん。 番号「13」を含むリク゚ストを受信した盎埌にsearchdが再起動する堎合がありたした。 これは、怜玢結果が䞻芁なコンテンツではないペヌゞでは特に䞍快です。 ゞェネレヌタヌで管理したした。OperationalErrorを受け取った堎合、静かに平和的に空の応答を返したす。







負荷がかかっおいる



サむトに倚くのデヌタがあり、それらが頻繁に倉曎される状況では、5分ごずにサむト党䜓を取埗しおむンデックスを䜜成するこずはできたせん。 もっず賢くなければなりたせん。 怜玢で「犬を食べた」人にずっお、このセクションはあたり面癜くありたせん。なぜなら、物事はほずんどよく知られおいるからです。しかし、私はそれらを簡朔に芁点たで説明したす。







  1. メむン+デルタ+キルリスト。 main-サむト党䜓を含むメむンむンデックスは1日に1回曎新されたす。 delta-メむンむンデックスの最埌のむンデックス䜜成以降に曎新されたドキュメントのみが含たれたす。 killlist- 前のむンデックスから陀倖する必芁があるドキュメントのリスト。







     #  IP   sql_query_pre = set @ip = substring_index(user(), '@', -1); #  delta-  KILL-  # ,    delta- + # ,     main  sql_query_killlist = select id from ... where ... and last_updated_ts > @last_index_ts
          
          





  2. global_idf 耇数のロヌカルむンデックスがある堎合、global_idf = 1パラメヌタを指定する䟡倀がありたす。 そうでない堎合、逆ドキュメント頻床はむンデックスごずに個別に考慮されたす。その結果、「デルタ」からの「たれな」単語が存圚しないはずの結果を抌し䞊げたす。
  3. いく぀かの怜玢゚ンゞン。 怜玢゚ンゞンのむンデックスファむルの耇補に぀いおは賢くならず、各サヌバヌが個別にデヌタベヌスのむンデックスを䜜成したす。 同期が取れおいないデヌタが発生し、さらに安定した゜リュヌションが発明されたしたが、これたでのずころ手が届きたせんでした。 解決策RT-index。ドキュメントの倉曎に関するメッセヌゞを受信するず、すべおの怜玢゚ンゞンで同時に曎新されたす。 長所むンスタントむンデックス䜜成、通垞状態でのデヌタrassynchronの欠劂。 短所開始コヌドを送信する非垞に耇雑なメッセヌゞ。 怜玢ドキュメントには、玄15のデヌタベヌステヌブルからのデヌタが含たれおおり、各怜玢サヌバヌにメッセヌゞハンドラが必芁です。
  4. サヌバヌの負荷。 もちろん、LoadをCPUの100にしない方が良いですが、これが暙準になっおいる堎合は、理論的なク゚リ実行時間を制限するmax_predicted_time



    オプションがありたす。 関連性は䜎䞋したすが、問題の䞀郚は削枛できたす。 「神はすべおを芋る」ので、可胜ですが、必芁ではありたせん。 神は線集者であり、すべおは、たずえば、ペヌゞ䞊の非垞に奇劙な「類䌌した」ものの倖芳です。 䞀時的な過負荷にCONN_TIMEOUT



    は、Django接続にCONN_TIMEOUT



    を蚭定しお、怜玢が他のすべおの速床を䜎䞋させないようにするのが理にかなっおいたす。
  5. 同矩語ず䟋倖リストの管理。 これをWebDAVで分解し、最も近いむンデックス付けでむンデックスの回転䞭に適甚したす。


RTむンデックスの倉曎に぀いお



それでも、sphinxsearchはデヌタベヌスではありたせん。 ただし、その䞭のデヌタを倉曎する可胜性がありたす。









生産で3幎間sphinxsearchを䜿甚した埌、怜玢チヌム党䜓が情熱的か぀心から圌を愛しおいたした。 おそらく、これはすべおの問題がずおも奇劙で面癜い唯䞀のプロゞェクトです:)









Rutubeのsphinxsearchは、Kibana自転車のログを保存および凊理するために䜿甚されたす-ちなみに、かなり高速に動䜜したす。 時間がありたす-圌に぀いおお話したす。








All Articles