Страница 1 из 1
разница в скорости выполнения простого апдейта
Добавлено: 29 янв 2008, 22:19
vik
есть простая таблица из 8 int полей, одно из которых field. триггеров не считая стандартного на айдишник нет, индекса на поле field нет. в таблице порядка 5-6К записей. открываем ibexpert и пишем
выполняем несколько раз подряд - время выполнения меняется от 0,5 сек до 5-6!!! секунд.
других подключений к FB нет (FB 2.0). план - natural.
насколько я понял из статистики в первом случае
Код: Выделить всё
Writes from cache to disk = 0
Fetches from cache = 54 334
и во втором
Код: Выделить всё
Writes from cache to disk = 7 430
Fetches from cache = 118 119
задержка выполнения связана с обработкой кеша и сбрасыванием на диск. проблема в том, что подобные запросы выполняются несколько раз подряд (в одной транзакции) и это подвисание очень не в тему. можно ли сделать так, чтобы данный запрос выполнялся стабильно быстро, т.е. порядка 0,5 сек??
всем заранее спасибо...
Добавлено: 29 янв 2008, 23:10
kdv
теоретически можно, но вообще - нельзя, и нет смысла. Потому что:
www.ibase.ru/devinfo/test3.htm
описание в деталях (есть эта же ссылка в начале предыдущей статьи)
http://ibdeveloper.com/issues/issue-2-o ... rbase-751/
также неплохо прочитать вот это:
http://www.sql.ru/forum/actualthread.as ... =4#3577997
Добавлено: 30 янв 2008, 08:46
dimitr
я бы сказал, что даже теоретически нельзя. Ибо второй апдейт в той же транзакции превращает предыдущую дельту в полноценную запись, что и приводит к большему I/O. Последующие, соотв-но, тоже работают с полной версией. Это архитектурная фича и ее не обойти. В противном случае плодились бы версии записи и скорость линейно падала бы на каждом последующем апдейте.
Добавлено: 30 янв 2008, 15:51
vik
пасиб за инфу. насколько я понял no savepoints в моём варианте должен решить проблему. я только не совсем понял что должно значить вот это (из summary статьи на айбидеве)
Because the option can create its own problems by inhibiting the advance of the OIT, it should be used with caution, of course. The developer will need to take extra care about database housekeeping, particularly with respect to timely sweeping.
в чём эти own problems заключаются и с чем я должен быть so much carefull? и кстати это нормально если у меня параллельно часть транзакций будет с savepoints, а часть без??
плюс есть ещё такой момент. насколько я понял если сборка мусора пройдет в перерывах между обработкой действий юзверя, то собсно время на эту обработку должно уйти меньше. т.е. с точки зрения конечного результата оно будет работать якобы быстрее. вопрос: как гарантировано "спровоцировать" сборку мусора? через api?
Добавлено: 30 янв 2008, 22:40
kdv
в чём эти own problems заключаются и с чем я должен быть so much carefull? и кстати это нормально если у меня параллельно часть транзакций будет с savepoints, а часть без??
www.ibase.ru/devinfo/garbage.htm
www.ibase.ru/devinfo/summary.htm
насколько я понял если сборка мусора пройдет в перерывах между обработкой действий юзверя, то собсно время на эту обработку должно уйти меньше. т.е. с точки зрения конечного результата оно будет работать якобы быстрее. вопрос: как гарантировано "спровоцировать" сборку мусора? через api?
www.ibase.ru/devinfo/sweep.htm
Добавлено: 31 янв 2008, 16:38
vik
тяжеловато чтото переварить это всё

объясните плз такую весчь:
1. если не-commited значение может быть только одно, то значит после трёх апдейтов подряд в одной транзакции у мну будет одна версионная запись? т.е. дельта будет переписываться исходя из сравнения значения из каждого апдейта с исходной записью? Или всё таки три, каждая из которых завязана на своём сейвпоинте?
2. по аналогии получаеца если я удаляю запись, потом инсертю новую и потом её обновляю, то должно быть две версионных записи - одна на удалённую и одна по сути дельта от пустой. И после комита они станут мусором? или опять же их будет три?
просветите плз...
Добавлено: 31 янв 2008, 17:05
vik
да, забыл ещё спросить про retaining

