powered by simpleCommunicator - 2.0.56     © 2025 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Sybase ASA, ASE, IQ [игнор отключен] [закрыт для гостей] / План запроса в пакете и без
20 сообщений из 20, страница 1 из 1
План запроса в пакете и без
    #37292269
LelikB
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Adaptive Server Enterprise/12.5.4/EBF

Вопрос больше теоретический.
Есть некий пакет в котором во временную таблицу с индексами вставляются данные (около 90000 строк), затем идет серия апдейтов этих данных.
insert #Temp...
update #Temp...
update #Temp...
update #Temp...

Так вот, обнаружилась интересная вещь: если выполнять каждый запрос последовательно, то оптимизатор корректно обнаруживает нужный индекс, все работает быстро. А если выполнить все в одном пакете, то на одном из запросов идет table scan. Если указать нужный индекс хинтом, то проблем не возникает.
Почему так происходит? Ведь данные и в первом и во втором случае в таблице одни и те же.
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
create table #Card 
(
  CardID         numeric( 15 , 0 )
 ,ResourceID     numeric( 15 , 0 ) null
 ,StateOrder     int           null  
 ,IsActive       bit   
 ,IsNew          bit
 ,CrdGroup       smallint      null 
 ,CardRole       smallint           
 ,isMain         smallint
 ,DateExpiration smalldatetime
 ,MidRest        numeric( 18 , 2 ) 
)

create clustered index i1 on #Card(CardID)
create index i2 on #Card(ResourceID, CardRole)
Запрос:

Код: plaintext
1.
2.
3.
4.
5.
6.
update #Card
set isMain =  1 
where isActive= 0 
  and not exists (select  1  from #Card c1  (index i2)       --если индекс не указать, будет Table Scan  
                 where #Card.ResourceID = c1.ResourceID
                   and isActive =  1 )
...
Рейтинг: 0 / 0
План запроса в пакете и без
    #37292285
LelikB
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
План при выполнении всего пакета (без хинта с индеком).
Код: 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.
QUERY PLAN FOR STATEMENT 11 (at line 77).
    STEP 1
        The type of query is UPDATE.
        The update mode is deferred.
        FROM TABLE
            #Card
        Nested iteration.
        Table Scan.
        Forward scan.
        Positioning at start of table.
        Run subquery 1 (at nesting level 1).
        Using I/O Size 8 Kbytes for data pages.
        With LRU Buffer Replacement Strategy for data pages.
        TO TABLE
            #Card
        Using I/O Size 8 Kbytes for data pages.
    STEP 1
NESTING LEVEL 1 SUBQUERIES FOR STATEMENT 11.
  QUERY PLAN FOR SUBQUERY 1 (at nesting level 1 and at line 80).
    Correlated Subquery.
    Subquery under an EXISTS predicate.
    STEP 1
        The type of query is SELECT.
        Evaluate Ungrouped ANY AGGREGATE.
        FROM TABLE
            #Card
            c1
        EXISTS TABLE : nested iteration.
        Table Scan.
        Forward scan.
        Positioning at start of table.
        Using I/O Size 8 Kbytes for data pages.
        With LRU Buffer Replacement Strategy for data pages.
  END OF QUERY PLAN FOR SUBQUERY 1.
Total estimated I/O cost for statement 11 (at line 77): 378.
Parse and Compile Time 0.

План при выполнении только одного этого запроса (также без хинта с индеком).
Код: 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.
QUERY PLAN FOR STATEMENT 1 (at line 1).
    STEP 1
        The type of query is SELECT.
Total estimated I/O cost for statement 1 (at line 1): 0.
Parse and Compile Time 0.
SQL Server cpu time: 0 ms.
QUERY PLAN FOR STATEMENT 1 (at line 1).
    STEP 1
        The type of query is UPDATE.
        The update mode is deferred.
        FROM TABLE
            #Card
        Nested iteration.
        Table Scan.
        Forward scan.
        Positioning at start of table.
        Run subquery 1 (at nesting level 1).
        Using I/O Size 64 Kbytes for data pages.
        With LRU Buffer Replacement Strategy for data pages.
        TO TABLE
            #Card
        Using I/O Size 8 Kbytes for data pages.
    STEP 1
