我正在进行大约600次INSERT ON DUPLICATE KEY UPDATE
次查询,其中每个插入可以有不同的列集。
我现在这样做的方式只是一个mysql_query()
的foreach循环。它真的很慢,php脚本由于最长执行时间30秒而停止。
我无法使用INSERT INTO table (columns) VALUES (values 1), (values 2), ..., (values n)
因为每个插入必须能够拥有不同的列集。
我还查看了准备好的查询,但从我看到的情况来看,似乎不适用于不同的列集。
我是数据库和MYSQL的新手。我只是将一些东西作为一个周末项目进行黑客攻击,而现在我只想让这个项目的最后一部分工作。对不这样做,我很抱歉。 (抱歉使用已弃用的php mysql函数。)也许我应该去睡觉并稍后重写。这样做的正确方法是什么?
编辑:这是关于表格类型的一些信息
-- phpMyAdmin SQL Dump -- version 3.5.1 -- http://www.phpmyadmin.net -- -- Host: localhost -- Generation Time: Jul 22, 2012 at 09:59 PM -- Server version: 5.5.24-log -- PHP Version: 5.3.13 SET SQL_MODE="NO_AUTO_VALUE_ON_ZERO"; SET time_zone = "+00:00"; -- -- Database: `trailerbay` -- -- -------------------------------------------------------- -- -- Table structure for table `movies` -- CREATE TABLE IF NOT EXISTS `movies` ( `id` int(11) NOT NULL AUTO_INCREMENT, `imdb` int(7) NOT NULL, `title` text COLLATE utf8_unicode_ci, `releasedate` date DEFAULT NULL, `enlistdate` datetime NOT NULL, `runtime` time DEFAULT NULL, `trailer` text COLLATE utf8_unicode_ci NOT NULL, `plot` text COLLATE utf8_unicode_ci, `cover` text COLLATE utf8_unicode_ci NOT NULL, PRIMARY KEY (`id`), UNIQUE KEY `id` (`id`), UNIQUE KEY `imdb` (`imdb`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=1145 ;
答案 0 :(得分:1)
我不认为你的桌子上有很多列,他们的开/关组合数量太多了。
因此,对于每一行,您可以提取其列组合(例如,您可以按字母顺序排序字段)并将其结构用作键:
// $tuple has been sorted based on keys
$syndrome = implode(',', array_keys($tuple));
$values = array_values($tuple);
if (isset($big_inserts[$syndrome]))
array_push($big_inserts[$syndrome], $values);
else
$big_inserts[$syndrome] = array($values);
在循环结束时,您会发现自己拥有一个带有一定数量键的$big_inserts
数组。每个键都将映射一组值,适用于多个插入。
除非你真的非常不走运,否则你的“多次插入”比你开始使用的单个插入要少得多。如果所有插入都具有相同的列,则big_inserts中只有一个键,包含所有元组。
现在,循环使用big_inserts,并为每个键准备一个语句。要发送到PDO的值数组是$big_inserts[$key]
中所有元组的串联。
foreach($big_inserts as $fields => $lot)
{
$SQL = "INSERT INTO table ($fields) VALUES ";
// I need a (?.?.?---) tuple
$tuple = '('.implode(',', array_fill(0, count($lot[0]), '?')).')';
// How many tuples are in a lot?
$SQL .= implode(',', array_fill(0, count($lot), $tuple));
$values = array();
foreach($lot as $set)
$values = array_merge($values, $set);
// Now $SQL has all the '?'s, and $values contains all the values.
// Run the statement.
}
如果这还不够,您可能必须将这些语句分成块,将它们保存在会话中并按顺序执行每个块,也许使用单独的表来模拟“多次往返”事务(如果连接丢失/用户关闭浏览器/其他一半已经执行的块,另一半仍然要去。使用直接INSERT到具有相同结构的表中,然后当表准备就绪时,在事务中运行一个INSERT INTO ... SELECT FROM提交后删除辅助表。
如果它们是简单的INSERT,我会尝试暂时禁用某些索引,但是你依赖它们进行ON DUPLICATE KEY UPDATE,所以这是不行的。
答案 1 :(得分:0)
一次将其分成50个插入,将其分成12个文件并按顺序执行。简单的javascript,可以在完成时重定向到下一个。
如果只是一次性交易可能是最简单的解决方案。
否则发布一些示例代码,以便我们提供一些更有帮助的答案。
答案 2 :(得分:0)
您的插入是否在mysql事务中执行?如果没有,这可能有助于提高您的表现。
http://kevin.vanzonneveld.net/techblog/article/improve_mysql_insert_performance/