sql >> データベース >  >> RDS >> Sqlserver

SQLServerのテーブル内の重複レコードの1つを除くすべてを更新します

    結合せずにこの問題を解決できます。つまり、パフォーマンスが向上するはずです。アイデアは、各object_idの行番号を数えて、object_idでデータをグループ化することです。これが「partitionby」が行うことです。次に、row_numが1より大きい場所を更新できます。これにより、最初のオブジェクトを除くすべての複製されたobject_idが更新されます。

    update t set t.status_val = 'some_status' 
    from (
        select *, row_number() over(partition by object_id order by (select null)) row_num  
        from foo
    ) t 
    where row_num > 1 
    

    82944レコードのテストテーブルでは、パフォーマンスはそのようなものでした(マイレージは異なる場合があります!):テーブル'テスト'。スキャンカウント5、論理読み取り82283、物理読み取り0、先読み読み取り0、lob論理読み取り0、lob物理読み取り0、lob先読み読み取り0。CPU時間=141ミリ秒、経過時間=150ミリ秒。

    >

    内部結合を使用してこの問題を解決することもできますが、一般に、これにより論理的な読み取りが増え、CPUが高くなります。

    テーブル'テスト'。スキャンカウント10、論理読み取り83622、物理読み取り0、先読み読み取り0、lob論理読み取り0、lob物理読み取り0、lob先読み読み取り0。表'ワークファイル'。スキャンカウント0、論理読み取り0、物理読み取り0、先読み読み取り0、lob論理読み取り0、lob物理読み取り0、lob先読み読み取り0。表'ワークテーブル'。スキャンカウント4、論理読み取り167426、物理読み取り0、先読み読み取り0、lob論理読み取り0、lob物理読み取り0、lob先読み読み取り0。CPU時間=342ミリ秒、経過時間=233ミリ秒。

    >

    結果をループして小さなバッチで更新するには:

    declare @rowcount int = 1;
    declare @batch_size int = 1000;
    
    while @rowcount > 0 
    begin
        update top(@batch_size) t set t.status_val = 'already updated'
        from (
            select *, row_number() over(partition by object_id order by (select null)) row_num  
            from foo
            where status_val <> 'already updated' 
        ) t 
        where row_num > 1 
        set @rowcount = @@rowcount;
    end
    

    これは、他の同時セッションがこのテーブルにアクセスしようとしている場合にロックダウンを維持するのに役立ちます。



    1. AWS上のWindowsでのShareplex入門、パート2

    2. SQL:Oracleテーブルの100,000レコードを5つのチャンクにどのように分割しますか?

    3. いくつかのワイルドカードに一致するMySQLデータベースを削除しますか?

    4. ORM /クエリビルダーライブラリの接続プールサイズとpgbouncer接続プールのサイズの違いは何ですか?