[ sawa @ 28.04.2005. 21:27 ] @
evo neceg interesantnog, a ne znam gde da nadjem odgovor:

Elem, imam tabelu za oko 70 polja. Tabela za sada ima 7 miliona recorda.
Najobicniji query nad njom traje poprilicno dugo.

E,sad, napravim drugu tabelu samo sa poljima koja koristim u queriju. Tabela ima istih 7 miliona recorda.

Obe tabele imaju iste indexe.

Isti query na tabeli sa manje polja radi 4-10 puta brze nego nad tabelom sa 70 polja.

Ima li iko neko logicno objasnjenje ove pojave?

Hvala
[ SmilieBG @ 28.04.2005. 22:06 ] @
pa sasvim je logicno :)

U zavisnosti od toga, kako je optimizovana baza, tabela i samo polje, do toga sta i kako trazis, gde su indexi, zavisi ce i koliko ce trajati query :)

Zamisli situaciju:

imas 70 korpi sa jabukama, u svakoj po nekoliko desetina jabuka. I trebas iz svih da nadjes samo crvene jabuke.

A sad zamisli isto to, samo umesto 70 korpi imas 7 korpi :)

Sta mislis, gde ces ih brze naci?

Poz,
Sale
[ sawa @ 28.04.2005. 22:14 ] @
>
>
Mislim da nisi shvatio problem. SQL je IDENTICAN samo sto je primenjen
na tabelu koja ima samo 10 polja (potrebnih za query) umesto 70. Indexi
na tabelama su takodje IDENTICNI. Tih 10 polja u obe tabele su takodje
IDENTICNI (tip i podaci).

Znaci nije mi jasno zasto SQL nad tabelom koja ima 70 polja traje 4-10
puta duze iako ostalih 60 polja nemaju veze sa doticnim SQL-om
[ sawa @ 28.04.2005. 22:16 ] @
>
>
eto jos da dodam da je db engine InnoDB i takodje da koristim force
index tako da optimizer nema uticaja na to koji se index koristi
[ SmilieBG @ 29.04.2005. 13:07 ] @
daj query, posto od njega zavisi :)

Poz,
Sale
[ sawa @ 29.04.2005. 13:29 ] @

evo ga:
Code:

SELECT case when cdr.originating_trunk_group is null then 'NULL' else 
cdr.originating_trunk_group 
end,count(*),round(sum(subscriber_duration)/60), round((sum(case when 
Subscriber_duration>0 then 1 else 0 end ))/count(*)*100), 
round(sum(Subscriber_duration )/(sum(case when Subscriber_duration>0 
then 1 else 0 end ))/60,2)
FROM cdr_core cdr force index(cdr_core2)
WHERE cdr.CDB_Date >= '2005-04-01 00:00'
AND cdr.CDB_Date < '2005-05-01 00:00'
AND CDB_Identifier='1110'
GROUP BY  case when cdr.originating_trunk_group is null then 'NULL' else 
cdr.originating_trunk_group end


// Edit by StRiPy: Dodan code tag.


[Ovu poruku je menjao StRiPy dana 29.04.2005. u 19:11 GMT+1]
[ SmilieBG @ 29.04.2005. 15:23 ] @
Ne znam kako mysql reaguje na case (moram da pogledam), ali 99% da ga ovo 'ubija':

count(*)

Zagledacu jos malo query veceras (na poslu sam :P)

Poz,
Sale
[ _owl_ @ 29.04.2005. 21:27 ] @
Mozda u tabeli sa vise kolona imas dosta kolona cija duzina nije fiksna pa MySQL ne moze toliko brzo da dodje do podataka.
[ sawa @ 29.04.2005. 22:28 ] @
>
>
>
da, u pravu si, imam dosta varchar polja.
Mogao bih da ih prebacim u char (i zrtvujem velicinu baze).
Testiracu taj scenario
[ ivan jeremic @ 28.06.2005. 13:32 ] @
Ako iko jos cita ovo neka zna jedno ....
database server .. koji god da je ... nezna da radi sa diskom.
Posto su mu slogovi nerazumljivi dok su na disku on mora sve slogove, za koje sumnja da imaju podatke koji mu trebaju, da digne u memoriju a onda da izdvoji samo polja koja mu trebaju ... E sad .. ucitaj ti 70 polja u memoriju po slogu, izvuci sta ti treba pa idi na sledeci slog ili to isto radi sa slogovima od po 10 polja. Meni se ono prvo cini kao malo veca zajebancija zar ne?
[ sawa @ 28.06.2005. 13:48 ] @
>
>
>
moguce da je tacno, ali ko zna kako su slogovi odnosno tabele i ostalo
rasporedjeni u jednom jedinom fajlu (innodb engine). u svakom slucaju
ako vuce po 70 polja imesto po 10 verovatno mora vise puta da pristupa
disku...ko ce ga znati
[ dragancesu @ 01.07.2005. 07:52 ] @
Baza je prilicno velika i tvoj uslov ce je terati da je procita celu. Ako mozes napravi pomocnu tabelu i onda ce sve ici brze. Napravi nesto kao

create pomocna
as
select polje, polje, polje,... from tabela
WHERE cdr.CDB_Date >= '2005-04-01 00:00'
AND cdr.CDB_Date < '2005-05-01 00:00'
AND CDB_Identifier='1110';

i onda uradis iz pomocne. Pitanje je koliko je ta tabela napadnuta s drugim upitima.