如何优化Php mysql查询以更快地执行
使用php脚本将数据从一个数据库复制到另一个数据库。它工作得很好,但需要很多时间。大约每分钟插入1000行,这意味着复制100000行最多需要2小时!可以通过优化以下代码来减少此时间吗?试图删除子查询并放置左联接,但无效 编辑-脚本根据单词或其组合从一个数据库db1中选择数据。它使用爆炸/内爆进行匹配。然后,它在其他db2数据库中创建该名称的新表。然后将所选数据插入新数据库db2。现在,它正在从旧数据库的两个表中选择数据。它正在为此使用子查询。使用left join会加快执行速度吗 我的代码如何优化Php mysql查询以更快地执行,php,mysql,optimization,Php,Mysql,Optimization,使用php脚本将数据从一个数据库复制到另一个数据库。它工作得很好,但需要很多时间。大约每分钟插入1000行,这意味着复制100000行最多需要2小时!可以通过优化以下代码来减少此时间吗?试图删除子查询并放置左联接,但无效 编辑-脚本根据单词或其组合从一个数据库db1中选择数据。它使用爆炸/内爆进行匹配。然后,它在其他db2数据库中创建该名称的新表。然后将所选数据插入新数据库db2。现在,它正在从旧数据库的两个表中选择数据。它正在为此使用子查询。使用left join会加快执行速度吗 我的代码 &
<?php
ini_set('max_execution_time', 30000);
ini_set('default_charset',"utf-8");
include('config_collect.php');
header('Content-Type: text/html; charset=utf-8');
$keywordId = $_GET['id'];
require_once("config_duplicate.php");
?>
<?php
try
{
$kewyQ = $db->query("SELECT * FROM collections where id =
$keyId");
$kVal = $kewyQ->fetch(PDO::FETCH_ASSOC);
$table = trim($kVal['words']);
//Create table
$Q = "CREATE TABLE IF NOT EXISTS `$table` (
`id` INT AUTO_INCREMENT NOT NULL,
`t_id` bigint(20) NOT NULL,
`t_text` TEXT,
`user_name` varchar(100),
`place` varchar(100),
`time` datetime,
`description` TEXT,
PRIMARY KEY (`id`))
CHARACTER SET utf8 COLLATE utf8_general_ci";
$db2->query($Q);
// Count all records based on words
if (preg_match('/\s/',$table)) {
$keySpace = explode(" ", $table);
if(count($keySpace) > 1){
$squery = "SELECT * FROM t WHERE t_text LIKE
'%".implode("%' AND t_text LIKE '%", $keySpace)."%' ";
}else{
$keyval = $keySpace[0];
$squery = "SELECT * FROM t WHERE t_text LIKE '%$keyval%' ";
}
}else{
$squery = "SELECT * FROM t WHERE t_text LIKE '%$tablename%'";
}
在我公司的最后两个项目中,我不得不处理类似的案例。 我们必须通过网络复制大约1000万行数据,想到的第一个解决方案是使用php。这种做法显然失败了 相反,我用这段代码替换了它,因为它是纯mysql,所以运行速度惊人
$this->logger->info('Dumping the data');
$biDbUser = $this->getContainer()->getParameter('bi_database_user');
$biDbPass = $this->getContainer()->getParameter('bi_database_password');
$biDbHost = $this->getContainer()->getParameter('bi_database_host');
$biDbName = $this->getContainer()->getParameter('bi_database_name');
$dumpFilePath = rtrim(sys_get_temp_dir(), '/').'/'.uniqid('init_dump_bi').'.sql';
exec(sprintf(
'mysqldump -u %s -p%s -h %s --single-transaction --compress %s %s > %s',
$biDbUser,
$biDbPass,
$biDbHost,
$biDbName,
$contextConfig->getBiTableLast(),
$dumpFilePath
));
$this->logger->info('Dump completed. Now loading it to our db.');
$dpDbUser = $this->getContainer()->getParameter('dp_database_user');
$dpDbPass = $this->getContainer()->getParameter('dp_database_password');
$dpDbHost = $this->getContainer()->getParameter('dp_database_host');
$dpDbName = $this->getContainer()->getParameter('dp_database_name');
exec(sprintf(
'cat %s | mysql -u %s -p%s -h %s %s',
$dumpFilePath,
$dpDbUser,
$dpDbPass,
$dpDbHost,
$dpDbName
));
unlink($dumpFilePath);
$columns = array_diff($contextConfig->getColumns(), ['timestamp']);
$query = sprintf(
'INSERT INTO %s (%s) SELECT %s FROM %s',
$contextConfig->getInvoicingTable(),
implode(',', $columns),
implode(',', $columns),
$contextConfig->getBiTableLast()
);
$this->logger->info('Data moved to our db. Now inserting from bi to our table.');
exec(sprintf('mysql -u %s -p%s -h %s %s -e "%s"', $dpDbUser, $dpDbPass, $dpDbHost, $dpDbName, $query));
$this->logger->info('Insert done.');
$query = 'DROP TABLE '.$contextConfig->getBiTableLast();
exec(sprintf('mysql -u %s -p%s -h %s %s -e "%s"', $dpDbUser, $dpDbPass, $dpDbHost, $dpDbName, $query));
$this->logger->info('Finished synchronisation BI->DP.', [
'context' => $contextConfig->getContextCode()
]);
显然,我不打算解释很多变量,但这里是这个脚本的主要部分
exec(sprintf(
'mysqldump -u %s -p%s -h %s --single-transaction --compress %s %s > %s',
$biDbUser,
$biDbPass,
$biDbHost,
$biDbName,
$contextConfig->getBiTableLast(),
$dumpFilePath
));
我从symfony获得连接配置(在您的情况下,您应该从您的连接获得它),并调用mysqldump。我使用--single事务,因为用户具有只读访问权限。同时使用--compress可以避免给数据中心网络带来太大的压力
exec(sprintf(
'cat %s | mysql -u %s -p%s -h %s %s',
$dumpFilePath,
$dpDbUser,
$dpDbPass,
$dpDbHost,
$dpDbName
));
使用此命令完成转储后,您将把转储的数据放入目标数据库。
最后
$query = sprintf(
'INSERT INTO %s (%s) SELECT %s FROM %s',
$contextConfig->getInvoicingTable(),
implode(',', $columns),
implode(',', $columns),
$contextConfig->getBiTableLast()
);
$this->logger->info('Data moved to our db. Now inserting from bi to our table.');
exec(sprintf('mysql -u %s -p%s -h %s %s -e "%s"', $dpDbUser, $dpDbPass, $dpDbHost, $dpDbName, $query));
我使用mysql insert select查询将数据从新转储的表传递到我们的表。
我尝试使用pdo连接来执行最后一个调用,但我猜在mysql的所有会话都可以全局使用该表之前,会有一个延迟。所以PDO一直说找不到桌子
希望能有所帮助。计划A: 将所有行从一个表复制到另一个表的最快方法是在单个查询中执行:
INSERT INTO new (a,b,c)
SELECT a,b,c FROM old;
没有行计数,没有循环,MySQL和PHP之间没有来回,等等
我不清楚你到底在做什么,但看看你是否能从这个目标上后退
方案B:
由于您似乎正在浏览一大堆表格,因此这可能会更好:
在PHP之外,做什么
mysqldump ... old_db | mysql ... new_db
注意:这也可以为新的数据库提供相同的创建表
方案C:
这是上述两种方法的结合。它为传输创建一个CSV文件
SELECT a,b,c FROM old_tbl INTO OUTFILE ...;
LOAD DATA INFILE ...;
更多(查看示例SQL后)
是否有多个由$table
表示的“相同”表格?如果是这样的话,这是模式设计中的一个大危险信号;请解释你的意图
嗯,我不喜欢使用单词
和集合
,但这将插入与两个选项结合起来:
INSERT INTO $table
( t_id, t_text, user_name, time,
description, place )
SELECT t.t_id, t.t_text, t.user_name, t.time,
u.description, u.place
FROM t
JOIN users u ON u.user_name = t.user_name
WHERE t_text LIKE '%blue%'
AND t_text LIKE '%car%' ;
我不太熟悉这种类型的代码。你能提供任何链接来记录同样的内容吗?你能告诉我如何在我的代码中使用左连接而不是子查询吗?对不起,这里没有这样的文档:)这里也没有子查询,这只是给你一个想法。代码不是那么简单。脚本根据单词或它们的组合从一个数据库db1中选择数据。它使用爆炸/内爆进行匹配。然后,它在其他db2数据库中创建该名称的新表。然后将所选数据插入新数据库db2。现在,它正在从旧数据库的两个表中选择数据。它正在为此使用子查询。使用left join会加快执行速度吗?也许您可以向我们展示每个SQL语句的示例?@RickJames SELECT*来自id=30的集合;选择*FROM t,其中t_文本如“%red%”和t_文本如“%car%”;选择描述,从用户处放置user_name=Rick
;将值('30'、'Nice red and big car'、'Rick'、'California'、'2017/06/03'、'developer')插入$表中
SELECT a,b,c FROM old_tbl INTO OUTFILE ...;
LOAD DATA INFILE ...;
INSERT INTO $table
( t_id, t_text, user_name, time,
description, place )
SELECT t.t_id, t.t_text, t.user_name, t.time,
u.description, u.place
FROM t
JOIN users u ON u.user_name = t.user_name
WHERE t_text LIKE '%blue%'
AND t_text LIKE '%car%' ;