sybase: problem s order by ... DESC (jeste delsi)

Jan Serak sherry na pikebo.cz
Pátek Listopad 24 22:30:15 CET 2000


Pavel Kolesnikov wrote:
[...]
> V one tabulce mam i dvojity
> index pres b_id a posted. Stejny problem ale pozoruji i pri prostem
> 
>         SELECT * FROM table ORDER BY posted DESC
> 
> kde je nad "posted" jednoduchy index.
> 
> Proste ocekaval bych, ze se ten index pri trizeni pouzije.
> 
> Pri listovani moudrymi knihami jsme tu nakonec narazili na stranku
[...]
> kde se pomerne nesmlouvave pravi:
> 
>         "The use of desc in an order by clause, to get results in
>         descending order, always requires a sort."
> 
> Prijde mi divne, ze by Sybase SQL server byl nejak mimoradne hloupy,
> takze chyba bude asi na me strane a skutecnost, ze ORDER BY DESC
> proste indexy nemuze pouzit je nejaky notoricky znamy a logicky
> zduvodnitelny fakt platny pro vetsinu SQL serveru - je tomu tak?

Indexy jsou primarne urceny pro urychleni vyberu, nikoli pro radeni
vystupu. Neznam Sybase SQL, ale Oracle pri pouziti ORDER BY tridi
vzdy. Duvod je prosty:

Index obsahuje (velice zjednodusene) hodnotu nejake n-tice sloupcu
a odkazy do vsech datovych bloku, kde se n-tice vyskytuje. To pomuze
pri vyhledavani zaznamu, kde se vyskytuje dana n-tice, ponevadz se
vytahnou jen ty datove bloky, ktere zaznamy s danou n-tici obsahuji.
Ty se nactou do pameti a mohou se uz bez obav prolezt sekvencne.

Pokud by RDBMS provadel uvedeny SELECT * FROM table ORDER BY posted
tak, ze by postupne prochazel indexem a vytahoval jednotlive zaznamy
z datovych bloku, pak KAZDY blok, ktery obsahuje x ruznych hodnot
sloupce posted, by precetl x-krat. To drasticky zvysuje io-operace
a tim zpomaluje cele vyhodnoceni dotazu. Preliti (v tomto pripade)
vsech zaznamu z tabulky do struktury vhodne pro trideni podle sloupce
posted a jeji jednorazove setrideni, bude ve vetsine pripadu mene
narocne na io-operace nez pripadne pouziti indexu.

/* tuto poznamku lze preskocit, mam dnes nejake grafomanske sklony ;-)

Oracle RDBMS ma vlastnost, ktera mu umoznuje vytvaret clustery, coz
jsou (opet zjednodusene) shluky zaznamu, ktere maji stejnou hodnotu
nejake n-tice sloupcu. Fyzicky tedy podobne (stejne zaklicovane)
zaznamy Oracle uklada fyzicky do tychz bloku. V takovem pripade
lze pouzit index pri sestavovani vysledku ORDER BY, ponevadz se
vi, ze v kazdem bloku jsou vyhradne zaznamy s touz n-tici hodnot
prislusnych sloupcu, a kazdy blok se tudiz precte prave jednou.

Pokud tedy "clusterujeme" data podle sloupcu sl1,sl2,sl3, tak v
dotazech ORDER BY sl1,sl2,sl3 lze pouzit vyse popsany zpusob
(teoreticky, v praxi jsem nikdy nemel odvahu to pouzit). Pri ORDER
BY sl1,sl2,sl3,sl4 to vsak jiz opet neni vhodne. Navic ma cluste-
rovani vyznam jen na sloupcich, plnenych relativne malym mnozstvim
kombinaci, coz pripad sloupce posted rozhodne neni ;-)
*/
> 
> : Neznam sybase, ale principialne se vzdy selecty s order by musi
> : provadet tak, ze se data vyberou a pak setridi. Jestli se pred
> : tridenim ulozi nekam do docasnych struktur v databazi nebo
> : nekam do pameti je vcelku lhostejne.
> 
> To nesouhlasim nebo aspon neco nechapu:
> 
> Pokud si dam set showplan on (tj. neco jako explain, proste popis
> toho, co se zrovna deje :), tak pri provadeni ORDER BY (ASC) ma query
> plan pouze jeden krok, a to
[...]

> Z toho bych si dovolil odvodit, ze pokud mam pouzitelny index, tak
> SQL server umi jit podle indexu a v jednom kroku tedy vracet data
> jiz setrizena.

Ne. K tomu, aby si to mohl dovolit, musi mit jeste nejakou dodatecnou
informaci. Napr. o tom, ze posted je pridelovano ve vzrustajicim
poradi a uvnitr datovych bloku jsou zaznamy podle posted jiz setridene.
Jinak by musel minimalne tridit zaznamy uvnitr bloku (coz muze, aniz
by Vam o tom rekl), ale obecne muze nastat napr. tato situace:

blok 1:
	zaznam 1: posted=1
	zaznam 2: posted=5
blok 2:
	zaznam 1: posted=2
	zaznam 2: posted=3

