基于Oracle的查询优化

基于Oracle的查询优化,oracle,database-performance,sql-tuning,Oracle,Database Performance,Sql Tuning,我不是一名查询性能专家,我正在学习Oracle optimizer如何处理不同的查询,并对它们进行调优以供使用。下面是我的项目中的查询,我一直在为大数据集优化它(对于大数据集,它的速度变慢了) 我尝试了SQL开发人员查询优化顾问,没有推荐。这里的问题是,它在查询的两个部分上都要进行完整的表扫描,并且不使用任何索引,并且ver表包含近1M条记录。下面是ver表脚本 create table ver ( "Ver_id" VARCHAR2(36 BYTE) Primary key "N

我不是一名查询性能专家,我正在学习Oracle optimizer如何处理不同的查询,并对它们进行调优以供使用。下面是我的项目中的查询,我一直在为大数据集优化它(对于大数据集,它的速度变慢了)

我尝试了SQL开发人员查询优化顾问,没有推荐。这里的问题是,它在查询的两个部分上都要进行完整的表扫描,并且不使用任何索引,并且ver表包含近1M条记录。下面是ver表脚本

create table ver 
 (  "Ver_id" VARCHAR2(36 BYTE) Primary key
    "NAME" VARCHAR2(255 BYTE) 
    "ACTIVE" VARCHAR2(1 BYTE) 
    "ARCHIVED" VARCHAR2(1 BYTE) 
    "DESCRIPTION" VARCHAR2(255 BYTE), 
    "ID" VARCHAR2(36 BYTE) 
    "DATE_CREATED" NUMBER(*,0)
    "CREATED_BY_USER" VARCHAR2(64 BYTE) 
    "SIZE" NUMBER(*,0)
    "LAST_MODIFIED" NUMBER(*,0))
索引是id上的一个非唯一索引和(id,名称)上的一个唯一索引,以及上次修改的非唯一索引


现在查询的执行时间大约为2-3分钟。任何建议。

首先,您不需要在
id
上建立索引,因为您已经在
(id,name)
对上建立了索引

您可以在版本(id、创建日期)上创建树索引,在版本(活动、存档)上创建位图索引。

您也没有在
SELECT
语句中使用v2,因此上述查询可以重写为

SELECT
     v1.id,
     v1.date_created,
     v1.name,
     v1.size
 FROM
      ver v1
 WHERE EXISTS (
     SELECT 1
     FROM ver v2
     WHERE v1.id = v2.id 
       and v2.id IN (
            ...500 ids
       )
       AND v2.active = 'Y'
       AND v2.archived = 'N'
     GROUP BY v2.id
     HAVING MAX(v2.date_created) = v1.date_created
 )

如果从1M行表中仅选择2到3K行,则使用索引可能会带来好处

基本上,您希望a)选择具有定义的
ID
s列表的所有行,b)为每个
ID
只筛选创建了
MAX
date\u的记录

您只需要
ID

create index ver_idx on ver(id);
这里有两种可供选择的策略:

使用分析函数获取最近的行

在子查询中,您将获得具有指定
ID
s的所有行,并使用
RANK
分析函数定义行的顺序。主查询仅选择具有
rn=1
的行,即具有max(创建日期)的行

请注意,我使用
RANK
获得与查询相同的结果。如果最大基准面上有联系,则会得到更多记录。如果您只想要一条记录,即使是领带,也可以使用
ROW\u NUMBER

with dt as (
select 
 id,date_created, name, "SIZE",
rank() over (partition by id order by date_created desc) rn
from ver
where id between 1 and 500
AND active = 'Y'
AND archived = 'N')
select 
  id,date_created, name, "SIZE"
from dt
where rn = 1;
您可以使用索引来获取具有选定
ID
s的所有行,并使用附加过滤器来仅获取具有最大日期的行

使用相关子查询

您可以使用关联子查询筛选具有最大日期的行:

select 
 id,date_created, name, "SIZE"
from ver a
where id between 1 and 500  
AND active = 'Y'
AND archived = 'N'
AND date_created in (select max(date_created) 
                     from ver where id = a.id and active = a.active 
                              and archived = a.archived)
不可能说哪种方法是最好的。这取决于表中的数据


简单的测试,检查并找到性能最好的查询。

Hi Simonare,感谢您的快速响应,我们如何选择适合某个问题的索引?新手,因此寻找这些问题的性能指南。位图索引在列数据不经常更改时使用。例如是、否或isArchived=>1,0。Btree用于username等其他对象。@Simonare位图索引的问题不在于数据是否相对静态,而在于数据是否由多个会话同时更新。而且,别忘了,您需要担心的不仅仅是位图索引列上的并发更新:表上的并发插入和删除也会锁定位图条目,导致序列化和死锁。@witswickey如果您觉得这个答案对您有用,请考虑回答以下问题:从你的总1M中,多少行匹配500个选择的<代码> ID <代码> s 2K到3K,通常是“MMME轰炸机”。
select 
 id,date_created, name, "SIZE"
from ver a
where id between 1 and 500  
AND active = 'Y'
AND archived = 'N'
AND date_created in (select max(date_created) 
                     from ver where id = a.id and active = a.active 
                              and archived = a.archived)