oracle-запрос - ORA-01652: невозможно расширить временный сегмент, но только в некоторых версиях sql * plus - PullRequest
5 голосов
/ 20 октября 2010

Это меня довольно запутало. Я написал запрос, который работает нормально с моего клиента разработки, но не работает на рабочем клиенте с ошибкой «ORA-01652: невозможно увеличить временный сегмент на ....». В обоих случаях база данных и пользователь совпадают. На моей машине разработки (MS Windows) у меня есть SQL * PLUS (выпуск 9.0.1.4.0) и Toad 9.0 (оба используют версию 9.0.4.0.1 файла oci.dll). Оба запускают код без ошибок.

Однако, когда я запускаю один и тот же файл для той же базы данных, используя одно и то же имя пользователя / пароль с другого компьютера, на этот раз версия 10.2.0.4.0 (из клиента мгновенного доступа 10.2.0.4-1), я получаю ошибка.

Это происходит воспроизводимо.

К сожалению, у меня только ограниченный доступ к представлениям словаря в базе данных, которая настроена только для чтения (даже не могу получить план объяснения!).

Я попытался обойти эту проблему, настроив запрос (подозреваю, что существует большой промежуточный набор результатов, который впоследствии урезается), но мне не удалось изменить поведение ни на одном из клиентов.

Может быть возможно развернуть другую версию клиента на компьютере, вызывающем проблемы, но в настоящее время это похоже на переход к предыдущей версии.

Есть идеи?

ТИА

Обновление

Основываясь на ответе Гэри ниже, я взглянул на сценарии glogin.sql - единственное отличие заключалось в том, что SET SQLPLUSCOMPATIBILITY 8.1.7 присутствовал на работающем клиенте, но отсутствовал на отказавшем клиенте - но его добавление не давало решить проблему.

я тоже пробовал

alter session set workarea_size_policy=manual;
alter session set hash_area_size=1048576000;

и

alter session set sort_area_size=1048576000;

безрезультатно: (

Обновление 2

Мне удалось найти то же самое поведение, на этот раз, разговаривая с бэкэндом Oracle 8i. В данном случае база данных была RW. Это позволило мне подтвердить, что разные клиенты, как я подозревал, генерировали разные планы. Но почему ????

Глядя на вывод 'SHOW PARAMETERS', оба клиента сообщили точно такие же настройки !

Ответы [ 3 ]

0 голосов
/ 26 октября 2010

Не совсем ответ - но немного больше информации ...

Наши локальные администраторы баз данных смогли подтвердить, что табличное пространство TEMP 16 Гб (!) Действительно использовалось и заполнилось, но только от клиентов Linux (я смог воссоздать ошибку, совершив вызов oci8 из PHP). В случае с клиентом sqlplus я фактически использовал один и тот же файл для выполнения запроса на обоих клиентах (скопировал с помощью scp без преобразования текста - поэтому окончания строк были CRLF - т.е. байт для байта такой же, как был запущен на клиенте Windows) .

Таким образом, единственное рациональное решение состояло в том, что 2 стека клиентов приводили к различным планам выполнения!

Выполнение запроса от обоих клиентов примерно одновременно в СУБД с очень небольшой нагрузкой дало одинаковый результат - это означает, что два клиента также генерировали разные sqlids для запроса.

(а также Oracle игнорировал мои намеки - я ненавижу, когда это делает).

Нет способа, которым Oracle должен был бы это делать - даже если бы он выполнял некоторое внутреннее манипулирование запросом перед его представлением в СУБД (что привело бы к различным sqlids), используемый стек клиента должен быть полностью прозрачным в отношении выбор плана выполнения - он должен изменяться только в зависимости от содержания запроса и состояния СУБД.

Проблема была сложной из-за отсутствия планов объяснения, но для того, чтобы запрос использовал так много временного табличного пространства, он должен был выполнить очень уродливое соединение (по крайней мере, частично декартово) перед фильтрацией набора результатов. Добавление подсказок для отмены этого не имело никакого эффекта. Поэтому я решил проблему, разделив запрос на 2 курсора и выполнив вложенный поиск с использованием PL / SQL. Очень уродливое решение, но оно решило мою непосредственную проблему. К счастью, мне просто нужно сгенерировать текстовый файл.

В интересах любого, кто окажется в подобном рассоле:

BEGIN

DECLARE
CURSOR query_outer IS
    SELECT some_primary_key, some_other_stuff
    FROM atable
    WHERE....

CURSOR query_details (p_some_pk) IS
    SELECT COUNT(*), SUM(avalue)
    FROM btable
    WHERE fk=p_some_pk
    AND....

FOR m IN query_outer
LOOP
    FOR n IN query_details(m.some_primary_key)
    LOOP
        dbms_out.put_line(....);
    END LOOP;
END LOOP;

END;

Чем больше я использую Oracle, тем больше я его ненавижу!

0 голосов
/ 15 декабря 2010

Немного больше информации - я столкнулся с той же проблемой при подключении к другой базе данных - на этот раз Oracle 8i. И я могу получить объяснения планов.

Хотя в этом случае запрос был выполнен на обоих клиентах, он потребовал на 50% больше времени для Linux sql * плюс 10.2.0.4.0 против WinXP sql * плюс 8.0.6.0

Как я и подозревал, планы разные, но оба используют настройки клиента по умолчанию, оба используют один и тот же режим оптимизатора. Кажется, кажется, что план, сгенерированный из клиента Linux, имеет меньшую стоимость, чем у клиента XP (хотя для его выполнения требуется больше времени). Как оптимизатор сокращает путь поиска потенциальных планов?

0 голосов
/ 21 октября 2010

Несколько лет назад я работал с базой данных DR, которая была полностью READONLY, и даже табличное пространство TEMP не было доступно для записи. Любой запрос, который пытался перекинуться на временную шкалу, потерпел бы неудачу (даже если временное пространство, которое нужно было использовать, было довольно тривиальным).

Если это та же самая ситуация, я не удивлюсь, если бы был login.sql (или glogin.sql или триггер входа в систему), который выполняет ALTER SESSION, чтобы установить большее значение памяти PGA для сеанса, и / или изменяет цель оптимизатора на FIRST_ROWS.

Если вы можете, сравните результаты следующих от обоих клиентов:

выберите * из параметра v $ где ismodified! = 'ЛОЖЬ';

Также от каждого клиента для проблемного SQL, попробуйте EXPLAIN PLAN FOR SELECT ... и ВЫБРАТЬ * ИЗ ТАБЛИЦЫ (DBMS_XPLAN.DISPLAY);

Посмотрите, подходит ли он к другим планам запросов.

...