※細かい検証は行っていないので、あくまでも参考程度に!!
一意となるレコードが存在する時はupdateをして、存在しない時はinsertしたい時、昔はdeleteしてからinsertするか、とりあえずinsertしてみて一意制約エラーの割り込みでupdateするということをしていたけど、LaravelのメソッドにはupdateOrInsertという便利なメソッドが用意されている。
しかし、updateOrInsert()って遅そうだしdelete->insertの方がシンプルでいいなと思っていたけど、updateOrInsert()が用意されているのに使わないと「このコード書いた人、あまりLaravelのこと詳しくないんだ」って思われそうだし、納得する為にupdateOrInsert()はどれくらい遅いのかと調べてみた。
※検証はdocker環境で、しかもwindowsのwslで更にハードディスクなので比較の参考程度に!!
■updateOrInsert()の場合
まずはupdateOrInsert()
"処理時間: 0.14294290542603 [s]"
"メモリ使用量: 0.81157684326172 [MB]"
"処理時間: 0.14393591880798 [s]"
"メモリ使用量: 0.81209564208984 [MB]"
"処理時間: 0.14344096183777 [s]"
"メモリ使用量: 0.81209564208984 [MB]"
なるほどなるほど。
■delete() -> create()の場合
まず、クエリビルダのdelete()でdeleteしてcreate()でinsert
"処理時間: 26.259877920151 [s]"
"メモリ使用量: 0.55281066894531 [MB]"
"処理時間: 24.490818023682 [s]"
"メモリ使用量: 0.55281066894531 [MB]"
"処理時間: 24.807777166367 [s]"
"メモリ使用量: 0.55281066894531 [MB]"
うん??20倍くらい遅いんだけど??
■delete() -> insert()
create()はいろんな処理をしてくれるので、シンプルにinsertしてくれるinsert()でも試してみる。
"処理時間: 23.877470016479 [s]"
"メモリ使用量: 0.49762725830078 [MB]"
"処理時間: 27.689697027206 [s]"
"メモリ使用量: 0.49762725830078 [MB]"
"処理時間: 23.548000097275 [s]"
"メモリ使用量: 0.49762725830078 [MB]"
delete() -> create()とあまり変わらない。
意外過ぎる結果となってしまった。
細かい検証とLaravelのソースのリーディングはまたの機会にするとして、今回の実装はupdateOrInsert()を採用しようと思う。
2021.12.27追記
ハードディスクだし、データベースをマウントしているせいか単純にinsertに時間がかかっている気がする。
delete->insertだと必ず全レコードinsertすることになるのでこういう結果になってしまっているのかもしれない。