NESTING LEVEL 1 SUBQUERIES FOR STATEMENT 1.
  QUERY PLAN FOR SUBQUERY 1 (at nesting level 1 and at line 4).
    Correlated Subquery.
    Subquery under an EXISTS predicate.
    STEP 1
        The type of query is SELECT.
        Evaluate Ungrouped ANY AGGREGATE.
        FROM TABLE
            #Card
            c1
        EXISTS TABLE : nested iteration.
        Index : i2
        Forward scan.
        Positioning by key.
        Keys are:
            ResourceID  ASC
        Using I/O Size 64 Kbytes for index leaf pages.
        With LRU Buffer Replacement Strategy for index leaf pages.
        Using I/O Size 64 Kbytes for data pages.
        With LRU Buffer Replacement Strategy for data pages.
  END OF QUERY PLAN FOR SUBQUERY 1.
И в первом и во втором случае данные в таблице одинаковые.
...
Рейтинг: 0 / 0
План запроса в пакете и без
    #37292359
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
On 02.06.2011 20:41, LelikB wrote:
> Вопрос больше теоретический.

Теоретически такого быть не должно.

> Есть некий пакет в котором во временную таблицу с индексами вставляются данные
> (около 90000 строк), затем идет серия апдейтов этих данных.
> insert #Temp...

После пачки insert-ов очень хорошо было бы сделать UPDATE STATISTICS.
Или, ещё лучше, СНАЧАЛА вставлять данные,
а ПОТОМ делать

Код: plaintext
1.
2.
create clustered index i1 on #Card(CardID)
create index i2 on #Card(ResourceID, CardRole)

(UPDATE STATISTICS при этом уже не нужно )

Да, надеюсь, что create table и create index-ы у вас В ОТДЕЛЬНОМ
БАТЧЕ ?

> Так вот, обнаружилась интересная вещь: если выполнять каждый запрос
> последовательно, то оптимизатор корректно обнаруживает нужный индекс, все
> работает быстро. А если выполнить все в одном пакете, то на одном из запросов
> идет table scan.Ведь данные и в первом и во втором случае в таблице одни
> и те же.

Да, и кстати, если вы не делаете так, как я выше написал,
то оптимизатор при этом ничего о данных не знает.

Код: plaintext
1.
2.
3.
4.
5.
6.
  update #Card
  set  isMain =  1 
  where  isActive=  0 
     and  not  exists  (select  1  from #Card c1 (index  i2)
                    where #Card.ResourceID = c1.ResourceID
                      and isActive =  1  )

Странно, что не решают сканиться ВСЕ запросы на UPDATE,
поскольку для оптимизатора таблица ваша пуста.
Других данных у него нет, и он считает, что она пуста.
Или немного заполнена.
Скорее всего, случайно оптимизатор решает сканить именно
на этом запросе. А ещё вернее всего, для остальных
запросов table scan -- реально самая оптимальная стратегия,
и вы просто не заметили, что там тоже table scan-ы.




Posted via ActualForum NNTP Server 1.4
...
Рейтинг: 0 / 0
План запроса в пакете и без
    #37292365
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
On 02.06.2011 20:52, LelikB wrote:

> И в первом и во втором случае данные в таблице одинаковые.

Рассказывайте подробнее какими батчами всё это выполнялось
в двух случаях, а особенно как create table и index.

Да, кстати, "чисто теоретически" в таком случае вовсе не
зазорно поставить хинты.

Posted via ActualForum NNTP Server 1.4
...
Рейтинг: 0 / 0
План запроса в пакете и без
    #37293421
LelikB
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
MasterZivДа, надеюсь, что create table и create index-ы у вас В ОТДЕЛЬНОМ
БАТЧЕ ?

Нет, все запросы в одном пакете.
В общем-то в этом и была проблема, просто я не понимал почему для оптимизатора это может быть важно.
MasterZivДа, и кстати, если вы не делаете так, как я выше написал,
то оптимизатор при этом ничего о данных не знает.

MasterZivдля оптимизатора таблица ваша пуста.
Других данных у него нет, и он считает, что она пуста.

Спасибо за развернутый ответ теперь все предельно понятно.
...
Рейтинг: 0 / 0
План запроса в пакете и без
    #37293438
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
On 03.06.2011 14:39, LelikB wrote:

