Zeer trage query wat doe ik fout?

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • Voxyn
  • Registratie: April 2009
  • Laatst online: 09-09 18:04
Hallo mensen ik ben bezig met een query te schrijven die de nieuwste prijzen van alle producten moet ophalen(prijs wisselt iedere dag en soms vaker) alleen de query is zeer traag met ~20.000 records doet hij er al 6 secondes over en hij zal in de toekomst toch wel iets van 1 miljoen records krijgen.

de tabel ziet er als volgt uit:
tabel: product_prijs
product_id int(11)
prijs decimal(8,4)
datum timestamp (default value: current_timestamp)


en de query:

code:
1
2
3
select pp.product_id,pp.prijs,pp.datum 
from product_prijs pp
where p.datum = (select max(datum) from product_prijs where pp.product_id = product_id)


heeft iemand enig idee hoe dit sneller kan?

[ Voor 8% gewijzigd door Voxyn op 06-04-2012 10:12 ]


Acties:
  • 0 Henk 'm!

  • Cyphax
  • Registratie: November 2000
  • Laatst online: 18:58

Cyphax

Moderator LNX
Kijk eens naar het execution plan (met EXPLAIN, daar kun je de bottlenecks mee vinden. :)
Wat heb je aan indexen liggen op de tabellen?

Welk DBMS is dit? MySQL lijkt het?

[ Voor 34% gewijzigd door Cyphax op 06-04-2012 09:44 ]

Saved by the buoyancy of citrus


Acties:
  • 0 Henk 'm!

  • EfBe
  • Registratie: Januari 2000
  • Niet online
Per row in product_prijs executeert hij een subquery die een max aggregate uitvoert (en dus ALLE rows leest) over tankstations_brandstoffen_prijs. Dat is dus een n*m query.

Plaats in ieder geval een index op datum en een index op product_id in tankstations_brandstoffen_prijs

Creator of: LLBLGen Pro | Camera mods for games
Photography portfolio: https://fransbouma.com


Acties:
  • 0 Henk 'm!

  • Voxyn
  • Registratie: April 2009
  • Laatst online: 09-09 18:04
Cyphax schreef op vrijdag 06 april 2012 @ 09:42:
Kijk eens naar het execution plan, daar kun je de bottlenecks mee vinden. :)
Wat heb je aan indexen liggen op de tabellen?
Hoe kan ik de execution plan bekijken?

en phpmyadmin geeft de volgende gegevens bij de tabel aan
sleutelnaam: fk_product_prijs_producten type: BTREE, unieke waarde: nee, gecomprimeerd:nee, kolom: product_id,datum, kardinaliteit: 400,20000, collatie: A,A
EfBe schreef op vrijdag 06 april 2012 @ 09:44:
Per row in product_prijs executeert hij een subquery die een max aggregate uitvoert (en dus ALLE rows leest) over tankstations_brandstoffen_prijs. Dat is dus een n*m query.

Plaats in ieder geval een index op datum en een index op product_id in tankstations_brandstoffen_prijs
ik heb geloof een index die en product_id en datum doet is verkeerd of moet ik er twee hebben een voor product_id en een voor datum?

[ Voor 34% gewijzigd door Voxyn op 06-04-2012 09:52 ]


Acties:
  • 0 Henk 'm!

  • Meekoh
  • Registratie: April 2005
  • Laatst online: 14:50
Veel query's vallen of staan door het gebruik van de juiste indexen.
Ik heb queries gezien die na het toevoegen van een bepaalde index van 10s naar 1s of lager gingen.

Computer says no


Acties:
  • 0 Henk 'm!

  • Cyphax
  • Registratie: November 2000
  • Laatst online: 18:58

Cyphax

Moderator LNX
Voxyn schreef op vrijdag 06 april 2012 @ 09:47:
[...]

Hoe kan ik de execution plan bekijken?

en phpmyadmin geeft de volgende gegevens bij de tabel aan
sleutelnaam: fk_product_prijs_producten type: BTREE, unieke waarde: nee, gecomprimeerd:nee, kolom: product_id,datum, kardinaliteit: 400,20000, collatie: A,A
Ik heb na een edit een linkje toegevoegd naar de documentatie van MySQL waar dat in staat. :)
Hier is nog een linkje met uitleg van een andere bron, misschien leest die prettiger: http://www.devshed.com/c/...s-for-Speed-with-EXPLAIN/

