Автор Тема: Удаление 10000 записей из таблицы  (Прочитано 6280 раз)

0 Пользователей и 1 Гость просматривают эту тему.

Оффлайн Nikita Krivtsov

  • Заглянувший
  • Новичок
  • *
  • Сообщений: 10
  • +0/-0
  • 0
    • Просмотр профиля
    • http://
Удаление 10000 записей из таблицы
« : 10 Марта 2004, 10:55:26 »
Господа, подскажите:

Есть такая задача:
удалить из таблицы А строки, у которых поле ID встречается в таблице B.

Пишу на ПХП
MySQL версии 3.23.xx !

В таблице А 80000 строк, в таблице В 250000 строк.

Насколько я понял нужно сделать в 2 этапа:

1. выбрать совпадающие айдишники из 2х таблиц, положить их в массив. Массив преобразовать в строку (123, 124, 345, .... 34567)
2. Выполнить Delete from table A where ID in  (123, 124, 345, .... 34567)

Как бы всё должно работать. Но! Один знакомый сказал что существует какое то ограничение на количество элементов в выражении IN ().
В моем случае таких айдишников для удаления может быть от 3000 до 80000.
И вот вроде бы существует ограничение по количеству , примерно 1000 штук?

Что делать??
Как бы не правильно делать удаление where ID in  (80000 значений, перечисленных через запятую), а как по другому сделать не могу придумать :(

Оффлайн fidget

  • Непоседа
  • Глобальный модератор
  • Ветеран
  • *****
  • Сообщений: 607
  • +0/-0
  • 2
    • Просмотр профиля
    • http://
Удаление 10000 записей из таблицы
« Ответ #1 : 10 Марта 2004, 11:38:02 »
Никакого ограничения на кол-во элементов в IN() нет.
Есть ограничение на длинну запроса.

> а как по другому сделать не могу придумать

в этой версии вы никак по другому и не сделаете. Хотите по другому - обновляйте MySQL сервер до 4.0
На Машине Тьюринга далеко не уедешь.

Оффлайн Nikita Krivtsov

  • Заглянувший
  • Новичок
  • *
  • Сообщений: 10
  • +0/-0
  • 0
    • Просмотр профиля
    • http://
Удаление 10000 записей из таблицы
« Ответ #2 : 10 Марта 2004, 11:50:24 »
Цитировать
fidget:
Есть ограничение на длинну запроса.


То есть отсюда следуют и что есть ограничение на количество элементов :)), так как каждый элемент это несколько символов :))

А какова эта максимальная длина запроса? Сколько символов??

Оффлайн fidget

  • Непоседа
  • Глобальный модератор
  • Ветеран
  • *****
  • Сообщений: 607
  • +0/-0
  • 2
    • Просмотр профиля
    • http://
Удаление 10000 записей из таблицы
« Ответ #3 : 10 Марта 2004, 12:46:14 »
1048574 байт
На Машине Тьюринга далеко не уедешь.

Оффлайн Nikita Krivtsov

  • Заглянувший
  • Новичок
  • *
  • Сообщений: 10
  • +0/-0
  • 0
    • Просмотр профиля
    • http://
Удаление 10000 записей из таблицы
« Ответ #4 : 10 Марта 2004, 13:14:51 »
А вот такой вопрос ещё:

Допустим нужно удалить 10000 записей из таблицы (у нас есть список нужных ID для удаления).

В теории как лучше всего делать:
удалить все 10000 записей в виде одного DELETE .. where id in () или сделать 10 раз DELETE и в каждом удалять по 1000 записей?

Другуми словами лучше удалить все записи за один раз, или в несколько приемов по 1000 штук за раз?

Интересует: при каком методе удаление произойдёт быстрее, и при каком методе нагрузка на сервер БД будет меньшей??

Оффлайн Chs

  • Perl программер
  • Глобальный модератор
  • Ветеран
  • *****
  • Сообщений: 1108
  • +0/-0
  • 2
    • Просмотр профиля
    • http://chs.now.at/
Удаление 10000 записей из таблицы
« Ответ #5 : 10 Марта 2004, 13:15:55 »
Можно одним запросом через LEFT JOIN, но запрос тяжелый получается.
2B OR NOT 2B = FF

Оффлайн Chs

  • Perl программер
  • Глобальный модератор
  • Ветеран
  • *****
  • Сообщений: 1108
  • +0/-0
  • 2
    • Просмотр профиля
    • http://chs.now.at/
