Subselect sehr langsam - Order by mit Group Lösung gesucht

MsvP@habdichliebhasi

Erfahrenes Mitglied
Hallo ihr Lieben,

ich habe vor einiger Zeit etwas umfangreichere Datenbankabfragen gebastelt. Dabei war es wichtig, dass zusammengehörige Datensätze gruppiert werden. Das führte aber dazu, dass leider immer die ersten treffenden Beiträge als Datensatz zurück geworfen wurden. Ich brauchte aber immer den neusten dieser gruppierten.
Damals habe ich das ganze via Subselect gelöst. Dabei wurden die Datensätze vorab sortiert im Subselect und dann richtig herum ausgegeben.

Mittlerweile ist die Datenbank aber sehr angewachsen, und es gibt viele tausend Beiträge. Ich kämpfe sehr mit Leistungseinbrüchen und ewig langen Response Zeiten. Jetzt habe ich die Subselects als ein Nadelör herausfinden können. Denn die Abfragezeiten steigen bei der Anwendung teilweise auf das Doppelte.
Leider habe ich noch keine Alternative gefunden, um mein Problem anderweitig zu lösen...

Hat jemand eine Idee?
 
Hallo,

die reguläre Vorgehensweise in diesem Fall: Löse das Problem mittels JOIN und erstelle ggf. auf die Spalten, die in der WHERE-Condition liegen einen Index. Wobei abzuwägen ist, auf was alles ein Index erstellt werden soll. Ohne nähere Infos bzgl. Tabellen-Struktur und Referenzen lässt sich leider kein detailierterer Vorschlag in Form von SQL machen.
 
Ein bisschen abgewandelt aus Sicherheitsgründen, aber vom Prinzip her ist es dieser Code - Joins werden schon zu genüge genutzt:

Code:
'SELECT
     `comment`.`answerId` AS `aId`,
     `comment`.`id_extern`,
     `comment`.`id`,
     `comment`.`created_at`,
     `picture`.`id` AS `pictureid`,
     `picture`.`name`,
     `user`.`username`,
     `user`.`id` AS `userId`,
     `user`.`gender`,
     `user`.`picture`,
      `user`.`created_at` AS `userDate`
FROM (SELECT `comment`.* FROM `comment` ORDER BY `comment`.`created_at` DESC) AS `comment`
INNER JOIN `picture` ON comment.id_extern = picture.id
INNER JOIN `user` ON comment.created_user = user.id
WHERE (picture.iduser = "3")
     AND (comment.created_user != "3")
     AND (user.deleted = 0)
     AND (user.active = 1)
     AND (comment.answerId > 0)
GROUP BY `comment`.`answerId`
LIMIT 6'


Es werden Antworten zu Kommentaren hochgeladener Bilder aus der Datenbank geholt.
 
Ohne Garantie:

item:
Nimm den ODER BY zum Subselect raus, bzw verscheibe ihn ins haubtquery.Dadurch fällt das Subquery weg und dur sortierst nur die Treffer.

item: Da du keine Aggregationsfunktionen brauchst, kannst du den GROUP BY durch ein DISTINCT ersetzen

item: Dazu noch Imdexe auf die JOIN-Felder und ggf auf die WHERE-Felder.

SQL:
SELECT DISTINCT
     `comment`.`answerId` AS `aId`,
     `comment`.`id_extern`,
     `comment`.`id`,
     `comment`.`created_at`,
     `picture`.`id` AS `pictureid`,
     `picture`.`name`,
     `user`.`username`,
     `user`.`id` AS `userId`,
     `user`.`gender`,
     `user`.`picture`,
      `user`.`created_at` AS `userDate`
FROM `comment`
INNER JOIN `picture` ON comment.id_extern = picture.id
INNER JOIN `user` ON comment.created_user = user.id
WHERE (picture.iduser = "3")
     AND (comment.created_user != "3")
     AND (user.deleted = 0)
     AND (user.active = 1)
     AND (comment.answerId > 0)
ORDER BY `comment`.`created_at` DESC
LIMIT 6
 
Habe es gerade kurz getestet und ich glaube, es klappt! Muss es morgen nochmal in Ruhe durchsehen. Aber die Performance ist in jedem Fall deutlich schneller. Bei dem Testquery wären es statt 300 MS nur noch 100. Ich gebe morgen nochmal kurz Bescheid, ob sich auch alle Datensätze richtig auslesen lassen.

Vielen Dank schon mal für die Hilfe! =)
 
100ms ist immer noch sehr viel für meinen Geschmack - ohne zu wissen, von wievielen Einträgen wir hier reden. Hast du die Indizes geprüft? comment.id_extern, comment.created_user, picture.iduser und comment.answerId wären Optionen für ein CREATE INDEX-Statement.
 
Einbau der Indizes auf die Spalten war ein super Tipp! Damit konnte ich die Abfragezeit auf 50 ms drücken.

Edit: Es ist sogar noch weniger, die ersten 45ms gehen anscheinend auf die generelle Antwortzeit des Servers zurück. Denn die braucht das Script auch ohne DB Abfrage...
 
Zuletzt bearbeitet:
Zurück