многострочный синтаксис INSERT в MySQL, где один заполнитель фактически является константой - PullRequest
0 голосов
/ 17 февраля 2019

Я вставляю около 3000 записей в таблицу mysql, используя многострочный синтаксис INSERT mysql .Ради краткого примера в этой таблице всего два столбца.Фактическая таблица (таблицы), конечно, имеет больше столбцов, в которых имеется значимый индекс ...

mysql> INSERT INTO table (A, B) VALUES 
("constant", 1), 
("constant", 2),
("constant", 3);

Как вы можете заметить COLUMN A всегда одно и то же значение.

Что приводит меня к актуальному вопросу: есть ли способ определить COLUMN A как константу в инструкции вставки sql, как описано в следующем псевдокоде :

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 );
}

... 

Думаете, это то, что я ищу?Нет, к сожалению нет.Как упоминалось ранее, я разговариваю с MySQL через TCP / IP.То, что на самом деле делает приведенный выше код, выполняет это

INSERT INTO table (A, B) VALUES ("constant", 1);
INSERT INTO table (A, B) VALUES ("constant", 2);
etc ...

Каждый из них в одном SQL-запросе.Теперь не говоря уже о времени запроса, давайте предположим, что время пересылки по сети равно 5 мсВот только пять секунд в приведенном выше примере.Теперь ... я написал функцию, которая решает этот беспорядок и создает что-то компактное, как вы видите в этом вопросе.Теперь просто представьте объединенную строку как один запрос с миллионом вставок.Ну, это работает.Как колдовство.Однако, экономя около 50 процентов трафика, опуская VALUE A, поскольку это на самом деле постоянное значение, которое никогда не меняется, было бы еще лучше.

Post Scriptum

Если вам интересно почему я спрашиваю это и о чем все это?Это сводится к одной вещи: объединение строки, которая отправляется (по сети в моем случае) в mysql, который затем разделяется, чтобы что-то делать с ним, когда половина информации избыточна ... неэффективно imho.ЕСЛИ есть другой способ - отлично.Если нет, я делаю это так, как раньше ... с частичкой чувства "не чувствую себя хорошо"

1 Ответ

0 голосов
/ 17 февраля 2019

mysql> INSERT INTO table (A = "constant", B) VALUES

Нет, в MySQL такой синтаксис отсутствует.Вот справочная страница синтаксиса для INSERT в MySQL: 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);

Или вы можете загрузить значения во временную таблицу и затем скопировать их в финальную таблицу (прокомментировал Маурисио Хавьер Био) выше:

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';

Вы сделали еще одно утверждение в своем вопросе:

... примите время в 5 мс в качестве перегрузки сети.

Я думаю, это невероятное предположение.Я только что измерил задержку сети моего приложения в моем центре обработки данных, и он в 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 * 5 мс = 15 секунд.Если задержка в сети делает вашу задачу неприемлемой, вы должны улучшить свою сеть.

Наконец, вы можете увидеть тесты, которые я сделал для своей презентации Быстрая загрузка данных! Я сравниваюINSERT с одной строкой или INSERT с несколькими строками и LOAD DATA.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...