> Да, надеюсь, что create table и create index-ы у вас В ОТДЕЛЬНОМ
> БАТЧЕ ?
>
>
> Нет, все запросы в одном пакете.

И CREATE TABLE ?
Posted via ActualForum NNTP Server 1.4
...
Рейтинг: 0 / 0
План запроса в пакете и без
    #37293562
LelikB
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
MasterZiv,
В данном конкретном случае create table и create index в одном пакете, а insert и серия update - в другом. Т.е. всего два пакета.
Но я никогда не задумывался над необходимостью их разделения на разные пакеты, в данном случае я сделал это только для удобства. Не подскажете, почему это может быть необходимо?
...
Рейтинг: 0 / 0
План запроса в пакете и без
    #37293604
cherrex_Den
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
LelikBMasterZiv,
В данном конкретном случае create table и create index в одном пакете, а insert и серия update - в другом. Т.е. всего два пакета.
Но я никогда не задумывался над необходимостью их разделения на разные пакеты, в данном случае я сделал это только для удобства. Не подскажете, почему это может быть необходимо?

Так как индекс создан до вставки, при вставке(insert), ASE нужно заполнить не только таблицу , но и индекс! плюс оптимизатор нечего не знает о статистике по этой таблице и по индексам.

Нужно так:

1-батч:
а. создал таблицу
б. залил(insert) данные
2-батч
а. сделал индекс
б. сделал апдэйт

И индекс создадите быстрей и статистика на апдэйтах будет актуальной!!!
...
Рейтинг: 0 / 0
План запроса в пакете и без
    #37293691
LelikB
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
cherrex_Den
Так как индекс создан до вставки, при вставке(insert), ASE нужно заполнить не только таблицу , но и индекс!

А в случае кластерного индекса? Его-то наверняка имеет смысл создать до вставки?
cherrex_Den2-батч
а. сделал индекс
б. сделал апдэйт

Но тогда оптимизатор не будет знать об индексе при апдейтах, т.е. а. и б. также имеет смысл разделить?
...
Рейтинг: 0 / 0
План запроса в пакете и без
    #37293776
cherrex_Den
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
LelikB,

LelikBА в случае кластерного индекса? Его-то наверняка имеет смысл создать до вставки?

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

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

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

Спасибо за развернутый ответ теперь все предельно понятно.

не считает он её пустой
но и реальной картины у него нет

насколько я помню из документации, оптимизатор предполагает некоторое кол-во записей ... в районе сотни, если не изменяет память
...
Рейтинг: 0 / 0
План запроса в пакете и без
    #37293842
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
On 03.06.2011 16:35, LelikB wrote:

> А в случае кластерного индекса? Его-то наверняка имеет смысл создать до вставки?
> cherrex_Den

Нет. После.

> Но тогда оптимизатор не будет знать об индексе при апдейтах, т.е. *а.* и *б.*
> также имеет смысл разделить?

Да.

Я что понять-то не могу, так это как вы умудряетесь в один батч запихать
create table, create index и всё остальное, когда вроде бы как все DDL
дожны быть ТОЛЬКО ОТДЕЛЬНЫМ БАТЧЕМ (если не в процедуре или триггере).
Posted via ActualForum NNTP Server 1.4
...
Рейтинг: 0 / 0
План запроса в пакете и без
    #37293844
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
On 03.06.2011 16:35, LelikB wrote:
> А в случае кластерного индекса? Его-то наверняка имеет смысл создать до вставки?

Вообще, не делали бы вы на временные таблицы-то кластерные индексы. Нафиг они
там ?
Posted via ActualForum NNTP Server 1.4
...
Рейтинг: 0 / 0
План запроса в пакете и без
    #37293849
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
On 03.06.2011 17:10, komrad wrote:

> не считает он её пустой
> но и реальной картины у него нет

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

Posted via ActualForum NNTP Server 1.4
...
Рейтинг: 0 / 0
План запроса в пакете и без
    #37293870
Фотография komrad
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
...
Рейтинг: 0 / 0
План запроса в пакете и без
    #37293875
Фотография komrad
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MasterZivOn 03.06.2011 17:10, komrad wrote:

> не считает он её пустой
> но и реальной картины у него нет

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



нашел таки в документации ;)

