2010-07-07 3 views
9

Я пытаюсь понять, что +0 в конце этого запроса 9i Oracle означает:Что +0 означает, после ORDER BY в Oracle

SELECT /*+ INDEX (a CODE_ZIP_CODE_IX) */ 
     a.city, 
     a.state, 
     LPAD(a.code,5,0) ZipCode, 
     b.County_Name  CoName, 
     c.Description  RegDesc, 
     d.Description  RegTypeDesc 
FROM TBL_CODE_ZIP a, 
    TBL_CODE_COUNTY b, 
    TBL_CODE_REGION c, 
    TBL_CODE_REGION_TYPE d 
WHERE a.City = 'LONDONDERRY' 
    AND a.State = 'NH' 
    AND lpad(a.Code,5,0) = '03038' 
    AND a.Region_Type_Code = 1 
    AND b.County(+) = a.County_Code 
    AND b.STATE(+) = a.STATE 
    AND c.Code(+) = a.Region_Code 
    AND d.Code(+) = a.Region_Type_Code 
ORDER BY a.Code +0 

Есть идеи?

Примечание: Я не думаю, что это имеет отношение к возрастанию или убыванию, так как я не могу добавить или возрастанию DESC между a.Code и +0, и я могу добавить или возрастанию DESC после +0

+0

Это способ заставить a.Code ввести числовой тип данных, вызвав неявное преобразование? –

+0

a.Code указывается как НОМЕР (5) –

+0

Все становится понятнее, если код выложен правильно. – APC

ответ

8

+ 0 был хитом назад в дни оптимизатора на основе правил, что делало невозможным использование индекса в числовом столбце. Аналогично, они сделали || '' для буквенно-цифровых столбцов.

По вашему запросу единственный вывод, который я могу достичь после проверки, заключается в том, что его создатель боролся с производительностью. Если (это мое предположение) индекс CODE_ZIP_CODE_IX является индексом в TBL_CODE_ZIP (Code), тогда запрос не будет использовать его, даже если он намекает на его использование. Создатель, вероятно, не знал, что при использовании LPAD (a.code, 5,0) вместо a.code индекс не может быть использован. Предложение order by принимает свой промежуточный результирующий набор, который находится в памяти, и сортирует его. Для этого не нужен индекс. Но с + 0 похоже, что он думал отключить его.

Итак, используемые трюки были неэффективными, и теперь они только вводят в заблуждение, как вы выяснили.

С уважением, Роб.

PS1: Лучше использовать LPAD (TO_CHAR (a.code), 5, '0') или TO_CHAR (a.code, 'fm00009'). Тогда ясно, что вы делаете с типом данных.

PS2: Ваш запрос может быть полезен при использовании индекса, основанного на функции, для LPAD (TO_CHAR (a.code), 5, '0') или любого выражения, которое вы используете, чтобы оставить свой почтовый индекс.

7

Мои предположил бы, что a.code - это VARCHAR2, содержащий цифровую строку, а +0 эффективно линяет его в NUMBER, поэтому сортировка будет числовой, а не α

Вы должны иметь возможность добавить ASC/DESC после +0

+0

@MarkBaker CODE - НОМЕР (5) ... если это помогает. Тем не менее, я смог указать asc или desc после, и это сработало! –

+2

Кажется странным способом сделать это - есть ли преимущество делать это таким образом, а не просто использовать 'to_number (a.code)'? – FrustratedWithFormsDesigner

+0

@FrustratedWithFormsDesigner - короче писать? В противном случае нет существенной разницы (кроме форматирования с TO_NUMBER). –

3

Примечание: я удалил этот ответ, потому что Марк Б был быстрее машинистки. Тем не менее, я обновил его, потому что я думаю, что есть некоторая ценность в демонстрации того, что могло быть основным намерением SQL, который опубликовал Лукас.


Предположим, что CODE был колонкой VARCHAR2, содержащей строки цифр (почтовые индексы). Проблема состоит в том, что varchars сортируют как строки, а не числа. Добавление нуля к коду нерестится неявное приведение к числу, и, следовательно, сортирует численно:

SQL> select id, code 
    2 from t72 
    3 order by code 
    4/

     ID CODE 
---------- ----- 
     1 1 
     2 11 
     3 111 
     4 12 

SQL> select id, code 
    2 from t72 
    3 order by code+0 
    4/

     ID CODE 
---------- ----- 
     1 1 
     2 11 
     4 12 
     3 111 

SQL> 

Если сохраненные коды были оставлены мягкими с нулями, то бросок не был бы необходим, так как они будут отсортированы в числовой порядок в любом случае.

Как и другие наблюдатели, использование TO_NUMBER() было бы лучшим выбором. +0 менее очевидна, чем явный приведение, и всегда полезно четко понимать намерение.

+0

Будет ли «to_number (a.code)» иметь тот же эффект, или есть разница с «+ 0»? – FrustratedWithFormsDesigner

+1

Я думаю, что to_number будет иметь тот же эффект и будет более очевидным для читателя. –

+0

+1 для обработанного примера того, что я предложил –

1

Есть ли индекс на TBL_CODE_ZIP.Code? Я видел запросы, которые добавляют 0 к числу (или «к строке»), чтобы заставить оптимизатора избегать использования индекса для этой части запроса. (Разумеется, правильный способ избежать использования индекса - добавить соответствующий подсказку)

Возможно, у оригинального автора возникла проблема, когда ORDER BY оптимизировался на сканирование индекса, что заставило запрос работать медленнее; поэтому они добавили +0, чтобы создать другой путь доступа и сделать обычный вид.

+0

Да, есть индекс, называемый CODE_ZIP_CODE_IX, в котором есть. Код в нем, и в этом запросе мы «намекаем» на использование этого индекса. Когда я смотрю на нее через План объяснения, сравнивая с + и +, планы идентичны. –

+1

@ Лукас, да, это не обязательно будет иметь значение * сейчас *. В качестве альтернативы разработчик, возможно, ошибочно полагал, что это ускорит его работу, потому что «это сработало для меня раньше» :) –

+0

Я согласен, один из моих сотрудников подумал, что это может быть оставлено от реализации для Oracle 8. Спасибо за проницательность. –

0

Fisrt извините за вопрос, потому что очень старый вопрос сейчас. Однако +0 является подсказкой для вашей базы данных, чтобы игнорировать индекс (если он находится в столбце. Код) для этого конкретного запроса,

Некоторое время индексирование делает быстрый поиск, в то время как некоторое время делает его очень медленным в зависимости от режима оптимизатора база данных.

так что теперь у вас есть два варианта использования eigther +0 подсказка или удаление индекса, если он на a.code вы получите такую ​​же скорость.