首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何从数百万行的多个表中优化select

如何从数百万行的多个表中优化select
EN

Stack Overflow用户
提问于 2010-11-17 23:08:41
回答 5查看 7.9K关注 0票数 7

具有以下表格(Oracle 10g):

代码语言:javascript
运行
复制
catalog (
  id NUMBER PRIMARY KEY,
  name VARCHAR2(255),
  owner NUMBER,
  root NUMBER REFERENCES catalog(id)
  ...
)
university (
  id NUMBER PRIMARY KEY,
  ...
)
securitygroup (
  id NUMBER PRIMARY KEY
  ...
)
catalog_securitygroup (
  catalog REFERENCES catalog(id),
  securitygroup REFERENCES securitygroup(id)
)
catalog_university (
  catalog REFERENCES catalog(id),
  university REFERENCES university(id)
)

目录:500000行,catalog_university: 500000,catalog_securitygroup: 1500000。

我需要从目录中选择任意50行,其中指定的根按当前大学和当前安全组的名称排序。有一个查询:

代码语言:javascript
运行
复制
SELECT ccc.* FROM (
  SELECT cc.*, ROWNUM AS n FROM (
      SELECT c.id, c.name, c.owner
        FROM catalog c, catalog_securitygroup cs, catalog_university cu
        WHERE c.root = 100
          AND cs.catalog = c.id
          AND cs.securitygroup = 200
          AND cu.catalog = c.id
          AND cu.university = 300
        ORDER BY name
    ) cc 
) ccc WHERE ccc.n > 0 AND ccc.n <= 50;

其中100 -一些目录,200 -一些安全组,300 -一些大学。此查询在3分钟内从~170000返回50行。

但next查询在2秒内返回以下行:

代码语言:javascript
运行
复制
SELECT ccc.* FROM (
  SELECT cc.*, ROWNUM AS n FROM (
      SELECT c.id, c.name, c.owner
        FROM catalog c
        WHERE c.root = 100
        ORDER BY name
    ) cc 
) ccc WHERE ccc.n > 0 AND ccc.n <= 50;

我构建下一个索引:(catalog.id,catalog.name,catalog.owner),(catalog_securitygroup.catalog,catalog_securitygroup.index),(catalog_university.catalog,catalog_university.university)。

第一次查询的计划(使用PLSQL Developer):

http://habreffect.ru/66c/f25faa5f8/plan2.jpg

第二次查询的计划:

http://habreffect.ru/f91/86e780cc7/plan1.jpg

有什么方法可以优化我的查询?

EN

Stack Overflow用户

发布于 2010-11-18 00:26:23

rownum的使用是错误的,会导致所有行都被处理。它将处理所有行,为它们分配一个行号,然后查找0到50之间的行。当您想要在解释计划中查找时是COUNT STOPKEY而不是仅仅计数

下面的查询应该是一个改进,因为它只会得到前50行...但是仍然有连接的问题需要考虑:

代码语言:javascript
运行
复制
SELECT ccc.* FROM (
  SELECT cc.*, ROWNUM AS n FROM (
      SELECT c.id, c.name, c.owner
        FROM catalog c
        WHERE c.root = 100
        ORDER BY name
    ) cc 
    where rownum <= 50
) ccc WHERE ccc.n > 0 AND ccc.n <= 50;

另外,假设这是一个网页或类似的东西,也许有一种更好的方法来处理这个问题,而不仅仅是再次运行查询来获取下一个页面的数据。

票数 0
EN
查看全部 5 条回答
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/4205749

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档