我有一个数据库,它建模的数据类似于您可能看到的为体育收集的数据类型。我在这些活动中有用户和事件,用户拥有角色。这些事件中的每一个还具有 stats 并且属于类别,这些都是当前相关的:
========= ========== ============
| users | | events | | category |
|=======| |========| |==========|
| id | | id | | id |
--------- ---------- ------------
========================= =======================
| roles | | stats |
|=======================| |=====================|
| id | |id |
| user_id -> users.id | | role_id -> roles.id |
| event_id -> events.id | -----------------------
| category_id -> cat... |
-------------------------
我一直在努力保持一切都很好地分离和规范化,但我开始看到一个重要的效率权衡。数据是分批添加的,粗略估计每个事件有大量的 stats ,我一次吸引了数百个事件。目前我只玩一个用户并拥有170,000个统计数据,这可能是此用户的四分之一* 统计
以下是我如何查询此内容的示例:
SELECT avg(some_data) FROM stats
JOIN roles ON stats.role_id = roles.id
JOIN users ON roles.user_id = roles.id
JOIN events ON roles.event_id = events.id
JOIN categories ON roles.category_id = categories.id
WHERE users.u_thing = 'something'
AND categories.name = 'something'
GROUP BY stats.timestamp
此查询(在授予的虚拟主机上)平均花费8秒,并且正在执行超过14000行的avg()
。
我对数据库架构或设计并不是特别熟悉,所以我不知道我能在这里做些什么来优化我的架构/访问模式。
Addtional
答案 0 :(得分:1)
对于类JOIN操作,从多个表中查询或过滤等常规技术效率很低。由于数据库必须提取满足第一个where子句的所有角色,然后如果它们在表“users”中并且满足第二个where子句“roles.user_id = roles.id”作为示例,则逐个检查它们列表。
相反,最有效的方法是从所有基础表构建物化视图。您将认为物化视图是一种冗余数据结构,旨在加速复杂的JOIN查询。
JOIN via materialized view帖子详细阐述了这一主题。