2017-01-20 6 views
0

Ich möchte einige Hilfe beschleunigen meine SQL-Abfrage mit mehreren Joins. Was ich versuche abzurufen, entspricht allen Benutzerfeldern mit ihrer neuesten entsprechenden Seite, Artikel und Club. Die folgende Abfrage funktioniert in Ordnung, aber es dauert ein paar Sekunden. Ich habe Indizes zu allen user_id-Fremdschlüsselfeldern sowie den User-Klassen- und College-Feldern hinzugefügt, nach denen gefiltert wird, aber es hat nicht viel geholfen.Beschleunigung von mehreren linken äußeren Join SQL-Abfrage

Ich glaube nicht, dass ich einfache innere Joins machen kann, weil ich möchte alle Benutzer und innere Beitritt über alle Tabellen würde einige Benutzer ohne Seiten zum Beispiel zu beseitigen. Jeder Benutzer hat zwischen null und vielen Seiten, Gegenständen und Vereinen.

SQL-Tabellen

User 
id 
first_name 
last_name 
class 
college 

Page 
id 
user_id 
created_at 
page_text 

Item 
id 
user_id 
created_at 
item_text 

Club 
id 
user_id 
created_at 
club_text 

Aktuelle Arbeits aber langsam Abfrage

SELECT u.id,u.first_name,u.last_name,p.page_text,i.item_text,c.club_text FROM user u LEFT OUTER JOIN LATERAL \ 
    (SELECT page_text FROM page p2 WHERE u.id = p2.user_id ORDER BY p2.created_at DESC LIMIT 1) p ON TRUE LEFT OUTER JOIN LATERAL \ 
    (SELECT item_text FROM item i2 WHERE u.id = i2.user_id ORDER BY i2.created_at DESC LIMIT 1) i ON TRUE LEFT OUTER JOIN LATERAL \ 
    (SELECT club_text FROM club c2 WHERE u.id = c2.user_id ORDER BY c2.created_at DESC LIMIT 1) c ON TRUE \ 
    WHERE u.class = 'Senior' AND u.college = 'University' ORDER BY u.first_name; 

Antwort

0

ich glaube, Sie die Abfrage mit entsprechenden Indizes verbessern können:

SELECT u.id, u.first_name ,u.last_name, p.page_text, i.item_text, c.club_text 
FROM user u LEFT OUTER JOIN LATERAL 
    (SELECT page_text 
     FROM page p2 
     WHERE u.id = p2.user_id 
     ORDER BY p2.created_at DESC 
     LIMIT 1 
    ) p ONTRUE LEFT OUTER JOIN LATERAL 
    (SELECT item_text 
     FROM item i2 
     WHERE u.id = i2.user_id 
     ORDER BY i2.created_at DESC 
     LIMIT 1 
    ) i ON TRUE LEFT OUTER JOIN LATERAL 
    (SELECT club_text 
     FROM club c2 
     WHERE u.id = c2.user_id 
     ORDER BY c2.created_at DESC 
     LIMIT 1 
    ) c ON TRUE 
WHERE u.class = 'Senior' AND u.college = 'University' 
ORDER BY u.first_name; 

Der Verbund (mehrspaltige) Indizes, die Sie möchten, sind:

  • user(class, college, first_name, id)
  • page(user_id, created_at desc, page_text)
  • item(user_id, created_at desc, item_text)
  • club(user_id, created_at desc, club_text)
+0

Danke, stellt sich heraus, dass ich nicht die Fremdschlüsselindizes erstellt haben, wie ich dachte, Ich hatte. Nach der Korrektur wird die Abfragegeschwindigkeit stark verbessert. Können Sie erklären, warum ein Index auf einer Seite (Seitentext), einem Element (Elementtext) und einem Club (Clubtext) erforderlich ist, da die Abfrage nichts auf diesen Feldern ausführt, außer sie auf der Grundlage einer bereits indizierten anderen Spalte abzurufen? – user1071182

+0

@ user1071182. . . Ich verstehe nicht, warum diese einzelnen Spaltenindizes helfen würden. –

+0

Okay, vielleicht habe ich Ihre Antwort missverstanden und Sie schlagen mehrspaltige Indizes vor, im Gegensatz zu einigen einzelnen Indizes, wie ich sie jetzt habe – user1071182

0

Probieren Sie es einfach einfacher:

select * 
from (
    select distinct on (u.id) 
     u.id, u.first_name, u.last_name, p.page_text, i.item_text, c.club_text 
    from 
     user u 
     left outer join page p on p.user_id = u.id 
     left outer join item i on i.user_id = u.id 
     left outer join club c on c.user_id = u.id 
    where u.class = 'Senior' and u.college = 'University' 
    order by u.id, p.created_at desc, i.created_at desc, c.created_at desc 
) s 
order by last_name, first_name; 
Verwandte Themen