2009/03/18
久しぶりのソフトウェアねた。 
仕事で作成中のソフトウェアで、ガリガリと検索や更新を行うわけはないし、さほど複雑なデータ構造を扱うわけではないが、データ量はそこそこあるのでSQLで検索したい、というものがあり、SQLite を使ってみる事にした。 
 SQLite 
開発は Linux 上で行っていたのだが、コンパイル、インストールとも、すんなり成功。 
いい感じだ。 
ただ、開発時に問題が浮上。 
SQLite は、トランザクションを開始すると、データベースそのものがロックされてしまう。 
更新中のテーブルとは関係ないテーブルへのアクセスもロックされてしまうし、INSERT、UPDATE、DELETE だけでなく、SELECT などの単純な問い合せもロックされてしまう。 
つまり、トランザクションを開始すると、他からのアクセスを完全に受け付けなくなってしまう。 
タイムアウト時間を長くして、トランザクションの処理が完了するまで後追いの処理を待たせれば問題はないのだが、今回作成しているソフトウェアでは、20万件弱のレコードを一気に投入する処理があるので、後追いの処理を待たせ続けるわけにはいかない。 
仕方がないので、トランザクションを使わずに、自動コミットがオンの状態で1件づつ書き込んでいくようにプログラムを変更してみた。 
すると...処理が遅い。とても遅い。 
20万件弱のレコードの投入に何十分もかかる。 
どうも、SQLite は、INSERT や UPDATE を連続してを実行するのは苦手なようだ。 
自動コミットがオンの状態で1件づつ処理すれば、データベースがロックされてしまう問題は解消できるが、20万件弱のレコードの投入に何十分もかかってしまうのはいただけない。どうするか。 
ロックも回避できて、かつ、実用上、問題とならない速度を出すには...折衷案的な実装であるが、1000件くらいづつの単位でトランザクションとコミットを繰り返し、全件をブロック単位で書き込むようにしてみた。 
うん、成功。 
劇的に速度があがった。 
開発環境での動作確認が終わり、実機上に移してみる。 
そこで、また新たな問題が。 
実機は Solaris 8 なのだが、普通にコンパイルして実行してみると、バスエラーが発生し、コアダンプして落ちてしまう。 
ぐぉ...。 
何が問題だ? 
gcc の問題か? 
gcc をアップグレードしてみる。 
バスエラー。(T_T) 
逆に、ダウングレードしてみる。 
やっぱりバスエラー。(T_T)(T_T) 
むー。 
コンパイラの問題ではなさそうだ。 
SQLite の FAQ を探ってみる。 
あった。 
 Ticket 3553: Bus error with 32bit build on Solaris SPARC 
ん~、どうも、構造体のアライメントの変化によって、正しく構造体のメンバにアクセスできず、バスエラーになるらしい。 
パッチも準備されている。が、今回使用しているバージョンは、3.6.10 なのだが、このパッチは3.6.6.2 用。 
当然、3.6.10 には適用済みだよなぁ...。 
パッチをダウンロードして、当該ファイルと目視で付き合せてみると、確かにパッチは適用された状態になっていて、問題は解消されているように見える。 
どうも、問題はここではない。 
じゃぁというので、ダメ元で、アライメントで問題が起きているという事は、おそらくコンパイラが構造体のパッキングを最適化しようとしておかしな事になっているのではないかと推測。 
試しに、Makefile を編集して gcc の最適化オプションである -O2 を削除してコンパイルしてみる。 
実行してみると、おぉ、バスエラーは発生しない。 
これなら、とりあえず問題はなさそうだ。 
が...最適化なしでコンパイルしたものを使うのはちょっとヤダなぁ。 
前述の資料によれば、3.6.6.2 では、バスエラーの問題は解消されている事になっているので、試しに 3.6.6.2 をコンパイルしてみる。 
実行してみると、おぉ、バスエラーは発生しない。 
きちんと問題は解消されているようだ。 
では、ひとつ上の 3.6.7 をコンパイルしてみる。 
バスエラー。(T_T) 
むぅ...。 
3.6.6.2 で解消したはずのアライメントの問題が、3.6.7 にメジャーアップしたときに、新しく作成したソースの部分で再発した感じだろうか。 
それとも、3.6.7 からは、Solaris 8 の対応が切られてしまったのだろうか。 
で、結局、最適化なしでコンパイルする 3.6.10 を使うか、最適化ありでコンパイルする 3.6.6.2 を使うかの選択になった。 
迷ったのだが、動作実績がより多いであろう、3.6.6.2 の方を選択する事にした。 
開発環境上と実機上の SQLite を 3.6.6.2 にダウングレードし、動作確認。 
一件落着。 
はふぅ、苦労した。 
 
 
 
投稿者 zunbe : 2009/03/18 10:00:00 
 
	| 
	トラックバック
	 | 
	
	〔http://blog.zunbe.com/mt/mt-tb.cgi/1016〕
	 | 
 
 
 
 
 
 |