1. в одной из статей сказано, что по факту retaining стартует новую транзакцию (если были изменены какие-нить данные). при этом там же сказано
Не рекомендуется слишком часто завершать одну и ту же транзакцию по retaining, или производить в каждом таком "интервале" много изменений - это чревато появлением ошибки 287 "too many savepoints" в interbase.log
Если не ошибаюсь сейвпоинты являются составляющей транзакций, но никак не наоборот. Если retaining фактически завершает транзакцию, то он же должен очистить стек сейвпоинтов? или этот стек входит в контекст транзакции и передаётся по наследству при retaining?
2. из той же статьи
Кроме того, транзакция, завершаемая по CommitRetaining, с точки зрения сервера и сборки мусора выглядит как длительно работающая транзакция SNAPSHOT (то есть, CommitRetaining в этом плане не является аналогом Commit). А это значит, что CommitRetaining фактически препятствует сборке мусора, независимо от типа транзакции - Snapshot или ReadCommitted.
Нужно ли это понимать так, что мусорные версии не становяться мусором и не будут собраны до тех пор, пока не будет вызван Commit?
Добавлено: 31 янв 2008, 19:42
kdv
Нужно ли это понимать так
да, так это нужно понимать.
1. если не-commited значение может быть только одно, то значит после трёх апдейтов подряд в одной транзакции у мну будет одна версионная запись?
разумеется. версия идентифицируется номером транзакции, ее создавшей. Соответственно, не может быть трех версий с одинаковым идентификатором.
2. по аналогии получаеца если я удаляю запись, потом инсертю новую и потом её обновляю, то должно быть две версионных записи - одна на удалённую и одна по сути дельта от пустой.
не знаю, где аналогия. При удалении записи будет создана версия с признаком удаления. При создании записи будет новая запись. При ее обновлении - еще версия у новой записи.
удаленная и новая - две разные записи. что-то ты фигню какую-то спрашиваешь.
www.ibase.ru/devinfo/mga.htm читал?
И после комита они станут мусором?
какой еще мусор после commit??? нифига не читал.
Лучше почитай, а потом спрашивай.
Добавлено: 31 янв 2008, 19:45
kdv
тяжеловато чтото переварить это всё
кстати, ты не в том порядке это читаешь.
начинать надо с mga.htm . потом читать остальные статьи garbage.htm, swepp.htm, utl.htm и так далее.
и в последнюю очередь те статьи про внутренний механизм savepoints.
Кстати, неясно, зачем тебе понадобилось массовый апдейт одних и тех же записи в одной транзакции делать. Блокируешь? читай
www.ibase.ru/devinfo/pslock.htm
Добавлено: 31 янв 2008, 20:27
vik
кстати, ты не в том порядке это читаешь.
вообще я уже весь раздел транзакций по несколько раз перечитал ))
не знаю, где аналогия
аналогия в работе с версиями записей. кароче всё правильно, только упустил что инсерт тоже создаёт свою версию.
какой еще мусор после commit???
я имел в виду, что единственная ситуация когда версии записей становятся мусором и могут быть удалены - это перевод транзакции в подтверждённое состояние. а пока транзакция активна в любом случае живут ВСЕ созданные в этой транзакции версии. Верно?
так как быть с сейвпоинтами? Если retaining фактически завершает транзакцию, то он же должен очистить стек сейвпоинтов? или этот стек входит в контекст транзакции и передаётся по наследству при retaining?
и кстати ещё такой момент. если policy = cooperative и мы удаляем записи, то что будет считаться обращением к удалённым записям, которое должно инициировать сборку мусора? любое обращение к таблице? или то что переберает всю таблицу аля select count?
Кстати, неясно, зачем тебе понадобилось массовый апдейт одних и тех же записи в одной транзакции делать. Блокируешь?
Нет, блокировок там нет. просто пытался упростить алгоритм, но производительность слишком упала. так что пришлось переделать расчёт и уменьшить количество модификаций.
Добавлено: 31 янв 2008, 22:08
kdv
че-то ты фигово читаешь. никак у тебя не складывается, и читаешь ты явно мимо, с пропусками.
я имел в виду, что единственная ситуация когда версии записей становятся мусором и могут быть удалены - это перевод транзакции в подтверждённое состояние. а пока транзакция активна в любом случае живут ВСЕ созданные в этой транзакции версии. Верно?
не так. пока активна транзакция, которая МОЖЕТ прочитать нужную ей версию, версии удерживаются от сборки мусора.
кроме того, commit сам по себе ничего не освобождает. Интервал проверки на "мусорность" - это OIT, OAT, OST, Next (header page). А он меняется только когда стартует новая транзакция. Т.е. например, если есть старая активная транзакция, то это OAT. Если эта транзакция завершится коммитом, никто об этом не узнает до тех пор, пока не стартанет новая транзакция, и OAT в header page изменится.
так как быть с сейвпоинтами? Если retaining фактически завершает транзакцию, то он же должен очистить стек сейвпоинтов? или этот стек входит в контекст транзакции и передаётся по наследству при retaining?
при чем тут сэйвпойнты??? не надо думать про версии и мусор вместе с сэйвпойнтами. Сэйвпойнты - это внутренний механизм сервера, который предназначен для ОТКАТА изменений. В базе, на диске, никаких сэйвпойнтов нет - они есть только в памяти.
так вот, retaining НАСЛЕДУЕТ локальные OAT/OST старой транзакции со всеми вытекающими.
и кстати ещё такой момент. если policy = cooperative и мы удаляем записи, то что будет считаться обращением к удалённым записям, которое должно инициировать сборку мусора? любое обращение к таблице? или то что переберает всю таблицу аля select count?
тьфу, блин. вот опять, не читал ты garbage.htm . Там же написано, что мусорные версии удаляются только при чтении или обновлении. Накой фиг серверу проверять мусор во всей таблице, если конкретный запрос например обращается только к ЧАСТИ таблицы? Опять же, в garbage.htm этот момент ОПИСАН СПЕЦИАЛЬНО!!!
просто пытался упростить алгоритм, но производительность слишком упала. так что пришлось переделать расчёт и уменьшить количество модификаций.
может, тебе надо временные таблицы FB 2.1 ? там нет никакого мусора, версий и т.п.
Добавлено: 31 янв 2008, 22:12
kdv
короче. я считаю что ответы на твои вопросы есть в статьях, на которые я специально указываю.
например, garbage.htm :
кооперативная явная. используется в Classic и во всех версиях до InterBase 6 SuperServer (также оставлена в Yaffil, как Classic так и SuperServer). Мусор убирается пользовательским процессом (или thread-ом) только в тех данных, которые читаются или обновляются.
...
Мусорными версии записей становятся, когда нет транзакций, которые в них нуждаются. То есть, когда идентификатор транзакции версии записи меньше номера транзакции Oldest Snapshot в Header Page. Это означает, что пока есть долгоживущие активные транзакции, версии записей не станут "мусором" и не будут убраны кооперативной сборкой мусора или запуском sweep.
При отсутствии длительно работающих транзакций, для сборки мусора требуется обращение к записи.
Таким образом, существует два случая - один общий, это "нечтение" записей, где есть мусорные версии, и второй - для SuperServer, когда даже обновление записей не приводит к сборке мусора (фоновый сборщик мусора или "не успевает" или "не может").
цитировать дальше интереса нет. Буду отвечать на вопросы, которые могут быть непонятны в статьях, со ссылками на фразы из статей.
Добавлено: 31 янв 2008, 22:57
vik
че-то ты фигово читаешь. никак у тебя не складывается, и читаешь ты явно мимо, с пропусками.
та нормально я читаю, просто разобраться с этим не так просто, как хотелось бы... сори, может спрашиваю нетак, просто иногда очень нуна услышать ту же мысль но другими словами. зато теперь я начинаю понимать каким образом оно работает
на тему
Не рекомендуется слишком часто завершать одну и ту же транзакцию по retaining, или производить в каждом таком "интервале" много изменений - это чревато появлением ошибки 287 "too many savepoints" в interbase.log
- т.е. получаеца что ретейнинг тут не при чём, а лимит сейвпоинтов может быть превышен просто из-за слишком большого количества операций? т.е. того же эффекта можно достигнуть просто запустив в цикле update по таблице записей эдак на 5М?
и кстати ещё такой момент. если policy = cooperative и мы удаляем записи, то что будет считаться обращением к удалённым записям, которое должно инициировать сборку мусора? любое обращение к таблице? или то что переберает всю таблицу аля select count?
тьфу, блин. вот опять, не читал ты garbage.htm . Там же написано, что мусорные версии удаляются только при чтении или обновлении. Накой фиг серверу проверять мусор во всей таблице, если конкретный запрос например обращается только к ЧАСТИ таблицы? Опять же, в garbage.htm этот момент ОПИСАН СПЕЦИАЛЬНО!!!
подожди, наверно я не удачно описал.
Во-первых - если политика cooperative, то фонового процесса нет и сборка мусора осуществляется либо а) при чтении/обновлении данных либо б) при авто sweep'e. предположим что автосвип мы отключили, т.е. мусор может быть удалён только при чтении/обновлении.
Во-вторых - Теперь возьмём таблицу в которой есть десяток записей, удаляем их все и комитим транзакцию.
Вопрос: верно ли во-первых, и если да то когда и при каком запросе будут собраны мусорные записи от
удалённых записей?
если я сделаю select * from table where id = 15 это приведёт к сборке мусора от удалённых записей??
т.е. я хочу сказать, что удалённые записи никто ни читать, ни обновлять не будет, соответственно кто тогда собирёт мусор от удалённых записей??
может, тебе надо временные таблицы FB 2.1 ? там нет никакого мусора, версий и т.п.
не видел ещё таких, пасиб посмотрю...
Добавлено: 01 фев 2008, 10:11
kdv
т.е. получаеца что ретейнинг тут не при чём
примерно так. правда, ошибка и ее причины выявлены не по коду, а по откликам. так что указанная ошибка появляется именно в указанной ситуации.
запустив в цикле update по таблице записей эдак на 5М?
где у каждой записи пара триггеров, которые что-нибудь еще делают с другими таблицами, где опять есть тригггеры...
Во-первых - если политика cooperative, то фонового процесса нет и сборка мусора осуществляется либо а) при чтении/обновлении данных либо б) при авто sweep'e.
ручной или авто-свип ВСЕГДА является сборкой мусора, принудительной, поэтому в контесте ТИПА сборки мусора о нем говорить нельзя.
предположим что автосвип мы отключили, т.е. мусор может быть удалён только при чтении/обновлении.
ок
Вопрос: верно ли во-первых, и если да то когда и при каком запросе будут собраны мусорные записи от удалённых записей?
стартует транзакция, в этой транзакции выполняется запрос, который обращается к этим записям. при чтении версий (select/update) сервер проверит их на мусорность, и если нет других транзакций которые заинтересованы в старых версиях, то записи будут удалены.
сделаю select * from table where id = 15 это приведёт к сборке мусора от удалённых записей??
если хоть одна удаленная запись попадает под такое условие - "у нее" и будет собран мусор.
забодал ты с этим вопросом, честное слово.

