SQL_CALC_FOUND_ROWS()
sebo
- datenbank
Ich mal wieder mit Problemen
SELECT
SQL_CALC_FOUND_ROWS
a.id,
a.name,
a.birthday,
b.id
FROM defaultusers AS a
LEFT JOIN photos AS b ON
b.id = (SELECT MAX(id) FROM photos WHERE user_id = a.id)
WHERE
a.status = 'N' and
a.sex = 'w'
ORDER BY a.lastlogin DESC
LIMIT 0, 10;
Das Problem: ohne SQL_CALC_FOUND_ROWS() dauert die Abfrage 0.13 Sekunden und das bei über 400.000 Bildern (LongBlob) in "photos". Es ist also eine richtig große Datenbank.
Aber sobald ich SQL_CALC_FOUND_ROWS() einsetze, dauert die Abfrage bis zu 16 Sekunden!
Es muss etwas mit dem JOIN zu tun haben, denn ohne JOIN ist SQL_CALC_FOUND_ROWS() extrem schnell.
Das komische ist aber, dass ohne SQL_CALC_FOUND_ROWS() der JOIN sehr schnell ist!
Woran bin ich denn nun?
Das sagt EXPLAIN:
+----+--------------------+--------+--------+---------------+------------+---------+------
------+-------+-----------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+--------------------+--------+--------+---------------+------------+---------+------
------+-------+-----------------------------+
| 1 | PRIMARY | a | ALL | NULL | NULL | NULL | NULL | 20531 | Using where; Using filesort |
| 1 | PRIMARY | b | eq_ref | PRIMARY | PRIMARY | 4 | func | 1 | Using index |
| 2 | DEPENDENT SUBQUERY | photos | ref | usernummer | usernummer | 3 | users.a.id | 2 | |
+----+--------------------+--------+--------+---------------+------------+---------+------
------+-------+-----------------------------+
3 rows in set (0.00 sec)
Wie man sieht sind INDEX's vorhanden.
yo,
Das komische ist aber, dass ohne SQL_CALC_FOUND_ROWS() der JOIN sehr schnell ist!
Woran bin ich denn nun?
höchstwahrscheinlich, weil das dbms ohne SQL_CALC_FOUND_ROWS() schon mal ergebnisdatensätze liefern kann, ohne dass er vollkommen fertig mit der abfrage ist. mit SQL_CALC_FOUND_ROWS() kann er genau das nicht tun, er muss schon bei dem ersten ergebnis alles bearbeitet haben.
Ilja
sowas in der art hab ich mir schon gedacht.
Man müsste irgendwie vermeiden, dass SQL_CALC_FOUND_ROWS auch den JOIN abarbeitet...
also irgendwie sowas wie:
SQL_CALC_FOUND_ROWS(a.id)
Mein Problem ist, dass zu der Abfrage später noch weitere Bedingungen hinzukommen, die das ganze ohnehin sehr mächtig machen.
Denn sonst hätte man dieselbe Abfrage nochmal mit einem COUNT() und ohne LIMIT und ORDER BY durchführen können. Aber das wäre ein Genickbruch für meinen Server.
Das dolle ist nämlich, dass ohne den JOIN SQL_CALC_FOUND_ROWS extrem schnell ist.
Andererseits ist aber auch der JOIN ohne SQL_CALC_FOUND_ROWS sehr erfreulich performant. Langsam wird es, wenn beide aufeinander treffen.