6

データベースに対して SELECT クエリを実行し、〜 33,000 レコードを解析するスクリプトを作成しています。残念ながら、cursor.fetchone()/cursor.fetchall()の段階で問題が発生しています。

私は最初にカーソルを一度に次のように繰り返してみました:

# Run through every record, extract the kanji, then query for FK and weight
printStatus("Starting weight calculations")
while True:
    # Get the next row in the cursor
    row = cursor.fetchone()
    if row == None:
        break

    # TODO: Determine if there's any kanji in row[2]

    weight = float((row[3] + row[4]))/2
    printStatus("Weight: " + str(weight))

(タイムスタンプと渡された文字列を出力する) の出力に基づいてprintStatus、スクリプトは各行を処理するのに約 1 秒かかりました。これにより、ループが繰り返されるたびに (LIMIT 1 または何かを使用して) クエリが再実行されていると信じるようになりました。SQLiteStudio [i]and[/ i] 33,000 行すべてを返します。その速度で、33,000 レコードすべてを処理するには約 7 時間かかると計算しました。

それを待つ代わりに、代わりにcursor.fetchall()を使用しようとしました:

results = cursor.fetchall()

# Run through every record, extract the kanji, then query for FK and weight
printStatus("Starting weight calculations")
for row in results:
    # TODO: Determine if there's any kanji in row[2]

    weight = float((row[3] + row[4]))/2
    printStatus("Weight: " + str(weight))

残念ながら、Python 実行可能ファイルは、ラインに到達した時点で 25% の CPU と ~6MB の RAM でロックアップしましたcursor.fetchall()。スクリプトを約 10 分間実行したままにしましたが、何も起こりませんでした。

~33,000 の返される行 (約 5MB のデータ) は、Python が一度に取得するには多すぎますか? 一度に 1 つずつ繰り返して行き詰まっていますか? または、物事をスピードアップするためにできることはありますか?

編集:ここにいくつかのコンソール出力があります

12:56:26.019: Adding new column 'weight' and related index to r_ele
12:56:26.019: Querying database
12:56:28.079: Starting weight calculations
12:56:28.079: Weight: 1.0
12:56:28.079: Weight: 0.5
12:56:28.080: Weight: 0.5
12:56:28.338: Weight: 1.0
12:56:28.339: Weight: 3.0
12:56:28.843: Weight: 1.5
12:56:28.844: Weight: 1.0
12:56:28.844: Weight: 0.5
12:56:28.844: Weight: 0.5
12:56:28.845: Weight: 0.5
12:56:29.351: Weight: 0.5
12:56:29.855: Weight: 0.5
12:56:29.856: Weight: 1.0
12:56:30.371: Weight: 0.5
12:56:30.885: Weight: 0.5
12:56:31.146: Weight: 0.5
12:56:31.650: Weight: 1.0
12:56:32.432: Weight: 0.5
12:56:32.951: Weight: 0.5
12:56:32.951: Weight: 0.5
12:56:32.952: Weight: 1.0
12:56:33.454: Weight: 0.5
12:56:33.455: Weight: 0.5
12:56:33.455: Weight: 1.0
12:56:33.716: Weight: 0.5
12:56:33.716: Weight: 1.0

SQL クエリは次のとおりです。

//...snip (it wasn't the culprit)...

SQLiteStudio からの EXPLAIN QUERY PLAN の出力:

0   0   0   SCAN TABLE r_ele AS re USING COVERING INDEX r_ele_fk (~500000 rows)
0   0   0   EXECUTE CORRELATED SCALAR SUBQUERY 1
1   0   0   SEARCH TABLE re_pri USING INDEX re_pri_fk (fk=?) (~10 rows)
0   0   0   EXECUTE CORRELATED SCALAR SUBQUERY 2
2   0   0   SEARCH TABLE ke_pri USING INDEX ke_pri_fk (fk=?) (~10 rows)
2   0   0   EXECUTE CORRELATED SCALAR SUBQUERY 3
3   0   0   SEARCH TABLE k_ele USING AUTOMATIC COVERING INDEX (value=?) (~7 rows)
3   0   0   EXECUTE CORRELATED SCALAR SUBQUERY 4
4   0   0   SEARCH TABLE k_ele USING COVERING INDEX idx_k_ele (fk=?) (~10 rows)
0   0   0   EXECUTE CORRELATED SCALAR SUBQUERY 5
5   0   0   SEARCH TABLE k_ele USING COVERING INDEX idx_k_ele (fk=?) (~10 rows)
0   0   0   EXECUTE CORRELATED SCALAR SUBQUERY 6
6   0   0   SEARCH TABLE re_pri USING INDEX re_pri_fk (fk=?) (~10 rows)
0   0   0   EXECUTE CORRELATED SCALAR SUBQUERY 7
7   0   0   SEARCH TABLE ke_pri USING INDEX ke_pri_fk (fk=?) (~10 rows)
7   0   0   EXECUTE CORRELATED SCALAR SUBQUERY 8
8   0   0   SEARCH TABLE k_ele USING AUTOMATIC COVERING INDEX (value=?) (~7 rows)
8   0   0   EXECUTE CORRELATED SCALAR SUBQUERY 9
9   0   0   SEARCH TABLE k_ele USING COVERING INDEX idx_k_ele (fk=?) (~10 rows)
4

1 に答える 1

3

SQLite はその場で結果レコードを計算します。 fetchoneの各レコードに対してすべてのサブクエリを実行する必要があるため、低速ですr_ele。 すべてのレコードに対してfetchall実行した場合と同じくらい時間がかかるため、さらに遅くなります。fetchone

SQLite 3.7.13 では、value列のすべてのルックアップが非常に遅くなると推定されるため、このクエリの一時インデックスが作成されます。SQLite 3.6.21 で使用できるように、永続的なインデックスを作成する必要があります。

CREATE INDEX idx_k_ele_value ON k_ele(value);

それでも問題が解決しない場合は、新しい SQLite バージョンの Python に更新するか、新しい SQLite バージョンが組み込まれた別のデータベース ライブラリ ( APSWなど) を使用してください。

于 2013-08-21T14:01:51.400 に答える