Убийство запросом (insert into select from)

Access Violation, некорректное выполнение запросов или вызовов API, ошибки утилит командной строки, в общем все, что вам мешает работать

Модераторы: kdv, dimitr

Ответить
Lars
Сообщения: 86
Зарегистрирован: 21 дек 2005, 16:34

Убийство запросом (insert into select from)

Сообщение Lars » 23 авг 2006, 06:20

В книге Т. Кайта по Oracle дается пример многоверс. архитектуры СУБД и приводится след. пример:

Код: Выделить всё

for х in (select * from t)
loop
insert into t values (x.username, x.user_id, x.created);
end loop ;

Синтаксис ORACLE, идея след.: открываем запрос на выборку и проходя по набору добавляем в эту же табличку данные!

Вот такая ХП получилась у меня в FB 1.5.3:

Код: Выделить всё

CREATE PROCEDURE TEST_PROC 
as
declare variable name_product varchar(80);
begin
  i=0;
  for select name from product into :name_product
  do
  begin
    insert into product (NAME) VALUES (:name_product );--уник. индекса по NAME нет
  end
  suspend;
end;
И получил максимум использ. проц. времени на fbserver.

Это так должно быть???

Lars
Сообщения: 86
Зарегистрирован: 21 дек 2005, 16:34

Сообщение Lars » 23 авг 2006, 07:53

Проверил на FB 1.5.3 и FB 2 RC 4.

На фб 2 работает около уже около 15 минут, нагрузка на проц. полная, файл с 7 Мб увелич. до 152 Мб.

Dimitry Sibiryakov
Заслуженный разработчик
Сообщения: 1436
Зарегистрирован: 15 сен 2005, 09:05

Сообщение Dimitry Sibiryakov » 23 авг 2006, 08:21

Это такой старый баян, что его уже никто и не принимает всерьез. Да, жар-птичку INSERT INTO table SELECT FROM table загоняет в бесконечный цикл. Малой кровью не фиксится ибо заложено в самой глубине архитектуры.

kdv
Forum Admin
Сообщения: 6595
Зарегистрирован: 25 окт 2004, 18:07

Сообщение kdv » 23 авг 2006, 10:08

потому что insert into select from все зависит от селекта. если селект выбирает записи поштучно (а не буферизирует все например при plan sort, или group by), то и insert идет поштучно. отсюда зацикл.
и никакого сравнения многоверсионной архитектуры СУБД тут нет.

Lars
Сообщения: 86
Зарегистрирован: 21 дек 2005, 16:34

Сообщение Lars » 23 авг 2006, 21:32

kdv писал(а): и никакого сравнения многоверсионной архитектуры СУБД тут нет.
Почему это нет? Разве на момент запуска SELECT не должен браться снимок таблицы, ведь я использую даже не

Код: Выделить всё

INSERT INTO table SELECT FROM table
а последовательный перебор в цикле в ХП.

Merlin
Динозавр IB/FB
Сообщения: 1502
Зарегистрирован: 27 окт 2004, 11:44

Сообщение Merlin » 23 авг 2006, 21:51

Lars писал(а):
kdv писал(а): и никакого сравнения многоверсионной архитектуры СУБД тут нет.
Почему это нет? Разве на момент запуска SELECT не должен браться снимок таблицы, ведь я использую даже не

Код: Выделить всё

INSERT INTO table SELECT FROM table
а последовательный перебор в цикле в ХП.
Видимостью записей заведует не оператор, а транзакция. Транзакция, независимо от уровня изоляции, всегда видит результаты своей работы. Чужой работы - в зависимости от уровня изоляции. Чтобы получить снимок на момент завершения селект, добавь в селект сортировку по какому-нибудь неиндексированному полю, тогда в процессе сортировки сначала будет сформирован в сторонке резалтсет и только потом пойдут инсёрты. Это трюк, использование особенностей implementation. Снимок на момент запуска селект получить невозможно. Можно добиться того, чтобы эти снимки были идентичны - выполнять в снапшоте и внутри этой транзакции до выполнения этого оператора эту таблицу не трогать, в смысле не модифицировать. Но это будет снимок на момент запуска транзакции.

Lars
Сообщения: 86
Зарегистрирован: 21 дек 2005, 16:34

Сообщение Lars » 23 авг 2006, 22:23

Вообще это недочет СУБД или архитектурная задумка?

