予想アルゴリズムは・・・
そんなに難しいことを考えているわけではありません。
出走馬の過去5Rを点数化し、競走馬の能力指数のようなものを算出し、順位付けします。
これをもとに、一定の買い方で馬券を買うというものを作ろうと考えました。
能力指数的なものでいえば、JRA-VANのデータマイニングという機能があります。
まずは、それを使って順位が自分のソフトで出力できるか試してみました。
1日単位で順位データをCSVに出力できれば、自動購入ソフトに取り込めますし、それを使えばバックテスト(過去のレースから成績を確認)できるので、能力指数の精度を高められます。
データマイニングを指数として作成するのは1日当たり10秒もかからず算出できました。
なので、これはいけるな…と。
独自指数を作るために過去レースデータを取り込もうとすると…
ここまではよかったんですよね。。。
各レースの出走馬の直近5走のレースデータを呼び出して、点数付けする。
これをまとめて競走馬に順位をつけていけばはいOK
の、はずでした。
まずは直近5走のデータを呼び出すプログラムを作って、ばっと一覧を出そうと試みたところ、ここでタイムアウト発生。
PHPのタイムアウトを伸ばしてみた。180秒=3分。
これで出力できなきゃお話になんない。
しかし、それでもタイムアウト。これは困った。
1日で3分も10分もかかるようでは、過去1年間のデータを出力していったん取り込んで検証、、、なんてことも全くできないじゃないか。これは困った。
DBのチューニング
どう見ても明らかにDB、SQL文の問題に見える。
何が悪いのかも今のところ見えていない。
しかしセオリー通りチューニングを行いながら、少しずつでもパフォーマンスアップを狙うしかないだろう。
インデックス
DBパフォーマンスアップの第一歩はインデックスだ。
Where句やorderbyで使うカラムにインデックスをかけるかかけないかでパフォーマンスが大きく変わってくる。
面倒であまりやらないのだが、はやり数百万件という馬毎のレース情報はインデックスをかけていかないと早くならないだろう。
今回は今Where句やOrderByで使っているカラムをすべてインデックスをかけた。
しかしながら、パフォーマンスは上がらない。
そこで、古馬重賞レースに出走予定の競走馬1頭を狙い打ってSQL文を実行してみたところ、0.01秒程度で過去5レースのデータを算出できた。
あれれ、、この秒数なら1日の全出走馬の過去5Rのデータを出力するくらいなら、10秒もかからない気がするが。。。
なぜだ。。。
原因がわかってきた。
パフォーマンス向上のために、Limitをかけているのだが、単純にLimit 0,5としているのだが、競走実績が5件に満たない馬がいる。
例えば新馬は競走実績が0件だし、5走していない競走馬なんて死ぬほどいるだろう。
新馬でこのクエリを発行すると30秒近くかかってデータなしとなる。
そりゃ、8頭立ての新馬戦があればもうその時点で4~5分近くかかるんだから1Rすらも結果を出せないだろう。
なるほど分かった。要は件数か。
でもどうしたら…
理由は分かったのだが、だからってどうやってこの馬は競走実績が0~4戦しかありませんよっていうのを認識するのか。これがまた問題だ。
SQL側だけでできないのならPHP側で何かできないか考えてみた。
そうか。
mysqli_num_rowsで、件数を見てみればいいのか!
と、さっそくレコード件数を出力する関数でSQLをたたいてみたが、、、
わかる人は分かるが、SQL文が変わったわけではないので、結局遅い。。。
だめだ、、、わかんない。。。
一度冷静になろう。
どうすればいいか考えながらコードをきれいにしよう。
クウォート【'】をはしょった個所がいくつかあったから書くべきところはクウォートをちゃんと書いておこう。
そして、SQLを一度シンプルにしよう。
データの区分コードがあって、成績発表の区分と出馬表発表の区分がある。
今回のレースの予想をするためには過去レースが必要なので、成績発表済みのレースだけに絞りたくてこの区分で成績発表済みのレースに絞っていたのだが、これはLimitで新しい順に並べた後に、Limit 1,5とすることで、最新レースの1個前からという処理ができるから一度レース区分での絞り込みをなくそう。
競走馬コードのみで絞ってとりあえず5件出力するようにしよう。
あれ?なんか早くなった気がする、、、
いやまて、これは重賞出走古馬だから、さっきも早かった。。。さっきより少し早いけど、それはMySQLのキャッシュかもしれないしね。。。出走経験のない新馬で一回やってみよう。さっきは30秒だからね。。。
あれ、、、0.01秒で出力したな。。。
あれ、、、何が違ったんだ???
まとめ~爆速クエリを作るために必要なこと~
さて、前文までで行ったことはすべて書きましたが、その後、削除したデータの区分の絞り込みも、Limitも完全に復活させましたが、1日分のデータを呼び出すのに2秒とかからなくなりました。
どこで早くなったかわかりますか?