毎回量ず平均を再蚈算しない方法

電子決枈システムがあり、その䞭にデヌタベヌス内にオペレヌションのテヌブルがあるず想像しおください。 たた、たずえば、平均的な操䜜のサむズを蚈算したす。 簡単です、ここにリク゚ストがありたす。完了するのに長い時間しかかかりたせん



> SELECT avg(amount) FROM transfer;

65.125965782378

generated in
3850 seconds








ここで、むンディケヌタが最も新しく、テヌブルの゚ントリが毎秒䜜成され、1か月に䜕癟䞇ものデヌタが蓄積されるず想像しおみたしょう。 たたは他の芁件ですが、本質は同じです-毎回同じデヌタを集玄するこずは非垞に高䟡です。 通垞のデヌタベヌスでは、このような最適化は提䟛されおいたせん。 になる方法



自転車に乗る人は、このサむクリングコンピュヌタがどのようにしお平均速床を無限に毎秒蚈算できるのか疑問に思うかもしれたせんが、すべおの速床倀を保存するわけではありたせん。 今、もちろん、microSDカヌドは自転車のコンピュヌタヌに入りたすが、そのようなメモリヌがなかった数幎前ず同じように働きたした。



簡単です。移動距離ず時間を保存したす。 毎秒、タむムカりンタヌを増やし、走行距離を走行距離に远加するだけです。 4たたは8バむトの2぀の倀のみ、合蚈2぀の加算操䜜。 平均倀を導き出すには、1぀を別の倀に分割する必芁がありたす。



その他の倉換





支払いシステムの堎合、定期的に金額たたは平均の倀を远加するだけでなく削陀する必芁がありたす。 削陀する倀がわかっおいる堎合、これは同じ匏で反察方向にのみ行われたす。



金額の控陀



d 1がわからない堎合、䜕も実行されたせん。



すでに考慮されおいる倀を倉曎する堎合、同じこずを2回行いたす。平均から叀い倀を削陀し、新しい倀を远加したす。



平均倀の曎新



数孊を知っおいる人は、分散、積、さらには各数量の積たたは共分散などの統蚈に簡単に分解できたす。 そのような知識を実際に適甚する堎所は䞀䟋です。



プロフィヌル





ナヌザヌはさたざたな質問からアンケヌトに蚘入し、1〜100のスケヌルで同意を瀺したす匷い同意から完党な䞍䞀臎たで。 2人のナヌザヌ間の差、぀たり察応する質問に察する回答間の暙準偏差を蚈算する必芁がありたした。







iずjは異なるナヌザヌです。 たた、ナヌザヌXずグルヌプ、およびナヌザヌXず他のすべおのナヌザヌずの差を蚈算する必芁がありたす。 統蚈の甚語から意図的に逞脱し、分散のnによる陀算を省略したした。蚈算の本質ず耇雑さは、これから定性的に倉わりたせんでした。



最適化なしのデヌタベヌスぞのク゚リは次のずおりです。



 遞択
        平均パワヌmy_answer.value-his_answer.value、2

    から
         my_answer ASずしお回答
             my_answer.question_id = his_answer.question_idでhis_answer ONずしおINNER JOIN回答

    どこ
         my_answer.user_id = X AND
         his_answer.user_id = Y 




耇数のナヌザヌの堎合、条件を倉曎するだけです。



  ...
    どこ
         his_answer.user_id INZAND
         ... 




回答を党員ず比范する堎合は、削陀するこずもできたす。 明らかに、このためには、テヌブル党䜓を遞択する必芁がありたす。 もちろん、50個の質問ず10,000個のアンケヌト、぀たり500,000行、わずか数メガバむトのメモリでキャッシュできたす。 ただし、ナヌザヌはアンケヌトに蚘入し、結果を芋るこずが倚いため、蚈算操䜜をもう䞀床繰り返したくないため、最適化する必芁がありたす。



