powered by simpleCommunicator - 2.0.44     © 2025 Programmizd 02
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Oracle Optimizer
25 сообщений из 38, страница 1 из 2
Oracle Optimizer
    #32051788
gminter
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Привет All.
Есть вопрос к оптимизатору:

1)
select id, name from _table order by id;
Оптимизатор отвечает, что будет использовать план по уникальному индексу_ID; все пока хорошо.

2) select id, name from _table order by name;
По name так же есть индекс, правда не уникальный но очень селективный.
При любых комбинациях этого запроса (не учитывая задействования индекса в where), несмотря даже на прописывание плана запроса, оптимизатор неуклонно стремится к TABLE ACCESS FULL.

Почему? Как с этим БОРОТЬСЯ ???!!! Неужели Interbase круче..
...
Рейтинг: 0 / 0
Oracle Optimizer
    #32051796
Фотография killed
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Похоже оптимизатор молчит ;)

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

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

Разумеется Interbase однозначно круче тут и спорить нечего.
...
Рейтинг: 0 / 0
Oracle Optimizer
    #32051806
Sergius
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Значит, оптимизатор считает, что так лучше :)

Само по себе TABLE ACCESS FULL - ничего страшного не значит. Посмотри по значениям COST'a в Explain Plan'e , может все не так плохо?

А еще можно попробовать порционирование (если таблица большая).
...
Рейтинг: 0 / 0
Oracle Optimizer
    #32051822
lvv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
lvv
Гость
а почему оптимизатор должен использовать индекс?
надо выбрать все записи из таблицы и отсортировать их, если Interbase при этом выбирает по одной записи, то это его проблема, Oracle делает по другому - считывает всю таблицу, а потом сортирует ее
...
Рейтинг: 0 / 0
Oracle Optimizer
    #32051827
Фотография killed
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
lw прав.

Я кстати очень сомневаюсь, что в первом селекте используется индекс.
...
Рейтинг: 0 / 0
Oracle Optimizer
    #32051861
buzz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Select Name from table1 order by name

А теперь сравним стоимость двух вариантов исполнения.

1. Используя индекс по Name
Сервак просто вычитывает по одной строке и отдает клиенту. Сортировка обеспечена порядком используемого индекса. Все вычитывать сразу не обязательно вычитывается столько сколько клиент попросит


2. Не используя индекс.
Вычитывание идет в хаотическом порядке, посему вычитать надо все и отсортировать результат. Только после этого начинается выдача клиенту первых записей.

