2012-02-20 84 views
4

什麼是最佳實踐,什麼能提供最佳性能?在一個API請求中有多個連接的單個查詢,或者在單獨的API請求中連接了幾個查詢?

我現在有很多LEFT JOIN個查詢獲取一個user和他的所有數據,喜歡的朋友,朋友的請求,等:

SELECT 
    `user`.`id` AS `user_id`, 
    `user`.`name` AS `user_name`, 
    `manager`.`id` AS `manager_id`, 
    `competition`.`id` AS `manager_competition_id`, 
    `competition`.`name` AS `manager_competition_name`, 
    `competition`.`week` AS `manager_competition_week`, 
    `country`.`id` AS `manager_competition_country_id`, 
    `country`.`name` AS `manager_competition_country_name`, 
    `club_template`.`id` AS `manager_club_template_id`, 
    `club_template`.`name` AS `manager_club_template_name`, 
    `club`.`id` AS `manager_club_id`, 
    `club`.`name` AS `manager_club_name`, 
    `club`.`ready` AS `manager_club_ready`, 
    `friend`.`friend_id` AS `friend_id`, 
    `friend_user`.`name` AS `friend_name` 
FROM 
    `users` AS `user` 
LEFT JOIN 
    `managers` AS `manager` 
ON 
    `manager`.`user_id` = `user`.`id` 
LEFT JOIN 
    `competitions` AS `competition` 
ON 
    `competition`.`id` = `manager`.`competition_id` 
LEFT JOIN 
    `countries` AS `country` 
ON 
    `country`.`id` = `competition`.`country_id` 
LEFT JOIN 
    `club_templates` AS `club_template` 
ON 
    `club_template`.`id` = `manager`.`club_template_id` 
LEFT JOIN 
    `clubs` AS `club` 
ON 
    `club`.`id` = `manager`.`club_id` 
LEFT JOIN 
    `friends` AS `friend` 
ON 
    `friend`.`user_id` = `user`.`id` 
LEFT JOIN 
    `users` AS `friend_user` 
ON 
    `friend_user`.`id` = `friend`.`friend_id` 
WHERE 
    `user`.`id` = 1 

正如你可以看到,這是一個非常大的查詢。我這背後的理由是,這是更好地只有一個查詢可以在一個API請求來完成,像這樣...

/api/users/1 

...與幾個疑問,各自在自己的API請求,像這...

/api/users/1 
/api/users/1/friends 
/api/users/1/friend_requests 
/api/users/1/managers 

但現在我很擔心,既然它已經成爲這實際上會損害性能更比它在單獨的API請求分割如此龐大的查詢。

什麼會縮放更好?

更新

我已經改變了查詢到完整的查詢。這不是最終的查詢;我打算添加更多的連接(或不是,取決於答案)。

每張桌子上有PRIMARY KEY,id。所有關聯列(competition_id,club_id等)都有一個常規的INDEX。數據庫引擎是InnoDB。

+1

如果您可以提供數據庫結構和密鑰背後的一些信息以及完整查詢 – 2012-02-20 15:56:30

+0

完成,將會有所幫助。讓我知道你是否需要更多 – Rits 2012-02-20 16:08:34

回答

2

在這兩者中,我會推薦後者:許多小衆查詢。它使調用者能夠靈活地回退他們想要的東西,並且不太可能默默地引入性能問題(例如,只有一種選擇來檢索數據,所以每個人都使用它,不管他們真正感興趣的數據的子集有多小)。這就是說,它肯定不會受到性能問題的影響,它只是意味着調用者可能會因爲發出如此多的API調用而更加意識到它們。

雖然你可以提供。從命名慣例中明確指出,昂貴的版本會將所有數據拉回,並在用戶需要進行20 - 30次調用以獲得完整圖像時使用。

例子:

1 - 想象一下,拿到完整的用戶對象只是爲了尋找出了名。真是浪費。如果在一個大循環中無意中完成,性能陷阱等待發生。建議使用getUserName(id)方法,只讀取一個值。

2另一方面,如果您想在一個頁面中顯示用戶的完整配置文件,那麼完整的getFullUserProfile(id)是最有效的(1次調用而不是10-20次)。

編輯 - 另一個有用的例子。預計需要許多值,例如,而不是強迫呼叫者運行500次以獲得某個條件的所有名稱(所有管理員用戶可能?),提供一個List<String> getAdminUserNames(),它在一次呼叫中提供所有數據。

1

很酷的問題。

我認爲你需要擔心查詢背後的領域概念,並儘量保持忠誠於你可以。因此,根據您的查詢進行瘋狂猜測,您的用戶處於各種完成狀態 - 創建其個人資料但尚未加入競賽的用戶;已參加比賽但尚未成立俱樂部的用戶等。這反映了您的域模型。我希望你的API,以反映這一點 - 因此,使用您的寧靜例如:

/api/users/profile 
/api/users/signedUpUsers/ 
/api/users/usersWithClubs/ 

第一次調用(/ API /用戶/配置文件)允許你返回用戶配置文件,但沒有你的外部聯接比其他細節用戶的狀態(也可能是可以找到其他附加數據的URL)。

堅持使用域方法,並在開發生命週期中構建性能測試;如果您能證明自己有問題,只需更改設計即可。

相關問題