PostgreSQLを使い始めたばかりで、SQL Serverを使っていましたが、現在、既存のプロセスの一部を移行しています。
私が直面している現在の問題は、Updateステートメントのパフォーマンスです。
1つのテーブル(MyTable_Historyなど)からすべてのレコードを更新し、いくつかの列に新しい値を設定しようとしています。
SQL Serverでは、次の構文を使用しました。
declare @NewEndDate datetime = (select dateadd(minute, -1, getdate()))
update MyTable_History
set isLastestVersion=0, ValidTo=@NewEndDate , ModifiedBy='TestSCriptSql',ModifiedTime=GETDATE()
PostgreSQL用に思いつくことができるコード(単純に変数を使用する方法がわからないため、一時的なtblを使用したため)は次のとおりです。
CREATE TEMP TABLE dates AS VALUES (current_timestamp + (-1 ||' minutes')::interval);
with d as (
select th.validto as validto, th.islatestversion as islatestversion,
th.modifiedby as modifiedby, th.modifiedtime as modifiedtime, d.column1 as newvalidto
from MyTable_History th, dates d
)
update MyTable_History
set validto = d.newvalidto, islatestversion=false, modifiedby='test_update_script', modifiedtime=current_timestamp
from d
SQL Serverは私のラップトップ(スーパー構成ではない)でローカルに実行され、PosgreSQLサーバーはAWSでRDSとして実行されます(正確な仕様はわかりません)。
私の質問は、PostgreSql更新ステートメントで何か間違ったことをしているのですか?Sql Serverの5000以上のデータセットサンプルでは、ステートメントが即座に実行されますが、PostgreSqlでは正常に終了するのに約50秒かかります。
また、私の観点からは、SQL Serverでは3行のコードがあり、postgreSqlではCTEを使用しているため、過剰に設計されているようです。
よろしく、
そもそもなぜ変数が必要なのかわかりません。current_timestamp
トランザクション全体でマニュアルに記載されているのと同じ値を返すため、更新されたすべての行で同じ値になります。
update mytable_history
set islastestversion = 0,
validto = current_timestamp - interval '1 minute',
modifiedby = 'test_update_script',
modifiedtime = current_timestamp;
しかしFROM
、UPDATEステートメントでのの使用法は間違っています。UPDATEステートメントでFROMを使用するセマンティクスは、PostgresとSQLServerで大きく異なります。
これを使用する方法により、CTEとmytable_historyの間に相互結合が作成されます。(つまり、基本的にテーブルとそれ自体の相互結合)。
主キーのWHERE句に結合条件が必要です。
with d as (...)
update MyTable_History
set validto = d.newvalidto, islatestversion=false,
modifiedby='test_update_script', modifiedtime=current_timestamp
from d
where d.pk_column = MyTable_History.pk_column;
しかし、本当に変数のようなものをシミュレートしたい場合は、CTEは必要ありません。
update mytable_history
set islastestversion = 0,
validto = t.newvalidto
modifiedby = 'test_update_script',
modifiedtime = current_timestamp
from (
values (current_timestamp - interval '1 minute')
) t (newvalidto);
上記は依然として「クロス結合」を作成しますが、結合されたテーブル(from (values ...))
単一の行のみが含まれているため、実際にはクロス結合ではありません)。
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加