2015-10-14 166 views
2

我想從3個不同的表中獲取數據,如下圖所示:SQL - 加入查詢運行緩慢

SELECT urs.id 
    ,urs.username 
    ,urs.b_avg_update 
    ,urs.b_set_min_avg 
    ,urs.b_set_max_avg 
    ,urs.b_min_avg 
    ,urs.b_max_avg 
    ,trs.TIME 
    ,trs.user 
    ,sum(trs.amount) 
    ,trs.type 
    ,ur.user_by 
FROM (
    SELECT DISTINCT user_by 
    FROM xeon_users_rented 
    ) AS ur 
LEFT JOIN users AS urs ON ur.user_by = urs.username 
LEFT JOIN transactions AS trs ON urs.id = trs.user 
    AND trs.type = 'Recycle' 
    AND trs.TIME >= UNIX_TIMESTAMP(CURDATE()) 
GROUP BY ur.user_by 

然而,查詢是相當緩慢運行:

Showing rows 0 - 29 (812 in total, request took 15.0095 sec) 

當運行一個EXPLAIN在上面的查詢,這是我得到:

id select_type table type possible_keys key key_len ref rows Extra 
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 1516 Using temporary; Using filesort 
1 PRIMARY urs ALL NULL NULL NULL NULL 14553 Using where; Using join buffer (flat, BNL join) 
1 PRIMARY trs ref user,type user 8 littlebu_maindb.urs.id 6 Using where 
2 DERIVED xeon_users_rented range NULL idx_user_by 62 NULL 1516 Using index for group-by 

我試圖添加INDEXES上的超速了一點東西,希望某些列:

桌上xeon_users_rented

Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type 
xeon_users_rented 0 PRIMARY 1 id A 37897 NULL NULL  BTREE  
xeon_users_rented 0 user 1 user A 37897 NULL NULL  BTREE  
xeon_users_rented 1 user_by 1 user_by A 1579 NULL NULL  BTREE  
xeon_users_rented 1 since 1 since A 4210 NULL NULL  BTREE  
xeon_users_rented 1 expire 1 expire A 7579 NULL NULL  BTREE  
xeon_users_rented 1 clicks 1 clicks A 176 NULL NULL  BTREE  
xeon_users_rented 1 clicks_last 1 clicks_last A 5413 NULL NULL  BTREE  
xeon_users_rented 1 avg 1 avg A 3445 NULL NULL  BTREE  
xeon_users_rented 1 click_hour 1 click_hour A 46 NULL NULL  BTREE  
xeon_users_rented 1 click_minute 1 click_minute A 102 NULL NULL  BTREE  
xeon_users_rented 1 idx_click_hour 1 click_hour A 46 NULL NULL  BTREE  
xeon_users_rented 1 idx_click_minute 1 click_minute A 112 NULL NULL  BTREE  
xeon_users_rented 1 idx_id 1 id A 37897 NULL NULL  BTREE  
xeon_users_rented 1 idx_user 1 user A 37897 NULL NULL  BTREE  
xeon_users_rented 1 idx_user_by 1 user_by A 1515 NULL NULL  BTREE  
xeon_users_rented 1 idx_expire 1 expire A 6316 NULL NULL  BTREE  
xeon_users_rented 1 idx_since 1 since A 4210 NULL NULL  BTREE  
xeon_users_rented 1 idx_clicks 1 clicks A 176 NULL NULL  BTREE  
xeon_users_rented 1 idx_clicks_last 1 clicks_last A 5413 NULL NULL  BTREE  
xeon_users_rented 1 idx_avg 1 avg A 3445 NULL NULL  BTREE  

桌上users

Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type 
users 0 PRIMARY 1 id A 14554 NULL NULL  BTREE  
users 1 idx_username 1 username A 14554 NULL NULL  BTREE  
users 1 upline 1 upline A 856 NULL NULL  BTREE  
users 1 upline 2 upline_expire A 856 NULL NULL  BTREE 

最後但並非最不重要的,transactions表:

Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type 
transactions 0 PRIMARY 1 id A 5293 NULL NULL  BTREE  
transactions 1 user 1 user A 882 NULL NULL  BTREE  
transactions 1 type 1 type A 9 NULL NULL  BTREE  
transactions 1 amount 1 amount A 378 NULL NULL  BTREE 

我看不到什麼是ca使用緩慢。總共沒有1000條記錄。 如何改進我的原始查詢和/或數據庫設計?

+0

你確定這個運行?因爲你在GROUP BY ur.user_by中只有一個字段,而你的選擇只有很多非聚合字段。 –

+0

@JuanCarlosOropeza是的,它運行 - 真的很慢。 – oliverbj

+0

我現在看到了。 Mysql不驗證一些ANSI組的事情。我的建議是將您的查詢拆分成小部分,並逐一添加,直到找到緩慢的地方。 –

回答

1

試試這個方法。我認爲users應該是JOIN的LEFT一側。但如果這不是你正在查詢的查詢,我會嘗試其他的。

SELECT urs.username 
    ,sum(trs.amount) 
FROM users AS urs 
LEFT JOIN xeon_users_rented AS ur 
     ON urs.username = ur.user_by 
LEFT JOIN transactions AS trs 
     ON urs.id = trs.user 
     AND trs.type = 'Recycle' 
     AND trs.TIME >= UNIX_TIMESTAMP(CURDATE()) 
WHERE ur.user_by IS NOT NULL 
GROUP BY ur.user_by 
+0

我想知道爲什麼你有'urs.username - ur.user_by - urs.id - trs.user'你應該有相同的用戶名,例如user_id ' –

+0

卡洛斯Oropeze這隻選擇「用戶名」和「trs(金額)」字段。不是b_set_min_avg等 – oliverbj

+0

我知道,但那些只是靜態字段,或者你想做一些聚合函數?我假設這些是靜態的並且爲了簡化問題而不會影響性能。 –

0

通常,這些類型的查詢可使用相關子查詢,而不是group by在外水平運行得更快。您從transactions中拉出任意字段,因此讓我假設您只需要amount。而那username是獨一無二的。然後,你可以編寫查詢爲:

SELECT u.*, 
     (SELECT sum(trs.amount) 
     FROM transactions trs 
     WHERE u.id = trs.user AND trs.type = 'Recycle' AND 
       trs.TIME >= UNIX_TIMESTAMP(CURDATE()) 
     ) as amt 
FROM (SELECT DISTINCT user_by 
     FROM xeon_users_rented 
    ) AS xur JOIN 
    users u 
    ON xur.user_by = u.username; 

然後,users(username)transactions(user, type, time, amount)指標是最適合這個查詢。

+0

這給了我這個錯誤:¨-你的SQL語法有錯誤;檢查與您的MariaDB服務器版本相對應的手冊,以找到正確的語法('SELECT sum(trs.amount)FROM transactions trs WHERE u.id = trs.u'at line2¨ – oliverbj

+0

@oliverbj ...。在第一行缺少一個逗號,這個方法應該比其他的答案更快。 –

+0

在'users u ON xur ....'附近也出現錯誤。 – oliverbj