3v4l.org

run code in 500+ PHP versions simultaneously
<?php /*---------------------------------------------------------------------- ユニークキーの値が既存ならIDを取得し, なければ保存してからIDを取得 という処理において早い方法はなにか? 以下メソッドを比較してテスト bulkInsertAndIfDuplicateGetIds1() bulkInsertAndIfDuplicateGetIds2() bulkInsertAndIfDuplicateGetIds3() ----------------------------------------------------------------------*/ $testUser = new TestUser(); // 挿入データ // initRows() でINSERTされるデータに対し2番目だけが新規なので // 挿入を試みると ["1","5","3"] が返ることを期待するが, 結果は下記 echo の通り $users = [ ['name' => 'John', 'kind' => 'TypeA', 'age' => 25], // 既存 ['name' => 'Bob', 'kind' => 'TypeC', 'age' => 22], // 新規 ['name' => 'Alice', 'kind' => 'TypeB', 'age' => 30], // 既存 ]; // 挿入実行 $testUser->initRows(); $result1 = $testUser->bulkInsertAndIfDuplicateGetIds1($users); $testUser->initRows(); $result2 = $testUser->bulkInsertAndIfDuplicateGetIds2($users); $testUser->initRows(); $result3 = $testUser->bulkInsertAndIfDuplicateGetIds3($users); // 結果確認 echo '<p>result1</p>' . json_encode($result1); // ["1","5","3"] echo '<p>result2</p>' . json_encode($result2); // ["4","4","4"] echo '<p>result3</p>' . json_encode($result3); // ["4","4","4"] // テストユーザークラス final class TestUser { private \PDO $pdo; public function __construct() { $host = 'localhost'; $dbname = 'database_name'; $user = 'username'; $password = 'password'; $dsn = "mysql:host=$host;dbname=$dbname;charset=utf8mb4"; $this->pdo = new PDO($dsn, $user, $password); } // 初期状態として3レコード入れておく final public function initRows(): void { try { // テーブル作成 $this->pdo->query(" CREATE TABLE IF NOT EXISTS test_users ( id INT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(255), kind VARCHAR(255), age INT, UNIQUE KEY unique_name_kind (name, kind) ) "); // レコード削除 $this->pdo->query(" TRUNCATE TABLE test_users; ALTER TABLE test_users AUTO_INCREMENT = 1; "); // 3レコード入れておく $this->pdo->query(" INSERT INTO test_users (name, kind, age) VALUES ('John', 'TypeA', 25), ('John', 'TypeB', 30), ('Alice', 'TypeB', 28) "); } catch (\PDOException $e) { echo $e->getMessage(); } } // 方法1 // execute() を複数回 // ON DUPLICATE KEY UPDATE は LAST_INSERT_ID を指定 final public function bulkInsertAndIfDuplicateGetIds1(array $users): array { // 返り値のID配列 $ids = []; // INSERT文 $sql = 'INSERT INTO test_users (name, kind, age) VALUES (:name, :kind, :age) ON DUPLICATE KEY UPDATE id = LAST_INSERT_ID(id)'; try { $stmt = $this->pdo->prepare($sql); foreach ($users as $user) { $stmt->execute($user); $ids[] = $this->pdo->lastInsertId(); } return $ids; } catch (\PDOException $e) { echo $e->getMessage(); } } // 方法2 // execute() を1回 // ON DUPLICATE KEY UPDATE は LAST_INSERT_ID を指定 final public function bulkInsertAndIfDuplicateGetIds2(array $users): array { // 返り値のID配列 $ids = []; // INSERT文 $placeholders = implode(', ', array_fill(0, count($users), '(?, ?, ?)')); $sql = 'INSERT INTO test_users (name, kind, age) VALUES ' . $placeholders . ' ON DUPLICATE KEY UPDATE id = LAST_INSERT_ID(id)'; try { $stmt = $this->pdo->prepare($sql); $params = []; foreach ($users as $user) { $params = array_merge($params, array_values($user)); } $stmt->execute($params); for ($i = 0; $i < count($users); $i++) { $ids[] = $this->pdo->lastInsertId(); } return $ids; } catch (\PDOException $e) { echo $e->getMessage(); } } // 方法3 // execute() を1回 // ON DUPLICATE KEY UPDATE は ユニークキーを指定 final public function bulkInsertAndIfDuplicateGetIds3(array $users): array { // 返り値のID配列 $ids = []; // INSERT文 $placeholders = implode(', ', array_fill(0, count($users), '(?, ?, ?)')); $sql = 'INSERT INTO test_users (name, kind, age) VALUES ' . $placeholders . ' ON DUPLICATE KEY UPDATE name = VALUES(name), kind = VALUES(kind)'; try { $stmt = $this->pdo->prepare($sql); $params = []; foreach ($users as $user) { $params = array_merge($params, array_values($user)); } $stmt->execute($params); for ($i = 0; $i < count($users); $i++) { $ids[] = $this->pdo->lastInsertId(); } return $ids; } catch (\PDOException $e) { echo $e->getMessage(); } } }
Finding entry points
Branch analysis from position: 0
1 jumps found. (Code = 62) Position 1 = -2
filename:       /in/pZvuD
function name:  (null)
number of ops:  38
compiled vars:  !0 = $testUser, !1 = $users, !2 = $result1, !3 = $result2, !4 = $result3
line      #* E I O op                               fetch          ext  return  operands
-----------------------------------------------------------------------------------------
   14     0  E >   NEW                                                  $5      'TestUser'
          1        DO_FCALL                                          0          
          2        ASSIGN                                                       !0, $5
   19     3        ASSIGN                                                       !1, <array>
   26     4        INIT_METHOD_CALL                                             !0, 'initRows'
          5        DO_FCALL                                          0          
   27     6        INIT_METHOD_CALL                                             !0, 'bulkInsertAndIfDuplicateGetIds1'
          7        SEND_VAR_EX                                                  !1
          8        DO_FCALL                                          0  $10     
          9        ASSIGN                                                       !2, $10
   28    10        INIT_METHOD_CALL                                             !0, 'initRows'
         11        DO_FCALL                                          0          
   29    12        INIT_METHOD_CALL                                             !0, 'bulkInsertAndIfDuplicateGetIds2'
         13        SEND_VAR_EX                                                  !1
         14        DO_FCALL                                          0  $13     
         15        ASSIGN                                                       !3, $13
   30    16        INIT_METHOD_CALL                                             !0, 'initRows'
         17        DO_FCALL                                          0          
   31    18        INIT_METHOD_CALL                                             !0, 'bulkInsertAndIfDuplicateGetIds3'
         19        SEND_VAR_EX                                                  !1
         20        DO_FCALL                                          0  $16     
         21        ASSIGN                                                       !4, $16
   34    22        INIT_FCALL                                                   'json_encode'
         23        SEND_VAR                                                     !2
         24        DO_ICALL                                             $18     
         25        CONCAT                                               ~19     '%3Cp%3Eresult1%3C%2Fp%3E', $18
         26        ECHO                                                         ~19
   35    27        INIT_FCALL                                                   'json_encode'
         28        SEND_VAR                                                     !3
         29        DO_ICALL                                             $20     
         30        CONCAT                                               ~21     '%3Cp%3Eresult2%3C%2Fp%3E', $20
         31        ECHO                                                         ~21
   36    32        INIT_FCALL                                                   'json_encode'
         33        SEND_VAR                                                     !4
         34        DO_ICALL                                             $22     
         35        CONCAT                                               ~23     '%3Cp%3Eresult3%3C%2Fp%3E', $22
         36        ECHO                                                         ~23
  184    37      > RETURN                                                       1