Если оракл не умеет действовать по варианту 1 - это убожество. Не хочется в это верить. Впрочем
Select /*+ FIRST_ROWS/ ID,Name from table1 order by ID

вправляет ему мозги и он работает по варианту 1. Но только в том случае когда order по первичному ключу... Остается вопрос как ему вернуть сообразительность в случае когда ордер по другому индексированному полю.

В заключение вопрос на засыпку. Что вернет

Select Name from table1
where RowNum<20
order by name

Лично меня результат позабавил. Его можно даже расценивать как баг.
...
Рейтинг: 0 / 0
Oracle Optimizer
    #32051869
nick
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Select Name from table1
where RowNum<20
order by name
это не баг это фича :)
order by выполняется только после where !!!
т.е. сначала выборка а уж потом сортировка
а то что ты хочешь делается так
select * from(Select Name from table1
order by name) where RowNum<20
...
Рейтинг: 0 / 0
Oracle Optimizer
    #32051870
buzz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Большое спасибо. Теперь по этому пункту я просвещен.
Но остается вопрос с сортировкой. Не устраивает меня что этот гад делает у себя всю выборку и ее сортирует.
...
Рейтинг: 0 / 0
Oracle Optimizer
    #32051874
nick
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
при указание FIRST_ROWS мой oracle всегда использут индекс в не зависимости от того первичный это ключ или нет
поробуй сначала дать analyze или указать явное использование индекса
...
Рейтинг: 0 / 0
Oracle Optimizer
    #32051879
buzz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Я уже и индекс указывал и статистику пересчитывал, монитор протирал, с бубном плясал. Он меня игнорит.
Може чего в глобальных настройках сервака крутануть надо? Ткните носом ...
...
Рейтинг: 0 / 0
Oracle Optimizer
    #32051880
Фотография killed
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
2 buzz

Этот "гад" делает все правильно.

В исходном запросе

select id, name from table order by id;

Вы же упростили ситуацию до

select id from table order by id; где индекс по id становится покрывающим

В первом случае поле name не входит в индекс. В этом вся разница.

Поэтому вправлять ему мозги не стоит, CBO гораздо умнее, чем вы предполагаете ;-)

Кстати FIRST_ROWS - это бестолковый хинт. Если есть нужда, то лучше использовать INDEX, INDEX_FFS и т.п.
...
Рейтинг: 0 / 0
Oracle Optimizer
    #32051887
buzz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
По вашему в

Select Name from table1 order by name

индекс по Name не покрывающий? Тогда что Вы имеете в виду под термином "Покрывающий"?
...
Рейтинг: 0 / 0
Oracle Optimizer
    #32051912
buzz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Идеи кончились?
...
Рейтинг: 0 / 0
Oracle Optimizer
    #32051921
lvv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
lvv
Гость
Ну во первых для случая с ID он пишет
INDEX FULL SCAN, т.е. ему достаточно пробежаться по всему индексу, а данные уже в нем и ходить за ними в таблицу не надо.

Варианты:
Для случая name, вроде тоже все данные в индексе(а может и нет)

В один блок индекса по id помещается значительно больше значений ключа, чем в блок данных. Значит по индексу бежать быстрее. Для случая с name ситуация другая, в блок индекса помещается значений почти столько же сколько и в блок данных, значит по таблице бежать выгоднее
...
Рейтинг: 0 / 0
Oracle Optimizer
    #32051925
user1
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
2 buz

А в чем собственно вопрос.
1. Почему СВО не подхватывает индекс - потому что ему быстрее выдать данные с помощью полного просмотра.
Оптимизатор потому и называеться оптимизатором, что выбирает ОПТИМАЛЬНЫЙ путь.

2. А вот почему Оракл быстрее считывает данные и сортирует в памяти (или даже на диске - см. план своего запроса), нежели чем с помощью индекса не по первичному ключу - читай архитектуру оракл.
...
Рейтинг: 0 / 0
Oracle Optimizer
    #32051936
buzz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
2 lvv

Чтоб не было отвлекающих рассуждений на тему integer vs varchar, скажу что ситуация сохраняется и для полей типа integer, но не входящих в первичный ключ.
То бишь

Select MyIntegerField from Table1 order by MyIntegerField
тоже не хочет пользовать индекс по MyIntegerField.

Далее насчет стоимости. Сортировка выборки 54000 записей по любому хуже выборки из индекса. Хотя бы за счет того что не нужно вычитать все записи для того, чтоб получить первую. К тому же понятно что сортируется вся выборка...

То бишь
Select * from Table1 order by MyIntegerField
сортируется на порядок медленней чем
Select MyIntegerField from Table1 order by MyIntegerField

В общем плохо это. Наглядно можно сравнивать результаты выполнения

Select * From Table1 order by ID
Скорость исполнения 2.3 сек.

с
Select /*+ FIRST_ROWS*/ * From Table1 order by ID
Скорость исполнения 0.07 сек.

На 54000 записей. Второй случай практически не зависит от количества полей в выборке. В первом все очень сильно зависит от того сколько в этой самой звездочке.
Результаты совершенно не удивительные. Удивительно что никакими силами не удается заставить оракл работать по варианту 2 в случае ордера с полями не входящими в первичный ключ.
...
Рейтинг: 0 / 0
Oracle Optimizer
    #32051937
ora600
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
2buzz
Поищите в init.ora
optimizer_index_caching
optimizer_index_cost_adj
и/или почитайте про них.
А сколько записей в табличке ?

