powered by simpleCommunicator - 2.0.60     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Sybase ASA, ASE, IQ [игнор отключен] [закрыт для гостей] / не работает индекс
7 сообщений из 7, страница 1 из 1
не работает индекс
    #34632503
Фотография spc
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Добрый день!

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

Например,

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
create table #tmp (
    id numeric( 15 ,  0 )
   ,name varchar( 255 )
)
create index i1 on #tmp(name)

set forceplan on

insert #tmp
  select top  100000  it.InstitutionID, it.Name
  from tInstitution it
  
select *
from #tmp t (index i1)
where t.name like 'Иванов%'

drop table #tmp

этот скрипт индекс не использует
Код: plaintext
1.
Index 'i1' specified as optimizer hint in the FROM clause of table '#tmp' does not exist.  Optimizer will choose another index instead.

сервер
Код: plaintext
Adaptive Server Enterprise/ 12 . 5 . 3 /EBF  13325  ESD# 7 /P/Sun_svr4/OS  5 . 8 /ase1253/ 1951 / 64 -bit/FBO/Fri Mar  24   11 : 00 : 22   2006 
_______________

The REAL McCOY is what the world would be doing every Saturday night if the Nazis had won the war.
...
Рейтинг: 0 / 0
не работает индекс
    #34632528
Фотография komrad
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
spcДобрый день!

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


таблицы и индексы надо создавать "над" хранимками
иначе оптимизатор считает, что такая таблица состоит из 10 записей.
ну и индексы туда же.
...
Рейтинг: 0 / 0
не работает индекс
    #34632577
Фотография spc
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
komrad spcДобрый день!

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


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

а можно пояснить на примере как это делается?
...
Рейтинг: 0 / 0
не работает индекс
    #34633262
Фотография komrad
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
spc komrad spcДобрый день!

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


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

а можно пояснить на примере как это делается?
примерно так:

Код: 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.
use tempdb
go
create table #test (i int, a varchar( 20 ))
go
declare @i int, @a varchar( 20 )
select @i= 1 
select @a=convert(varchar( 20 ),@i)
while @i<= 1000 
begin
    insert into #test (i,a)
    select @i,@a
    
    select @i=@i+ 1 
    select @a=convert(varchar( 20 ),@i)
end 
go
create index ndx1 on #test(a)
go
create proc seek_a 
    @srch varchar( 20 )
    as 
begin
    select * from #test where a=@srch
end 
go
set showplan on
go
select * from #test where a='65'
go
exec seek_a '33'
go
set showplan off

...
Рейтинг: 0 / 0
не работает индекс
    #34634542
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
komrad пишет:
> таблицы и индексы надо создавать "над" хранимками
> иначе оптимизатор считает, что такая таблица состоит из 10 записей.
> ну и индексы туда же.

Не обязательно.
Posted via ActualForum NNTP Server 1.4
...
Рейтинг: 0 / 0
не работает индекс
    #34634759
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
spc пишет:

> В хранимке необходимо создавать временные таблицы и индексы на них,
> которые затем используются в запросах
>
> Например,
>
> create table #tmp (
> id numeric(*15*, *0*)
> ,name varchar(*255*)
> )
> create index i1 on #tmp(name)
>
> set forceplan on

Вам здесь forceplan не нужен, вам нужен хинт на индекс.
Это разные вещи. forceplan on убирайте, а если впредь
будете ставить, то ставьте ТОЛЬКО НА ОДИН КОНКРЕТНЫЙ
ЗАПРОС, а после него убирайте. Иначе можете поиметь
очень много проблем с фактически отключенным оптимизатором.

>
> insert #tmp
> select top *100000* it.InstitutionID, it.Name
> from tInstitution it
>
> select *
> from #tmp t (index i1)
> where t.name like 'Иванов%'
>
> drop table #tmp
>
> этот скрипт индекс не использует
>
> Index 'i1' specified as optimizer hint in the FROM clause of table '#tmp' does not exist. Optimizer will choose another index instead.

Процедура оптимизируется ДО выполнения, и комманда create index еще не успевает
отработать, поэтому индекса еще нету. Текст процедуры анализируется на предмет
создания временных таблиц, но не на предмет создания индексов на них.
Вот это причина того, почему это не работает. Но вообще вопрос сложный.

0) То, что порекомендовал komrad - это правильно, и это один из подходов
к решению этой проблемы. Но он не единственный и возможно даже не нужный.
Объяснения ниже.

1) Создавать индекс имеет смысл ПОСЛЕ вставки данных во временную таблицу.
Во-первых, вставка будет быстрее, во-вторых, CREATE INDEX соберет уже реальную
статистику с таблицы. Хотя, если мы будем форсировать индекс, она нас уже мало
интересует.

2) Указывать индекс в хинте можно не только по имени индекса, но и по его
номеру. В этом случае оптимизатор не проверяет наличие индекса, а тупо его
использует. Вставляет в план, а потом процессор запросов уже во время
выполнения если его не найдет, будет план подгонять. Номер индекса в хинте -
это на самом деле просто идентификатор индекса для этой таблицы в sysindexes,
т.е.