Class TestUser:
Function __construct:
Finding entry points
Branch analysis from position: 0
1 jumps found. (Code = 62) Position 1 = -2
filename:       /in/pZvuD
function name:  __construct
number of ops:  18
compiled vars:  !0 = $host, !1 = $dbname, !2 = $user, !3 = $password, !4 = $dsn
line      #* E I O op                               fetch          ext  return  operands
-----------------------------------------------------------------------------------------
   45     0  E >   ASSIGN                                                       !0, 'localhost'
   46     1        ASSIGN                                                       !1, 'database_name'
   47     2        ASSIGN                                                       !2, 'username'
   48     3        ASSIGN                                                       !3, 'password'
   49     4        ROPE_INIT                                         5  ~10     'mysql%3Ahost%3D'
          5        ROPE_ADD                                          1  ~10     ~10, !0
          6        ROPE_ADD                                          2  ~10     ~10, '%3Bdbname%3D'
          7        ROPE_ADD                                          3  ~10     ~10, !1
          8        ROPE_END                                          4  ~9      ~10, '%3Bcharset%3Dutf8mb4'
          9        ASSIGN                                                       !4, ~9
   50    10        NEW                                                  $15     'PDO'
         11        SEND_VAR_EX                                                  !4
         12        SEND_VAR_EX                                                  !2
         13        SEND_VAR_EX                                                  !3
         14        DO_FCALL                                          0          
         15        ASSIGN_OBJ                                                   'pdo'
         16        OP_DATA                                                      $15
   51    17      > RETURN                                                       null

