【发布时间】:2013-11-14 23:29:38
【问题描述】:
假设我们有三个表:
-建筑物
-客房
-人
一栋建筑可以有 1 到 30 个房间(假设平均为 3 个)
一座建筑物可以容纳 0 到 30 人(平均为 3 人)
一个房间和一个人只能属于一个建筑物。
每个月,我们都会在我们的数据库中添加大约 50.000 座新建筑及其房间和人员。
我们可以删除超过 2 年的数据,因此我们将拥有大约 120 万个建筑物行。
主要问题是我们想要搜索并返回通常(但不总是)包含至少两个表(建筑物总是存在)的数据,因此我们必须执行连接。
我研究了 3 个解决方案。
- 具有标准化数据(由于连接和可扩展性低导致性能低下)
- 复制房间和人员表中的建筑数据。 (速度很快,但我通常不喜欢非规范化)
- Oracle 集群表。 (似乎提供了良好的性能,并且数据仍然正常化)
所以问题是:
Oracle Cluster 适合这种情况吗?
这样的Cluster可以连续添加行吗?
如果您不推荐 Cluster,为什么以及什么更适合?
详情:
集群:
SELECT *
FROM
(SELECT *
/*+ FIRST_ROWS(200)*/
FROM BUILDING_C R
INNER JOIN PEOPLE_C C
ON (R.BUILDING_id = C.BUILDING_id)
INNER JOIN ROOM_C S
ON (S.BUILDING_id = R.BUILDING_id)
WHERE S.OPEN_DATE >= SYSDATE - 60 -1
AND S.OPEN_DATE <= SYSDATE - 60
ORDER BY S.OPEN_DATE
)
WHERE rownum < 200;--17 consistent gets
标准化:
SELECT *
FROM
(SELECT *
/*+ FIRST_ROWS(200)*/
FROM BUILDING_N R
INNER JOIN PEOPLE_N C
ON (R.BUILDING_id = C.BUILDING_id)
INNER JOIN ROOM_N S
ON (S.BUILDING_id = R.BUILDING_id)
WHERE S.OPEN_DATE >= SYSDATE - 60 -1
AND S.OPEN_DATE <= SYSDATE - 60
ORDER BY S.OPEN_DATE
)
WHERE rownum < 200;--44 consistent gets
【问题讨论】:
-
非规范化并不邪恶。有时这是必须的。您可以将聚簇表视为在物理级别上进行了非规范化。你提到的卷太大了——1M 的行对于 Oracle 来说不算太多。集群通常用于不能独立“生存”的表,即与其他东西连接起来有一定意义的表。还要注意一些老派 DBA 不喜欢聚簇表,因为它们过去存在一些问题。
-
您是否调查过您为“低性能”查询获得的执行计划?联接是内在的,因此您说它们是一个问题似乎很奇怪。您是否有适合您正在进行的连接的索引,包括外键?如果没有看到架构、数据、查询和计划,很难猜测为什么它可能比您预期的要慢。
-
我同意上面的评论。调查执行计划。他们怎么了?您是否使用正确索引的表?您是否考虑过使用位图连接索引 (docs.oracle.com/cd/E11882_01/server.112/e25554/…)?此外,您需要数据的最新程度如何?物化视图是否适用于非规范化表示?
-
因为有很多数据,我们只需要前 200 个数据,我认为最好的执行计划是嵌套循环。在所有情况下都发生了什么。关于索引,是的,它们是创建的。当您需要过滤位于两个不同表中的数据时,就会出现问题。关于如何“最新”,拥有 2 到 3 秒的复制过程不会成为问题。是的,物化视图可以解决问题,但我不能使用它们(管理禁止):)
-
在任何半体面的服务器上,50 毫秒的 3 表连接对这么小的表应该很容易实现。听起来您的问题不是关于您的问题,而是您提出的解决方案。如果你真的问一个关于你的确切问题的问题,那么我相信有人会很容易地提供帮助。至少包括表结构、查询和解释计划以及示例数据。就目前而言,您只会得到通用答案,告诉您使用物化视图或添加索引。最好具体一点……
标签: oracle join oracle11g normalization