現在、DB2 サーバーから MySQL データベースにデータを入力するためのスクリプトがあります。動作しますが、非常に遅い速度で行を MySQL に挿入しているようです。スクリプトの実行中、サーバー プロセスは約 1% の CPU で実行されています。挿入を高速化するにはどうすればよいか考えています。
セキュリティ上の理由から、DB2 データベースの管理者は、データベース内の必要なテーブルの読み取り専用ビューのみを提供してくれました。
これは私のスクリプトです:
<?php
$selectQuery = "SELECT
PK AS COL1,
COL2,
COL3,
COL4,
CASE WHEN DATE > '" . date('Y-m-d') . "'
THEN 1
ELSE 0
END AS COL5
FROM table1";
$insertQuery = "INSERT INTO `table1` (
`fk`,
`col2`,
`col3`,
`col4`,
`col5`,
`last_updated`
)
SELECT :col1, f.`fid`, :col3, :col4, :col5, NOW()
FROM f
WHERE f.`code` = :col2
LIMIT 1
ON DUPLICATE KEY UPDATE
`col2` = VALUES(col2),
`col3` = VALUES(col3),
`col4` = VALUES(col4),
`col5` = VALUES(col5),
`last_updated` = NOW();";
$paramTypes = array(
'col1' => PDO::PARAM_STR,
'col2' => PDO::PARAM_STR,
'col3' => PDO::PARAM_STR,
'col4' => PDO::PARAM_STR,
'col5' => PDO::PARAM_BOOL
);
$sync->populate($selectQuery, $insertQuery, $paramTypes);
同期クラス (の$sync
インスタンスであるクラス):
<?php
class SyncObject {
private $db2;
private $db2_user = '...';
private $db2_pass = '...';
private $db2_dbname = '...';
private $db2_host = 'secure.example.net';
private $db2_port = ...;
private $mysql;
public function __construct() {
// Establish a DB2 connection
$this->db2 = db2_pconnect("DATABASE={$this->db2_dbname};HOSTNAME={$this->db2_host};PORT={$this->db2_port};PROTOCOL=TCPIP;UID={$this->db2_user};PWD={$this->db2_pass};", '', '');
// Establish a MySQL connection
$this->mysql = new PDO('mysql:host=secure-mysql.example.net;port=...;dbname=...', '...', '...', array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION));
}
public function populate($selectQuery, $insertQuery, $paramTypes = array()) {
$insStmt = $this->mysql->prepare($insertQuery);
foreach ($paramTypes as $parameterName => $parameterType) {
$$parameterName = '';
$insStmt->bindParam(":$parameterName", $$parameterName, $parameterType);
}
// Retrieve the data
$stmt = db2_exec($this->db2, $selectQuery);
while ($row = db2_fetch_assoc($stmt)) {
foreach ($row as $fieldName => &$fieldValue) {
$fieldName = strtolower($fieldName);
$$fieldName = trim($fieldValue);
$insStmt->execute();
}
}
}
}
ちなみに、このpopulate
メソッドはテーブルごとに 1 回、合計 6 回呼び出されます。ここでは 1 つのテーブルのみを示しました。テーブルのサイズは、20 行から 2100 万行の範囲です。
クエリで大文字のパラメーターをバインドして、strtolower
関数をすべてforeach
.