невозможно расширить временный сегмент на 128 в табличном пространстве TEMP

Я пытаюсь выполнить следующий запрос в Oracle:

SELECT DISTINCT
   t4.s_studentreference "Student ID",
  t3.p_surname "Surname",
  t3.p_forenames "Forenames",
t1.m_reference "Course",
 t2.e_name "Enrolment Name"
 FROM student t4,
  person t3,
  enrolment t2,
  course t1
WHERE t4.s_id(+) =t3.p_id
AND (t2.e_student=t3.p_id)
AND (t2.e_course =t1.m_id)
AND (t1.m_reference LIKE 'LL563%15')
OR (t1.m_reference LIKE 'LL562%15')
OR (t1.m_reference LIKE 'LL563%16')
OR (t1.m_reference LIKE 'LL562%16')

Но я получаю ошибку ниже:

ORA-01652: unable to extend temp segment by 128 in tablespace TEMP
01652. 00000 -  "unable to extend temp segment by %s in tablespace %s"
*Cause:    Failed to allocate an extent of the required number of blocks for
           a temporary segment in the tablespace indicated.
*Action:   Use ALTER TABLESPACE ADD DATAFILE statement to add one or more
           files to the tablespace indicated.

Я использовал следующий запрос, чтобы найти пространство временного сегмента:

    select inst_id, tablespace_name, total_blocks, used_blocks, free_blocks
 from gv$sort_segment;

Дает:

INST_ID, TABLESPACE_NAME, TOTAL_BLOCKS, USED_BLOCKS, FREE_BLOCKS
1           TEMP           3199872       15360         3184512

Любая идея, как решить?

Спасибо, Аруна


person Aruna Raghunam    schedule 13.02.2017    source источник
comment
Я думаю, что на этот вопрос лучше ответить на dba.stackexchange.com.   -  person BriteSponge    schedule 13.02.2017
comment
В сообщении об ошибке конкретно указано, какое действие следует предпринять.   -  person OldProgrammer    schedule 13.02.2017
comment
@OldProgrammer, это хороший пример того, почему иногда принятие рекомендации «Действие» из сообщения об ошибке оракула не всегда является лучшим способом действий :)   -  person Jeffrey Kemp    schedule 15.02.2017


Ответы (1)


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

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

Однако происходит то, что сначала вычисляются первые четыре предиката (поскольку И имеет приоритет над ИЛИ), и я подозреваю, что это вызывает некоторые проблемы с вашими соединениями - возможно, какое-то непреднамеренное перекрестное соединение, и это может быть то, что неожиданно взрывается ваше табличное пространство TEMP.

Чтобы этого не произошло, у вас есть два возможных решения:

<сильный>1. Уточните свою логику И/ИЛИ, расставив скобки в правильных местах:

SELECT DISTINCT
       t4.s_studentreference "Student ID",
       t3.p_surname "Surname",
       t3.p_forenames "Forenames",
       t1.m_reference "Course",
       t2.e_name "Enrolment Name"
FROM   student t4,
       person t3,
       enrolment t2,
       course t1
WHERE  t4.s_id(+) = t3.p_id
AND    t2.e_student = t3.p_id
AND    t2.e_course = t1.m_id
AND    (t1.m_reference LIKE 'LL563%15'
        OR t1.m_reference LIKE 'LL562%15'
        OR t1.m_reference LIKE 'LL563%16'
        OR t1.m_reference LIKE 'LL562%16');

Вышеупомянутое группирует все операторы ИЛИ вместе, а затем объединяет их с остальными предикатами.

<сильный>2. Используйте синтаксис соединения ANSI и отделите предикаты поиска от предикатов соединения:

SELECT DISTINCT
       t4.s_studentreference "Student ID",
       t3.p_surname "Surname",
       t3.p_forenames "Forenames",
       t1.m_reference "Course",
       t2.e_name "Enrolment Name"
FROM   student t4,
       RIGHT OUTER JOIN person t3 ON t4.s_id = t3.p_id
       INNER JOIN enrolment t2 ON t3.p_id = t2.e_student 
       INNER JOIN course t1 ON t2.e_course = t1.m_id
WHERE  t1.m_reference LIKE 'LL563%15'
OR     t1.m_reference LIKE 'LL562%15'
OR     t1.m_reference LIKE 'LL563%16'
OR     t1.m_reference LIKE 'LL562%16';

Конечно, последнее не исключает использования квадратных скобок в нужном месте, когда вы работаете с сочетанием И и ИЛИ в предложении where...

Вариант 2 был бы моим предпочтительным решением - синтаксис соединения ANSI действительно является шагом вперед при написании SQL.

person Boneist    schedule 13.02.2017
comment
Спасибо, Бонист. :) - person Aruna Raghunam; 13.02.2017
comment
На самом деле я часто вижу это, когда люди преобразуют синтаксис внешнего соединения Oracle в синтаксис внешнего соединения ANSI и путают или путают соединения и предикаты. В итоге они получают соединение с константой, которая, хотя и синтаксически допустима, часто не соответствует семантически тому, что требуется. - person BobC; 13.02.2017
comment
@BobC да; Я немного настороженно отношусь к синтаксису внешнего соединения ANSI, и мне обычно приходится создавать тестовый пример, чтобы доказать, что он работает так, как я хочу! Или я присоединяюсь к подзапросу *{;-) - person Boneist; 13.02.2017