2008-10-28 36 views
4

我可以做些什么来提高oracle查询的查询性能而不创建索引?在不编制索引的情况下提高oracle查询性能

这里是我想要跑得更快的查询:

SELECT c.ClaimNumber, a.ItemDate, c.DTN, b.FilePath 
FROM items a, 
itempages b, 
keygroupdata c 
WHERE a.ItemType IN (112,115,189,241) 
AND a.ItemNum = b.ItemNum 
AND b.ItemNum = c.ItemNum 
ORDER BY a.DateStored DESC 

这些列没有被索引,并且每个表中包含数百万条记录。不用说,查询执行需要花费3分半钟以上的时间。这是生产环境中的第三方数据库,我不允许创建任何索引,因此必须对查询本身进行任何性能改进。

谢谢!

+0

哪些列中的数据类型?特别是ItemType? – 2008-10-28 19:45:23

+0

计划是什么。每个表中有多少行? 如果您无法创建任何索引,那么您可能无法完成任何操作。 – 2008-10-28 22:05:20

回答

6

首先我重写查询是ANSI标准:

SELECT c.ClaimNumber, a.ItemDate, c.DTN, b.FilePath 
FROM items a 
INNER JOIN itempages b ON b.ItemNum = a.ItemNum 
INNER JOIN keygroupdata c ON c.ItemNum = b.ItemNum 
WHERE a.ItemType IN (112,115,189,241) 
ORDER BY a.DateStored DESC 

这使得它更容易阅读和理解正在发生的事情。它也可以帮助你不犯错误(即交叉连接),这可能会导致真正的大问题。然后,我会得到Explain计划,以查看DBMS正在使用该查询处理的内容。它试图使用一些索引?它是否正确加入表格?

然后,我会检查我正在使用的表格,看看是否有任何已存在的索引可用于更快地进行查询。最后,正如其他人所建议的,我会删除Order By子句,然后在代码中执行此操作。

-1

删除ORDER BY

进行排序,你拉的行回应用程序之后。

+1

数据库内核开发人员花费大量时间优化通用组件(如分类技术)是不是很明显?我觉得这不值得做这件事。 – 2008-10-28 18:14:38

+0

为什么是这样。 如果数据库淹没了,就像我认为的那样,那么可能是将数据拉回来然后对其进行排序将会有好处。 这将需要一些实验,看看这是否是一个有效的方法,但他是在寻求想法。这是一个想法。 – EvilTeach 2008-10-28 19:55:39

+0

好吧,通过一切手段更新你的回应,说:“如果数据库被淹没......”。然后,我们可以谈论什么“淹没”的意思,而无论是在这种情况下,除去ORDER BY也优化切换到FIRST_ROWS模式的执行计划等。 – 2008-10-29 12:22:03

0

没有索引,该查询只会随着表大小的增加而变差。 就这样说,尝试删除order by子句并在客户端执行此类操作。

+0

数据库内核开发人员花费大量时间优化通用组件(如分类技术)是不是很明显?我觉得这不值得做这件事。 – 2008-10-28 18:16:24

+1

我确定数据库排序是优化的,这不是问题。他问他如何提高查询性能,最明显的做法是删除这种排序。 我已经拉到客户端的一些重负载数据库的一些真正的改进。 – 2008-10-28 18:47:04

7

要求第三方索引它的连接列,因为它们应该在第一位完成!没有索引,甲骨文除了暴力之外别无他法。

6

你可能想尝试在任何这些表上创建一个物化视图。然后,您可以在物化视图上创建一个索引,以帮助加快查询速度(然后查询物化视图而不是原始表)。

当然,如果您的基础表已更新,您的视图和索引将需要刷新。

1

如果查询输入是恒定的或可预测的(itemType IN (...)),则另一种方法是每天运行一次或两次查询,并将结果存储在本地表中,并在适当的位置存储索引。

然后,您可以进行昂贵的查询'离线',并为交互式查询获得更快/更好的结果。

3

首先看执行计划。它是否准确地反映了在查询执行的每个阶段中要检索的行数?谓词“a.ItemType IN(112,115,189,241)”的选择性有多大?执行计划是否显示使用临时磁盘空间进行连接或排序?

其实,也许你可以修改问题来包含执行计划。

此外,请确保您没有禁用散列连接,这在OLTP调整的系统中有时就是这种情况,因为它们是在Oracle中平等批量数据的最有效方式。他们应该出现在执行计划中。

3

在加入表格之前,您可以尝试过滤项目类型,如下所示。

如果您在9i之前运行Oracle,这有时会带来令人惊喜的好处。

select 
    c.claimnumber, 
    a.itemdate, 
    c.dtn, 
    b.filepath 