Jak bude vypadat order by posted pouzitim indexu? Prvni "zaznam" v indexu rika,
ze posted=1 je v bloku 1. Nacte se blok 1. Co vsecko ma hodit na vystup?
Urcite zaznam 1, protoze ho pri pristupu pres index ocekava. Pokud by hodil
na vystup i zaznam 2, tak by vrati blbost. Tudiz nemuze. Tak s blokem 1 konci.
Druhy "zaznam" indexu ho vede do bloku 2. Vrati zaznam 1, protoze ceka posted=2
podle indexu. Opet nevi, jestli si muze dovolit vratit zaznam 2. V nasem pripade
by mohl, ale on nevi, ze muze. Tedy zahodi blok 2 a jde na treti "zaznam"
indexu,
ktery mu rekne, ze ma nacist blok 2 a v nem najit zaznam s posted=3.

Snadno je videt, jakym zpusobem narustaji io=operace. Setridenim v docasnych
blocich BEZ pouziti indexu je jednodussi: prectou se pouze dva bloky.

Vase zjisteni ze showplanu pro me znamenaji dvoji:

a) Sybase ma k dispozici nejakou informaci o fyzickem ulozeni dat. Tato
informace
je samozrejme pouzitelna pouze pri trideni ASC a nepouzitelna pri trideni DESC.

b) Sybase skutecne provadi to, co jsem zjednodusene popsal v prikladu. Pak
showplan
odpovida popisu toho, co skutecne provadi, ale pocet kroku nevypovida o skutecne
casove narocnosti.

Pokud chcete prijit veci skutecne na kloub a nechcete nebo nemate moznost
studovat
dokumentaci Sybasovych strev, je doporucenihodne provest nekolik drobnych
experimentu.

Prvni z nich bych smeroval na hypotezu a). Na nejak "prirozene" naplnene tabulce
bych provedl par dobre mirenych updatu, kterymi bych se snazil jednak prohazet
indexove "zaznamy" tim, ze bych z nejstarsich dat udelal novejsi a nejnovejsi.
Predpokladam, ze Sybase pri updatu indexovaneho sloupce fyzicky nehybe se
zaznamem. Co bude Sybase delat?

Pak bych defragmentoval bloky. Napr. tim, ze casove blizke zaznamy rozesadime
(v indexu), treba tak, ze casy (v sekundach) delitelne 3 se zbytkem 1 o hodne
zestarnul (opet dobre mirenym updatem), se zbytkem 2 o hodne omladil a beze
zbytku ponechal. Co bude Sybase delat?

Co bude Sybase delat, kdyz obe veci zkombinuji?

> Asi nemam ten vhled aby mi bylo jasne, ze po indexu
> se neda chodit pozpatku - proc?

Indexy jsou obvykle implementovany jako vyvazene B-stromy. Indexem tedy
nechodite ani dopredu ani pozadu, ale stromove. Fyzicky jsou vsak indexy
ulozeny vetsinou (zjednodusene) tak, ze za korenem lezi vzestupne ulozena
prvni generace potomku, pak vzestupne ulozena generace "vnuku" pochazejicich
z prvniho potomka korene,... na "vnukove" 2. potomka se ukladaji az za cely
podstrom 1. potomka. Sekvencni pruchod datovymi bloky indexu pak presne
odpovida stromovemu algoritmu "hledani do hloubky". Prochazeni indexu
vzestupne tedy je mozne a neni tak narocne. Opacny smer prochazeni je pak
velice narocny na io-operace a proto se nepouziva.


Doufam, ze jsem aspon trosku pomohl. Jeste nasleduje poznamka ohledne
Vasi aplikace.

> 
> :> Neprilis ciste metody, ktere me napadaji, jsou treba "odhadnout",
> :> ze zaznamy, ktere me zajimaji, nejsou starsi nez xyz hodin, a tim
> :> zmensit tridenou mnozinu.
> 
> : Nevim, co je necisteho na:
> 
> :       select ... from ... where b_id=xyz and posted>sysdate-3
> 
> : pokud me nezajimaji data starsi tri dnu (omlouvam se, sysdate-3
> : lze pravdepodobne pouzit pouze v Oracle). Pokud jsou v tabulce
> : data za posledni rok, muze to samozrejme VELMI pomoci.
> 
> No, problem je prave v tom, ze zaznamy do inkriminovane tabulky
> pribyvaji dost nepravidelne. Tzn. napr. pro b_id = 1 je vhodne
> to omezit tremi dny zpet, ale treba pro b_id = 2 maji smysl dva
> mesice.

To neni problem. Urcite ma Sybase funkci, ktera se umi chovat jako
prepisovaci tabulka. V Oracle je
decode(co,zdroj1,cil1,...,zdrojn,ciln[,default])
ktera na zaklade parametru co vrati cil1, pro co=zdroj1,... pripadne
default, pokud co uplne jinou hodnotu.

Takze staci:

select ... from ... where b_id=:nejaka_promenna
and posted>sysdate-decode(b_id,1,"tri dny",2,"dva mesice",...)

> 
> : Ohledne indexovani offsetu od pulnoci 1. 1. 3000: neverim, ze by Vam
> : to mohlo nejak vyrazne pomoci. Tridit se musi tak jako tak.
> 
> Pokud je normalni, ze databaze umi vyuzit indexu jen jednim smerem,
> tak mi to pochopitelne pomuze, protoze tim si vlastne vytvorim
> prevracene usporadany index :)

S tim nelze nez souhlasit. Jelikoz vsak nepovazuji vychodisko Vasi
implikace (v pripade ORDER BY, pri vybirani dat se index prochazi
stromove) za pravdive, indexovani offsetu od pulnoci 1. 1. 3000
Vam nepomuze.

						Jan Serak


Další informace o konferenci Test