End of function __construct

Function initrows:
Finding entry points
Branch analysis from position: 0
1 jumps found. (Code = 42) Position 1 = 17
Branch analysis from position: 17
1 jumps found. (Code = 62) Position 1 = -2
Found catch point at position: 13
Branch analysis from position: 13
2 jumps found. (Code = 107) Position 1 = 14, Position 2 = -2
Branch analysis from position: 14
1 jumps found. (Code = 62) Position 1 = -2
filename:       /in/pZvuD
function name:  initRows
number of ops:  18
compiled vars:  !0 = $e
line      #* E I O op                               fetch          ext  return  operands
-----------------------------------------------------------------------------------------
   58     0  E >   FETCH_OBJ_R                                          ~1      'pdo'
          1        INIT_METHOD_CALL                                             ~1, 'query'
          2        SEND_VAL_EX                                                  '%0A++++++++++++++++CREATE+TABLE+IF+NOT+EXISTS+test_users+%28%0A++++++++++++++++++++id+INT+PRIMARY+KEY+AUTO_INCREMENT%2C%0A++++++++++++++++++++name+VARCHAR%28255%29%2C%0A++++++++++++++++++++kind+VARCHAR%28255%29%2C%0A++++++++++++++++++++age+INT%2C%0A++++++++++++++++++++UNIQUE+KEY+unique_name_kind+%28name%2C+kind%29%0A++++++++++++++++%29%0A++++++++++++'
          3        DO_FCALL                                          0          
   69     4        FETCH_OBJ_R                                          ~3      'pdo'
          5        INIT_METHOD_CALL                                             ~3, 'query'
          6        SEND_VAL_EX                                                  '%0A++++++++++++++++TRUNCATE+TABLE+test_users%3B%0A++++++++++++++++ALTER+TABLE+test_users+AUTO_INCREMENT+%3D+1%3B%0A++++++++++++'
          7        DO_FCALL                                          0          
   75     8        FETCH_OBJ_R                                          ~5      'pdo'
          9        INIT_METHOD_CALL                                             ~5, 'query'
         10        SEND_VAL_EX                                                  '%0A++++++++++++++++INSERT+INTO+test_users%0A++++++++++++++++++++%28name%2C+kind%2C+age%29%0A++++++++++++++++VALUES%0A++++++++++++++++++++%28%27John%27%2C+%27TypeA%27%2C+25%29%2C%0A++++++++++++++++++++%28%27John%27%2C+%27TypeB%27%2C+30%29%2C%0A++++++++++++++++++++%28%27Alice%27%2C+%27TypeB%27%2C+28%29%0A++++++++++++'
         11        DO_FCALL                                          0          
         12      > JMP                                                          ->17
   83    13  E > > CATCH                                           last         'PDOException'
   84    14    >   INIT_METHOD_CALL                                             !0, 'getMessage'
         15        DO_FCALL                                          0  $7      
         16        ECHO                                                         $7
   86    17    > > RETURN                                                       null

End of function initrows