Если недочет, то почему не правится?

Dimitry Sibiryakov
Заслуженный разработчик
Сообщения: 1436
Зарегистрирован: 15 сен 2005, 09:05

Сообщение Dimitry Sibiryakov » 24 авг 2006, 07:44

То что в пределах транзакции видны ее изменения это, конечно, задумка. Нестабильность в пределах одного статемента это скорее недочет. Не правится потому что, как я написал выше, очень глубоко зарыт.

Lars
Сообщения: 86
Зарегистрирован: 21 дек 2005, 16:34

Сообщение Lars » 24 авг 2006, 08:05

Проблема решена, ответы получены.
Думаю, что тема закрыта.
Спасибо за ответы.

kdv
Forum Admin
Сообщения: 6595
Зарегистрирован: 25 окт 2004, 18:07

Сообщение kdv » 24 авг 2006, 10:22

я тебе посоветую почитать топик на sql.ru, где в частности я подробно описал неатомарность select в read_committed. А то там некоторые чуть ли не в обморок от этого падали :)

начиная с моего сообщения на эту тему, и дальше
http://www.sql.ru/forum/actualthread.as ... fc#1447129

или отсюда
http://www.sql.ru/forum/actualthread.as ... 73455&pg=2

dimitr
Разработчик Firebird
Сообщения: 888
Зарегистрирован: 26 окт 2004, 16:20

Сообщение dimitr » 25 авг 2006, 10:03

на самом деле, именно это поведение исправить несложно. Но проблема много ширше и править надо все сразу. А это уже действительно нетривиально.

Dimitry Sibiryakov
Заслуженный разработчик
Сообщения: 1436
Зарегистрирован: 15 сен 2005, 09:05

Сообщение Dimitry Sibiryakov » 25 авг 2006, 10:49

Угу, запуск селекта в отдельной транзакции... Остается всего полшага до запуска этого селекта с другим tdbb, а это уже полный ахтунг. :lol:

dimitr
Разработчик Firebird
Сообщения: 888
Зарегистрирован: 26 окт 2004, 16:20

Сообщение dimitr » 25 авг 2006, 11:09

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

Lars
Сообщения: 86
Зарегистрирован: 21 дек 2005, 16:34

Сообщение Lars » 25 авг 2006, 18:52

Dimitry Sibiryakov писал(а):Угу, запуск селекта в отдельной транзакции... Остается всего полшага до запуска этого селекта с другим tdbb, а это уже полный ахтунг. :lol:
ну а если открыть набор данных как снэпшот и дувайловским циклом проходить и добавлять? Пройдет же все в норме?

kdv
Forum Admin
Сообщения: 6595
Зарегистрирован: 25 окт 2004, 18:07

Сообщение kdv » 25 авг 2006, 18:58

ну а если открыть набор данных как снэпшот
во-первых, что значит "открыть набор" - это ж сервер, он целым "набором" не оперирует. Во-вторых - "как снэпшот" - нет такого понятия. есть snapshot-транзакция.

Lars
Сообщения: 86
Зарегистрирован: 21 дек 2005, 16:34

Сообщение Lars » 26 авг 2006, 10:25

Открыть набор в рамках snapshot-транзакции. Вот так именно я и хотел сказать :)

а потом его перебирать

kdv
Forum Admin
Сообщения: 6595
Зарегистрирован: 25 окт 2004, 18:07

Сообщение kdv » 26 авг 2006, 11:03

Lars, ты ведь так и не читал тот топик на sql.ru, который я тебе посоветовал. Еще раз замечу - будут санкции.

Lars
Сообщения: 86
Зарегистрирован: 21 дек 2005, 16:34

Сообщение Lars » 27 авг 2006, 21:36

kdv писал(а):Lars, ты ведь так и не читал тот топик на sql.ru, который я тебе посоветовал. Еще раз замечу - будут санкции.
Перечитал повторно!
И вот это имеет там смысл:
kdv писал(а): ...если нас напрягает "невоспроизводимость чтения" в read_committed, то мы должны использовать snapshot

kdv
Forum Admin
Сообщения: 6595
Зарегистрирован: 25 окт 2004, 18:07

Сообщение kdv » 27 авг 2006, 23:01

теперь ты меня убеди, что снапшот для запроса в read-committed имеет смысл. еще раз подчеркиваю, что update ... where field in (select) к этому отношения не имеет.

Ответить