from 
    (
    select itemdate 
    from items it 
    where it.itemtype in(112,115,189,241) 
) a 
    itempages b, 
    keygroupdata c 
where a.itemnum = b.itemnum 
    and b.itemnum = c.itemnum 

您也可以尝试添加提示/ + RULE /或/ +有序 /看个究竟......再次,特别是与旧版本,这有时会得到意想不到的结果。

SELECT /*+RULE*/ 
    c.ClaimNumber, a.ItemDate, c.DTN, b.FilePath 
FROM 
    items a, 
    itempages b, 
    keygroupdata c 
WHERE a.ItemType IN (112,115,189,241) 
    AND a.ItemNum = b.ItemNum 
    AND b.ItemNum = c.ItemNum 
ORDER BY a.DateStored DESC 
0

统计数据是收集在这些表上吗?如果不是,收集统计数据可能会改变执行计划,但不一定会更好。

除此之外,请看执行计划。您可能会发现它以非最优顺序连接表(例如,在连接具有过滤条件的a之前,它可能会连接b和c)。

您可以使用提示尝试影响访问路径,连接顺序或连接方法。

更新:应对评论使我this介绍,这可能是有益的,或者至少有趣。

1

这是您经常运行的查询吗?看起来数据库所有者有兴趣创建索引来加快查询的速度。您花费3.5分钟运行查询必须对其生产环境产生一些影响!

此外,他们是否已经在表上运行更新统计信息?这可能会提高性能,因为连接顺序是根据表的统计信息计算出来的。

顺便说一句,你允许做什么?刚刚阅读?如果您可以创建临时表并将索引放在这些表上,那么我可能会考虑制作表的临时副本,将它们编入索引,然后使用临时副本执行索引辅助连接。

0

有时,您可以通过为优化程序添加额外路径来选择它,通过在where子句中添加看起来像冗余元素的东西来获益。

例如,你有A.ItemNum = B.ItemNum AND B.ItemNum = C.ItemNum。尝试添加A.ItemNum = C.ItemNum。然而,我非常确定,优化器足够聪明,可以自行解决这个问题 - 尽管值得一试。

0

根据ItemType列的数据类型,如果它是varchar,使用以下命令可能会遇到更快的执行情况,Oracle将执行implict转换。

SELECT c.ClaimNumber, a.ItemDate, c.DTN, b.FilePath 
FROM items a, 
itempages b, 
keygroupdata c 
WHERE ((a.ItemType IN ('112','115','189','241')) 
AND (a.ItemNum = b.ItemNum) 
AND (b.ItemNum = c.ItemNum)) 
ORDER BY a.DateStored DESC 
0

如果你说没有索引,那么这是否也意味着没有定义主键或外键?显然,分析表格和收集统计数据非常重要,但是如果元数据(如定义应该如何连接表格)不存在,那么Oracle可能会选择一个糟糕的执行路径。

在这种情况下使用提示,如/ * + *有序/很可能使优化可靠地选择一个好的执行路径是唯一的选择。它可能也值得添加外键和主键,但将它们定义为DISABLE和VALIDATE。

我猜此评论的有效性依赖于厌恶指标走多远等等因人而异。

0

首先创建关于该查询的图,然后生成从该视图的表格。还可以在日期上创建索引,创建作业并在系统空闲时的午夜时间安排它。

1

我知道这个线程是很老,但对于搜索引擎我还是想提供一个替代的解决方案,将在甲骨文工作,并根据数据可能会快得多。

with a as (
    select 
    * 
    from 
    items 
    where 
    ItemType IN (112,115,189,241) 
) 
SELECT 
    c.ClaimNumber 
    , a.ItemDate 
    , c.DTN, b.FilePath 
FROM 
    a, 
    itempages b, 
    keygroupdata c 
WHERE 
    a.ItemNum = b.ItemNum 
    AND b.ItemNum = c.ItemNum 
ORDER BY 
    a.DateStored DESC 

您也可以尝试WITH子句中的/*+ MATERIALIZE */提示。

其实我发现甲骨文的老联接语法更容易比ANSI SQL ^^

0

好读,因为你不能创建索引,我会确保统计数据均达到最新那么,我已经重写了查询是这样的:

with a as (select /*+ MATERIALIZE */ ItemType, ItemNum, DateStored, ItemDate from items where ItemType in (112,115,189,241)) SELECT c.ClaimNumber, a.ItemDate, c.DTN, b.FilePath FROM a, itempages b, keygroupdata c WHERE a.ItemNum = b.ItemNum AND b.ItemNum = c.ItemNum ORDER BY a.DateStored DESC