0 - это сама таблица (table scan) для heap-таблиц (без кластерного
индекса или DOL-таблиц (они все heap).

1 - это кластерный индекс для APL-таблиц, он же - сама таблица.

>1 - все остальные индексы (nonclustered index or a clustered index
on a data-only-locked table).

Пишется это так:
Код: plaintext
1.
select * from #tmp t (index  2 ) where t.name like 'Иванов%'

2 здесь - наиболее вероятное зачение именно этого индекса, потому как он
некастерный , а других индексов нет. Но вы должны четко знать номер индекса
в вашей конкретной таблице, это зависит от типа таблицы (APL/DOL), от типа
индекса (clustered/nonclustered) и от порядка создания индексов. В случае
каких-то сомнений можно создать такую же невременную таблицу с индексами
и посмотреть вывод sp_helpindex или напрямую содержимое sysindexes.

3) Ну и совсем теоретическое отступление - дело в том, что вопрос-то
часто поднимается всем сообществом пользователей ASE, и когда он задавался
в sybase.public.ase.performance+tuning , Eric Miner, инженер группы
оптимизатора, если не ошибаюсь, ведущий, уверял, что такое ДОЛЖНО
работать в современных версиях ASE (тогда была 12, и только вышла 12.5).
Что при этом, когда изменяется схема таблиц, в том числе и временный,
во время выполнения процедуры, увеличивается внутренний счетчик схемы
в сервере и это должно приводить к тому, что план процедуры пересоздается
с учетом изменений в схеме и далее уже выполнение идет по новому плану,
с учетом индекса. Т.е. CREATE INDEX на временную таблицу должен приводить
к пересозданию плана и к видимости этого индекса для запроса. НО правда
в рассматриваемом нами случае сообщение возникает, конечно же, при первом
создании плана, а используется ли индекс во втором плане, в общем, и не
известно.

Я не смог найти конкретно ту ветку, в которой выступал Eric, но
вот что-то аналогичное, где Iann излагает что-то похожее.

http://groups.google.com/group/sybase.public.ase.performance+tuning/browse_frm/thread/96f2232fb08f369b/b1f7650bdff9616d?lnk=gst&q=temporary+table+index&rnum=5#b1f7650bdff9616d

Так что в общем, я думаю, если бы индекс создавался ПОСЛЕ заполнения данных,
и не использовался бы хинт (index) , то я думаю индекс бы пошел в запрос,
конечно, при условии его полезности для запроса (высокой селективности индекса).

Итог: выполните требования пунктов 1) и 2) и будет работать.
Posted via ActualForum NNTP Server 1.4
...
Рейтинг: 0 / 0
не работает индекс
    #34636353
just me
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Present new small feature called deferred compilation ( DC) or runtime compilation.
This feature is new to 15.0.2

Behavior before 15.0.2

All statements in a stored procedure are compiled right before the first execution of the procedure.
Query plan is generated and installed in a procedure cache.
During the compilation values of local variables are not known.
Similary a size of temporary tables created in a procedure is not known.
This may result in non optimal execution plan.

Example #1

create proc P1asdeclare @a intselect @a = max(col) from t
select * from tab1 where col = @a
go
exec P1
go

when optimizing the statement :select * from tab1 where col = @athe optimizer does not know the value of thevariable. It's unable to correctly estimatethe selectivity of the WHERE clause and asa result a suboptimal plan may be chosen.

Example #2

create proc P2asselect * into #a from tselect * from #a, tab1 where col1 = col2
go

exec P2
go

When optimizing the statement : select * from #a, tab1 where col1 = col2the optimizer is not aware of the size of thetable #a. It assumes the table has 100 rows.Based on this estimation we may end up with suboptimal plan.


Deferred compilation mechanism

Delays the statement optimization and generationof the plan until the runtime. The compilation is done right before executing the statement after executing the proceeding statement.

Example #1 with the deferred compilation

create proc P1 as
declare @a intselect @a = max(col) from t
select * from tab1 where col2 = @a
go
Exec P1 details :
When the procedure execution begins generate a procedure plan but skip the compilation for the statement select * from tab1 where col2 = @a
Execute select @a = max(col) from t
Now when the value of @a is known compile the statement select * from tab1 where col2 = @a
and use @a runtime value to optimize the statement
Integrate a plan for the statement into the procedure plan and resume the execution

Example #2 with the deferred compilation

create proc P2 as
select * into #a from t
select * from #a, tab1 where col1 = col2
go
exec P2
go
Execution details:
Compile a plan for all statements with exception of select * from #a, tab1 where col1 = col2
Execute the first select into statement
When executing the second select statement : select * from #a, tab1 where col1 = col2
first compile it
Integrate the plan for the statement into the procedure plan.

Additional information.

A statement will be compiled in a deferrede mode only once, before its first execution.
After the first execution the statement plan will be integrated into the procedure plan and cached.
If the procedure is executed or created WITH RECOMPILE a deferred compilation will happen at each execution because with each execution new procedure plan will be generated and cached plans will not be used.
If during the runtime compilation of the statement an error is hit the procedure if fully renormalized and recompiled without using the deferred compilation.

Deferred compilation criteria.

A statement will be compiled in a deferrede mode
When local variables or parameters are used in a WHERE clause
When a query is using a join with temporary table created in the same procedure

The feature is ON by default including system stored procedures.
One may use trace flag –T7730 to disable it server wide.
...
Рейтинг: 0 / 0
7 сообщений из 7, страница 1 из 1
Форумы / Sybase ASA, ASE, IQ [игнор отключен] [закрыт для гостей] / не работает индекс
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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