есть запись. У НЕЕ могут быть версии. Если ЭТУ ЗАПИСЬ читают или обновляют, и среди ЕЕ версий обнаруживаются мусорные, то ТОЛЬКО ЭТИ мусорные версии будут удалены.
я тебе уже третий раз про это талдычу.
соответственно кто тогда собирёт мусор от удалённых записей??
млин, НИКТО НЕ СОБИРАЕТ. О чем и написано в garbage.htm !!!
я сейчас в бешенство приду....
Давайте рассмотрим примеры систем, в которых может происходить подобное накопление мусорных версий
и с этого места идут описания как минимум ДВУХ случаев когда мусор образуется и НЕ СОБИРАЕТСЯ.
И после этого ты говоришь что нормально читаешь? Я если чего-то интересующее меня не понимал, читал по 5-10 раз, пока не доходило.
Добавлено: 01 фев 2008, 11:59
vik
сделаю select * from table where id = 15 это приведёт к сборке мусора от удалённых записей??
если хоть одна удаленная запись попадает под такое условие - "у нее" и будет собран мусор.
Вот!! Вот этого мне и не хватало

Просто я никак не мог понять что значит читать или обновлять удалённые записи.
Короче теперь всё стало на свои места. Если говорить другими словами, то получается что на уровне внутреннего представления данных движок оперирует не набором записей, а набором различных версий, и жизненный цикл версий прилично отличается от цикла записей (я имею в виду записей как набора данных с точки зрения конечного пользователя). Причем в каждом отдельном случае запись будет представлена одной из версий в зависимости от того, какой TIP использует транзакция, какие ещё транзакции работают с версиями этой записи и т.д. И вообще получается, что для всех алгоритмов первичными данными является набор версий! А уж как они коррелируют с конечным набором данных, которые получет юзер, это второй вопрос. Например теже индексы строяться по всем версиям записи и тогда понятно откуда берётся мусор в индексах

