Страница 1 из 1
Убийство запросом (insert into select from)
Добавлено: 23 авг 2006, 06:20
Lars
В книге Т. Кайта по 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.
Это так должно быть???
Добавлено: 23 авг 2006, 07:53
Lars
Проверил на FB 1.5.3 и FB 2 RC 4.
На фб 2 работает около уже около 15 минут, нагрузка на проц. полная, файл с 7 Мб увелич. до 152 Мб.
Добавлено: 23 авг 2006, 08:21
Dimitry Sibiryakov
Это такой старый баян, что его уже никто и не принимает всерьез. Да, жар-птичку INSERT INTO table SELECT FROM table загоняет в бесконечный цикл. Малой кровью не фиксится ибо заложено в самой глубине архитектуры.
Добавлено: 23 авг 2006, 10:08
kdv
потому что insert into select from все зависит от селекта. если селект выбирает записи поштучно (а не буферизирует все например при plan sort, или group by), то и insert идет поштучно. отсюда зацикл.
и никакого сравнения многоверсионной архитектуры СУБД тут нет.
Добавлено: 23 авг 2006, 21:32
Lars
kdv писал(а):
и никакого сравнения многоверсионной архитектуры СУБД тут нет.
Почему это нет? Разве на момент запуска SELECT не должен браться снимок таблицы, ведь я использую даже не
а последовательный перебор в цикле в ХП.
Добавлено: 23 авг 2006, 21:51
Merlin
Lars писал(а):kdv писал(а):
и никакого сравнения многоверсионной архитектуры СУБД тут нет.
Почему это нет? Разве на момент запуска SELECT не должен браться снимок таблицы, ведь я использую даже не
а последовательный перебор в цикле в ХП.
Видимостью записей заведует не оператор, а транзакция. Транзакция, независимо от уровня изоляции, всегда видит результаты своей работы. Чужой работы - в зависимости от уровня изоляции. Чтобы получить снимок на момент
завершения селект, добавь в селект сортировку по какому-нибудь неиндексированному полю, тогда в процессе сортировки сначала будет сформирован в сторонке резалтсет и только потом пойдут инсёрты. Это трюк, использование особенностей implementation. Снимок на момент
запуска селект получить невозможно. Можно добиться того, чтобы эти снимки были идентичны - выполнять в снапшоте и внутри этой транзакции до выполнения этого оператора эту таблицу не трогать, в смысле не модифицировать. Но это будет снимок на момент запуска
транзакции.
Добавлено: 23 авг 2006, 22:23
Lars
Вообще это недочет СУБД или архитектурная задумка?
Если недочет, то почему не правится?
Добавлено: 24 авг 2006, 07:44
Dimitry Sibiryakov
То что в пределах транзакции видны ее изменения это, конечно, задумка. Нестабильность в пределах одного статемента это скорее недочет. Не правится потому что, как я написал выше, очень глубоко зарыт.
Добавлено: 24 авг 2006, 08:05
Lars
Проблема решена, ответы получены.
Думаю, что тема закрыта.
Спасибо за ответы.
Добавлено: 24 авг 2006, 10:22
kdv
я тебе посоветую почитать топик на sql.ru, где в частности я подробно описал неатомарность select в read_committed. А то там некоторые чуть ли не в обморок от этого падали
начиная с моего сообщения на эту тему, и дальше
http://www.sql.ru/forum/actualthread.as ... fc#1447129
или отсюда
http://www.sql.ru/forum/actualthread.as ... 73455&pg=2
Добавлено: 25 авг 2006, 10:03
dimitr
на самом деле, именно это поведение исправить несложно. Но проблема много ширше и править надо все сразу. А это уже действительно нетривиально.
Добавлено: 25 авг 2006, 10:49
Dimitry Sibiryakov
Угу, запуск селекта в отдельной транзакции... Остается всего полшага до запуска этого селекта с другим tdbb, а это уже полный ахтунг.

Добавлено: 25 авг 2006, 11:09
dimitr
решается все и без отдельных транзакций, но слишком много неочевидных нюансов и тяжело тестить. Я надеялся закончить к 2.1, но не выходит пока каменный цветок.
Добавлено: 25 авг 2006, 18:52
Lars
Dimitry Sibiryakov писал(а):Угу, запуск селекта в отдельной транзакции... Остается всего полшага до запуска этого селекта с другим tdbb, а это уже полный ахтунг.

ну а если открыть набор данных как снэпшот и дувайловским циклом проходить и добавлять? Пройдет же все в норме?
Добавлено: 25 авг 2006, 18:58
kdv
ну а если открыть набор данных как снэпшот
во-первых, что значит "открыть набор" - это ж сервер, он целым "набором" не оперирует. Во-вторых - "как снэпшот" - нет такого понятия. есть snapshot-транзакция.
Добавлено: 26 авг 2006, 10:25
Lars
Открыть набор в рамках snapshot-транзакции. Вот так именно я и хотел сказать
а потом его перебирать
Добавлено: 26 авг 2006, 11:03
kdv
Lars, ты ведь так и не читал тот топик на sql.ru, который я тебе посоветовал. Еще раз замечу - будут санкции.
Добавлено: 27 авг 2006, 21:36
Lars
kdv писал(а):Lars, ты ведь так и не читал тот топик на sql.ru, который я тебе посоветовал. Еще раз замечу - будут санкции.
Перечитал повторно!
И вот это имеет там смысл:
kdv писал(а):
...если нас напрягает "невоспроизводимость чтения" в read_committed, то мы должны использовать snapshot
Добавлено: 27 авг 2006, 23:01
kdv
теперь ты меня убеди, что снапшот для запроса в read-committed имеет смысл. еще раз подчеркиваю, что update ... where field in (select) к этому отношения не имеет.