Удаление 10000 записей из таблицы
« Ответ #6 : 10 Марта 2004, 13:18:36 »
Цитировать
Интересует: при каком методе удаление произойдёт быстрее, и при каком методе нагрузка на сервер БД будет меньшей??

А это сильно зависит от того есть индекс по id или нет.
2B OR NOT 2B = FF

Оффлайн Nikita Krivtsov

  • Заглянувший
  • Новичок
  • *
  • Сообщений: 10
  • +0/-0
  • 0
    • Просмотр профиля
    • http://
Удаление 10000 записей из таблицы
« Ответ #7 : 10 Марта 2004, 14:21:13 »
Цитировать
Chs:
Можно одним запросом через LEFT JOIN, но запрос тяжелый получается.


А примерчик не подкинешь, который бы работал в MySQL версии 3.хх.хх ??

Оффлайн Chs

  • Perl программер
  • Глобальный модератор
  • Ветеран
  • *****
  • Сообщений: 1108
  • +0/-0
  • 2
    • Просмотр профиля
    • http://chs.now.at/
Удаление 10000 записей из таблицы
« Ответ #8 : 10 Марта 2004, 15:51:05 »
fidget права - одним запросом не получится (с select попутал немного), есть правда один извращенный способ:

Sub`SELECT\'s
............

MySQL Server until version 4.0 only supports nested queries of the form
`INSERT ... SELECT ...\' and `REPLACE ... SELECT ...\'.  You can,
however, use the function `IN()\' in other contexts.  Subselects are
being implemented in the 4.1 development tree.

Meanwhile, you can often rewrite the query without a subselect:

     SELECT * FROM table1 WHERE id IN (SELECT id FROM table2);

This can be rewritten as:

     SELECT table1.* FROM table1,table2 WHERE table1.id=table2.id;

The queries:
     SELECT * FROM table1 WHERE id NOT IN (SELECT id FROM table2);
     SELECT * FROM table1 WHERE NOT EXISTS (SELECT id FROM table2
                                            WHERE table1.id=table2.id);

Can be rewritten as:

     SELECT table1.* FROM table1 LEFT JOIN table2 ON table1.id=table2.id
                                            WHERE table2.id IS NULL;

For more complicated subqueries you can often create temporary tables
to hold the subquery.  In some cases, however, this option will not
work. The most frequently encountered of these cases arises with
`DELETE\' statements, for which standard SQL does not support joins
(except in subselects).  For this situation there are two options
available until subqueries are supported by MySQL Server.

The first option is to use a procedural programming language (such as
Perl or PHP) to submit a `SELECT\' query to obtain the primary keys for
the records to be deleted, and then use these values to construct the
`DELETE\' statement (`DELETE FROM ... WHERE ... IN (key1, key2, ...)\').

The second option is to use interactive SQL to construct a set of
`DELETE\' statements automatically, using the MySQL extension `CONCAT()\'
(in lieu of the standard `||\' operator).  For example:

     SELECT CONCAT(\'DELETE FROM tab1 WHERE pkid = \', "\'", tab1.pkid, "\'", \';\')
       FROM tab1, tab2
      WHERE tab1.col1 = tab2.col2;

You can place this query in a script file and redirect input from it to
the `mysql\' command-line interpreter, piping its output back to a
second instance of the interpreter:

     shell> mysql --skip-column-names mydb < myscript.sql | mysql mydb
2B OR NOT 2B = FF

Оффлайн Alexandr

  • Фанат форума
  • Ветеран
  • *****
  • Сообщений: 865
  • +0/-0
  • 0
    • Просмотр профиля
    • http://gtp.hobi.ru
Удаление 10000 записей из таблицы
« Ответ #9 : 11 Марта 2004, 08:43:37 »
CREATE TEMPORARY B_tmp SELECT B.*
FROM B LEFT JOIN A USING(id)
WHERE A.id IS NULL;
DROP TABLE B;
ALTER TABLE B_tmp
RENAME B;

ну, желательно ещё залочить это всё....
Kiss my CSS
Pусские gtp gp3 ( midi + tab ) -   - Все для Авто.

Оффлайн Nikita Krivtsov

  • Заглянувший
  • Новичок
  • *
  • Сообщений: 10
  • +0/-0
  • 0
    • Просмотр профиля
    • http://
Удаление 10000 записей из таблицы
« Ответ #10 : 11 Марта 2004, 10:18:18 »
Господа, спасибо огромное!!! Вы меня направили в нужном направлении :)

 

Sitemap 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28