У меня есть скрипт для заполнения базы данных MySQL с сервера DB2. Он работает, но, кажется, он вставляет строки в MySQL с чрезвычайно низкой скоростью. Процесс сервера выполняется на ~ 1% процессора во время работы скрипта, и мне интересно, как я могу ускорить вставки.Заполнение базы данных MySQL из базы данных DB2
По соображениям безопасности администратор базы данных 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-> заселить ($ 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
метод вызывается в шесть раз, один раз в таблице. Здесь я показал только один стол. Размер таблиц варьируется от 20 до 21 миллиона строк.
Я там думать, что я могу связать прописные параметры в запросе, чтобы избежать strtolower
функций все в foreach
, но кроме этого незначительных изменений будет какие-либо предложения о том, как улучшить производительность сценария?
+1 Согласовано дамп + насыпной импорт должен быть лучшим способом –
В настоящее время это не вариант для нас, как мы имеют очень мало контроля над сервером, однако я буду помнить это предположение, когда мы переходим на новый сервер. Благодаря! –