Function bulkinsertandifduplicategetids1:
Finding entry points
Branch analysis from position: 0
2 jumps found. (Code = 77) Position 1 = 9, Position 2 = 19
Branch analysis from position: 9
2 jumps found. (Code = 78) Position 1 = 10, Position 2 = 19
Branch analysis from position: 10
1 jumps found. (Code = 42) Position 1 = 9
Branch analysis from position: 9
Branch analysis from position: 19
1 jumps found. (Code = 62) Position 1 = -2
Branch analysis from position: 19
Found catch point at position: 23
Branch analysis from position: 23
2 jumps found. (Code = 107) Position 1 = 24, Position 2 = -2
Branch analysis from position: 24
1 jumps found. (Code = 62) Position 1 = -2
filename:       /in/pZvuD
function name:  bulkInsertAndIfDuplicateGetIds1
number of ops:  29
compiled vars:  !0 = $users, !1 = $ids, !2 = $sql, !3 = $stmt, !4 = $user, !5 = $e
line      #* E I O op                               fetch          ext  return  operands
-----------------------------------------------------------------------------------------
   91     0  E >   RECV                                                 !0      
   94     1        ASSIGN                                                       !1, <array>
   97     2        ASSIGN                                                       !2, 'INSERT+INTO+test_users+%28name%2C+kind%2C+age%29%0A++++++++VALUES+%28%3Aname%2C+%3Akind%2C+%3Aage%29%0A++++++++ON+DUPLICATE+KEY+UPDATE%0A++++++++id+%3D+LAST_INSERT_ID%28id%29'
  103     3        FETCH_OBJ_R                                          ~8      'pdo'
          4        INIT_METHOD_CALL                                             ~8, 'prepare'
          5        SEND_VAR_EX                                                  !2
          6        DO_FCALL                                          0  $9      
          7        ASSIGN                                                       !3, $9
  105     8      > FE_RESET_R                                           $11     !0, ->19
          9    > > FE_FETCH_R                                                   $11, !4, ->19
  106    10    >   INIT_METHOD_CALL                                             !3, 'execute'
         11        SEND_VAR_EX                                                  !4
         12        DO_FCALL                                          0          
  107    13        FETCH_OBJ_R                                          ~14     'pdo'
         14        INIT_METHOD_CALL                                             ~14, 'lastInsertId'
         15        DO_FCALL                                          0  $15     
         16        ASSIGN_DIM                                                   !1
         17        OP_DATA                                                      $15
  105    18      > JMP                                                          ->9
         19    >   FE_FREE                                                      $11
  110    20        VERIFY_RETURN_TYPE                                           !1
         21      > RETURN                                                       !1
         22*       JMP                                                          ->27
  111    23  E > > CATCH                                           last         'PDOException'
  112    24    >   INIT_METHOD_CALL                                             !5, 'getMessage'
         25        DO_FCALL                                          0  $16     
         26        ECHO                                                         $16
  114    27        VERIFY_RETURN_TYPE                                           
         28      > RETURN                                                       null

End of function bulkinsertandifduplicategetids1