2killed
FIRST/ALL_ROWS еще может повлиять на способ соединения или antijoin, так что иногда это удобнее (но менее интересно :-) ), чем делать длинные хинты типа ordered ... use_nl ... index...
Так что не так уж и бестолковый :)
...
Рейтинг: 0 / 0
Oracle Optimizer
    #32051941
buzz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
2ora600

Поищите в init.ora
optimizer_index_caching
optimizer_index_cost_adj
и/или почитайте про них.


Насколько я понял это будет влиять только на использование индексов в джойнах. Ордер бай вроде как побоку. Так?


А сколько записей в табличке ?

54000. Табличка тестовая, в общем то на ней пытаюсь оттестировать возможности Оракла и свои возможности повлиять на возможности Оракла. Гм... немного запутанно получилось.
...
Рейтинг: 0 / 0
Oracle Optimizer
    #32051947
Фотография killed
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
2 buzz

Ну почему же сразу кончились? :-) Их есть у меня. Я ведь не раскруткой этого форума занимаюсь. Извольтес подождать малость ;)

Чтобы ответить на вопрос, нужно знать есть индекс по полю name или его нет. Допустим индекс есть.

Ниже не ваш случай ?

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
eshevtsov@AFK1.SYSTEMA.RU>; create table t3(name varchar2( 30 ));

Table created.

eshevtsov@AFK1.SYSTEMA.RU>; insert into t3 values('Маша');

 1  row created.

eshevtsov@AFK1.SYSTEMA.RU>; insert into t3 values('Петя');

 1  row created.

eshevtsov@AFK1.SYSTEMA.RU>; insert into t3 values('Эдик');

 1  row created.

eshevtsov@AFK1.SYSTEMA.RU>; insert into t3 values(null);

 1  row created.

eshevtsov@AFK1.SYSTEMA.RU>; commit;

Commit complete.

eshevtsov@AFK1.SYSTEMA.RU>; create index t3_ix on t3(name);

Index created.

eshevtsov@AFK1.SYSTEMA.RU>; analyze table t3 compute statistics;

Table analyzed.

eshevtsov@AFK1.SYSTEMA.RU>; set null  "Это NULL" 
eshevtsov@AFK1.SYSTEMA.RU>; select name from t3;

NAME
 -------------------------
 
Маша
Петя
Эдик
Это NULL

eshevtsov@AFK1.SYSTEMA.RU>; set autotrace on exp
eshevtsov@AFK1.SYSTEMA.RU>; 
eshevtsov@AFK1.SYSTEMA.RU>; select name from t3 order by name;

NAME
 -------------------------
 
Маша
Петя
Эдик
Это NULL


Execution Plan
 ----------------------------------------------------------
 
    0    SELECT STATEMENT Optimizer=CHOOSE (Cost= 7  Card= 4  Bytes= 12 )
     NULL

    1      0    SORT (ORDER BY) (Cost= 7  Card= 4  Bytes= 12 )                   
    2      1      TABLE ACCESS (FULL) OF 'T3' (Cost= 1  Card= 4  Bytes= 12 ) 



eshevtsov@AFK1.SYSTEMA.RU>; select name from t3 where name is not null order by name;

NAME
 -------------------------
 
Маша
Петя
Эдик


Execution Plan
 ----------------------------------------------------------
 
    0    SELECT STATEMENT Optimizer=CHOOSE (Cost= 1  Card= 3  Bytes= 9 )  
     NULL

    1      0    INDEX (FULL SCAN) OF 'T3_IX' (NON-UNIQUE) (Cost= 1  Card= 3  B 
          ytes= 9 )


...
Рейтинг: 0 / 0
Oracle Optimizer
    #32051959
Фотография killed
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
2 Ora600

