我目前有一个用于从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-&gt; populate($ selectQuery,$ insertQuery,$ paramTypes);
在synchronize类($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行到2100万行。
我认为我可以在查询中绑定大写参数以避免strtolower
中的所有foreach
函数,但除了那个微小的变化之外,还有关于如何提高性能的任何建议脚本?
答案 0 :(得分:2)
无论您做什么,按行插入数据都不会有效。在我看来,更好的方法是使用DB2 EXPORT命令将DB2表数据提取到CSV文件中,然后使用MySQL LOAD DATA将它们加载到目标数据库中。我对PHP不是很熟悉,但我认为它应该允许你使用exec()运行外部命令。
您至少需要安装DB2 Data Server Runtime Client才能为EXPORT运行DB2命令行处理器。
答案 1 :(得分:0)
尝试将整个数据导出为csv文件格式,然后使用load data utilitity将其加载到MySQL数据库中。加载和导出实用程序肯定比获取单行并逐个插入更快。
答案 2 :(得分:0)
在简要调查InnoDB如何执行操作之后,我做了以下操作以加快插入速度:
$this->mysql->beginTransaction()
。每个事务的查询量是有限的,虽然我很确定MySQL会在InnoDB缓冲区填满时提交SET foreign_key_checks = 0
。 DB2数据库具有相当高的完整性,因此这是一种安全的操作。SET unique_checks = 0
。 DB2数据库已经强制使用唯一键,因此这是安全的。 SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
。需要考虑的其他事项是InnoDB system variables,但由于对服务器的访问权限有限,因此无法真正改变这些内容。
此页面也可能有所帮助,但它列出了此处列出的大部分内容:http://dev.mysql.com/doc/refman/5.6/en/optimizing-innodb-bulk-data-loading.html