Sehr langsamer Query

Sehr langsamer Query

am 20.11.2007 21:40:27 von devnull

Hallo,

ich habe ein Performance-Problem mit einer Abfrage:

In einer Tabelle (die leider nicht vollständig normalisiert ist/werden
kann) liegen ca. 200.000 Artikel.
Nun möchte ich blätterbare Listen erstellen, die:

- nach Künstlern gruppiert und sortiert
- pro Künstler den neuesten Artikel (dessen Veröffentlichungsdatum
gekommen ist) anzeigt
- und die Ergebnisse limitiert darstellt.

Da hier recht viele Felder beteiligt sind, bin ich unschlüssig, wie ich
die Indizes anlegen soll. Momentan sieht mein Query z.B. so aus:

====

SELECT shop_products.*,
shop_fixed_prices.fixed_price
FROM shop_products

LEFT JOIN shop_fixed_prices ON (shop_fixed_prices.EAN = shop_products.EAN)

LEFT JOIN shop_products_genres ON (shop_products_genres.EAN =
shop_products.EAN)

WHERE shop_products.ID>0
AND medium_type NOT LIKE 'LP%'
AND medium_type LIKE '%CD%'
AND date_release<=NOW()

AND (shop_products.genre='Musik für Kammerensemble' OR
shop_products.kw1='Musik für Kammerensemble' OR shop_products.kw2='Musik
für Kammerensemble' OR shop_products.kw3='Musik für Kammerensemble' OR
shop_products.kw4='Musik für Kammerensemble' OR shop_products.kw5='Musik
für Kammerensemble')

AND (shop_products.cover_link !='')

GROUP BY shop_products.artist
ORDER BY shop_products.artist ASC,
shop_products.date_release DESC
====

Folgende Indizes existieren:
EAN (index)
kw (index, über Felder genre, kw1, kw2, kw3, kw4, kw5, date_release)
title (fulltext)
artist (fulltext)

Ohne "group by" und ohne Sortierung ist er blitzschnell; mit allen
Filtern braucht er quälend lange durch "using temporary" und filesort.
Ach ja, MySql liegt in Version 4.0.25 vor.

Hat jemand eine Idee?

Vielen Dank und Gruß
Stefan

--
GPG-Key-ID: 0xE8288CF8

"In the beginning the Universe was created. This has made a lot of
people very angry and has been widely regarded as a bad move."

-- Douglas Adams

Re: Sehr langsamer Query

am 21.11.2007 08:46:23 von Harald Stowasser

Stefan T. Oertel schrieb:
> Hallo,
>
> ich habe ein Performance-Problem mit einer Abfrage:
>
> In einer Tabelle (die leider nicht vollständig normalisiert ist/werden
> kann) liegen ca. 200.000 Artikel.
....
>
> SELECT shop_products.*,
> shop_fixed_prices.fixed_price
> FROM shop_products
>
> LEFT JOIN shop_fixed_prices ON (shop_fixed_prices.EAN = shop_products.EAN)
>
> LEFT JOIN shop_products_genres ON (shop_products_genres.EAN =
> shop_products.EAN)
>
> WHERE shop_products.ID>0
> AND medium_type NOT LIKE 'LP%'
> AND medium_type LIKE '%CD%'
> AND date_release<=NOW()
>
> AND (shop_products.genre='Musik für Kammerensemble' OR
> shop_products.kw1='Musik für Kammerensemble' OR shop_products.kw2='Musik
> für Kammerensemble' OR shop_products.kw3='Musik für Kammerensemble' OR
> shop_products.kw4='Musik für Kammerensemble' OR shop_products.kw5='Musik
> für Kammerensemble')
>
> AND (shop_products.cover_link !='')
>
> GROUP BY shop_products.artist
> ORDER BY shop_products.artist ASC,
> shop_products.date_release DESC

1:Schick bitte immer einen Explain mit.

2:OR ist böse :-) Der Index kw bringt gar nix. Besser währe vielleicht
für die Suche nach einem Genre einen Subselect oder eine Temporäre
Tabelle mit Union-Join einzusetzten.

3: Das LIKE-gewurstel über den medium_type ist auch nicht gut.

4: ein Index über ID,medium_type,cover_link,artist,date_release hilft
vielleicht.

5: Explain posten.

6: Doch besser Normalisieren? (Wer verbricht eigentlich so ein Kaputtes
Design?)

Re: Sehr langsamer Query

am 21.11.2007 09:49:38 von petsch

On 20 Nov., 21:40, "Stefan T. Oertel" wrote:
>
> ORDER BY shop_products.artist ASC,
> shop_products.date_release DESC

Wenn Du nach date_release sortierts, solltest Du auch einen Index
drauf setzen - es sei denn date_release ist zufällig die führende
Spalte des mehrspaltigen Indizes.

Peter

Re: Sehr langsamer Query

am 21.11.2007 09:49:50 von Andreas Kretschmer

Andreas
--
q: why do so many people take an instant dislike to mysql?
a: it saves time (oicu in #postgresql)
Explaining the concept of referential integrity to a mysql user is like
explaining condoms to a catholic (Shadda in #postgresql)

Re: Sehr langsamer Query

am 21.11.2007 10:19:49 von Harald Stowasser

Peter Schleif schrieb:
> On 20 Nov., 21:40, "Stefan T. Oertel" wrote:
>> ORDER BY shop_products.artist ASC,
>> shop_products.date_release DESC
>
> Wenn Du nach date_release sortierts, solltest Du auch einen Index
> drauf setzen - es sei denn date_release ist zufällig die führende
> Spalte des mehrspaltigen Indizes.

*Ein* Index auf date_release bringt gar nichts, Da mysql sowieso nur
*einen* verwendet.
Außerdem ist date_release sowieso nur zweiter in der Sortier-Hirarchie.

Re: Sehr langsamer Query

am 21.11.2007 10:52:53 von petsch

On 21 Nov., 10:19, Harald Stowasser wrote:
>
> Außerdem ist date_release sowieso nur zweiter in der Sortier-Hirarchie.

Eben.

Je weiter hinter die zu sortierende Spalte in dem mehrspaltigen Index
steht, desto ineffektiver ist die Beschleunigung. Deshalb einen
zusätzlichen Index nur auf date_release.

Peter

Re: Sehr langsamer Query

am 21.11.2007 11:13:45 von Harald Stowasser

Peter Schleif schrieb:
> On 21 Nov., 10:19, Harald Stowasser wrote:
>> Außerdem ist date_release sowieso nur zweiter in der Sortier-Hirarchie.
>
> Eben.
>
> Je weiter hinter die zu sortierende Spalte in dem mehrspaltigen Index
> steht, desto ineffektiver ist die Beschleunigung. Deshalb einen
> zusätzlichen Index nur auf date_release.

Der bringt rein gar *NICHTS*. Da Mysql nur *einen* Index nutzen kann.
Der zu benutzte Index wird jedoch von der Where-Klausel und den
Kardinalitäten bestimmt.


In manchen Fällen kann MySQL Indizes nicht zur Auflösung von ORDER BY
verwenden, obwohl es mithilfe der Indizes Datensätze findet, die der
WHERE-Klausel entsprechen. Dies betrifft u. a. die folgenden Fälle:
.....
Der Schlüssel, der zum Holen der Datensätze verwendet wird, ist nicht
derselbe wie derjenige, der in der ORDER BY-Klausel verwendet wird:

SELECT * FROM t1 WHERE key2=constant ORDER BY key1;


Außerdem wird in vorliegender Query DESC und ASC vermischt was *immer*
einen filesort bedingt. Um Filesort zu beschleunigen hilft es ALLE
Datensätze, die der WHERE-Klausel entsprechen in einen Index zu packen.
Grundsatz:
Die Selektivste Spalte nach Links und zusätzlich die ORDER-BY spalten
nach rechts.

Genaueres zu filesort und order by:
[1]http://dev.mysql.com/doc/refman/5.1/de/order-by-optimizat ion.html

Re: Sehr langsamer Query

am 21.11.2007 12:31:32 von devnull

Andreas Kretschmer schrieb:
>> In einer Tabelle (die leider nicht vollständig normalisiert ist/werden
> Warum?

weil sie so angeliefert werden.

>> WHERE shop_products.ID>0
>> AND medium_type NOT LIKE 'LP%'
>> AND medium_type LIKE '%CD%'
>
> schlecht weil nicht sinnvoll indizierbar.
> Was für medium_typen gibt es denn, die darauf matchen?

jede Menge. Diese Typen ändern sich ständig, darum muss ich mit like
matchen.

> Normalisier Deine Daten. Alles andere führt zu nix.

Du meinst, wenn die Keywords ausgelagert wären, würde sich das ganze
erheblich beschleunigen?

Gruß Stefan

--
GPG-Key-ID: 0xE8288CF8

Re: Sehr langsamer Query

am 21.11.2007 12:33:27 von devnull

Harald Stowasser schrieb:

> Außerdem wird in vorliegender Query DESC und ASC vermischt was *immer*
> einen filesort bedingt. Um Filesort zu beschleunigen hilft es ALLE
> Datensätze, die der WHERE-Klausel entsprechen in einen Index zu packen.
> Grundsatz:
> Die Selektivste Spalte nach Links und zusätzlich die ORDER-BY spalten
> nach rechts.

ok, das probiere ich mal aus, danke.

Gruß Stefan


--
GPG-Key-ID: 0xE8288CF8

"Everything starts somewhere, although many physicists disagree"

-- Terry Pratchett

Re: Sehr langsamer Query

am 21.11.2007 13:44:29 von Harald Stowasser

Stefan T. Oertel schrieb:
> Andreas Kretschmer schrieb:
>>> In einer Tabelle (die leider nicht vollständig normalisiert ist/werden
>> Warum?
>
> weil sie so angeliefert werden.

Am besten du parst den misst und schmeißt in in eine eigene aufgeräumte
Datenbank.

>>> WHERE shop_products.ID>0
>>> AND medium_type NOT LIKE 'LP%'
>>> AND medium_type LIKE '%CD%'
>> schlecht weil nicht sinnvoll indizierbar.
>> Was für medium_typen gibt es denn, die darauf matchen?
>
> jede Menge. Diese Typen ändern sich ständig, darum muss ich mit like
> matchen.

Das Problem an Like ist das '%foo%' gar keinen index benutzt, und 'foo%'
immerhin einen index /zerbricht/ d.h. alles was im index in
darauffolgenden spalten kommen würde, nicht

>> Normalisier Deine Daten. Alles andere führt zu nix.
>
> Du meinst, wenn die Keywords ausgelagert wären, würde sich das ganze
> erheblich beschleunigen?

Ja. Es gibt 2 konkurierende Methoden bei und-Verknüpfungen in einer M:N
Beziehung. Trotzdem ist das schneller als LIKE gewurstel.

1: Mit Having.
2: Mit X-Join.

Vor und Nachteile dazu wurden hier schon oft diskutiert:

opr8nufmu7mddsn6 at news.individual.de

Re: Sehr langsamer Query

am 21.11.2007 13:48:46 von Harald Stowasser

Stefan T. Oertel schrieb:
> Andreas Kretschmer schrieb:
>>> In einer Tabelle (die leider nicht vollständig normalisiert
>>> ist/werden
>> Warum?
>
> weil sie so angeliefert werden.

Am besten du parst den misst und schmeißt in in eine eigene aufgeräumte
Datenbank.

>>> WHERE shop_products.ID>0 AND medium_type NOT LIKE 'LP%' AND
>>> medium_type LIKE '%CD%'
>> schlecht weil nicht sinnvoll indizierbar. Was für medium_typen gibt
>> es denn, die darauf matchen?
>
> jede Menge. Diese Typen ändern sich ständig, darum muss ich mit like
> matchen.

Das Problem an Like ist das '%foo%' gar keinen index benutzt, und 'foo%'
immerhin einen index /zerbricht/ d.h. alles was im index in
darauffolgenden spalten kommt benötigt einen scann.

>> Normalisier Deine Daten. Alles andere führt zu nix.
>
> Du meinst, wenn die Keywords ausgelagert wären, würde sich das ganze
> erheblich beschleunigen?

Ja. Es gibt 2 konkurierende Methoden bei und-Verknüpfungen in einer M:N
Beziehung. Trotzdem ist das schneller als LIKE gewurstel.

1: Mit Having.
2: Mit X-Join.

Vor und Nachteile dazu wurden hier schon oft diskutiert:

opr8nufmu7mddsn6 at news.individual.de

Re: Sehr langsamer Query

am 21.11.2007 16:15:48 von devnull

Harald Stowasser schrieb:
>> Du meinst, wenn die Keywords ausgelagert wären, würde sich das ganze
>> erheblich beschleunigen?
>
> Ja. Es gibt 2 konkurierende Methoden bei und-Verknüpfungen in einer M:N
> Beziehung. Trotzdem ist das schneller als LIKE gewurstel.
>
> 1: Mit Having.
> 2: Mit X-Join.

ich bekomme die Daten jetzt mit normalisierten Keywords (und frage per
inner join ab)- das war tatsächlich der Flaschenhals. Ich war schon
davon ausgegangen, dass das Gruppieren und zweimalige Sortieren das
Zeitaufwendige sei. Wieder etwas gelernt.

Vielen Dank,
Stefan

--
GPG-Key-ID: 0xE8288CF8