The*_*111 5 sql oracle database-design
我一直在学习Oracle SQL中的索引,我想用测试表进行一个小实验,看看索引是如何工作的.正如我在此前发表的一篇文章中所发现的,最好的方法是使用EXPLAIN PLAN.但是,我遇到了让我困惑的事情.
我的示例表包含属性(EmpID,Fname,Lname,Occupation,....等).我使用我编写的java程序(随机名称,职业等)用500,000条记录填充它.现在,这里有一些带索引和不带索引的示例查询:
没有索引:
SELECT Fname FROM EMPLOYEE WHERE Occupation = 'DOCTOR';
Run Code Online (Sandbox Code Playgroud)
EXPLAIN PLAN说:
OPERATION OPTIMIZER COST
TABLE ACCESS(FULL) TEST.EMPLOYEE ANALYZED 1169
Run Code Online (Sandbox Code Playgroud)
现在我创建索引:
CREATE INDEX occupation_idx
ON EMPLOYEE (Occupation);
Run Code Online (Sandbox Code Playgroud)
WITH INDEX"occupation_idx":
SELECT Fname FROM EMPLOYEE WHERE Occupation = 'DOCTOR';
Run Code Online (Sandbox Code Playgroud)
EXPLAIN PLAN说:
OPERATION OPTIMIZER COST
TABLE ACCESS(FULL) TEST.EMPLOYEE ANALYZED 1169
Run Code Online (Sandbox Code Playgroud)
所以...成本仍然相同,1169?现在我试试这个:
WITH INDEX"occupation_idx":
SELECT Occupation FROM EMPLOYEE WHERE Occupation = 'DOCTOR';
Run Code Online (Sandbox Code Playgroud)
EXPLAIN PLAN说:
OPERATION OPTIMIZER COST
INDEX(RANGE SCAN) TEST.OCCUPATION_IDX ANALYZED 67
Run Code Online (Sandbox Code Playgroud)
因此,似乎仅当该列是我从中提取值的列时才使用索引.但我认为索引的重点是使用索引列作为关键来解锁整个记录?上面的搜索是一个非常毫无意义的搜索...它会搜索您已经知道的值.唯一有价值的查询我可以想到哪个只涉及索引列的值(而不是记录的其余部分)将是一个聚合,如COUNT或其他东西.
我错过了什么?
即使使用索引,Oracle也决定对第二个查询进行全面扫描.
为什么这样做?甲骨文会创建两个计划并为每个计划提出成本: -
1)全扫描
2)索引访问
Oracle以较低的成本选择了该计划.显然,它提出了全扫描,因为成本较低.
如果您想查看索引计划的成本,可以使用这样的提示来执行解释计划以强制使用索引:
SELECT /*+ INDEX(EMPLOYEE occupation_idx) */ Fname
FROM EMPLOYEE WHERE Occupation = 'DOCTOR';
Run Code Online (Sandbox Code Playgroud)
如果您对上述内容做了解释计划,您将看到成本高于完整扫描成本.这就是Oracle没有选择使用索引的原因.
考虑指数计划成本的简单方法是: -
对于索引中匹配的记录,必须随后读取的表块数.这取决于甲骨文对拥有"医生"职业的员工人数的估计.在您的简单示例中,这将是:
行数/不同值的数量
更复杂的考虑因素包括聚类工厂和索引成本调整,它们都反映了读取的块已经存储在内存中的可能性,因此不需要从磁盘读取.
也许您可以使用索引提示的查询结果以及此查询的结果更新您的问题: -
SELECT COUNT(*), COUNT(DISTINCT( Occupation ))
FROM EMPLOYEE;
Run Code Online (Sandbox Code Playgroud)
这将允许人们评论指数计划的成本.