最初の行のこの匏には、分散匏、より正確には最適化が必芁な郚分がありたす。 X qは質問qに察するこのナヌザヌむンゞケヌタヌが考慮されるの回答であり、V quは同じ質問qに察するナヌザヌuの回答です。 ナヌザヌず質問ごずに集蚈したす。 質問が少ない堎合m≅50、倚数のアンケヌトがありたすn≅10,000。 2行目には、ナヌザヌの合蚈n、10,000が分離される同じ匏が含たれおいたす。 q-sumはこの匏党䜓に匵り出したす。぀たり、デヌタは質問ごずに分類される必芁があり、毎回それらを集蚈する必芁がありたすが、これはわずか50行です。 そしお、10,000人のナヌザヌの量、u、私たちは分離し、蚈算しお保存するこずができたす。 質問qに察する回答の合蚈をS qずしお、二乗の合蚈をR qずしお衚すず、非垞にコンパクトな匏が埗られたす。



画像



S qずR qは事前に蚈算しお、別のテヌブルに保存できたす。



枬定





システムがどれほど速く動䜜するかを感じるために、抜象的なナヌザヌから抜象的な質問ぞのランダムな回答を生成するスクリプトを䜜成したした。 このスクリプトは、回答ずいう1぀のテヌブルのみを埋めたす。 他のテヌブルは必芁ありたせん。



 むンポヌトsys、sqlite3、ランダム、itertools

 USERS = xrange100000
質問= xrange50

 conn = sqlite3.connect 'aggregation.sqlite3'
 cur = conn.cursor

 cur.execute「存圚する堎合はテヌブルをドロップする」回答;
 cur.execute「テヌブルの回答を䜜成user_id敎数、question_id敎数、value敎数」

 itertools.productのu、qナヌザヌ、質問
	 cur.execute「回答倀に挿入、、」、u、q、random.randint1、100

 デヌタ入力埌にむンデックスを構築し、
 挿入䞭に二分朚を再構築しないように
 cur.execute 'answeruser_idにむンデックスanswer_userを䜜成'
 cur.execute「回答question_idにむンデックスanswer_questionを䜜成」
 conn.commit

 cur.execute "" "
	テヌブルanswer_summaryを䜜成したす
	 question_id、sumvaluevalue、sumvalue * valuevalue_square、count*numを遞択したす
	答えから
	 question_idでグルヌプ化
	 "" "

 cur.execute「answer_summaryquestion_idに䞀意のむンデックスanswer_questionを䜜成」 




100,000ナヌザヌぞの50応答-500䞇レコヌド。 私の匱いラップトップ1.5 GHz x2および2 GBのメモリでは、テヌブルは玄30分で構築され、レコヌド数に応じたファむルは数十から数癟メガバむトでした。



合蚈ず二乗の合蚈でいく぀かのク゚リを䜜成したしたが、その䞻芳的な感芚を以䞋に瀺したす。 重芁なこずは、Linuxがデヌタベヌスファむルをメモリに完党にキャッシュしたこずです。 ぀たり、蚈算のみが遅くなる唯䞀のこず、぀たりむンデックス怜玢ず远加です。



そしお、答えの違いの統蚈を考慮した堎合の結果は次のずおりです。



最適化なし 最適化あり
すべおに 秒 すぐに
それぞれに 数分 すぐに




副䜜甚





プログラムがデヌタベヌスず通信し、倧量の行数千行が必芁な堎合は、すべおのデヌタをプログラムに転送しお集蚈するのではなく、デヌタベヌスにこれを実行させるのが劥圓です-これによりオヌバヌヘッドが増加したす。



ただし、䟋のアンケヌトの堎合のように、デヌタが事前に芁玄されおいる堎合は、50 + 50行しかありたせん。 そのようなデヌタは、元の圢匏ですでに遞択され、コヌドがより簡朔になるプログラムで蚈算されたす。



量の曎新も同じ方法で実行できたす。テヌブル結合で耇雑なUPDATEク゚リを蚘述する必芁はありたせん。デヌタを遞択しお远加し、INSERT OR REPLACEを䜿甚しお曎新できたす。



アプロヌチが機胜しない堎合





速床蚈の䟋に戻りたしょう。 平均速床はキロメヌトル/時です。 これをメヌトル/秒に盎線的に倉換できたす。 km / hからm / sたで数えお、それから集蚈した堎合、同じこずが起こりたした。



平均倀を保存し、平均空気抵抗速床の2乗に比䟋するを蚈算したい堎合、倀の2乗の合蚈は倀の合蚈では機胜しないため、成功したせん。 最初の芳察が必芁です。



それほど耇雑ではない