А разница получается в управлении версиями и тем, какую версию считать актуальной в конкретно взятом контексте. Просто на малых выборках и при малой конкурентности об этом механизме мона и не вспоминать, разницы в производительности всё равно не будет. А вот на большом объёме и при большой нагрузке это всё нуна держать в уме - и количество версий которые плодят разные операции, и когда и как будет проходить сборка мусора, и распределение объёма операций по транзакциям. Тогда в результате производительность может меняться на порядки. По идее в конечном счёте это всё имеет смысл учитывать именно ради производительности, имхо архитектура при высокой конкурентности это уже несколько о другом и вообще другой разговор.
Если я сейчас в чём ошибся - пристрелите меня нахрен. Если нет - Дим, тебе большой респект и спасибо за просвещение, а я пошёл перечитывать, теперь там для меня будет на порядок больше смысла

Добавлено: 01 фев 2008, 13:14
kdv
Просто я никак не мог понять что значит читать или обновлять удалённые записи.
мда.
Если говорить другими словами, то получается что на уровне внутреннего представления данных движок оперирует не набором записей, а набором различных версий
Разумеется. Есть записи, у записей - версии. Сервер читает пакет версий одной записи, затем смотрит какую версию можно показывать данной транзакции.
Это написано в статьях, черным по белому.
причем в каждом отдельном случае запись будет представлена одной из версий в зависимости от того, какой TIP использует транзакция, какие ещё транзакции работают с версиями этой записи и т.д.
Видимость версий описана в
www.ibase.ru/devinfo/mga.htm
конкурирующие транзакции на видимость версий никак не влияют.
видимость определяется только уровнем изоляции конкретной транзакции, а также состоянием транзакции, номер которой прописан в конкретной версии.
например теже индексы строяться по всем версиям записи и тогда понятно откуда берётся мусор в индексах
разумеется. с поправкой - мусор, он и в африке мусор. у версии разумеется есть ключи в индексах. Когда версия становится мусорной, то же и с ключами происходит. Только у ключей нет идентификаторов транзакций.
А вот на большом объёме и при большой нагрузке
для того я и сделал IBAnalyst, чтобы все это можно было смотреть визуально.
имхо архитектура при высокой конкурентности это уже несколько о другом и вообще другой разговор.
не согласен. потому что любая долгоживущая транзакция приводит к росту числа версий, если конечно данные обновляются и удаляются. В любой системе - с одним пользователем или 500, в базе 100мб или 100гб.
Если я сейчас в чём ошибся - пристрелите меня нахрен.
уже почти все ок

на самом деле, проще все это объяснять вживую, на курсах.
Добавлено: 01 фев 2008, 13:30
vik
на самом деле, проще все это объяснять вживую, на курсах.
да, было б неплохо, но пока будем постигать на практике

кстати, теперь я на 95% уверен откуда "периодические необъяснимые тормоза" у одного клиента с довольно старой и кривоватой системой. и база растёт не пропорционально, и бэкапом от 40% до 60% размера убиваецо. наверняка дето мусор зависает, теперь есть куда копать...
В общем исчо раз спасибо
