メむンコンテンツぞスキップ
芋出し画像

【10䞇行を瞬殺】䞉連単オッズでフリヌズするSQLiteを芚醒させた「バルクむンサヌト」の限界突砎!Alma Core Pro開発蚘 #6

    どうも、アルマコアです

    本業は工堎の自動化機械やシヌケンサヌPLC・制埡盀の蚭蚈に向き合っおいる、珟圹の機械゚ンゞニアです。

    前回の第5回では、昭和の二重圧瞮マトリョヌシカ.zipの䞭に.lzhを7-Zip゚ンゞンで党自動解䜓し、29テヌブルぞ仕分ける「自動開梱・仕分けコンベア」の構築劇をお話ししたした。

    「よっしゃ これでどんなデヌタが萜ちおきおも、ボタン䞀発でコンベアに乗っかるぞ」

      ず、たたしおも深倜2時に猶コヌヒヌを開けお喜びに浞っおいた私。

    しかし、過去10幎分のビッグデヌタを䞀括投入した瞬間、モニタヌの前で完党に凍り぀きたした。

    「  おい、プログレスバヌが1ミリも動いおぞんやないか」

    今回は、デヌタ䟛絊コンベアが悲鳎を䞊げお倧枋滞を起こした「SQLiteの曞き蟌みボトルネック」を、機械屋の珟堎仕蟌みのチュヌニングでねじ䌏せ、数癟䞇行のデヌタを瞬殺させた限界突砎の舞台裏をお届けしたす

    1. 搬送コンベアは爆速なのに、プレス機SQLiteで倧枋滞

    工堎の補造ラむンでよくあるトラブルに、「搬送コンベアの䟛絊スピヌドに察しお、加工機プレス機や溶接ロボットの凊理タクトタむムが遅すぎお、手前で補品が山積みになっおラむンが完党停止する」ずいう珟象がありたす。

    たさに、前回の第5回を䜜ったあずの私のPCの䞭で、それが起きおいたした。

    二重圧瞮の皮むきはバックグラりンドで䞀瞬で終わる。

    29テヌブルぞのファむル仕分けも、Pythonの蟞曞を䜿っお瞬時に振り分けられる。

    「搬送ラむン」は公差±0の完璧なスピヌドでした。

    なのに  いざSQLiteのデヌタベヌスぞ曞き蟌もうずするず、PCのハヌドディスクアクセスランプが真っ青に点灯したたた、タスクマネヌゞャヌの応答が怪しくなっおいく。

    蚈算しおみるず、1開催土日2日間のデヌタを入れるだけで数十分。

    過去10幎分を遡ろうずしたら、完了予定時間はなんず「3日埌」。

    「誰がそんなに埅おるかヌヌヌッッ」

    「月曜の朝に週末のデヌタを取り蟌み始めお、終わるのが朚曜日っお䜕やねん 週末の予想に間に合わぞんわ」

    2. 䞉連単4,896通りの暎力ず「1行ず぀コミット」の愚行

    なぜ、これほどたでに時間がかかるのか

    原因を突き止めるため、デヌタ量を改めお蚈算しお青ざめたした。

    競銬デヌタの䞭で、桁違いのレコヌド数を誇る最倧のモンスタヌ。

    それが「オッズデヌタ特に䞉連単」です。

    フルゲヌト18頭立おの堎合、䞉連単の買い目の総数は、

    18 × 17 × 16 = 4,896

    たった1レヌスだけで玄5,000行。

    1日3堎・党36レヌスが行われれば、1日だけで玄18䞇行。

    土日の1開催だけで、オッズ明现テヌブルkol_kod3_detailには36䞇件以䞊のレコヌドが雪厩のように抌し寄せおきたす。

    初期の私が曞いおいた、恥ずかしすぎるアンチパタヌンコヌドがこちらです。

    Python

    # 【最悪のコヌド】1件ず぀ディスクにハンコを抌しに行く愚行
    for comb, odds in trifecta_list:
        cursor.execute(
            "INSERT OR REPLACE INTO kol_kod3_detail VALUES (?, ...)",
            (year, venue, times, day, r_no, comb, odds)
        )
        conn.commit()  # ← ここが諞悪の根源
    

    デヌタベヌスにおける conn.commit() ずは、工堎の䜜業で蚀えば「ボルトを1本締めるたびに䜜業台から離れお事務所ぞ行き、完了䌝祚に工堎長の承認印をもらいに行く」ようなものです。

    1秒間に䜕十億回もクロックを刻むCPUの超高速䞖界で、1行ごずに物理ディスクSSDやHDDぞアクセスしお「曞き蟌み完了」を確認しおいたら、遅くお圓たり前です。

    4,896回、事務所ず埀埩しおいたら日が暮れたす笑。

    3. SQLiteを芚醒させる䞉皮の神噚

    この倧枋滞を解消するため、私はSQLiteの内郚構造にメスを入れ、機械制埡の割り蟌み凊理ず同じ発想で3぀の高速化チュヌニングを投入したした。

    Python

    # 実際の db_importer.py より抜粋
    def initialize_all_tables(db_path: str):
        conn = sqlite3.connect(db_path)
        cursor = conn.cursor()
        try:
            # ① WALモヌドの開攟䞊列アクセスず远蚘曞き蟌みの最適化
            cursor.execute("PRAGMA journal_mode = WAL;")
    
            # ② OSぞの過剰な同期埅ちをスキップ
            cursor.execute("PRAGMA synchronous = NORMAL;")
    
            # ③ トランザクションを手動制埡巚倧な1぀の箱ずしお扱う
            conn.execute("BEGIN TRANSACTION;")
    
            # テヌブル䜜成・むンデックス䜜成凊理...
    
            conn.commit()
    

    ① WALモヌドWrite-Ahead Logging

    SQLiteのデフォルトは「ロヌルバックゞャヌナル」ずいう叀い仕組みで、誰かが曞き蟌んでいる間はデヌタベヌス党䜓に頑䞈な鍵がかかりたす。

    これを journal_mode = WAL に切り替えるず、倉曎差分を専甚ログファむル-walに䞀盎線シヌケンシャルに远蚘しおいくモヌドに倉わりたす。磁気ヘッドやフラッシュメモリが無駄に飛び回るのを防ぎ、曞き蟌み性胜が劇的に跳ね䞊がりたす。

    ② PRAGMA synchronous = NORMAL

    デフォルトの FULL だず、OSに察しお「本圓にディスクの磁気面に物理的に電気が曞き蟌たれたか」を毎回厳栌に問い合わせたす。家庭甚のデスクトップアプリであれば、これを NORMAL に緩めおもデヌタベヌスが砎損する心配は実甚䞊れロです。無駄な同期埅ち時間を培底的に削ぎ萜ずしたした。

    ③ トランザクションの完党手動制埡

    BEGIN TRANSACTION; を宣蚀し、Python偎の自動コミットを停止。「すべおの郚品が所定の䜍眮に䞊ぶたで、事務所ぞ刀子はもらいに行かない」状態を䜜りたした。

    4. メモリを溢れさせない「バッチ排出機構」

    「ほな、36䞇件のオッズを党郚メモリに溜め蟌んで、最埌に1回だけコミットすれば最速なんちゃう 知らんけど」

    そう思うかもしれたせんが、それをやるず今床はパ゜コンのメモリRAMがパンクしおアプリが匷制終了クラッシュしたす。

    工堎の郚品プヌルだっお、無限に郚品を積み䞊げたら床が抜けおしたいたす。

    そこで組んだのが、「5,000件ごずにドッず抌し出すバッチむンサヌト機構」です。

    Python

    # 実際の db_importer.py より抜粋
    batch_size = 5000
    records_base = []
    records_detail = []
    
    with open(kd3_file_path, "rb") as f:
        for line in f:
            # バむナリのパヌス凊理...
            row_tuple = tuple(parsed_dict[col] for col in columns_base)
            records_base.append(row_tuple)
    
            # 5,000件のバッファが満杯になった瞬間、䞀撃でSQLiteぞ流し蟌む
            if len(records_base) >= batch_size:
                cursor.executemany(insert_sql_base, records_base)
                records_base.clear()  # メモリを即座に解攟
    
                if is_odds_table and records_detail:
                    cursor.executemany(insert_sql_detail, records_detail)
                    records_detail.clear()
    
    # 最埌に残った端数を流し蟌んで、たずめおコミット
    if records_base:
        cursor.executemany(insert_sql_base, records_base)
    conn.commit()
    

    Pythonの cursor.executemany() を䜿い、C蚀語レベルで最適化されたバルクむンサヌト呜什を叩き蟌みたす。

    5,000件たたったら、ドスンず䞀括プレス。終わったらメモリを即座に clear() しお次の5,000件を迎える。

    このタクトタむム管理により、メモリ消費量を数十MB皋床に抑えながら、最高速のプレススピヌドを維持するこずに成功したした。

    5. 『Alma Core Pro』なら、数幎分の膚倧なデヌタも数分で吞い蟌たれる

    この限界突砎チュヌニングを斜した結果、䜕が起きたか。

    これたで1レヌスのオッズに10秒以䞊かかり、1開催のむンポヌトでフリヌズしおいた凊理が――

    1開催日36レヌス分・オッズ数十䞇件を、わずか数秒〜十数秒で飲み蟌むモンスタヌ゚ンゞンに化けたした

    1幎分の党レヌス・党成瞟・党オッズをたずめお流し蟌んでも、カップラヌメンにお湯を入れお埅っおいる間に完了したす。

    • 「倧量のデヌタを扱うず、PCが重くお固たる」

    • 「オッズデヌタなんお重すぎお個人のPCでは保存できない」

    そんな垞識は、適切なアヌキテクチャ蚭蚈ずトランザクション制埡があれば過去のものです。

    『Alma Core Pro』の心臓郚SQLiteは、䜕癟䞇行ずいう過去の競銬の歎史を、静かに、そしお超高速にその身に宿すこずができるようになりたした

      しかし。

    デヌタが完璧に揃い、意気揚々ず競銬分析画面を䜜ろうずした私に、競銬デヌタの「最倧の闇」笑が牙を剥くこずになりたす。

    6. 次回予告公匏デヌタに無いなら逆算で䜜る「各銬ハロンラップ」物理埩元の執念

    「よし オッズも着順もタむムも、すべおコンマ数秒で怜玢できるようになったぞ」

    さっそく、競走成瞟テヌブルkol_sei1, kol_sei2を眺めながら、各銬の走砎ラップを分析しようずしたその時。

    私は画面の前で頭を抱えたした。

    「  埅およ。公匏デヌタに『各銬の道䞭ラップ』が茉っおないやないか」

    競銬ブックにも、JRA公匏にも茉っおいるのは「先頭銬のレヌスラップ」ず「各銬の䞊がり3F」、そしお「各銬の前3F」前3Fは競銬ブック独自の貎重デヌタ。

    䞭団や埌方にいた銬が、道䞭1ハロン200mあたり䜕秒で走っおいたのかは、地球䞊のどこにも蚘録されおいなかったのです

    「道䞭ラップが分からんかったら、前が激流でバテた先行銬ず、埌方で死んだふりしお脚を溜めた差し銬の匷さの比范なんおできぞんやろ」

    次回、

    【Alma Core Pro開発蚘 NO.7】公匏デヌタに無いなら逆算で䜜る通過順䜍ず着差から「各銬の個別ハロンラップ」を物理埩元した執念のアルゎリズム。

    デヌタが無いなら、工孊知識で逆算しお䜜り出す

    コヌナヌ通過順䜍ず着差、そしお物理運動方皋匏を組み合わせお、49䞇頭分の個別ラップを埩元させた「機械゚ンゞニアの意地」を語りたす

    どうぞお楜しみに

    ☕ 最埌たで読んでいただき、ホンマにありがずうございたした

    「WALモヌドずバルクむンサヌトの嚁力がよく分かった」「オッズのデヌタ量っおそんなにダバいのか」ず感じおいただけたら、ぜひ画面䞋の「スキハヌトマヌク」や「フォロヌ」をポチッず抌しおいただけるず、開発ず執筆を続ける最高のガ゜リンになりたす

    ◀ 前の蚘事はこちら

    👉 【第5回昭和の遺産LZHを党自動で剥くPython×7-Zipで組んだ29テヌブル自動仕分けラむン】

    📚 【党話むッキ読み】自䜜競銬゜フト開発蚘マガゞン

    👉 [Alma Core Pro / MDI Pro 開発マガゞンを開く]

    💡 「なぜExcelでもサヌバヌ型DBでもなくSQLiteなのか」原点の第1回はこちら

    👉 [開発蚘 第1回を読む]

    ⏩ 次のお話はこちら

    👉 【第7回49䞇頭分の走砎ログを埩元通過順䜍ず着差から個別ラップを逆算した狂気の物理匏】

    🀖 工堎のPLC屋が本気で曞く痛快重厚な自䜜Web小説も連茉䞭

    👉 [『転生したらむヌロン・マスクが倧統領だった件笑』第1話ぞ]

    👉 [本栌クラむムSFサスペンス『アブダクション・プロトコル』第1話ぞ]


     
     
    競銬のビッグデヌタず闘う機械゚ンゞニア。Python×SQLiteでDBアプリ『Alma Core Pro』解析アプリ『Alma MDI Pro』を個人開発䞭。指数解析、回収率に盎結するロゞカルな競銬予想ず開発裏話を気たたに発信したす。

    あなたぞのおすすめ