3v4l.org

run code in 300+ 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 = 23, Position 2 = 33
Branch analysis from position: 23
2 jumps found. (Code = 78) Position 1 = 24, Position 2 = 33
Branch analysis from position: 24
1 jumps found. (Code = 42) Position 1 = 23
Branch analysis from position: 23
Branch analysis from position: 33
1 jumps found. (Code = 42) Position 1 = 45
Branch analysis from position: 45
2 jumps found. (Code = 44) Position 1 = 48, Position 2 = 39
Branch analysis from position: 48
1 jumps found. (Code = 62) Position 1 = -2
Branch analysis from position: 39
2 jumps found. (Code = 44) Position 1 = 48, Position 2 = 39
Branch analysis from position: 48
Branch analysis from position: 39
Branch analysis from position: 33
Found catch point at position: 51
Branch analysis from position: 51
2 jumps found. (Code = 107) Position 1 = 52, Position 2 = -2
Branch analysis from position: 52
1 jumps found. (Code = 62) Position 1 = -2
filename:       /in/pZvuD
function name:  bulkInsertAndIfDuplicateGetIds2
number of ops:  57
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                                               'implode'
          3        SEND_VAL                                                 '%2C+'
          4        INIT_FCALL                                               'array_fill'
          5        SEND_VAL                                                 0
          6        COUNT                                            ~10     !0
          7        SEND_VAL                                                 ~10
          8        SEND_VAL                                                 '%28%3F%2C+%3F%2C+%3F%29'
          9        DO_ICALL                                         $11     
         10        SEND_VAR                                                 $11
         11        DO_ICALL                                         $12     
         12        ASSIGN                                                   !2, $12
  127    13        CONCAT                                           ~14     'INSERT+INTO+test_users+%28name%2C+kind%2C+age%29%0A++++++++VALUES+', !2
         14        CONCAT                                           ~15     ~14, '%0A++++++++ON+DUPLICATE+KEY+UPDATE%0A++++++++id+%3D+LAST_INSERT_ID%28id%29'
  126    15        ASSIGN                                                   !3, ~15
  132    16        FETCH_OBJ_R                                      ~17     'pdo'
         17        INIT_METHOD_CALL                                         ~17, 'prepare'
         18        SEND_VAR_EX                                              !3
         19        DO_FCALL                                      0  $18     
         20        ASSIGN                                                   !4, $18
  134    21        ASSIGN                                                   !5, <array>
  135    22      > FE_RESET_R                                       $21     !0, ->33
         23    > > FE_FETCH_R                                               $21, !6, ->33
  136    24    >   INIT_FCALL                                               'array_merge'
         25        SEND_VAR                                                 !5
         26        INIT_FCALL                                               'array_values'
         27        SEND_VAR                                                 !6
         28        DO_ICALL                                         $22     
         29        SEND_VAR                                                 $22
         30        DO_ICALL                                         $23     
         31        ASSIGN                                                   !5, $23
  135    32      > JMP                                                      ->23
         33    >   FE_FREE                                                  $21
  138    34        INIT_METHOD_CALL                                         !4, 'execute'
         35        SEND_VAR_EX                                              !5
         36        DO_FCALL                                      0          
  140    37        ASSIGN                                                   !7, 0
         38      > JMP                                                      ->45
  141    39    >   FETCH_OBJ_R                                      ~28     'pdo'
         40        INIT_METHOD_CALL                                         ~28, 'lastInsertId'
         41        DO_FCALL                                      0  $29     
         42        ASSIGN_DIM                                               !1
         43        OP_DATA                                                  $29
  140    44        PRE_INC                                                  !7
         45    >   COUNT                                            ~31     !0
         46        IS_SMALLER                                               !7, ~31
         47      > JMPNZ                                                    ~32, ->39
  144    48    >   VERIFY_RETURN_TYPE                                       !1
         49      > RETURN                                                   !1
         50*       JMP                                                      ->55
  145    51  E > > CATCH                                       last         'PDOException'
  146    52    >   INIT_METHOD_CALL                                         !8, 'getMessage'
         53        DO_FCALL                                      0  $33     
         54        ECHO                                                     $33
  148    55        VERIFY_RETURN_TYPE                                       
         56      > RETURN                                                   null

End of function bulkinsertandifduplicategetids2

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

End of function bulkinsertandifduplicategetids3

End of class TestUser.

Generated using Vulcan Logic Dumper, using php 8.0.0


preferences:
172.04 ms | 1027 KiB | 18 Q