2

SQLSoup (SQLAlchemy エクステンション) を使用して、SQL Server 2008 データベースのレコードを更新しようとしています。接続には pyobdc を使用しています。関連する例を見つけるのを難しくする問題がいくつかあります。

非常に大きなテーブル (200 万以上のレコード) のジオメトリ フィールドを再投影しているため、フィールドを更新する標準的な方法の多くは使用できません。ジオメトリ フィールドから座標をテキストに抽出し、変換して戻す必要があります。これですべて問題なく、個々の部分はすべて機能しています。

ただし、レコードを 1 つずつループしながら、各行で SQL Update ステートメントを実行したいと考えています。これにより、レコードセットがロックされるか、接続が使用されていると想定されます-以下のコードを使用するかのように、最初のレコードを正常に更新した後にハングします。

新しい接続を作成する方法、既存のものを再利用する方法、またはこれを別の方法で達成する方法についてのアドバイスをいただければ幸いです。

s = select([text("%s as fid" % id_field),
            text("%s.STAsText() as wkt" % geom_field)],
           from_obj=[feature_table])

rs = s.execute()

for row in rs:
    new_wkt = ReprojectFeature(row.wkt)

    update_value = "geometry :: STGeomFromText('%s',%s)" % (new_wkt, "3785")
    update_sql = ("update %s set GEOM3785 = %s where %s = %i" %
                  (full_name, update_value, id_field, row.fid))

    conn = db.connection()
    conn.execute(update_sql)
    conn.close() #or not - no effect..

更新された作業コードは次のようになります。いくつかのレコードでは問題なく動作しますが、テーブル全体でハングするため、データを読み込んでいると思われます。

db = SqlSoup(conn_string)
#create outer query

Session = sessionmaker(autoflush=False, bind=db.engine)
session = Session()
rs = session.execute(s)

for row in rs: 
    #create update sql...
    session.execute(update_sql)
session.commit()

接続ビジー エラーが発生するようになりました。

DBAPIError: (エラー) ('HY000', '[HY000] [Microsoft][ODBC SQL Server Driver] Connection is busy with results for another hstmt (0) (SQLExecDirectW)')

これは ODBC ドライバーに問題があるようです - http://sourceitsoftware.blogspot.com/2008/06/connection-is-busy-with-results-for.html

さらなる更新

プロファイラーを使用しているサーバーでは、選択ステートメントが表示され、最初の更新ステートメントは「開始」されていますが、どちらも完了していません。上位 10 行を返すように Select ステートメントを設定すると、ステートメントは完了し、更新が実行されます。

SQL: Batch Starting   Select...
SQL: Batch Starting   Update...

これはpyodbcと SQL Server ドライバーの問題だと思います。SQL Alchemy を削除して同じ SQL を pyodbc で実行すると、ハングします。更新用の新しい接続オブジェクトを作成しても。

また、MARS - Multiple Active Record Setsを許可する SQL Server Native Client 10.0 ドライバーも試しましたが、違いはありませんでした。最終的に、「結果をページング」し、pyodbc と SQL を使用してこれらのバッチを更新することにしました (以下を参照)。

4

3 に答える 3

1

別の解決策が見つかるまで、単一の接続とカスタム SQL を使用して一連のレコードを返し、これらをバッチで更新しています。私がやっていることは特にユニークなケースだとは思わないので、複数の結果セットを同時に処理できない理由がわかりません。

以下は動作しますが、非常に遅い..

cnxn = pyodbc.connect(conn_string, autocommit=True)
cursor = cnxn.cursor()

#get total recs in the database
s = "select count(fid) as count from table"
count = cursor.execute(s).fetchone().count

#choose number of records to update in each iteration
batch_size = 100
for i in range(1,count, batch_size):
    #sql to bring back relevant records in each batch
    s = """SELECT fid, wkt from(select ROW_NUMBER() OVER(ORDER BY FID ASC) AS 'RowNumber'
,FID
,GEOM29902.STAsText() as wkt
    FROM %s) features
    where RowNumber >= %i and RowNumber <= %i""" % (full_name,i,i+batch_size)

    rs = cursor.execute(s).fetchall()
    for row in rs:
        new_wkt = ReprojectFeature(row.wkt)
        #...create update sql statement for the record
        cursor.execute(update_sql)
        counter += 1
cursor.close()
cnxn.close()  
于 2011-02-06T19:20:26.980 に答える
1

Sessionを使用してみてください。

rs = s.execute()となりsession.execute(rs)、最後の 3 行を に置き換えることができますsession.execute(update_sql)。自動コミットをオフにしてセッションを構成session.commit()し、最後に呼び出すこともお勧めします。

于 2011-02-05T11:17:52.287 に答える
1

プロセスがハングしたときsp_who2に、Sql ボックスで を実行して、何が起こっているかを確認することをお勧めします。ブロックされた spid をチェックし、何が起こっているかを示唆できるものを SQL コードで見つけることができるかどうかを確認します。他の spid をブロックしている spid が見つかった場合はdbcc inputbuffer(*spidid*)、実行されたクエリが何であるかがわかるかどうかを確認できます。それ以外の場合は、Sql プロファイラーをアタッチして呼び出しを追跡することもできます。

場合によっては、SQL サーバーでの並列処理がブロックの原因になることもあります。これがデータ ウェアハウスでない限り、Max DOP をオフにすることをお勧めします (1 に設定します)。お知らせください。午前中に再度確認した際にサポートが必要な場合は、喜んでお手伝いさせていただきます。

于 2011-02-06T10:52:37.890 に答える