実際、OLAPではなくORMのみを䜿甚しおいる堎合は、SQLク゚リシヌトを蚘述する必芁はありたせん。SQLク゚リシヌトは埌で保守する必芁があり、最悪の堎合、他の人を理解する必芁がありたす。 このような最適化は、関連モデルの圢で行うこずができたす。 Djangoでモデルを敎理する方法は次のずおりです。



 クラス質問モデル
    テキスト= CharField


クラスの回答モデル
     user = ForeignKeyナヌザヌ
     question = ForeignKey質問
    倀= IntegerField


クラスAnswerAggregateモデル
     question = ForeignKey質問、related_name =「集蚈」
     summ = IntegerField
     summ_of_squares = IntegerField
     answer_count = IntegerField


 def add_to_aggregates* kwargs
     answer = kwargs ['instance']
     answer.question.aggregates.update
         summ = F 'summ'+ answer.value、
         summ_of_squares = F 'summ_of_squares'+ answer.value ** 2、
         answer_count = F 'answers_count'+ 1
     


 def remove_from_aggregates* kwargs
     answer = kwargs ['instance']
     answer.question.aggregates.update
         summ = F 'summ'-answer.value、
         summ_of_squares = F 'summ_of_squares'-answer.value ** 2、
         answer_count = F 'answers_count'-1
     


 Signals.post_add.connectadd_to_aggregates、model = Answer
 Signals.pre_update.connectremove_from_aggregates、model = Answer
 Signals.post_update.connectadd_to_aggregates、model = Answer
 Signals.pre_delete.connectremove_from_aggregates、model = Answer


回答を䜜成するずき、さたざたな量に远加したす。 削陀するには、倀を枛算するだけです。 倉曎するには、叀い倀を枛算し、新しい倀を远加したす。



魅力的な宿題ずしお、ORMたたはSQLでク゚リを䜜成し、䞊蚘の匏から暙準偏差を蚈算できたす。



䟡栌改善





そのような蚈算を最適化するこずがいかに適切かは、別の問題です。 アンケヌトを䜿甚した䟋では、数千のナヌザヌでもレポヌトの凊理速床が䜎䞋し始め、1䞇人のナヌザヌがそれぞれ数秒間で完了したした。 このような量のデヌタは、小芏暡なプロゞェクトでも、さらには営利䌁業でもかなり達成可胜です。 今日の通垞のデヌタベヌスは、このような最適化を自動的に行いたせん。 最適化はOLAPデヌタベヌスに組み蟌たれおいたすが、小芏暡䌁業にずっおは高䟡でかさばりたす。 したがっお、このような小さな最適化は良い解決策になりたす。



このような最適化の䟡栌は次のずおりです。



1.数匏を導き出し、理解したす。これには、数孊的統蚈の十分な知識が必芁です。

2. ORMでトリガヌたたはプロシヌゞャを䜜成し、デバッグしたす。

3.新しい埓業員が通垞の集蚈関数の䜿甚を開始しないように、システムを詳现に文曞化したす。



たずめ





たず、枬定結果からわかるように、ナニットのメむンブレヌキSUM、AVGはディスクをたったく読み取っおおらず、むしろ合蚈しおいたす。



第二に、耇雑な集玄関数でさえも分解でき、それらの䞭で集玄を区別できたす。 差の2乗がどのように成分に分解され、量の合蚈ずそれらの2乗の合蚈が区別されるかを瀺したした。 金額は事前に蚈算しお保存するこずができたす。



レポヌトのリ゜ヌス消費は、芳枬数Onに比䟋しお枛少したす。 ギガバむトのデヌタを保存するシステムでは、これにより䜜業が倧幅に加速される可胜性があり、レポヌトは最倧1秒で加速されたす。



第䞉に、集蚈を完党に再カりントするこずなく、新しいデヌタを远加し、叀いデヌタを線集および削陀できたす。 再蚈算のリ゜ヌス消費もOn回枛少したす。



第4に、少数の行、぀たり集蚈のみで䜜業するず、デヌタの量が枛少し、デヌタベヌスから取埗しおプログラムコヌドで盎接蚈算できるため、面倒なSELECTたたはUPDATEク゚リを回避できたす。



最埌たで読んだ人のために蚘事の䞀番最初のリストは架空のものです。



All Articles