pyodbcを使用してMicrosoft Accessデータベースとやり取りするpythonプログラムを作成しました。データベースには、井戸(約630万)の測定値を含むテーブルが含まれています。"システムリソースを超過しました" pyodbcでSELECTクエリを実行するとODBC MS Accessドライバからのエラー
プログラムの基本的な作業の流れは、化学物質のリストを取得することです。次に、すべての化学物質について、その化学物質のデータを持つテーブル内のすべてのウェルを見つけるために選択クエリを使用します。各ウェルについて、化学物質のウェルのすべての測定値を含むデータセットをフェッチするために別の選択クエリを使用する。
このデータセットを取得すると、そのデータセットの化学物質とウェルペアの新しい行を作成するために使用される統計が計算されます。これらの新しい行は、それぞれ新しいデータベース表に出力されます。
私はpythonのマルチプロセッシングパッケージを使用して、プログラムがより多くのCPU容量を使用できるようにしています。プログラムには常に、キューからデータを取り出し、入力データベースから新しい別のデータベースに挿入する1つのコンシューマ・プロセスがあります。次に、プログラムには、化学物質をキューから取り出し、処理し、そこにデータを出力キューに追加する様々な量のプロデューサプロセスがあります。
私はおよその長さである化学リスト上のプログラムを実行すると、それは時々エラーになります。
Starting: 01027
Failed on 01027 when selecting wells for chemical.
Failed. Wells processed: 371693
Traceback (most recent call last):
File "C:\Users\jrutledge\Desktop\well_trend_processor_python_2016\python_processor\well_trends.py", line 230, in read_data_sets_into_queue
raise e
これは96の化学物質のリストのためではなく、10以下のために少なくとも一回(時にはそれ以上)が起こります、どこが切れているか分からない。このエラーメッセージの意図された原因は、あまりにも多くのメモリを消費するクエリを実行しているようですが、これはここでの結果ではないようです。 1つの理由は、それが間違っている化学物質が、試み間で一貫していないということです。さらに、化学物質の不足している化学物質を含む小さなリストを実行すると、エラーなしで処理されます。
問題は、私は化学のために井戸を選択していたときに起こっているようだ:
# Find each well that has samples of this chemical
wells_cursor = measurement_db_chemical.cursor()
sql_string = """SELECT DISTINCT {0}.Well_ID, PSCODE, STAID, Status
FROM {0}
LEFT JOIN {1}
ON {0}.Well_ID = {1}.Well_ID
WHERE STORE_NUM = ?""".format(
well_records_table_name, well_sites_table_name)
try:
wells_cursor.execute(sql_string, chemical.STORE_NUM)
# Close db connection if error, outer try will close connection
except Exception, e:
print ('Process {}: Failed on {} when selecting wells for chemical.'.format(process_number, chemical.STORE_NUM))
raise e
このSQLクエリは道より頻繁に、それはエラーが発生するよりも、問題なく実行されるので、それはないの前に言ったように、が、 SQLにエラーがあるようです。しかし、これはプログラムが作成する最も集中的なクエリであり、リソースを超えるものであることが理にかなっています。
この問題は、プログラムの挿入部分を削除すると解決しません。このようにして、通常どんなこともしますが、統計を計算した後に新しいテーブルに挿入することはありません。
DBへの接続をあまりに長く開いたままにしておけば、何とかガーベッジメモリなどが蓄積されている可能性があると思っていました。これにより、pythonプログラムを各化学物質のデータベースへの新しい接続を開き、その化学物質の処理が完了したら閉じます。しかし、問題は解決しません。
特に、私がそれをどのように実行しても、総メモリ使用量は60%を超えることはありませんので、それは問題ではないと思います。
また、データベースのサイズは800 MB未満です。これは、MS Accessデータベースの2 GBのサイズ制限付近ではありません。
私は1つのプロセスでプログラムを実行していました。これは、誰かが照会を選択しても、ODBCドライバーが処理するにはリソースがあまりにも高価ではないかもしれませんが、同時に複数の実際に高価な照会が実行され、ドライバーがそのリソース制限に達する可能性があると考えています。私は今、プログラムを修正し、python RLocksを追加しました。データベース内でSQLクエリが実行されているので、一度に1つのプログラムしかデータベースから読み取れないため、この問題は解決されません。昨日、4つのプロセスが正常に完了して実行されましたが、この問題は修正されましたが、今日では選択されたウェルのクエリで同じエラーが発生しています。
は(私はそれが解決策だと思ったとき、私は答えとしてこれを掲示し、今それを削除してしまった)。またないこの方法のCPU使用率を使用した場合のプロセスが1を待つ必要があるため決して80%の上に行かないこともう1つはクエリに使用され、それでもエラーが発生します。つまり、dbとのODBCドライバのインタフェースには、使用上のコード化された制限が必要です。
このエラーの原因は何だと思いますか、それを修正する方法を教えてください。
もっと多くのコードをご覧になりたい場合は、その部分がたくさんあることを教えてください。
* System Resource Exceeded *が投稿に表示されないため、完全なトレースバックを投稿できますか?また、これはPythonエラーではなく、MS Accessエラーです。通常、このメッセージには、複雑なクエリ、NULL値の処理、予約語、および構文項目が含まれます。 – Parfait
また、テストとして、MSAccess.exe内で同じ操作を実行できますか(Officeプログラムがある場合)? LEFT JOINのDISTINCTはあまり最適化されていません。 – Parfait
@Parfait私はAccessでよく選択されたクエリを実行し、正常に動作します。私は全体の操作を実行する方法がわかりません:100個のクエリを連続して実行しています。それを手動で行う以外は、クリックするのに1時間以上かかります。クエリはpyodbcインターフェイスを介してすべての化学物質のために働いているだけでなく、すべてが一度に機能するわけではありません。 –