Function bulkinsertandifduplicategetids2:
Finding entry points
Branch analysis from position: 0
2 jumps found. (Code = 77) Position 1 = 20, Position 2 = 30
Branch analysis from position: 20
2 jumps found. (Code = 78) Position 1 = 21, Position 2 = 30
Branch analysis from position: 21
1 jumps found. (Code = 42) Position 1 = 20
Branch analysis from position: 20
Branch analysis from position: 30
1 jumps found. (Code = 42) Position 1 = 42
Branch analysis from position: 42
2 jumps found. (Code = 44) Position 1 = 45, Position 2 = 36
Branch analysis from position: 45
1 jumps found. (Code = 62) Position 1 = -2
Branch analysis from position: 36
2 jumps found. (Code = 44) Position 1 = 45, Position 2 = 36
Branch analysis from position: 45
Branch analysis from position: 36
Branch analysis from position: 30
Found catch point at position: 48
Branch analysis from position: 48
2 jumps found. (Code = 107) Position 1 = 49, Position 2 = -2
Branch analysis from position: 49
1 jumps found. (Code = 62) Position 1 = -2
filename:       /in/pZvuD
function name:  bulkInsertAndIfDuplicateGetIds2
number of ops:  54
compiled vars:  !0 = $users, !1 = $ids, !2 = $placeholders, !3 = $sql, !4 = $stmt, !5 = $params, !6 = $user, !7 = $i, !8 = $e
line      #* E I O op                               fetch          ext  return  operands
-----------------------------------------------------------------------------------------
  119     0  E >   RECV                                                 !0      
  122     1        ASSIGN                                                       !1, <array>
  125     2        INIT_FCALL                                                   'array_fill'
          3        SEND_VAL                                                     0
          4        COUNT                                                ~10     !0
          5        SEND_VAL                                                     ~10
          6        SEND_VAL                                                     '%28%3F%2C+%3F%2C+%3F%29'
          7        DO_ICALL                                             $11     
          8        FRAMELESS_ICALL_2                implode             ~12     '%2C+', $11
          9        ASSIGN                                                       !2, ~12
  127    10        CONCAT                                               ~14     'INSERT+INTO+test_users+%28name%2C+kind%2C+age%29%0A++++++++VALUES+', !2
         11        CONCAT                                               ~15     ~14, '%0A++++++++ON+DUPLICATE+KEY+UPDATE%0A++++++++id+%3D+LAST_INSERT_ID%28id%29'
  126    12        ASSIGN                                                       !3, ~15
  132    13        FETCH_OBJ_R                                          ~17     'pdo'
         14        INIT_METHOD_CALL                                             ~17, 'prepare'
         15        SEND_VAR_EX                                                  !3
         16        DO_FCALL                                          0  $18     
         17        ASSIGN                                                       !4, $18
  134    18        ASSIGN                                                       !5, <array>
  135    19      > FE_RESET_R                                           $21     !0, ->30
         20    > > FE_FETCH_R                                                   $21, !6, ->30
  136    21    >   INIT_FCALL                                                   'array_merge'
         22        SEND_VAR                                                     !5
         23        INIT_FCALL                                                   'array_values'
         24        SEND_VAR                                                     !6
         25        DO_ICALL                                             $22     
         26        SEND_VAR                                                     $22
         27        DO_ICALL                                             $23     
         28        ASSIGN                                                       !5, $23
  135    29      > JMP                                                          ->20
         30    >   FE_FREE                                                      $21
  138    31        INIT_METHOD_CALL                                             !4, 'execute'
         32        SEND_VAR_EX                                                  !5
         33        DO_FCALL                                          0          
  140    34        ASSIGN                                                       !7, 0
         35      > JMP                                                          ->42
  141    36    >   FETCH_OBJ_R                                          ~28     'pdo'
         37        INIT_METHOD_CALL                                             ~28, 'lastInsertId'
         38        DO_FCALL                                          0  $29     
         39        ASSIGN_DIM                                                   !1
         40        OP_DATA                                                      $29
  140    41        PRE_INC                                                      !7
         42    >   COUNT                                                ~31     !0
         43        IS_SMALLER                                                   !7, ~31
         44      > JMPNZ                                                        ~32, ->36
  144    45    >   VERIFY_RETURN_TYPE                                           !1
         46      > RETURN                                                       !1
         47*       JMP                                                          ->52
  145    48  E > > CATCH                                           last         'PDOException'
  146    49    >   INIT_METHOD_CALL                                             !8, 'getMessage'
         50        DO_FCALL                                          0  $33     
         51        ECHO                                                         $33
  148    52        VERIFY_RETURN_TYPE                                           
         53      > RETURN                                                       null

End of function bulkinsertandifduplicategetids2

