Table access full oracle что значит
Описание операций плана выполнения в Oracle
Данная статья представляет собой описание основных операций, отображаемых в планах выполнения запросов СУБД Oracle RDBMS.
Index Unique Scan
Выполняет только обход B-дерева. Эта операция используется, если уникальное ограничение гарантирует, что критерии поиска будут соответствовать не более чем одной записи.
Index Range Scan
Выполняет обход B-дерева и просматривает цепочки конечных узлов, чтобы найти все подходящие записи.
Index Full Scan
Читает индекс целиком (все строки) в порядке, представленном индексом. В зависимости от различной системной статистики СУБД может выполнять эту операцию, если нужны все строки в порядке индекса, например, из-за соответствующего предложения ORDER BY. Вместо этого оптимизатор может также использовать операцию Index Fast Full Scan и выполнить дополнительную операцию сортировки.
Index Fast Full Scan
Читает индекс целиком (все строки) в порядке, хранящемся на диске. Эта операция обычно выполняется вместо полного сканирования таблицы, если в индексе доступны все необходимые столбцы. Подобно операции TABLE ACCESS FULL, INDEX FAST FULL SCAN может извлечь выгоду из многоблочных операций чтения.
Table Access By Index ROWID
Извлекает строку из таблицы, используя ROWID, полученный из предыдущего поиска по индексу.
Table Access Full
Полное сканирование таблицы. Читает всю таблицу (все строки и столбцы), в порядке, хранящемся на диске. Хотя многоблочные операции чтения значительно повышают скорость сканирования полной таблицы, это все еще одна из самых дорогих операций. Помимо высоких затрат времени ввода-вывода, полное сканирование таблицы должно проверять все строки таблицы, что также занимает значительное количество процессорного времени.
Merge Join
Соединение слиянием объединяет два отсортированных списка. Обе стороны объединения должны быть предварительно отсортированы.
Nested Loops
Соединение вложенными циклами объединяет две таблицы, выбирая результат из одной таблицы и запрашивая другую таблицу для каждой строки из первой. Встречается очень часто. Выполняет довольно эффективное соединение относительно небольших наборов данных. Соединение вложенными циклами не требует сортировки входных данных.
Hash Join
Хеш-соединение загружает записи-кандидаты с одной стороны соединения в хеш-таблицу, которая затем проверяется для каждой строки с другой стороны соединения. Операция используется всегда, когда невозможно применить другие виды соединения: если соединяемые наборы данных достаточно велики и/или наборы данных не упорядочены по столбцам соединения.
Sort Unique
Сортирует строки и устраняет дупликаты.
Hash Unique
Более эффективная реализация алгоритма сортировки и устранения дупликатов с использованием хэш-таблицы. Заменяет операцию Sort Unique в определенных обстоятельствах.
Sort Aggregate
Вычисляет суммарные итоги с использованием агрегатных функций SUM, COUNT, MIN, MAX, AVG и пр.
Sort Order By
Сортирует результат в соответствии с предложением ORDER BY. Эта операция требует больших объемов памяти для материализации промежуточного результата.
Sort Group By
Сортирует набор записей по столбцам GROUP BY и агрегирует отсортированный результат на втором этапе. Эта операция требует больших объемов памяти для материализации промежуточного результата.
Sort Group By Nosort
Агрегирует предварительно отсортированный набор записей в соответствии с предложением GROUP BY. Эта операция не буферизует промежуточный результат.
Hash Group By
Группирует результат, используя хеш-таблицу. Эта операция требует больших объемов памяти для материализации промежуточного набора записей. Вывод не упорядочен каким-либо значимым образом.
Filter
Применяет фильтр к набору строк.
Создает промежуточное представление данных.
Count Stopkey
Прерывает выполение операций, когда было выбрано нужное количество строк.
Sort Join
Сортирует набор записей в столбце соединения. Используется в сочетании с операцией Merge Join для выполнения сортировки соединением слияния.
Intersection
Выполняет операцию пересечения между двумя источниками.
Union-All
Выполняет операцию объединения всех записей между двумя таблицами. Дублирующиеся строки не удаляются.
Load As Select
Прямая загрузка с использованием оператора SELECT в качестве источника.
Temp Table Generation/Transformation
Создает/преобразует временную таблицу. Используется в специфичных для Oracle преобразованиях типа Star.
Методы доступа к данным в Oracle
Не найдя на хабре статьи, объединяющей в удобном для чтения виде информацию о методах доступа к данным, используемых СУБД Oracle, я решил совершить «пробу пера» и написать эту статью.
Общая информация
Не углубляясь в детали, можно утверждать что Oracle хранит данные в таблицах, вместе с которыми могут существовать особые структуры данных – индексы, призванные ускорить запросы к таблицам. При выполнении запросов Oracle по-разному обращается к таблицам и индексам – способы доступа к данным в различных ситуациях и являются предметом этой статьи.
Для примеров мы будем использовать следующую таблицу и данные в ней:
Для анализа плана выполнения запроса будем пользоваться следующими средствами:
После создания индекса и использования его в примерах и перед созданием следующего индекса, он должен быть удален. Это можно сделать с помощью следующего запроса:
TABLE FULL SCAN
Данный метод доступа, как следует из названия, подразумевает перебор всех строк таблицы с исключением тех, которые не удовлетворяют предикату where (если таковой есть). Применяется он либо в случае, когда условия предиката отсутствуют в индексе, либо когда индекса нет в принципе. Примеры:
TABLE ACCESS BY ROWID, он же ROWID
INDEX FULL SCAN
Данный метод доступа просматривает все листовые блоки индекса для поиска соответствий условиям предиката. Для того чтобы Oracle мог применить этот метод доступа, хотя бы одно из полей ключа должно иметь ограничение NOT NULL, т.к. только в этом случае соответствующая строка таблицы попадет в индекс. Этот метод обычно быстрее чем TABLE FULL SCAN, но медленнее, чем INDEX RANGE SCAN (см. ниже).
INDEX FAST FULL SCAN
Этот метод доступа применяется, когда выполнены все требования для INDEX FULL SCAN, а также все данные, выбираемые запросом, содержатся в индексе и таким образом доступ к самой таблице не требуется. В отличие от INDEX FULL SCAN этот метод может читать блоки индекса в несколько параллельных потоков и таким образом порядок возвращаемых значений не регламентирован. Oracle также не может использовать этот метод для bitmap-индексов.
Soft — Consulting
Построение запросов (ORACLE)
Оглавление:
Структуры данных для примеров.
Рекомендации по оптимизации запросов
Данные рекомендации взяты мной из руководства Oracle по настройке базы данных, со временем они практически не меняются, посмотреть их можно здесь, это глава 11.5. Ссылка может не работать, все зависит от того, как долго Oracle решит хранить этот фрагмент документации в интернете.
Не используйте SQL-функции в предикатах. Любое выражение в котором используется колонка (expression), например функция, использующая колонку, как аргумент, приведет к тому, что индекс для данной колонки (если он есть) использоваться не будет, даже если это уникальный индекс. Хотя, если для колонки имеется составной индекс (function-based) на основе применяемой в предикате функции, то он может быть использован.
где numexpr выражение числового типа, то Oracle преобразует ваше условие в:
и индекс использован не будет.
Где по числовой колонке numcol построен индекс.
План запроса.
Практически любую задачу по получению каких-либо результатов из базы данных можно решить несколькими способами, т.е. написать несколько разных запросов, которые дадут один и тот же результат. Это, однако не означает, что база данных эти запросы будет выполнять по-разному. Также неверно мнение о том, что структура запроса может повлиять на то, как Oracle будет его выполнять, это касается порядка временных таблиц, JOINS и условий отбора в WHERE. Решение о том, как построить запрос принимает оптимизатор Oracle. Алгоритм получения сервером данных для конкретного запроса называют планом запроса.
Практически все продукты для работы с базой данных Oracle позволяют просмотреть план конкретного запроса. Так как слушатели этих лекций используют PL/SQL Developer, то для получения плана запроса в нем необходимо сделать следующее:
Существует стандартный механизм получения плана запроса. Для этого используется конструкция (команда) EXPLAIN PLAN FOR:
План запроса будет выведен в виде таблицы с одним полем, выглядит он так:
План всегда имеет иерархическую структуру. Операция соединения результирующих наборов оперирует парами дочерних операций. Операция получения данных может использовать вспомогательную операцию, такую, например, как сканирование индекса.
Данные результирующих наборов получаются в порядке следования этих наборов в плане запроса. Операция получения данных результирующего набора может состоять из нескольких шагов, которые характеризуются глубиной операции (колонка Depth).
При анализе плана в первую очередь необходимо обращать внимание на способы, с помощью которых получены данные результирующих наборов.
Некоторые термины в плане запроса.
План запроса имеет форму таблицы, один из столбцов которой описывает тип производимых сервером операций. Вот некоторые из них, которые встречаются наиболее часто:
Анализ плана запроса.
При анализе плана запроса вам необходимо примерно представлять объемы записей в таблицах и наличие у них индексов, которые могут пригодиться при фильтрации записей. Для доступа к данным Oracle использует несколько стратегий, какие из них выбраны для каждой из таблиц можно понять из плана запроса. При просмотре плана, вам необходимо решить, правильная ли выбрана стратегия в том или ином случае. Ниже приведены краткие описания способов доступа и механизмов отбора записей при соединениях результирующих наборов.
Full Table Scan (Table Access Full).
Может показаться, что доступ к данным таблицы быстрее осуществлять через индекс, но это не так. Иногда дешевле прочитать всю таблицу целиком, чем прочитать, например, 80% записей таблицы через индекс, так как чтение индекса тоже требует ресурсов. Очень не желательна ситуация, когда эта операция стоит первой в объединении наборов записей и таблица, которая читается полностью, большая. Еще хуже ситуация с большой таблицей на второй позиции в объединении, это означает, что она также будет прочитана полностью, как минимум, один раз, а если объединение производится через NESTED LOOPS, то таблица будет читаться несколько раз, поэтому запрос будет работать очень долго.
Nested Loops.
Такое соединение может использоваться оптимизатором, когда небольшой основной набор записей (стоит первым в плане запроса) объединяется с помощью условия, позволяющего эффективно выбрать записи из второго набора. Важным условием успешного использования такого соединения является наличие связи между основным и второстепенным набором записей. Если такой связи нет, то для каждой записи в первом наборе, из второго набора будут извлекаться одни и те же записи, что может привести к значительному увеличению времени запроса. Если вы видите, что в плане запроса применен NESTED LOOPS, а соединяемые наборы не удовлетворяют этому условию, то налицо ошибка.
Hash Joins.
Используется при соединении больших наборов данных. Оптимизатор использует наименьший из наборов данных для построения в памяти хэш-таблицы по ключу соединения. Затем он сканирует большую таблицу, используя хэш-таблицу для нахождения записей, которые удовлетворяют условию объединения.
Оптимизатор использует HASH JOIN, если наборы данных соединяются с помощью операторов и ключевых слов эквивалентности (=, AND) и если присутствует одно из условий:
■ Необходимо соединить наборы данных большого объема.
■ Большая часть небольшого набора данных должна быть использована в соединении.
Sort Merge Join.
Данное соединение может быть применено для независимых наборов данных. Обычно Oracle выбирает такую стратегию, если наборы данных уже отсортированы ранее, и если дальнейшая сортировка результата соединения не требуется. Обычно это имеет место для наборов, которые соединяются с помощью операторов , >=. Для этого типа соединения нет понятия главного и вспомогательного набора данных, сначала оба набора сортируются по общему ключу, а затем сливаются в одно целое. Если какой-то из наборов уже отсортирован, то повторная сортировка для него не производится.
Cartesian Joins.
Это соединение используется, когда одна и более таблиц не имеют никаких условий соединения с какой-либо другой таблицей в запросе. В этом случае произойдет объединение каждой записи из одного набора данных с каждой записью в другом. Такое соединение может быть выбрано между двумя небольшими таблицами, а в дальнейшем этот набор данных будет соединен с другой большой таблицей. Наличие такого соединения может обозначать присутствие серьезных проблем в запросе, особенно, если соединяемые таблицы по MERGE JOIN CARTESIAN. В этом случае, возможно, упущены дополнительные условия соединения наборов данных.
Хинты.
Хинт — это ключевое слово, иногда с набором параметров, которое может повлиять на оптимизатор при составлении плана запроса. Другими словами, с помощью хинтов вы можете попытаться изменить способ с помощью которого будут получены или обработаны данные (хинты есть не только у операторов SELECT).
Если у вас есть желание более детально ознакомиться с хинтами, то я рекомендовал бы вам просмотреть эту статью.
Использование хинтов.
Хинт ставится после ключевого слова, которое определяет некую цельную конструкцию запроса, в данном разделе речь пойдет о хинтах в запросах к данным, т.е. тех, которые оформляются оператором SELECT и ключевых словах, используемых в сочетании с ним. Хинт указывается в закрытом комментарии после оператора:
В данном примере используется хинт RULE.
Этот хинт официально не поддерживается с версии Oracle 10G. При его успешном применении включается оптимизация по определенным правилам (RBO — Rule Based Optimization). Данный хинт может быть полезен, если у вас сложный запрос с неэффективным планом выполнения и использование других хинтов может занять время, которого мало. Если в запросе не пропущены какие-то JOINS или условия и вы считаете, что он написан верно, то есть достаточно большая вероятность, что RBO построит верный план.
В 11G этот хинт пока работает с некоторыми ограничениями, важны для практической работы следующие:
■ В запросе не должны использоваться другие хинты.
■ Не должен использоваться синтаксис ANSI (left join | full outer join …)
FIRST_ROWS.
Данный хинт дает указание оптимизатору выбрать такой план запроса при котором первые записи результатов будут получены максиально быстрым способом. Хорош при отладке запроса, чтобы убедиться, что выдается то, что необходимо. Если предполагается, что запрос вернет много записей, то при использовании такого хинта он может работать дольше.
ORDERED / LEADING.
При использовании этого хинта оптимизатор соединяет наборы данных в том порядке, в каком они следуют после оператора FROM. Вот пример разных последовательностей:
Порядок наборов данных необходимо выбирать аккуратно, чтобы соединяемые объекты имели какое-то условие связи в WHERE или после ключевого слова ON. Например в приведенном выше примере 4 версия списка во FROM приведет к перемножению таблиц GOODS и OFFER, так как они не связаны друг с другом условиями.
Данный хинт часто бывает полезен, если статистика по таблицам не собрана, план запроса не верный, и вам точно известно, как должны соединяться таблицы. При использовании данного хинта старайтесь выстроить порядок соединения так, чтобы тяжесть обработки данных следовала в сторону увеличения, т.е. сначала соедините наборы поменьше или с хорошими условиями отбора, чтобы результат их соединения был наименьшим по количеству записей, затем подключайте наборы данных большего размера.
Более удобен в использовании хинт LEADING. Он позволяет соединить наборы данных в порядке перечисления их (или их алиасов) в списке аргументов хинта:
MATERIALIZE.
Дает указание оптимизатору построить временную таблицу (материализовать результаты) для запроса, к которому этот хинт применяется, работает только в конструкции WITH. Очень полезен при обработке больших объемов данных, так как позволяет разбить запрос на части, в этом случае улучшается читабельность запроса, а также может быть получен правильный план. Пример использования:
План запроса выглядит так:
Красным цветом помечена таблица при ее создании, зеленым ее использование в соединении.
INDEX.
Дает указание оптимизатору использовать индекс при чтении данных из таблицы. Полезен тем, что может предотвратить чтение всего содержимого таблицы, если вы считаете, что этого делать не нужно. Пример использования:
Этот хинт сработает в том случае, если у таблицы есть указываемый индекс, и его можно использовать на основе одного или нескольких условий при получении данных таблицы. В приведенном примере в составе индекса есть поле OFFER_ID на второй позиции и он может быть использован, план запроса выглядит в этом случае так:
Комбинации хинтов.
Использование комбинации хинтов допустимо. Нужный эффект можно получить, если хинты в одном запросе не протеворечат друг другу. При записи хинты разделяются пробелами:
В данном примере используется хинт для установки порядка соединения наборов данных и способа доступа к таблице, противоречия в их использовании нет.
Анализ результатов tkprof
Эта статья посвящена анализу результатов работы утилиты tkprof и выявлению причин проблем производительности, о которых эти результаты свидетельствуют.
Анализ результатов tkprof
Ответ Тома Кайта
При полном просмотре (full scan) таблица просматривается вплоть до HWM. Рассмотрим пример:
Как сбросить HWM?
У меня есть таблица, увеличивающаяся в размерах со, скажем, 200 строк утром до, примерно, 11000 строк вечером, когда пакетное задание удаляет из нее строки. Поскольку эта таблица хранит данные сеансов, она очень интенсивно используется. Какой подход следует применять, чтобы гарантироват актуальности статистической информации в течение дня и сбрасывать HWM по вечерам, чтобы стоимостной оптимизатор не вел себя так, как было продемонстрировано в твоем примере? Можно ли сбросить значение HWM, не теряя доступа к данным?
В твоем примере, если проанализовать таблицу t после удаления, что это даст?
Ответ Тома Кайта
Относительно последнего вопроса, см. это обсуждение.
Alter table move
Вместо использования промежуточной таблицы+ truncate + insert для понижения значения HWM я предпочитаю использовать » alter table t move «. Нужен всего один оператор и гарантируется отсутствие конфликтов с любыми ограничениями целостности, индексами триггерами и т.п.
Откуда 2275 блоков?
Том, как ты определил, что в таблице 2275 блоков?
Ответ Тома Кайта
query mode gets делится на количество выполнений запроса.
Уточнение
query mode gets делится на количество выполнений запроса.
Не дает ли эта формула количество блоков, выбираемых при каждом выполнении? Как это может дать нам общее количество блоков в таблице?
И еще, почему количество строк, которое возвращает tkprof (19012) отличается от указанного в плане выполнения (4905)?
Ответ Тома Кайта
Далее, не стоит надеяться, что ПРЕДПОЛАГАЕМОЕ количество строк (ESTIMATED cardinality) всегда будет совпадать или онемного тличаться от реального. Это же ПРЕДПОЛОЖЕНИЯ.
Спасибо. Комментарий читателя от 17 декабря 2002 года
Расчет количества блоков в таблице теперь мне намного понятнее, спасибо.
Ответ Тома Кайта
Хорошо, потребовалось немного подумать, но вот их ситуация, воспроизведенная с точностью до деталей:
Знакомые результаты? Примерно такое же количество query mode gets (постоянный полный просмотр 2275 блоков).
Утилита tkprof показывает, что parses=execute. Что делать?
В книге Expert one on one. вы рекомендуете использовать связываемые перменные, но здесь мне нужна константа.
В другом тесте я получил parse = execute = fetch =159 при том же количестве обработанных строк. Как это понять?
Ответ Тома Кайта
Row source 0
Ответ Тома Кайта
Я лично такой статьи не помню. Если в результатах tkprof есть план выполнения и параметр explain=пользователь/пароль не задавался, значит, записи STAT были.
Возможно, вы используете параметр explain=пользователь/пароль для генерации плана? Например, если я сделаю так:
а если потом выйти и вернуться в sqlplus :
Consistent gets?
Меня интересует, как узнать, что у таблицы очень большое значение HWM, и каким должно быть отношение значения consistent gets к общему количеству строк или к какому-нибудь другому параметру?
Ответ Тома Кайта
Очерь РЕДКО большое количество consistent gets бывает связано с тем, что таблица просматривается до (слишком большого) HWM.
В миллион раз чаще это связано со следующими причинами:
Постарайтесь выявить запросы, наиболее существенно загружающие систему (с помощью statspack ). Сконцентрируйтесь на уменьшении количства операций логического ввода/вывода, выполняемых ими, а для этого:
Еще проблемы с tkprof
Как определить, что процесс не использует обработку массивов (array processing)?
Если для запроса я получаю:
используется ли в нем обработка массивов?
И еще, откуда на стадии execute берутся чтения с диска/чтения буферов?
Ответ Тома Кайта
Я сомневаюсь. Но если и использовалась, что с того? Выбрано было всего две строки.
В общем случае, поделите количество строк на количество операций выборки. Вы и получите размер массива.
В вашем случае, похоже, кто-то выполняет неэффективный поиск.
Большое количество прочитанных буферов при вставке
Хотелось бы узнать, что может привести к большому количеству buffer gets при вставке данных. Я получил следующий результат tkprof :
В таблице есть всего один индекс (первичный ключ, одностолбцовый), значение current gets невелико (так что, я предполагаю, в таблице выполнено не так уж много изменений), но buffer gets составляет порядка 110 на каждое выполнение. Мне кажется, для вставки многовато. В чем может быть причина?
Ответ Тома Кайта
Определение таблицы
Таблица создается так:
Ответ Тома Кайта
Да, триггер и является причиной. Рассмотрим пример:
Когда я попытался выполнить указанный пример из книги (на самом деле, весь PL/SQL-блок после выполнения команды ALTER SESSION SET EVENTS ), то получил следующий результат:
Выдана также информация об ожиданиях (wait events). Я думаю, что это новое свойство утилиты TKPROF в Oracle9i (9.2.0.3). Значит ли это, что изучать исходные трассировочные файлы более не придется?
В представленных результатах выдано ожидание события » enqueue » и общее время этого ожидания. Меня интересует столбец » Times Waited «. Почему в этом столбце указано, что ждать пришлось 33 раза? Откуда взялось это число?
Ответ Тома Кайта
Да, это новая замечательная возможность tkprof в Oracle9i’s (начиная с версии 9.0).
Мы проверяем состояние ожидания enqueue wait каждые три секунды, проверяя, «и что же происходит», а затем снова засыпая в ожидании того, что блокирующий сеанс зафиксирует или откатит транзакцию.
А нельзя ли изменить этот интервал в 3 секунды?
Совсем забыл про значения связываемых переменных в исходном файле трассировки. Спасибо, что напомнил. Но, в принципе, утилита tkprof свободно могла бы выдавать и эти значения тоже (они же есть в исходном файле трассировки). Мне интересно, почему она их не выбирает?
В своем ответе ты написал:
Мы проверяем состояние ожидания enqueue wait каждые три секунды, проверяя, «и что же происходит».
1). Является ли этот таймаут 3 секунды стандартным для всех версий Oracle или он различен для разных версий Oracle (или может измениться в будущем)?
2). Зависит ли хоть как-то это значение от конфигурации сервера?
3). Оно где-то описано в документации или мы просто «его знаем»?
Ответ Тома Кайта
Утилита tkprof значения связываемых переменных пока не выдает.
1) Это значение, как все вообще, «может измениться».
3) Мы просто «его знаем». Точнее, это значение можно определить по таким результатам, как представленные выше.
Рекурсивный SQL в tkprof
«Ресурсы, выдаваемые для оператора, включают весь SQL, выполненный по ходу обработки оператора. Поэтому включаются все ресурсы, использованные в триггере, а также ресурсы, используемые любыми рекурсивными SQL-операторами (например, используемыми при выделении пространства). Если включена трассировка SQL Trace, TKPROF учитывает эти ресурсы дважды. Не пытайтесь настраивать производительность оператора DML, если фактически ресурс использован на нижнем уровне рекурсии.»
Однако я выполнил простой тест:
В функции sto_select.get_id я выполняю запрос:
Этот sql-оператор я вижу в трассировочном файле:
Итак, значение buffer gets явно не было включено в исходный запрос. Что, в руководстве Performance Tuning Guide ошибка? А как насчет операторов DML? (Я выполнял тест на сервере версии 9.2.0.3.)
Ответ Тома Кайта
Это было правильно. Рассмотрим пример:
Так что значение consistent gets ранее агрегировалось. Но по тем же данным в 9ir2 получаем:
так что он больше не учитывает это дважды.
Я выставлю ошибку в документации.
Количество строк, обработанных при выполнении insert
Утилита TKPROF выдает:
Вопрос : оператор был выполнен 291 раз. Это означает, что обработана (вставлена) может быть максимум 291 строка. Почему обработано больше строк, чем количество выполнений оператора?
И еще, что этот оператор (insert) делает на диске?
Ответ Тома Кайта
Разработчик выполнил замечательную вставку массивом. Около 370 строк всатвляется при каждой вставке (жаль только, что курсор не оставили открытым! В идеале должен быть 1 анализ, 291 выполнение.)
Пакетное задание: elapsed time. Комментарий читателя от 19 декабря 2003
У нас есть пакетное задание, которое выполняется около 5 часов, но, протрассировав задание, мы обработали файл трассировки с помощью tkprof и получили следующее:
На что уходит 1,1 часа?
Ответ Тома Кайта
Эти 1,1 часа уходят на передачу данных по сети + время обработки на клиенте. Вероятно, в основном на обработку на клиенте, с учетом среднего количества возвращаемых строк (если только у вас не слишком медленная сеть)
Возможно, SOFT parse.
В представленном отчете TKPROF большинство выполненных анализов могли быть типа SOFT PARSE. Правильно? И как разработчики могут это исправить?
Ответ Тома Кайта
Разработчики должны писать так:
Анализ есть анализ. Быстрее всего он будет выполняться, если ВООБЩЕ НЕ АНАЛИЗИРОВАТЬ.
Но это же web-приложение
/* никогда не закрывать его, оставить открытым */
Ответ Тома Кайта
Можено держать курсоры открытыми как можно дольше.
Если поступать иначе, вы резко снизите производительность.
Не вижу причин, почему, если вы анализируете и выполняете оператор 500 раз на одной web-странице, НЕЛЬЗЯ проанализировать его один раз и выполнить 500 раз.
Нет причин (кроме «мне лень»).