ďťż
 
Optymalizacja zapytania ďťż
 
Optymalizacja zapytania
Zobacz wiadomości
 
Cytat
A gdyby tak się wedrzeć na umysłów górę, / Gdyby stanąć na ludzkich myśli piramidzie, / I przebić czołem przesądów chmurę, / I być najwyższą myślą wcieloną. . . Juliusz Słowacki, Kordian
Indeks BCB i MySQL subiekt gt fototapeta
 
  Witamy

Optymalizacja zapytania



Piotr [PKi] - 20-03-2006 01:30
Optymalizacja zapytania
  No i jeszcze raz ja, temat ciut inny.

Tabela 'pomiar', wrzucane sa tutaj cyklicznie pomiary w roznych
miernikow. obecnie baza ma 18 milionów rekordów.
Komp to sempron >2GHz, 1GB ramu.

Struktura tabeli:
CREATE TABLE `pomiary` (
`Id` bigint(8) unsigned NOT NULL auto_increment,
`data` datetime NOT NULL default '0000-00-00 00:00:00',
`miernik` tinyint(3) unsigned NOT NULL default '0',
`komorka` smallint(5) unsigned NOT NULL default '0',
`wartosc` int(10) NOT NULL default '0',
PRIMARY KEY (`Id`),
KEY `data` (`data`),
KEY `miernik` (`miernik`),
KEY `komorka` (`komorka`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_german1_ci
COMMENT='testowa tabela pomiary';

zapytanie:
SELECT data, UNIX_TIMESTAMP(data) AS xlabel,
(SELECT wartosc FROM pomiary WHERE miernik = 1 AND komorka = 98 AND
p.data = data) AS moc_g1,
(SELECT wartosc FROM pomiary WHERE miernik = 2 AND komorka = 98 AND
p.data = data) AS moc_g2
FROM pomiary AS p
WHERE (UNIX_TIMESTAMP() - UNIX_TIMESTAMP(data)) < (60*60*3)
GROUP BY data
HAVING
moc_g1 IS NOT NULL AND
moc_g2 IS NOT NULL
ORDER BY data ASC;

Zapytanie to wyciaga z bazy wartość dla komorka 98 dla miernik 1 i 2
jako moc_g1 i moc_g2 z ostatnich 3 godzin (60 sekund * 60 minut * 3
godziny).

Obecnie zapytanie trwa 52 sekundy! i daje 334 rekordy, a powinno być
1080 rekordów (rejestracja jest co 10 sekund) i nie wiem czy mysql
konczy zapytanie ze wzgedu na jakis timeout czy przepełnienie ??

W podobnej tabeli gdzie pomiar idzie co 5 minut dziala poprawnie, zwraca
36 wierszy z 3 godzin, zapytanie trwa jednak około 6 sekund, rekordów
jest około miliona.

Pozdrowionka

Piotr





pedroz - 21-03-2006 01:00

  Piotr [PKi] wrote:
> zapytanie:
> SELECT data, UNIX_TIMESTAMP(data) AS xlabel,
> (SELECT wartosc FROM pomiary WHERE miernik = 1 AND komorka = 98 AND
> p.data = data) AS moc_g1,
> (SELECT wartosc FROM pomiary WHERE miernik = 2 AND komorka = 98 AND
> p.data = data) AS moc_g2
> FROM pomiary AS p
> WHERE (UNIX_TIMESTAMP() - UNIX_TIMESTAMP(data)) < (60*60*3)
> GROUP BY data
> HAVING
> moc_g1 IS NOT NULL AND
> moc_g2 IS NOT NULL
> ORDER BY data ASC;

Zrezygnuj z podzapytan. I wydaje mi sie, ze to zapytanie mozna napisac
znacznie prosciej. Czy to nie da tych samych wynikow?

SELECT
moc_g1.data, UNIX_TIMESTAMP(moc_g1.data) AS xlabel,
moc_g1.wartosc,
moc_g2.wartosc
FROM
pomiary as moc_g1,
pomiary as moc_g2
WHERE
(UNIX_TIMESTAMP() - UNIX_TIMESTAMP(moc_g1.data)) < (60*60*3)
and ( moc_g1.miernik = 1 AND moc_g1.komorka = 98 )
and ( moc_g2.miernik = 2 AND moc_g2.komorka = 98 )
and ( moc_g1.data = moc_g2.data )
ORDER BY data ASC;

--
pedroz




Piotr [PKi] - 21-03-2006 01:00

  > SELECT
> moc_g1.data, UNIX_TIMESTAMP(moc_g1.data) AS xlabel,
> moc_g1.wartosc,
> moc_g2.wartosc
> FROM
> pomiary as moc_g1,
> pomiary as moc_g2
> WHERE
> (UNIX_TIMESTAMP() - UNIX_TIMESTAMP(moc_g1.data)) < (60*60*3)
> and ( moc_g1.miernik = 1 AND moc_g1.komorka = 98 )
> and ( moc_g2.miernik = 2 AND moc_g2.komorka = 98 )
> and ( moc_g1.data = moc_g2.data )
> ORDER BY data ASC;
>

Nono, zeszło z >50 sekund na 14 sekund.

Mógłbyś wyjasnic dlaczego w FROM tabela pomiary wystepuje 2 razy?

Zmieniłem sobie tak:
SELECT
moc_g1.data, UNIX_TIMESTAMP(moc_g1.data) AS xlabel,
moc_g1.wartosc AS moc_g1,
moc_g2.wartosc AS moc_g2
FROM
pomiary as moc_g1,
pomiary as moc_g2
WHERE
(UNIX_TIMESTAMP() - UNIX_TIMESTAMP(moc_g1.data)) < (60*60*3)
and ( moc_g1.miernik = 1 AND moc_g1.komorka = 98 )
and ( moc_g2.miernik = 2 AND moc_g2.komorka = 98 )
and ( moc_g1.data = moc_g2.data )
ORDER BY data ASC

zeby wyniki były takie same. Ma to jakieś znaczenie że alias moc_g1 i
moc_g2 wystepuje dwa razy?




pedroz - 22-03-2006 00:05

 
Piotr [PKi] wrote:
> > SELECT
> > moc_g1.data, UNIX_TIMESTAMP(moc_g1.data) AS xlabel,
> > moc_g1.wartosc,
> > moc_g2.wartosc
> > FROM
> > pomiary as moc_g1,
> > pomiary as moc_g2
> > WHERE
> > (UNIX_TIMESTAMP() - UNIX_TIMESTAMP(moc_g1.data)) < (60*60*3)
> > and ( moc_g1.miernik = 1 AND moc_g1.komorka = 98 )
> > and ( moc_g2.miernik = 2 AND moc_g2.komorka = 98 )
> > and ( moc_g1.data = moc_g2.data )
> > ORDER BY data ASC;
> >
>
>
> Nono, zeszło z >50 sekund na 14 sekund.
>
> Mógłbyś wyjasnic dlaczego w FROM tabela pomiary wystepuje 2 razy?

Dlatego, ze z tego co napisales wynika, iz wyniki 2 pomiarow zapisujesz
w tej samej kolumnie w 2 rekordach - zgadza sie? W takim wypadku musisz
ta tabele dwukrotnie wyciagnac pod innymi aliasami. Zauwaz, ze dzieki
temu znika grupowanie po dacie (zamiast tego jest polaczenie tabel po
tej wartosci), ktore tez jest czasochlonne.

> Zmieniłem sobie tak:
> SELECT
> moc_g1.data, UNIX_TIMESTAMP(moc_g1.data) AS xlabel,
> moc_g1.wartosc AS moc_g1,
> moc_g2.wartosc AS moc_g2
> FROM
> pomiary as moc_g1,
> pomiary as moc_g2
> WHERE
> (UNIX_TIMESTAMP() - UNIX_TIMESTAMP(moc_g1.data)) < (60*60*3)
> and ( moc_g1.miernik = 1 AND moc_g1.komorka = 98 )
> and ( moc_g2.miernik = 2 AND moc_g2.komorka = 98 )
> and ( moc_g1.data = moc_g2.data )
> ORDER BY data ASC
>
> zeby wyniki były takie same. Ma to jakieś znaczenie że alias moc_g1i
> moc_g2 wystepuje dwa razy?

Chodzi Ci o te aliasy przy kolumnach? Szczerze mowiac nie mam pojecia
jak to dziala w MySQL, ale np. ASE na cos takiego pozwala. Mysle, ze
jesli dobrze ulozysz indeks do tego zapytania, to bedziesz mogl zejsc
jeszcze nizej ;-) I tworz raczej indeksy wielokolumnowe.

--
pedroz





Piotr [PKi] - 22-03-2006 00:06

  > Chodzi Ci o te aliasy przy kolumnach? Szczerze mowiac nie mam pojecia
> jak to dziala w MySQL, ale np. ASE na cos takiego pozwala. Mysle, ze
> jesli dobrze ulozysz indeks do tego zapytania, to bedziesz mogl zejsc
> jeszcze nizej ;-) I tworz raczej indeksy wielokolumnowe.
>