этот хинт модифицирует значение стоимости в отличие от дефолтного поведения (ALL_ROWS) а вот как модифицирует - это знает только весьма ограниченный круг людей в Редмонде :-) Далее он не эквивалентен набору хинтов, который ты упомянул. Ставя хинт INDEX ты четко понимаешь чего ожидаешь. Ставя FIRST_ROWS ты полагаешься на интеллект оптимизатора, не зная, что будет точно сделано и как. Хинты не всегда есть гуд, но раз уж ими пользоваться, то нужна абсолютная однозначность (в этом собственно смысл хинтов), а чтобы ее добиться нужно очень хорошо знать внутренние алгоритмы CBO. Я их не знаю, поэтому пытаюсь использовать хинты по минимуму и те, которые попроще.
...
Рейтинг: 0 / 0
Oracle Optimizer
    #32051975
buzz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Спасибо. Это действительно тот самый случай который я анализирую. Беда в том что

для
select name from t3 where name is not null order by name
У меня получается не тот план что вы привели, а:

0 Это SELECT STATEMENT Optimizer=CHOOSE (Cost=3 Card=3 Bytes=9) Это NULL
NULL

1 0 SORT (ORDER BY) (Cost=3 Card=3 Bytes=9) Это NULL
2 1 INDEX (FULL SCAN) OF 'T3_IX' (NON-UNIQUE) (Cost=1 Card=3 Это NULL
Bytes=9)


Так что ... вопрос остается в силе. Где непорядок?


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

Там же где все по правильному план выглядит как

1 0 TABLE ACCESS BY INDEX ROWID
2 1 INDEX (FULL SCAN)
...
Рейтинг: 0 / 0
Oracle Optimizer
    #32052001
Фотография killed
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
А какая версия ?

Последний план для какого селекта был привиден?
...
Рейтинг: 0 / 0
Oracle Optimizer
    #32052007
buzz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Версия -921

План по

select /*+ FIRST_ROWS*/
* from myprobtovar
order by id


Или так

select
/*+INDEX(myprobtovar PK_TOVAR) */ * from myprobtovar
order by id

Все тот же первичный ключ.

Не понимаю почему

select
/*+INDEX(myprobtovar IND_TOVAR_NAME) */
* from myprobtovar
order by name

Не производит на сервер никакого впечатления. Он по прежнему думает за

TABLE ACCESS FULL
с последующим
SORT ORDER BY
...
Рейтинг: 0 / 0
Oracle Optimizer
    #32052026
Фотография killed
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Я вот смысла не улавливаю.

В первом случае ты говоришь ораклу:
Прочти каждое значение id из каждого листа индекса, затем иди и читай каждую строку таблицы. Общее число блоков = блоки индекса + блоки таблицы.

Вместо того, чтобы через фул скан прочесть все блоки таблицы за n/db_file_multiblocl_count число операций, где n - кол-во блоков таблицы. И затем сортировка.

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

Во втором случае, я так понял, что поле name определено как NULL
...
Рейтинг: 0 / 0
Oracle Optimizer
    #32052028
buzz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
В первом случае ты говоришь ораклу:
Прочти каждое значение id из каждого листа индекса, затем иди и читай каждую строку таблицы. Общее число блоков = блоки индекса + блоки таблицы.

Вместо того, чтобы через фул скан прочесть все блоки таблицы за n/db_file_multiblocl_count число операций, где n - кол-во блоков таблицы. И затем сортировка.


Ключевое слово - сортировка. Я ее просто избегаю. Кроме того я ж не фетчу сразу все. Реально ~30 чтений... пусть даже блоки индекса + блоки таблицы - это все равно быстрей чем все блоки таблиц + сортировка 54000 записей. Быстрей во много раз. И не зависит ни от количества записей, ни от количества полей в таблице вообще.

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

Гм... ну не только. См. выше.
Кроме того я ж говорю, согласен для разборок ограничиться

Select name from T1 order by name.
Индекс по Name покрывающий? То бишь с любой точки зрения достаточно читать именно его? Так почему ж Оракл его игнорит????

Во втором случае, я так понял, что поле name определено как NULL

В смысле может быть нуллом? Специально сделал только что нот нулл. Анфас тот же только в профиль.
...
Рейтинг: 0 / 0
25 сообщений из 38, страница 1 из 2
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Oracle Optimizer
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]