MySql: работа на многих строках с использованием длинного списка составных ПК - PullRequest
5 голосов
/ 12 февраля 2010

Какой хороший способ работы со многими строками в MySql, учитывая, что у меня есть длинный список ключей в клиентском приложении, которое соединяется с ODBC?

Примечание: мой опыт в основном основан на SQL Server, поэтому я немного знаю, но не MySQL, в частности.

Задача состоит в том, чтобы удалить несколько строк из 9 таблиц, но у меня может быть более 5000 пар ключей.

Я начал с простого способа циклического перебора всех моих ключей и отправки выписки для каждого из них против каждой таблицы, например:

DELETE FROM Table WHERE Key1 = 123 AND Key2 = 567 -- and 8 more tables
DELETE FROM Table WHERE Key1 = 124 AND Key2 = 568 -- and 8 more tables
DELETE FROM Table WHERE Key1 = 125 AND Key2 = 569 -- and 8 more tables
...

За исключением того, что получается 45 000 отдельных утверждений, которые, как вы можете себе представить, немного медленны.

Итак, не беспокоясь о языке программирования, который я использую во внешнем интерфейсе, каков хороший способ отправки списка, чтобы я мог ПРИСОЕДИНЯТЬСЯ и выполнять операцию одновременно или хотя бы большими партиями? Вот мои идеи на данный момент:

  • Создайте временную таблицу и вставьте в нее, затем присоединитесь. Я с радостью найду синтаксис MySQL для создания временной таблицы, но разве это хороший путь?

  • Если я использую временную таблицу, какой метод является лучшим для заполнения временной таблицы ? 5000 INSERT Table VALUES () заявлений? SELECT 123, 456 UNION ALL SELECT 124, 457? Я только что проверил, что MySql допускает такой тип SELECT, который не выдается против таблицы. Но SQL Server в конечном итоге взрывается, если список становится слишком длинным, так что это хороший способ в MySQL? Должен ли я просто сохранить список до нескольких сотен сразу?

    --CREATE Temp Table ( I do not know the syntax in MySql yet)
    
    INSERT INTO TempTable
    SELECT 123, 456
    UNION ALL SELECT 124, 457
    UNION ALL SELECT 125, 458
    
    DELETE T
    FROM
       Table T
       INNER JOIN TempTable X ON T.Key1 = X.Key1 AND T.Key2 = X.Key2
    
  • XML . Я вижу, что MySQL 5.1 имеет некоторые функции XML, но из беглого поиска он не поддерживает превращение фрагмента текста XML в набор строк, к которому можно присоединиться. Это правда? Мне очень легко получить значения в XML.

  • Виртуальная разделенная операция . Я предполагаю, что в MySql есть какой-то процедурный язык. В SQL Server я мог бы написать некоторый пользовательский код, который анализирует строку и превращает ее в набор строк:

    CREATE PROCEDURE DoStuff @KeyString varchar(max)
    AS
    DECLARE @Keys TABLE (
       Key1 int,
       Key2 int,
       PRIMARY KEY CLUSTERED (Key1, Key2)
    )
    DECLARE @Pos int
    WHILE @Pos < Len(@KeyString) BEGIN
       -- loop to search for delimiting commas in @KeyString
       -- and insert pairs of parsed tokens to table variable @Keys
    END
    
    DELETE T
    FROM
       Table T
       INNER JOIN @Keys K ON T.Key1 = K.Key1 AND T.Key2 = K.Key2
    

Так как я незнаком с MySQL, я действительно не знаю, какую возможность сначала исследовать, и я был бы признателен за некоторую помощь, чтобы уберечь меня от неправильного решения и / или трудного обучения.

1 Ответ

2 голосов
/ 12 февраля 2010

Я бы использовал решение временной таблицы и добавил его к каждой основной таблице в операторах DELETE. Таким образом, вам нужно сделать только девять удалений, по одному для каждой таблицы.

  • CREATE TEMPORARY TABLE

    CREATE TEMPORARY TABLE Keys (
        Key1 INT UNSIGNED NOT NULL, 
        Key2 INT UNSIGNED NOT NULL, 
        PRIMARY KEY(Key1, Key2)
    );
    
  • Загрузить файл данных, разделенных табуляцией, во временную таблицу, используя LOAD DATA LOCAL INFILE

    LOAD DATA LOCAL INFILE 'C:/path/to/datafile' INTO TABLE Keys;
    
  • Удалить с использованием многотабличного MySQL DELETE синтаксис.

    DELETE t FROM Table1 t JOIN Keys USING (Key1, Key2);
    DELETE t FROM Table2 t JOIN Keys USING (Key1, Key2);
    DELETE t FROM Table3 t JOIN Keys USING (Key1, Key2);
    DELETE t FROM Table4 t JOIN Keys USING (Key1, Key2);
    DELETE t FROM Table5 t JOIN Keys USING (Key1, Key2);
    DELETE t FROM Table6 t JOIN Keys USING (Key1, Key2);
    DELETE t FROM Table7 t JOIN Keys USING (Key1, Key2);
    DELETE t FROM Table8 t JOIN Keys USING (Key1, Key2);
    DELETE t FROM Table9 t JOIN Keys USING (Key1, Key2);
    

Ваш комментарий:

Документы MySQL на CREATE TABLE говорят следующее:

Таблица TEMPORARY видна только текущему соединению и автоматически удаляется при закрытии соединения. Это означает, что два разных соединения могут использовать одно и то же временное имя таблицы, не конфликтуя друг с другом или с существующей, не являющейся TEMPORARY, таблицей с одним и тем же именем. (Существующая таблица скрыта, пока временная таблица не будет удалена.)

Это довольно ясно!

Что касается загрузки данных, вы можете просто сделать это с INSERT. 5000 строк это не страшно. Я использую PHP-скрипт для загрузки миллионов строк (например, дамп XML-данных StackOverflow) в MySQL, и это занимает всего около 20 минут. Я использую подготовленный оператор и затем выполняю его с параметрами.

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