Mam indeksy na każdej kolumnie, ale zakładałem pojedyńczo. Czyli wywalić
i zrobić

ALTER TABLE pomiary ADD INDEX(id,data,miernik,komorka,wartosc); ??????




pedroz - 22-03-2006 13:13

  Piotr [PKi] wrote:
> > Chodzi Ci o te aliasy przy kolumnach? Szczerze mowiac nie mam pojecia
> > jak to dziala w MySQL, ale np. ASE na cos takiego pozwala. Mysle, ze
> > jesli dobrze ulozysz indeks do tego zapytania, to bedziesz mogl zejsc
> > jeszcze nizej ;-) I tworz raczej indeksy wielokolumnowe.
> >
>
> Mam indeksy na każdej kolumnie, ale zakładałem pojedyńczo. Czyli wywalić
> i zrobić
>
> ALTER TABLE pomiary ADD INDEX(id,data,miernik,komorka,wartosc); ??????

Wywalic i stworzyc jeden/kilka indeksow, ktore beda zbudowane z kolumn,
ktore sa uzywane w klauzuli WHERE, ORDER, GROUP BY. Koumny id i wartosc
nie sa wykorzystywane w zadnej z nich, wiec w indeksie nie beda
potrzebne. Sproboj na poczatek stworzyc indeks:

