中央競馬の予想や購入したもののメモなどを書いて行こうかと。まあ、個人的なメモ的なブログです。
[PR]上記の広告は3ヶ月以上新規記事投稿のないブログに表示されています。新しい記事を書く事で広告が消えます。
Windowsでのプログラミングの基本をVisual Basicで始めたのはもう30年近く前になるのかな~^^; ループで回して長い処理する時にはDoEvents入れよう的な習慣が染みついてたと思うんですが、それは昔の話? まあ、当初Windows2000かWindowsNTだったのかな?OSがMS-DOSでその上に乗るWindows Ver2.1辺りから使ってますが、当初はマルチタスクすら完全じゃなかったが、今ではしっかりとOSが頑張ってくれてる(?)ので、あまり意識する必要が無くなってるのかな?
4万件程度のレコード追加処理が非常に時間が掛かっており、バルクインサートまで試してみたのですが、一向に改善されなくて、ボトルネックを探ししてたんですが、SQLite関連全てコメントアウトして処理しても10%程度しか時間が減らず、ループの根本的な改善が必要なのかな~っと見てたんですが、
Application.DoEvents();
が時間食ってましたorz 4万件の登録で80秒がこれ削るだけで7秒とかに改善しました。ただ、当たり前ですが、その見返りとして、ステータスバーに登録してるレコードの簡単な表示したり、ログに出力してるんですが、これらがステータスバーの表示はされず、まあ、でもプログレスバーは動いてくれているのでハングではなく処理してるのは視覚的に分かるのはありがたいです。この辺りがOSがきっちりとマルチに動作してるおかげなんですかね? でも、ログの表示もリアルタイムじゃなく行毎にだったり、ログをスクロールバックして前を見ようとしても反応してくれないし、まあ、そもそも、アプリをクリックしても最前列に来ないとか...
代わりのってか、DoEventsで処理させていたものを個々に必要な部分のみ行う修正をして行かなきゃならなくなりました。フルセットアップなり更新処理なりの間に必須な事かは別として、可能な範囲はやってみたいと思います。
1レコードに1,700以上の項目があるテーブルの登録処理に時間が掛かってたんですが、このやり方を改善してみました。これまでは
cmd.Parameters.Add(new SQLiteParameter("@PARA", value));
って感じで毎回やってたんですが、事前に
cmd.Parameters.Add(new SQLiteParameter("@PARA", dummy));
とパラメーターは追加しておき、レコード追加時は値のみを
cmd.Parameters[0].Value = value;
として全てのパラメーターが準備出来たら
cmd.Prepare();
cmd.ExecuteNonQuery();
とする事でかなりの時短が出来ました。このテーブルは元ファイルから約2,500レコード分のデータを登録してまして80秒前後掛かってましたが、今回の修正で4秒とか劇的に早くなりました^^
で、全ての修正はまだなんですが、昨夜フルセットアップしてみた所、これまで13時間だったものが半分以下の6時間弱に改善しててほっとしてます。ただ、まだまだ項目数が少ないけど元ファイルから数万レコード分登録するテーブルがあるんですが、これが4万レコードとかだと30秒以上掛かっているのを何とかしなきゃです。接続文字列は今回はデフォルトに戻してフルセットアップしました。これはdatabase is busyのエラーがトラップ出来ずに延々とハマる時があるので、それを回避する為です。
今回の修正を全てに行った後にまたフルセットアップがどの程度まで短縮されるかは分かりませんが、今回程は期待出来ないので何か考えないとダメかも^^;
今朝起きてみると、フルセットアップが終了してました。13時間38分と1時間程度短縮されてました。ここまでの苦労に見合うかは別として、まだまだなのは確かです。ただ、今回の諸々の変更で、データベースファイルのサイズが60ギガ→40ギガにサイズダウン。ん?大丈夫か?って感じです。簡単に検証出来ないので、無事に全てのデータが問題なく登録出来ているかが心配なくらいです。単にこれがMicrosoft.EntityFrameworkCore系の悪事からの解放の結果なら良いのですがね。
データベースファイルサイズが落ちた副産物は最適化が4時間近く掛かってたと思うのが2時間弱で済んでました。まあ、最適化は頻繁にはやらないかとは思うけど、半減してるのはありがたい。
更なる改善と開発を進めるしかないですね。
まだまだ色々と分かってないとは思うけど、データベース新規作成時に指定しておくものと、毎回指定しなきゃなものがある気がする。毎回メモリの指定するとしばらくしてリソース不足のエラーが出始めるので、これは何となく作成時のみにしておく。ジャーナルモードは毎回メモリとかしないと気が付くとジャーナリストファイルが出来てるのを目視出来ます。
PRAGMA JOURNAL_MODE = MEMORY;
PRAGMA TEMP_STORE = MEMORY;
これらは毎回指定する様にしてみました。これで久しぶりにフルセットアップ開始してみたので明日の明け方には終わるのかな^^;
接続文字列指定で出ていたエラーは無くなりましたが、根本的なスピードアップにはなってませんのでまだまだ学習して改善して行くしかないかも。
SQLiteの接続文字列でのdatabase is lockedな問題だけど、なぜ起きているのか不明な感じではあるが、疑わしいのはMicrosoft(笑) そもそも、この会社何? YESかNOかで言えば、確実にNOなんだが、今のPCではってか、今でもlinuxへの逃げやChromeなんかがあるにしてもMS必須なんだよね~orz で、疑ったのは
Microsoft.EntityFrameworkCore.Sqlite
Microsoft.EntityFrameworkCore.Tools
の謎w 中途半端なこれらのおかげで随分と苦労している気がして、今回、新たに別プロジェクトを作成してMicrosoftの妨害を阻止してみました。
System.Data.SQLite.Core
これ1本のみでの開発に挑戦してみようかと作業を進めています。つまり、Migration無しで自力でデータベース構築する訳ですが、まあ、CREATE文を全てのテーブル分用意すれば良い訳ですが、これもまた、かなりの作業です。一番気になっている出走別着度数テーブルの1,700項目超えなんですが、ここは既に済ませ接続文字列で色々テストすると、これまでのdatabase is lockedは消えました^^ でもね、処理スピードは不変orz
それでも、database is lockedの犯人はMicrosoftなのは確定です。