我使用mysql multiple-row INSERT syntax将大约3000条记录插入到mysql表中。为了简短的例子,该表只有两列。实际的表当然有更多的列,其中有一个有意义的索引...
mysql> INSERT INTO table (A, B) VALUES
("constant", 1),
("constant", 2),
("constant", 3);
您可能会注意到COLUMN A始终是相同的值。
这引出了我的实际问题:是否有一种方法可以将COLUMN A定义为sql insert语句中的常量,如下面的伪代码所述:
mysql> INSERT INTO table (A="constant", B) VALUES
(1),
(2),
(3);
准备好的陈述......
现在这个更具体一点。一些实际的perl代码:
#!/usr/bin/perl -W
use strict;
use warnings;
use DBI;
my $dbh = DBI->connect( 'lalalala' );
my $sth = $dbh->prepare( q|INSERT INTO table (A, B) VALUES ("constant",?)| );
foreach my $increment (1 .. 100000){
$sth->execute( $increment );
}
...
认为这就是我要找的东西?不幸的是,没有。如前所述,我通过TCP / IP与mysql对话。上面的代码实际上是执行此操作
INSERT INTO table (A, B) VALUES ("constant", 1);
INSERT INTO table (A, B) VALUES ("constant", 2);
etc ...
单个sql查询中的每一个。现在更不用说查询时间假设5ms往返时间作为网络开销。在上面的例子中仅有5个seonds。现在......我已经编写了一个函数来解决这个问题并创建一个紧凑的查询,就像你在这个问题中看到的一样。现在想象一个连接的字符串作为一个带有一百万个插入的查询。好吧它有效。喜欢魅力。但是,通过省略VALUE A来节省大约50%的流量,因为它实际上是一个永不改变的常数值会更好。
后
如果你想知道为什么我问这个以及这是什么呢?它归结为一件事:将一个正在发送的字符串(在我的情况下通过网络)汇总到mysql,然后当一半的信息是多余的时,它就会被分开以对它做一些事情......而不是高效的imho。如果有另一种方式 - 很好。如果不是我像以前那样做......带着一种“感觉不对我”的感觉
mysql> INSERT INTO表(A =“常量”,B)值
不,MySQL中没有这样的语法。这是MySQL中INSERT的语法参考页面:https://dev.mysql.com/doc/refman/8.0/en/insert.html
如果要使用多行INSERT,则必须为每行的元组中的每个列提供一个表达式。表达式在每一行上可以是相同的常量,如原始示例中所示:
mysql> INSERT INTO table (A, B) VALUES
("constant", 1),
("constant", 2),
("constant", 3);
或者它可以是一个会话变量(如上面评论的@wchiquito)。
mysql> SET @c = 'constant';
mysql> INSERT INTO table (A, B) VALUES
(@c, 1),
(@c, 2),
(@c, 3);
或者您可以将值加载到临时表中,然后将它们复制到最终表(由上面的Mauricio Javier Biott评论):
mysql> CREATE TEMPORARY TABLE temptable (B INT);
mysql> INSERT INTO temptable (A, B) VALUES
(1),
(2),
(3);
mysql> INSERT INTO table (A, B)
SELECT 'constant', B FROM temptable;
这是另一种解决方案。假设data.txt
仅包含每行需要具有不同值的字段,则可以使用LOAD DATA LOCAL INFILE,并在最终的SET子句中设置不变列。
mysql> LOAD DATA LOCAL INFILE 'data.txt'
INTO TABLE mytable (B)
SET A = 'constant';
你在问题中又发表了一个声明:
...假设5ms往返时间作为网络开销。
我认为这是一个不可能的假设。我刚刚在我的数据中心测量了我的应用程序的网络延迟,它比你建议的小36到50倍。
64 bytes from (10.4.12.100): icmp_seq=1 ttl=64 time=0.112 ms
64 bytes from (10.4.12.100): icmp_seq=2 ttl=64 time=0.138 ms
64 bytes from (10.4.12.100): icmp_seq=3 ttl=64 time=0.103 ms
64 bytes from (10.4.12.100): icmp_seq=4 ttl=64 time=0.108 ms
...
这是每次往返十分之一毫秒,而不是5毫秒。
执行准备语句3000次的网络延迟最多为414毫秒,而不是3000 * 5ms = 15秒。如果网络延迟使您的任务具有不可接受的开销,则需要改进网络。
最后,您可能希望看到我为演示文稿Load Data Fast!所做的基准测试我将单行INSERT与多行INSERT与LOAD DATA进行比较。