using filesort, und ich weiß nicht warum

xtramen01

Erfahrenes Mitglied
Hallo Leute,

hab hier eine Abfrage welche auf using filesort bei "nur" 20.000 Datensätzen zugreift und ich weis nich warum.
Mach ich die Abfrage OHNE SQL_CALC_FOUND_ROWS, dann wirds nich genutzt und die Abfrage rennt in 0.0002 sek

Hab die Abfrage und die Indizes schon auf verschiedenste weise umgebaut. Hilft aber alles nix.
Ich finde die Abfrage mit 0.15 sek auch übertrieben langsam für die Anzahl.

Vielleicht sieht ja von euch jemand das Problem oder kann mir sagen wie man die Indizes am sinnvollsten setzen könnte.

Code:
SELECT SQL_CALC_FOUND_ROWS p.products_id

FROM products_description pd

INNER JOIN products p ON pd.language_id = '2' AND pd.products_id = p.products_id
INNER JOIN products_to_categories p2c ON p.products_id = p2c.products_id

WHERE p2c.categories_id = '52'

AND p.products_status = '1'
AND (p.section_id = '0' || p.section_id = '13')

ORDER BY p.products_id LIMIT 0,20

Das sagt EXPLAIN:

Code:
1 	SIMPLE 	p 	ALL 	PRIMARY,status  	NULL  	NULL  	NULL 	19966 	Using where; Using filesort
1 	SIMPLE 	p2c 	eq_ref 	PRIMARY,pid,cid 	PRIMARY 	8 	db1.p.products_id,const 	1 	Using index
1 	SIMPLE 	pd 	eq_ref 	PRIMARY,pid,lid 	PRIMARY 	8 	db1.p2c.products_id,const 	1 	Using where; Using index

Indizes:
Code:
products(p): products_id = PRIMARY
products_to_categories(p2c): products_id, categories_id = PRIMARY
products_description(pd): products_id, language_id = PRIMARY

Gruss
 
Zuletzt bearbeitet:
Moin xtramen01,

du weißt aber schon, wozu der Parameter SQL_CALC_FOUND_ROWS gut ist?
Natürlich muss der, um zu checken, wie viele Datensätze OHNE Limit x,y-Einschränkung zurückkommen würden, eine etwas andere Strategie wählen.

Was daran genau ist für dich jetzt unerwartet?

Grüße
Biber
 
Mach doch mal die Probe aufs exempel und erzwinge die Indizes

Code:
SELECT SQL_CALC_FOUND_ROWS p.products_id
FROM products_description pd
 USE INDEX (PRIMARY) 
INNER JOIN products p 
 USE INDEX (PRIMARY)
ON pd.language_id = '2' AND pd.products_id = p.products_id
INNER JOIN products_to_categories p2c 
 USE INDEX(PRIMARY)
ON p.products_id = p2c.products_id
WHERE p2c.categories_id = '52'
AND p.products_status = '1'
AND (p.section_id = '0' || p.section_id = '13')
ORDER BY p.products_id LIMIT 0,20

btw, es ist schlechter SQL Stil, dein objektnetz nicht mit der eigentliche ROOT-Entity abzufragen. Besserer Stil ist es, Deine FROM Clause mit products zu beginnen (da alle inner-gejointen Tabellen Wiederholungsgruppen von Products sind.

Also irgendwas im Stile von

Code:
SELECT SQL_CALC_FOUND_ROWS p.products_id
FROM INNER JOIN products p 
 USE INDEX (FOOBAR) 
INNER JOIN products_description pd
 USE INDEX (PRIMARY)
ON pd.language_id = '2' AND pd.products_id = p.products_id
INNER JOIN products_to_categories p2c 
 USE INDEX(PRIMARY)
ON p.products_id = p2c.products_id
WHERE p2c.categories_id = '52'
AND p.products_status = '1'
AND (p.section_id = '0' || p.section_id = '13')
ORDER BY p.products_id LIMIT 0,20

Damit das ordentlich fluppt, brauchst Du aber noch einen Index auf Products nämlich FOOBAR (products_id, products_status, section_id).

Achso, und nimm doch bitte OR statt ||. || ist ein Appeasement an die C++ Entwickler bei MySQL und wird in anderen Datenbanken zur Stringkatenation verwendet.

Grüße
gore

Grüße
gore
 
Zurück