цитатаThe optimizer assumes that any such table has 10 data pages and 100 rows. If the table is really large, this assumption can lead the optimizer to choose a suboptimal query plan.
...
Рейтинг: 0 / 0
План запроса в пакете и без
    #37293944
LelikB
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
MasterZiv
Вообще, не делали бы вы на временные таблицы-то кластерные индексы. Нафиг они там ?

Не задумывался над этим.
Чтобы ссылка во втором ключе была сразу на CardID и в случае если надо узнать CardID по ResourceID, то не требовалось бы чтение таблицы, достаточно было чтения индекса.
Можно, конечно, для достижения того же результата сделать CardID первичным ключом:
Код: plaintext
1.
2.
3.
create table #Card 
(  CardID         numeric( 15 , 0 ) primary key
...
и сделать обычный индекс на CardID и ResourceID:
Код: plaintext
1.
2.
create index i1 on #Card(CardID)  
create index i2 on #Card(ResourceID, CardRole)  
В моем случае происходит только одна вставка в таблицу, дополнительных данных в середину таблицы (по CardID) не предвидится.
В чем будет недостаток временной таблицы в случае кластерного индекса?


MasterZiv
как вы умудряетесь в один батч запихать
create table, create index и всё остальное, когда вроде бы как все DDL
дожны быть ТОЛЬКО ОТДЕЛЬНЫМ БАТЧЕМ (если не в процедуре или триггере).

Код: plaintext
1.
2.
3.
4.
5.
create table #t (t int)
insert #t select  1 
insert #t select  2 
select * from #t
drop table #t
Никаких проблем. Особенности связки Diasoft FA# --- BDE --- Sybase ASE?

komrad , благодарю за ссылки.
...
Рейтинг: 0 / 0
План запроса в пакете и без
    #37294000
LelikB
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
[quot LelikB]MasterZiv
Можно, конечно, для достижения того же результата сделать CardID первичным ключом:
и сделать обычный индекс на CardID

Написал не подумав, что для первичного ключа и так кластерный индекс будет создан.
...
Рейтинг: 0 / 0
План запроса в пакете и без
    #37294057
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
On 03.06.2011 18:08, LelikB wrote:

> Чтобы ссылка во втором ключе была сразу на CardID и в случае если надо узнать
> CardID по ResourceID, то не требовалось бы чтение таблицы, достаточно было
> чтения индекса.

В этом что ли ?

create clustered index i1 on #Card(CardID)
create index i2 on #Card(ResourceID, CardRole)

Это, извини, ты попутал. Это тебе не MSSQLServer, это ASE.

В листах некластерных индексов ROWID лежит, а не значения ключей
кластерного индекса.

> Можно, конечно, для достижения того же результата сделать CardID первичным ключом:
>
> create table #Card
> ( CardID numeric(*15*,*0*)primary key
> ..
>
> и сделать обычный индекс на CardID и ResourceID:
>
> create index i1on #Card(CardID)

Зачем тебе ДВА индекса по CardID ?

> create index i2on #Card(ResourceID, CardRole)
>
> В моем случае происходит только одна вставка в таблицу, дополнительных данных в
> середину таблицы (по CardID) не предвидится.


> В чем будет недостаток временной таблицы в случае кластерного индекса?

Да особенно ни в чём, просто на фиг он не нужен. Создание кластерного
вызовет больше IO, потому что данные таблицы надо копировать, и ещё
пересоздаст все некластерные индексы, если они есть.

> Никаких проблем. Особенности связки Diasoft FA# --- BDE --- Sybase ASE?

Не знаю ... странно очень.
Posted via ActualForum NNTP Server 1.4
...
Рейтинг: 0 / 0
План запроса в пакете и без
    #37294110
LelikB
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
MasterZiv,

Код: plaintext
1.
2.
Это, извини, ты попутал. Это тебе не MSSQLServer, это ASE.
В листах некластерных индексов ROWID лежит, а не значения ключей
кластерного индекса.
Действительно, здесь я ошибался. Посмотрел планы запросов и убедился в этом.

Спасибо за ответы!
...
Рейтинг: 0 / 0
20 сообщений из 20, страница 1 из 1
Форумы / Sybase ASA, ASE, IQ [игнор отключен] [закрыт для гостей] / План запроса в пакете и без
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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