2012-07-02 28 views
3

我對Joining many-to-many relationships有更多疑問,但認爲最好能提出一個新問題。加入多對多關係,執行時間

全面查詢:

SELECT p.id 
    ,(100 * sum((a.price > 0)::int))/cc.ct AS commercial 
    ,(100 * sum((a.price = 0)::int))/cf.ct AS free 
FROM (SELECT count(*)::float AS ct FROM applications WHERE price > 0) AS cc 
    ,(SELECT count(*)::float AS ct FROM applications WHERE price = 0) AS cf 
    ,permissions p 
LEFT JOIN applications_permissions ap ON ap.permission_id = p.id 
LEFT JOIN applications a ON a.id = ap.application_id 
GROUP BY 1, cc.ct, cf.ct 
ORDER BY 2 DESC, 3 DESC, 1; 

關於執行時間:

SELECT p.id 

- >總運行時間:2,467.801毫秒

SELECT (SELECT regex FROM permissions WHERE id = p.id) AS regex 

- >總運行時間:28,882.293毫秒

什麼在這裏發生? 這是做什麼的正確方法?

SELECT p.id

QUERY PLAN 
Sort (cost=123257.63..123258.07 rows=178 width=24) 
    Sort Key: (((sum(((a.price > 0::double precision))::integer))::double precision/((count(*))::double precision))), (((sum(((a.price = 0::double precision))::integer))::double precision/((count(*))::double precision))), p.id 
    -> HashAggregate (cost=123244.74..123250.97 rows=178 width=24) 
     -> Hash Left Join (cost=53709.64..115103.31 rows=651315 width=24) 
       Hash Cond: (ap.application_id = a.id) 
       -> Hash Left Join (cost=42222.11..82232.48 rows=651315 width=24) 
        Hash Cond: (p.id = ap.permission_id) 
        -> Nested Loop (cost=18283.65..18305.06 rows=178 width=20) 
          -> Index Scan using permissions_pkey on permissions p (cost=0.00..17.85 rows=178 width=4) 
           Filter: (regex IS NOT NULL) 
          -> Materialize (cost=18283.65..18283.66 rows=1 width=16) 
           -> Nested Loop (cost=18283.60..18283.65 rows=1 width=16) 
             -> Aggregate (cost=9016.51..9016.52 rows=1 width=0) 
              -> Seq Scan on applications (cost=0.00..8915.85 rows=40262 width=0) 
                Filter: (price > 0::double precision) 
             -> Aggregate (cost=9267.09..9267.10 rows=1 width=0) 
              -> Seq Scan on applications (cost=0.00..8915.85 rows=140494 width=0) 
                Filter: (price = 0::double precision) 
        -> Hash (cost=11271.65..11271.65 rows=772065 width=8) 
          -> Seq Scan on applications_permissions ap (cost=0.00..11271.65 rows=772065 width=8) 
       -> Hash (cost=8453.68..8453.68 rows=184868 width=8) 
        -> Seq Scan on applications a (cost=0.00..8453.68 rows=184868 width=8) 
22 row(s) 
Total runtime: 4.524 ms 

SELECT(SELECT ...)

QUERY PLAN 
Sort (cost=3796049.42..3796049.86 rows=178 width=24) 
    Sort Key: (((sum(((a.price > 0::double precision))::integer))::double precision/((count(*))::double precision))), (((sum(((a.price = 0::double precision))::integer))::double precision/((count(*))::double precision))), ((SubPlan 1)) 
    -> HashAggregate (cost=3795033.06..3796042.76 rows=178 width=24) 
     -> Hash Left Join (cost=53709.64..3786891.62 rows=651315 width=24) 
       Hash Cond: (ap.application_id = a.id) 
       -> Hash Left Join (cost=42222.11..82232.48 rows=651315 width=24) 
        Hash Cond: (p.id = ap.permission_id) 
        -> Nested Loop (cost=18283.65..18305.06 rows=178 width=20) 
          -> Index Scan using permissions_pkey on permissions p (cost=0.00..17.85 rows=178 width=4) 
           Filter: (regex IS NOT NULL) 
          -> Materialize (cost=18283.65..18283.66 rows=1 width=16) 
           -> Nested Loop (cost=18283.60..18283.65 rows=1 width=16) 
             -> Aggregate (cost=9016.51..9016.52 rows=1 width=0) 
              -> Seq Scan on applications (cost=0.00..8915.85 rows=40262 width=0) 
                Filter: (price > 0::double precision) 
             -> Aggregate (cost=9267.09..9267.10 rows=1 width=0) 
              -> Seq Scan on applications (cost=0.00..8915.85 rows=140494 width=0) 
                Filter: (price = 0::double precision) 
        -> Hash (cost=11271.65..11271.65 rows=772065 width=8) 
          -> Seq Scan on applications_permissions ap (cost=0.00..11271.65 rows=772065 width=8) 
       -> Hash (cost=8453.68..8453.68 rows=184868 width=8) 
        -> Seq Scan on applications a (cost=0.00..8453.68 rows=184868 width=8) 
       SubPlan 1 
       -> Seq Scan on permissions (cost=0.00..5.64 rows=1 width=26) 
         Filter: (id = $0) 
25 row(s) 
Total runtime: 6.566 ms 

回答

1

貌似你試圖相關子查詢添加到SELECT列表,而你可以只選擇列:

SELECT p.id, p.regex 
    ,(100 * sum((a.price > 0)::int))/cc.ct AS commercial 
    ,(100 * sum((a.price = 0)::int))/cf.ct AS free 
FROM (SELECT count(*)::float AS ct FROM applications WHERE price > 0) AS cc 
    ,(SELECT count(*)::float AS ct FROM applications WHERE price = 0) AS cf 
    ,permissions p 
LEFT JOIN applications_permissions ap ON ap.permission_id = p.id 
LEFT JOIN applications a ON a.id = ap.application_id 
GROUP BY p.id, p.regex, cc.ct, cf.ct 
ORDER BY commercial DESC, free DESC, p.id; 

如果p.id是主鍵,它涵蓋整個表格並且自Postgres 9.1開始,您不必在GROUP BY中添加p.regex

+0

-_-當然......你是對的。 –