Saved by the buoyancy of citrus


Acties:
  • 0 Henk 'm!

  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 13-09 00:05
Voxyn schreef op vrijdag 06 april 2012 @ 09:47:
ik heb geloof een index die en product_id en datum doet is verkeerd of moet ik er twee hebben een voor product_id en een voor datum?
Voor deze query wil je het liefste een index op product_id zonder datum. Dan is er geen twijfel over dat die gebruikt kan worden voor de subquery.

Man hopes. Genius creates. Ralph Waldo Emerson
Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein


Acties:
  • 0 Henk 'm!

  • cariolive23
  • Registratie: Januari 2007
  • Laatst online: 18-10-2024
En wat als je de subquery verplaatst naar een JOIN?
SQL:
1
2
3
4
5
6
SELECT 
  pp.product_id,pp.prijs,pp.datum 
FROM
  product_prijs pp
    JOIN (SELECT product_id, MAX(datum) m_datum FROM product_prijs GROUP BY product_id) sub
      ON pp.product_id = sub.product_id AND pp.datum = sub.m_datum;


Een gecombineerde index op product_id en datum is voor deze query het meest ideaal. Zie de resultaten van EXPLAIN voor de verschillen met de oorspronkelijke query.

Acties:
  • 0 Henk 'm!

  • GlowMouse
  • Registratie: November 2002
  • Niet online
zo is hij het snelste:
SQL:
1
2
3
select pp.product_id,pp.prijs,pp.datum 
from product_prijs pp
where not exists(select 1 from product_prijs where pp.product_id = product_id and pp.datum < datum)

met de index die je al hebt (op (product_id,datum)).
Meekoh schreef op vrijdag 06 april 2012 @ 09:51:
Veel query's vallen of staan door het gebruik van de juiste indexen.
Ik heb queries gezien die na het toevoegen van een bepaalde index van 10s naar 1s of lager gingen.
over open deuren gesproken
MSalters schreef op vrijdag 06 april 2012 @ 11:36:
[...]

Voor deze query wil je het liefste een index op product_id zonder datum. Dan is er geen twijfel over dat die gebruikt kan worden voor de subquery.
waarom twijfel je?

Acties:
  • 0 Henk 'm!

  • cariolive23
  • Registratie: Januari 2007
  • Laatst online: 18-10-2024
Gebruik dan wel EXISTS() i.p.v. NOT EXISTS()...

En meten = weten, het hoeft echt niet sneller te zijn dan een JOIN, daar is geen garantie op te geven.

Acties:
  • 0 Henk 'm!

  • DukeBox
  • Registratie: April 2000
  • Laatst online: 17:52

DukeBox

loves wheat smoothies

Soms is het sneller om een max waarde in PHP te bepalen i.p.v. MySQL. (max($array)). Een beetje afhankelijk van je dataset en verbinding tussen je webserver en db.

Duct tape can't fix stupid, but it can muffle the sound.


Acties:
  • 0 Henk 'm!

  • GlowMouse
  • Registratie: November 2002
  • Niet online
cariolive23 schreef op zaterdag 07 april 2012 @ 20:15:
[...]

Gebruik dan wel EXISTS() i.p.v. NOT EXISTS()...
Nee, ik bedoel NOT EXISTS.
En meten = weten, het hoeft echt niet sneller te zijn dan een JOIN, daar is geen garantie op te geven.
Gebruik van een join vs. not exists is nauwelijks relevant.

Acties:
  • 0 Henk 'm!

  • cariolive23
  • Registratie: Januari 2007
  • Laatst online: 18-10-2024
GlowMouse schreef op zondag 08 april 2012 @ 12:31:
[...]

Nee, ik bedoel NOT EXISTS.

[...]
Ah, ik had de < datum compleet gemist!

Acties:
  • 0 Henk 'm!

Verwijderd

Voxyn schreef op vrijdag 06 april 2012 @ 09:47:
[...]

Hoe kan ik de execution plan bekijken?

en phpmyadmin geeft de volgende gegevens bij de tabel aan
sleutelnaam: fk_product_prijs_producten type: BTREE, unieke waarde: nee, gecomprimeerd:nee, kolom: product_id,datum, kardinaliteit: 400,20000, collatie: A,A


[...]
Staat net vandaag iets over te lezen op Reddit.
Pagina: 1