我正在實施以下訪問策略:User
如果他創建了它,則可以訪問Resource
,屬於Resource
的組成員或資源是公共可用的。在兩個索引+排序上的MySQL查詢性能
這裏是我的數據庫結構(表是MyISAM數據):
User (1K-10K Users)
id
nickame
…
index user_name(id, nickname)
Group (1K)
id
…
Resource (10K-100K)
id
user_id
access_type (int)
group_id
created (int/timestamp)
…
indexes by_user(user_id, created), by_group(access_type, group_id, created), public(access_type, created)
User_Group (5K-20K)
user_id
group_id
membership_type (int)
index user_group(user_id, membership_type, group_id)
授予訪問權的條件是這種方式實現的: *的User
是Resource
的創造者(user_id = <his id>
,無論ACCESS_TYPE是) *或者資源是公開可用的:Resource.access_id = 3
*或者資源在組中共享並且用戶被接受爲該組的成員: ** Resource.access_id = 2
(在組中共享) ** Ressource.group_id
匹配User_Group
的group_id
**這User_Group
的user_id
的用戶的ID **匹配這個User_Group
的membership_type
是1,2或3(接受成員或組慢化劑/管理員)
我的問題是:什麼是列出Resources
(和Resource
創建者的nickname
)最有效的方式,當我們有他的ID時,用戶可以訪問它。並按資源的created
時間戳排序。
我最好的嘗試,到目前爲止是使用UNION
,允許同時使用by_user
和by_group
指標,但可能會掙扎後排序:
SELECT SQL_NO_CACHE
a.*, user.nickname
FROM (
(SELECT resource.* FROM resource WHERE user_id = '000000-0000-0000-0000-000000000000')
UNION
(SELECT resource.* FROM resource WHERE access_type = 3)
UNION
(SELECT resource.* FROM resource
INNER JOIN user_group ON (access_type = 2 AND user_group.group_id = resource.group_id)
WHERE user_group.user_id = '000000-0000-0000-0000-000000000000'
AND user_group.type IN (1, 2, 3)
)
) a
LEFT JOIN user ON (user.id = a.user_id)
ORDER BY created DESC;
的EXPLAIN
輸出告訴我,它使用索引都SELECT
s並在UNION
的行上以type: ALL/Using filesort
結束ORDER BY
。但是,如果我想排序和限制,我猜可能會變得很沉重,因爲在元組上沒有索引。
另一種可能是爲Groups
的User
子查詢一個簡單的查詢是:
SELECT SQL_NO_CACHE
resource.*, user.nickname
FROM resource
LEFT JOIN user ON (user.id = resource.user_id)
WHERE user_id = '000000-0000-0000-0000-000000000000'
OR access_type = 3
OR (access_type = 2 AND group_id IN
(SELECT group_id FROM user_group USE INDEX (`user_group`)
WHERE user_id = '000000-0000-0000-0000-000000000000' AND type IN (1, 2, 3)
)
)
ORDER BY created DESC;
但這裏的EXPLAIN
告訴我,它不會使用索引,並在Resource
執行選擇type: ALL/Using where; using filesort
表,女巫是我想要避免的。如果我嘗試FORCE INDEX(by_user, by_group)
,則首先合併兩個索引type: index_merge/Using sort_union(by_user,by_group); Using where; Using filesort
,這可能也很昂貴。
有什麼更好的想法嗎?這個請求可能會頻繁地叫......
感謝您花時間閱讀和回答。當我開始工作時,我會運行一些測試。 – 2010-01-04 17:13:33