Vertikalni deleni tabulek

Honza Pazdziora adelton na informatics.muni.cz
Středa Říjen 30 16:56:56 CET 2002


On Wed, Oct 30, 2002 at 10:44:27AM +0100, Martin Majkus wrote:
> 
> zajímá mě, jestli má cenu vertikálně dělit tabulky, pokud obsahují velká 
> pole variabilní délky. Například, jestli je lepší následující tabulku 
> rozdělit na 2 tabulky a spojit je 1:1 vazbou přes id (tedy ve druhé 
> tabulce by byly pouze poslední dva sloupce + id).
> 
> CREATE TABLE clanky (
> 	id	INTEGER	NOT NULL PRIMARY KEY,
> 	datum	DATE,
> 	konec	DATE,
> 	...
> 	abstrakt 	TEXT,
> 	abstrakt_idx	TXT_IDX);
> 
> Zlepší se potom rychlost vyhledávání ve sloupcích datum a podobně?

Snažil jsem se najít v dokumentaci PostgreSQL a na webu, jak je
uložen atribut typu TEXT a co je to TXT_IDX, ale neuspěl jsem.

Čili čistě teoreticky: pokud by ten abstrakt a abstrakt_idx byly na
disku uloženy přímo v tom záznamu v tabulce clanky a zabíraly by
tam nějaké podstatné místo, tak by to znamenalo, že na to, abyste
získal datum pro deset článků s id od 1 do 10, musíte načíst
podstatně více diskových bloků než když ty záznamy budou fyzicky na
disku krátké. Když ty záznamy na disku budou fyzicky krátké, tak se
může stát, že se do jednoho diskového bloku vejde těch záznamů několik
(desítek, stovek, záleží, co je nejmenší element se kterým databáze
pracuje). Je ale možné, že TEXT je natolik speciální typ, že
v záznamu je fyzicky uložena pouze reference (oid) a obsah je někde
bokem.

Čili pokud by ten abstrakt a abstrakt_idx byly chary nebo varchary,
u kterých předpokládám, že jsou ukládány přímo v záznamu, a byly
netriviálně dlouhé, a nepoužívaly by se často, a naopak by se
používaly často jiné atributy, jako třeba datum, tak by bylo vhodné
dát tyhle velké věci do extra tabulky, a pokud by byly potřeba, tak
pro ně jít přes join (či outer join). Tím pádem bude ta většina dotazů
rychlejší, protože se třeba celá ta bázová tabulka vejde do paměti,
a holt když v malém procentu případů bude potřeba abstrakt, tak se
dotáhne z disku.

Naopak, pokud v podstatě vždy, když děláte select, abyste získal
datum, tak zároveň načítáte i abstrakt a abstrakt_idx, pak nemá cenu
uklízet je do zvláštní tabulky, protože akorát zpomalíte selecty o ten
join.

A podobně, pokud je TEXT a TXT_IDX uložen v tabulce interně tak, že
je tam pouze (řekněme) osmibajtový identifikátor ukazující někam
jinam, kde jsou už ta koncová data, tak nemá cenu to rozhazovat na dvě
tabulky, protože to vlastně už udělala databáze za Vás.

Nicméně je třeba zvážit nejen to, že jsou tam dva sloupce s nějakými
atributy, ale i to, jakým způsobem jsou údaje v té tabulce používány,
jestli všechny stejně často, nebo ne, jak je na tom ten stroj s pamětí
(a jaká je tudíž šance, že se to všechno vejde do RAM a s diskem se
vůbec nebude pracovat), a tak. Čili vertikální partitioning může
pomoci, ale záleží na spoustě dalších okolností, jaký bude mít efekt.
Můžná nejlepší by bylo to zkusit -- napsat si benchmark na základě
skutečných selectů, nebo prostě tu tabulku takhle rozdělit,
nadefinovat view, které ty dvě části zpřístupní zpět jako jednu
relaci, a dát na to view trigger, který z toho udělá zase tabulku.
Čímž si zajistíte zpětnou kompatibilitu, a pak můžete změnit příslušné
selecty tak, aby šly pouze na jednu nebo druhou partition.

-- 
------------------------------------------------------------------------
 Honza Pazdziora | adelton na fi.muni.cz | http://www.fi.muni.cz/~adelton/
      ... all of these signs saying sorry but we're closed ...
------------------------------------------------------------------------


Další informace o konferenci Databases