2017-02-10 1 views
0

Ich habe eine Abfrage im Moment, die gut funktioniert, aber Skalierungsprobleme haben wird. Die Lösung, die ich gefunden habe, ist sehr langsam. Ich möchte die zweite Abfrage beschleunigen.Postgresql IN-Klausel versus verschachtelte SELECT mit JOIN-Leistung

Alte Abfrage, die nicht gut skaliert:

SELECT user.score 
FROM users 
WHERE 
    user.id IN (
    SELECT user_id 
    FROM companies_users 
    ON companies_users.company_id = X 
) 

Dann habe ich sie über die verschiedenen Noten Gruppe laufen würde. Scores reichen von -10 bis 10. Das Problem kommt von der IN SELECT-Anweisung und der Iteration. Es könnten mehr als eine Million user_ids zurückgegeben werden.

Die Alternative, die ich habe kommen mit sollte besser skalieren, ist aber wild langsam:

SELECT 
    COUNT(*) as total_scores, 
    (SELECT COUNT(*) FROM users 
    JOIN companies_users as cu ON cu.company_id = cu.user_id 
    WHERE users.score = 10 AND cu.company_id = X) as "10", 
    (SELECT COUNT(*) FROM users 
    JOIN companies_users as cu ON cu.company_id = cu.user_id 
    WHERE users.score = 9 AND cu.company_id = X) as "9", 
... 
    (SELECT COUNT(*) FROM users 
    JOIN companies_users as cu ON cu.company_id = cu.user_id 
    WHERE users.score = -9 AND cu.company_id = X) as "-9", 
    (SELECT COUNT(*) FROM users 
    JOIN companies_users as cu ON cu.company_id = cu.user_id 
    WHERE users.score = -10 AND cu.company_id = X) as "-10" 
FROM users 
    JOIN companies_users as cu ON cu.company_id = cu.user_id 
    WHERE cu.company_id = X 

Die erste Abfrage erfordert Iteration in Arbeitsdaten zu erhalten. Der zweite ist gut zu gehen.

Gibt es eine Möglichkeit, das JOIN aus den geschachtelten SELECTs zu ziehen? Das scheint den Großteil der Verlangsamung in der zweiten Abfrage zu verursachen. Habe ich auch recht, dass die erste Abfrage bei Millionen von IDs nicht gut skalieren wird?

Antwort

1

Was ist das Problem mit sein würde:

SELECT u.score 
FROM companies_users cu 
    JOIN users u ON cu.user_id = u.id 
WHERE cu.company_id=? 
GROUP BY u.score 
ORDER BY u.score 

?

Haben Sie auch geeignete Indizes? Sie benötigen einen Index für companies_users(company_id) und einen für users(id). Sie können versuchen, eine auf companies_users (user_id) hinzuzufügen, nur für den Fall, dass der Planer entscheidet, dass es besser ist, die Abfrage umgekehrt zu machen. EXPLAIN und EXPLAIN ANALYZE sind deine Freunde.

+0

Danke für die Antwort! Das ist fast perfekt. Ich suche eigentlich nach den Punkten auf den verschiedenen Punkten. Ich habe deine Lösung benutzt, aber den Select-Teil in u.score geändert, gezählt (u.score) und alle Daten erhalten! Danke noch einmal. – amiksch

Verwandte Themen