Function bulkinsertandifduplicategetids3:
Finding entry points
Branch analysis from position: 0
2 jumps found. (Code = 77) Position 1 = 20, Position 2 = 30
Branch analysis from position: 20
2 jumps found. (Code = 78) Position 1 = 21, Position 2 = 30
Branch analysis from position: 21
1 jumps found. (Code = 42) Position 1 = 20
Branch analysis from position: 20
Branch analysis from position: 30
1 jumps found. (Code = 42) Position 1 = 42
Branch analysis from position: 42
2 jumps found. (Code = 44) Position 1 = 45, Position 2 = 36
Branch analysis from position: 45
1 jumps found. (Code = 62) Position 1 = -2
Branch analysis from position: 36
2 jumps found. (Code = 44) Position 1 = 45, Position 2 = 36
Branch analysis from position: 45
Branch analysis from position: 36
Branch analysis from position: 30
Found catch point at position: 48
Branch analysis from position: 48
2 jumps found. (Code = 107) Position 1 = 49, Position 2 = -2
Branch analysis from position: 49
1 jumps found. (Code = 62) Position 1 = -2
filename:       /in/pZvuD
function name:  bulkInsertAndIfDuplicateGetIds3
number of ops:  54
compiled vars:  !0 = $users, !1 = $ids, !2 = $placeholders, !3 = $sql, !4 = $stmt, !5 = $params, !6 = $user, !7 = $i, !8 = $e
line      #* E I O op                               fetch          ext  return  operands
-----------------------------------------------------------------------------------------
  153     0  E >   RECV                                                 !0      
  156     1        ASSIGN                                                       !1, <array>
  159     2        INIT_FCALL                                                   'array_fill'
          3        SEND_VAL                                                     0
          4        COUNT                                                ~10     !0
          5        SEND_VAL                                                     ~10
          6        SEND_VAL                                                     '%28%3F%2C+%3F%2C+%3F%29'
          7        DO_ICALL                                             $11     
          8        FRAMELESS_ICALL_2                implode             ~12     '%2C+', $11
          9        ASSIGN                                                       !2, ~12
  161    10        CONCAT                                               ~14     'INSERT+INTO+test_users+%28name%2C+kind%2C+age%29%0A++++++++VALUES+', !2
         11        CONCAT                                               ~15     ~14, '%0A++++++++ON+DUPLICATE+KEY+UPDATE%0A++++++++name+%3D+VALUES%28name%29%2C%0A++++++++kind+%3D+VALUES%28kind%29'
  160    12        ASSIGN                                                       !3, ~15
  167    13        FETCH_OBJ_R                                          ~17     'pdo'
         14        INIT_METHOD_CALL                                             ~17, 'prepare'
         15        SEND_VAR_EX                                                  !3
         16        DO_FCALL                                          0  $18     
         17        ASSIGN                                                       !4, $18
  169    18        ASSIGN                                                       !5, <array>
  170    19      > FE_RESET_R                                           $21     !0, ->30
         20    > > FE_FETCH_R                                                   $21, !6, ->30
  171    21    >   INIT_FCALL                                                   'array_merge'
         22        SEND_VAR                                                     !5
         23        INIT_FCALL                                                   'array_values'
         24        SEND_VAR                                                     !6
         25        DO_ICALL                                             $22     
         26        SEND_VAR                                                     $22
         27        DO_ICALL                                             $23     
         28        ASSIGN                                                       !5, $23
  170    29      > JMP                                                          ->20
         30    >   FE_FREE                                                      $21
  173    31        INIT_METHOD_CALL                                             !4, 'execute'
         32        SEND_VAR_EX                                                  !5
         33        DO_FCALL                                          0          
  175    34        ASSIGN                                                       !7, 0
         35      > JMP                                                          ->42
  176    36    >   FETCH_OBJ_R                                          ~28     'pdo'
         37        INIT_METHOD_CALL                                             ~28, 'lastInsertId'
         38        DO_FCALL                                          0  $29     
         39        ASSIGN_DIM                                                   !1
         40        OP_DATA                                                      $29
  175    41        PRE_INC                                                      !7
         42    >   COUNT                                                ~31     !0
         43        IS_SMALLER                                                   !7, ~31
         44      > JMPNZ                                                        ~32, ->36
  179    45    >   VERIFY_RETURN_TYPE                                           !1
         46      > RETURN                                                       !1
         47*       JMP                                                          ->52
  180    48  E > > CATCH                                           last         'PDOException'
  181    49    >   INIT_METHOD_CALL                                             !8, 'getMessage'
         50        DO_FCALL                                          0  $33     
         51        ECHO                                                         $33
  183    52        VERIFY_RETURN_TYPE                                           
         53      > RETURN                                                       null

End of function bulkinsertandifduplicategetids3

End of class TestUser.

Generated using Vulcan Logic Dumper, using php 8.5.0


preferences:
200 ms | 1223 KiB | 12 Q