ALTER TABLE pomiary ADD INDEX(data,miernik,komorka);

i sprawdzic jak zmieni sie query plan i czasy wykonania zapytania.
Jesli nie bedzie satysfakcjonujacy, to mozesz sprobowac przestawic
kolejnosc kolumn w indeksie. Niestety nie jestem w stanie Ci pomoc do
konca, bo nie znam specyfiki MySQL'a i nie wiem, co na tej bazie moze
miec jeszcze wplyw na szybkosc wykonania zapytania. Mozliwe, ze np.
wyeliminowanie w tym wyrazeniu

(UNIX_TIMESTAMP() - UNIX_TIMESTAMP(moc_g1.data)) < (60*60*3)

mnozenia i podstawienie juz wyliczonej wartosci moze przyniesc jakies
efekty. Mozliwe tez ze lepiej uzyc tu BETWEEN. Wszystko zalezy jak
daleko chcesz sie posunac w optymalizacji i jakie czasy sa dla Ciebie
akceptowalne. Czasami lepiej zdenormalizowac troche baze i zyskac na
wydajnosci. Tu moglbys np. UNIX_TIMESTAMP(moc_g1.data) trzymac zapisane
od razu w bazie, co wyeliminowaloby koniecznosc kazdorazowego
wyliczania tego wyrazenia przy raporcie. Drog jest wiele ;-)
  • zanotowane.pl
  • doc.pisz.pl
  • pdf.pisz.pl
  • effulla.pev.pl
  • comp
    Oracle, SQL, PL/SQL. Jak =?ISO-8859-2?Q?napisa=E6_zapytanie=2C?==?ISO-8859-2?Q?_kt=F3re_zwr=F3ci_nazw=EA_atrybutu=2C_kt=F3reg o?==?ISO-8859-2?Q?_warto=B6ci_spe=B3niaj=B1_zadany_warunek?= =?ISO-8859-2?Q?Narz=EAdzie_do_budowania_zapyta=F1_SQL=2C?==?I SO-8859-2?Q?_PL/PgSQL=2C_PL/SQL=2C_T-SQL?= [ms sql] =?ISO-8859-2?Q?wy=B6wietlenie_pierwszych_5_rekord?==?ISO-8859-2?Q?=F3w_z_zapytania_=3F_odpowiednik_ROWNUM_w_o?== ?ISO-8859-2?Q?raclu_dla_MS_SQL=27a?= phpMyAdmin zadaje =?ISO-8859-2?Q?z=B3e_zapytania=2E=2E=2E_Dl?==?ISO-8859-2?Q?aczego=3F?= [MSSQL2000] Problem z =?ISO-8859-2?Q?tabel=B1/indeksem/zapytanie?==?ISO-8859-2?Q?m_czy_b=B3=B1d_w_bazie_danych=2E=2E=2E?= [mysql 5.x] jak =?ISO-8859-2?Q?zrealizowa=E6_zapytanie=3F_cz?==?ISO-8859-2?Q?yli_podzapytanie_i_wi=EAcej_ni=BF_jeden_rz=B1? ==?ISO-8859-2?Q?d_wynik=F3w?= [oracle] zapytanie dynamiczne z =?ISO-8859-2?Q?=22dynamiczn=B1_?==?ISO-8859-2?Q?nazw=B1_tabeli=22?= [mysql/php] jak =?ISO-8859-2?Q?zliczy=E6_ilo=B6=E6_unikalnyc?==?ISO-8859-2?Q?h_rekord=F3w_w_jednym_zapytaniu=3F?= [MySQL] Zapytanie z =?ISO-8859-2?Q?dw=F3ch_tabel_na_raz_?==?ISO-8859-2?Q?i_grupowanie_po_wsp=F3lnym_polu=2E_Jak_=3F?= mecze sie i mecze i nic - zapytanie czesciowe
  • zanotowane.pl
  • doc.pisz.pl
  • pdf.pisz.pl
  • quentinho.opx.pl
  • Cytat

    Decede mihi sole - nie zasłaniaj mi słonca.
    Gdy kogoś kochasz, jesteś jak stworzyciel świata - na cokolwiek spojrzysz, nabiera to kształtu, wypełnia się barwą, światłem. Powietrze przytula się do ciebie, choćby był mróz, a ty masz w sobie tyle radości, że musisz ją rozdawać wokoło, bo się w tobie nie mieści
    Hoc fac - tak czyń.
    A tergo - od tyłu; z tyłu.
    I czarne włosy posiwieją. Safona

    Valid HTML 4.01 Transitional

    Free website template provided by freeweblooks.com