12、表的访问方式(索引)_2

news/2024/12/25 13:33:07/文章来源:https://www.cnblogs.com/xgq20210831/p/18558478

表的访问方式

以t1表为例来看表的访问方式
首先创建了一个用户,建立了一张表t1,按照object_id列排序的:

SQL> create user u1 identified by u1;    -- 创建用户u1
User created.SQL> grant connect,resource,dba to u1;   -- 给u1授权
Grant succeeded.SQL> connect u1/u1    -- 连接用户u1
Connected.SQL> create table t1 as select * from dba_objects order by object_id;   -- 创建t1表
Table created.SQL> exec dbms_stats.gather_table_stats('U1','T1');     -- 收集t1表的统计信息
PL/SQL procedure successfully completed.SQL>

查询t1表的统计信息:
1、t1表的块数:

select * from dba_tables s where s.table_name='T1';


占1261个块

2、object_id列的唯一值数量:

select * from dba_tab_columns a where a.OWNER='U1' and a.TABLE_NAME='T1';


object_id列有86315个唯一值

对于一个表,我们收集完统计信息以后,关注的几个东西:
1、表的行数
2、表的块数
3、重点列的唯一值的数量

查询从t1表里取object_id = 150的数据SQL语句的执行计划(无索引,全表扫描):

SQL> set autotrace trace
SQL> set linesize 150
SQL> set pagesize 0SQL> select * from t1 where object_id = 150;Execution Plan   -- 语句select * from t1 where object_id = 150;的执行计划
----------------------------------------------------------
Plan hash value: 3617692013--------------------------------------------------------------------------
| Id  | Operation	      | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |	     |     1 |    98 |   344   (1)| 00:00:05 |
|*  1 |  TABLE ACCESS FULL| T1      |     1 |    98 |   344   (1)| 00:00:05 | --TABLE ACCESS FULL:全表扫描,因为没有索引,所以只能全表扫描
--------------------------------------------------------------------------Predicate Information (identified by operation id):
---------------------------------------------------1 - filter("OBJECT_ID"=150)    -- 过滤条件Statistics
----------------------------------------------------------18  recursive calls0  db block gets1244  consistent gets   -- 内存读0  physical reads    -- 物理读0  redo size1625  bytes sent via SQL*Net to client524  bytes received via SQL*Net from client2  SQL*Net roundtrips to/from client2  sorts (memory)0  sorts (disk)1  rows processedSQL> /   -- 再次执行一下Execution Plan
----------------------------------------------------------
Plan hash value: 3617692013--------------------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      |     1 |    98 |   344   (1)| 00:00:05 |
|*  1 |  TABLE ACCESS FULL| T1    |     1 |    98 |   344   (1)| 00:00:05 |
--------------------------------------------------------------------------Predicate Information (identified by operation id):
---------------------------------------------------1 - filter("OBJECT_ID"=150)Statistics
----------------------------------------------------------0  recursive calls0  db block gets1235  consistent gets1232  physical reads0  redo size1625  bytes sent via SQL*Net to client523  bytes received via SQL*Net from client2  SQL*Net roundtrips to/from client0  sorts (memory)0  sorts (disk)1  rows processed

在t1表的object_id列上建一个索引:

SQL> create index i_t1_id on t1(object_id);
Index created.

建完索引之后,再次统计一下t1表的信息:

SQL> exec dbms_stats.gather_table_stats('U1','T1');    -- 再次收集t1表的统计信息

查询t1表关于索引的相关信息:

select * from dba_indexes s where s.table_name='T1' and s.owner='U1';


索引的叶子数量191,唯一值数量86315

查询索引在哪个列上:

select * from dba_ind_columns x where x.table_name='T1' and x.table_owner='U1';

查询t1表索引的集群因子:

select * from dba_indexes s where s.table_name='T1' and s.owner='U1';


集群因子:1233

关于索引需要关注的几个东西:
1、唯一值的数量
2、集群因子

查询有索引时从t1表里取object_id = 150的数据SQL语句的执行计划(走索引):

SQL> set autotrace trace
SQL> set linesize 150
SQL> set pagesize 0SQL> select * from t1 where object_id = 150;Execution Plan
----------------------------------------------------------
Plan hash value: 1111474805---------------------------------------------------------------------------------------
| Id  | Operation		            | Name    | Rows  | Bytes | Cost (%CPU)| Time  |
---------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT	      |	    |     1 |    98 |     2(0)| 00:00:01 |
|   1 |  TABLE ACCESS BY INDEX ROWID| T1      |     1 |    98 |     2(0)| 00:00:01 |    -- 先访问索引之后,在通过INDEX ROWID访问表
|*  2 |   INDEX RANGE SCAN	      | I_T1_ID |     1 |       |     1(0)| 00:00:01 |    -- INDEX RANGE SCAN:走索引了
---------------------------------------------------------------------------------------Predicate Information (identified by operation id):
---------------------------------------------------2 - access("OBJECT_ID"=150)Statistics
----------------------------------------------------------0  recursive calls0  db block gets4  consistent gets    -- 内存读从原来全表扫描的1244降低到4了0  physical reads0  redo size1628  bytes sent via SQL*Net to client524  bytes received via SQL*Net from client2  SQL*Net roundtrips to/from client0  sorts (memory)0  sorts (disk)1  rows processed

查询从t1表里取object_id 1到8000的数据SQL语句的执行计划(走索引):

SQL> select * from t1 where object_id between 1 and 8000;
7960 rows selected.Execution Plan
----------------------------------------------------------
Plan hash value: 1111474805---------------------------------------------------------------------------------------
| Id  | Operation		            | Name    | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT	      |	    |  7879 |   754K|   132(0)| 00:00:02 |
|   1 |  TABLE ACCESS BY INDEX ROWID| T1      |  7879 |   754K|   132(0)| 00:00:02 |
|*  2 |   INDEX RANGE SCAN	      | I_T1_ID |  7879 |       |    19(0)| 00:00:01 |    -- 走的还是索引
---------------------------------------------------------------------------------------Predicate Information (identified by operation id):
---------------------------------------------------2 - access("OBJECT_ID">=1 AND "OBJECT_ID"<=8000)Statistics
----------------------------------------------------------1  recursive calls0  db block gets1173  consistent gets     -- 内存读:11730  physical reads0  redo size838468  bytes sent via SQL*Net to client6354  bytes received via SQL*Net from client532  SQL*Net roundtrips to/from client0  sorts (memory)0  sorts (disk)7960  rows processed

建另外一张表:t2表,按照object_name排序的

SQL> create table t2 as select * from dba_objects order by object_name;
Table created.

在t2表的object_id列上建一个索引:

SQL> create index i_t2_id on t2(object_id);
Index created.

收集t2表的统计信息:

SQL> exec dbms_stats.gather_table_stats('U1','T2');
PL/SQL procedure successfully completed.

查询t2表索引的集群因子:

select * from dba_indexes s where s.table_name='T2' and s.owner='U1';


集群因子:46382,相对于t1表的1233来说,这个集群因子就很大了,这个索引就不是很好了

查询从t2表里取object_id 1到8000的数据SQL语句的执行计划(全表扫描,有索引,但是没有走索引):

SQL> select * from t2  where object_id between 1 and 8000;
7960 rows selected.Execution Plan
----------------------------------------------------------
Plan hash value: 1513984157--------------------------------------------------------------------------
| Id  | Operation	      | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |	     |  7879 |   754K|   344   (1)| 00:00:05 |
|*  1 |  TABLE ACCESS FULL| T2          |  7879 |   754K|   344   (1)| 00:00:05 |  -- 全表扫描
--------------------------------------------------------------------------Predicate Information (identified by operation id):
---------------------------------------------------1 - filter("OBJECT_ID"<=8000 AND "OBJECT_ID">=1)Statistics
----------------------------------------------------------1  recursive calls0  db block gets1762  consistent gets    -- 内存读:17620  physical reads0  redo size452436  bytes sent via SQL*Net to client6354  bytes received via SQL*Net from client532  SQL*Net roundtrips to/from client0  sorts (memory)0  sorts (disk)7960  rows processed

查询从t2表里取object_id 1到8000的数据SQL语句的执行计划(强制走索引):

SQL> select /*+ index(t2,i_t2_id) */ * from t2 where object_id between 1 and 8000;
7960 rows selected.Execution Plan
----------------------------------------------------------
Plan hash value: 3661687773---------------------------------------------------------------------------------------
| Id  | Operation		    | Name    | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT	        |	    |  7879 |   754K|  4254(1)| 00:00:52 |
|   1 |  TABLE ACCESS BY INDEX ROWID| T2      |  7879 |   754K|  4254(1)| 00:00:52 |
|*  2 |   INDEX RANGE SCAN	        | I_T2_ID |  7879 |       |    19(0)| 00:00:01 |
---------------------------------------------------------------------------------------Predicate Information (identified by operation id):
---------------------------------------------------2 - access("OBJECT_ID">=1 AND "OBJECT_ID"<=8000)Statistics
----------------------------------------------------------1  recursive calls0  db block gets5750  consistent gets   -- 内存读:57500  physical reads0  redo size838468  bytes sent via SQL*Net to client6354  bytes received via SQL*Net from client532  SQL*Net roundtrips to/from client0  sorts (memory)0  sorts (disk)7960  rows processed

这时候,走索引的效果比全表扫描的效果更差,因为受集群因子的影响

查询从t2表里取object_id = 150的数据SQL语句的执行计划(走了索引):

SQL> select * from t2  where object_id = 150;Execution Plan
----------------------------------------------------------
Plan hash value: 3661687773---------------------------------------------------------------------------------------
| Id  | Operation		            | Name    | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT	      |	    |     1 |    98 |        2(0)| 00:00:01 |
|   1 |  TABLE ACCESS BY INDEX ROWID| T2      |     1 |    98 |        2(0)| 00:00:01 |
|*  2 |   INDEX RANGE SCAN	      | I_T2_ID |     1 |       |        1(0)| 00:00:01 |
---------------------------------------------------------------------------------------Predicate Information (identified by operation id):
---------------------------------------------------2 - access("OBJECT_ID"=150)Statistics
----------------------------------------------------------1  recursive calls0  db block gets4  consistent gets    -- 内存读:40  physical reads0  redo size1628  bytes sent via SQL*Net to client524  bytes received via SQL*Net from client2  SQL*Net roundtrips to/from client0  sorts (memory)0  sorts (disk)1  rows processed

访问一行,原来是4,现在也是4,访问一行数据时走索引还不错

arraysize参数
每次返回给用户数据行数的限制

查询arraysize大小:

SQL> show arraysizearraysize 15

一般情况:全表扫描最大的内存读取量不会超过表的总的block的数量,但是由于参数arraysize(每次读取返回给用户数据的行数)的设置,可能一个块要读取多次,比如一个块有100行数据,arraysize的大小设置为了25,一个块就要读取4次了

在程序里面叫做:FetchSize
JAVA程序:(设置fetch size)

public class FetchSize {static final String driver_class  = "oracle.jdbc.driver.OracleDriver";static final String connectionURL = "jdbc:oracle:thin:@linux1:1521:orcl1";static final String userID        = "scott";static final String userPassword  = "tiger";public FetchSize() {}public void runTest() {Connection  con = null;Statement   stmt = null;ResultSet   rset = null;String      query_string = "SELECT * FROM tables WHERE rownum < 200 ORDER BY owner, table_name";int         newFetchSize = 50;try {System.out.println("+-------------------------------+");System.out.println("| SETUP CONNECTION              |");System.out.println("+-------------------------------+");System.out.println("Loading JDBC Driver  -> " + driver_class);Class.forName (driver_class).newInstance();System.out.println("Connecting to        -> " + connectionURL);con = DriverManager.getConnection(connectionURL, userID, userPassword);System.out.println("Connected as         -> " + userID);System.out.println("Turning Off AutoCommit...");con.setAutoCommit(false);/***  EXECUTE GENERIC QUERY*/System.out.println("+-------------------------------+");System.out.println("| EXECUTE GENERIC QUERY         |");System.out.println("+-------------------------------+");System.out.println("Executing Generic (SYSDATE) Query...");System.out.println("Creating Statement...");stmt = con.createStatement ();System.out.println("Get Default Fetch Size:" + stmt.getFetchSize());System.out.println("Manually Set Default Fetch Size to " + newFetchSize);stmt.setFetchSize(newFetchSize);System.out.println("Get New Fetch Size:" + stmt.getFetchSize());System.out.println("Opening ResultsSet...");rset = stmt.executeQuery (query_string);while (rset.next ()) {System.out.println("  RESULTS            -> " + rset.getString (2));}System.out.println("Closing ResultSet...");rset.close();System.out.println("Closing Statement...");stmt.close();}  catch (SQLException e) {e.printStackTrace();if (con != null) {try {con.rollback();} catch (SQLException e1) {e1.printStackTrace();}}} catch (Exception e) {e.printStackTrace();} finally {if (con != null) {try {System.out.println("+-------------------------------+");System.out.println("| CLOSE DOWN ALL CONNECTIONS    |");System.out.println("+-------------------------------+");System.out.println("Closing down all connections...");con.close();} catch (SQLException e) {e.printStackTrace();}}} // FINALLY}public static void main(String[] args) {FetchSize fetchSize = new FetchSize();fetchSize.runTest();}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/837365.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

第十一课 接口测试之postman11.1

一、介绍postman Postman是一个网页调试工具,也可以调试css、html等 Postman的操作环境 环境:Postman Mac、Windows X32、Windows X64、Linux系统、 postman 浏览器扩展程序、postman chrome应用程序 Postman下载:https://www.postman.com/downloads/ 二、postman安装:略 三…

蠢就是坏,坏就是蠢

如题看着如今的社会乱象,我们不禁想:是什么人让我们的社会变成这样? 我们下面来讨论这个问题。 请注意,我们将阻碍社会发展的反动行为定义为坏的,行使这种行为的人定义为坏人。 而我的观点则如标题所示。 第一种 “蠢” 是自以为是,也就是以为自己无所不知,不认同或忽略…

为什么你的工作总是越忙越乱?答案可能出乎意料!

信息过载与任务混乱:现代职场的隐形敌人信息洪流对现代工作的挑战在现代社会,无论个人还是团队,几乎每天都要面对海量的信息。邮件、聊天工具、项目需求文档,甚至口头传递的信息,都让我们感到“时间不够用,信息处理不过来”。这种现象在企业和团队中尤为严重: 信息分散:…

CF1102(*^▽^*)

红黄橙黄绿绿,已完成A.Integer Sequence Dividing CF原题链接 题目大意: 给出\(n\),要求把序列\(1,2,…,n\)分成两个集合,输出两个集合的和的最小差值。\((1\leqslant n\leqslant 2\times 10^{9})\) 解题思路: 我们坚信它是可以分成我们想要的两个差值最小的集合的 差值一…

Qt - 多线程之线程的开始、暂停、恢复、停止

示例1 在Qt中,可以使用QThread的线程控制功能来暂停和恢复一个线程。这里是一个简单的例子:#include <QThread> #include <QDebug>class WorkerThread : public QThread {void run() override {qDebug() << "Thread is running";// 执行一些任务…

linux学习day03_linux文件与目录管理

1、相对路径和绝对路径的区别 绝对路径:路径的写法“一定由根目录 / 写起”,例如: /usr/share/doc 这个目录。相对路径:路径的写法“不是由 / 写起”,例如由 /usr/share/doc 要到 /usr/share/man 下面 时,可以写成: “cd ../man”这就是相对路径的写法啦!相对路径意指“…

我为什么要舍弃CSDN改用博客园

作为博客园老用户,我希望更加积极的在博客园分享技术而非CSDN,因为CSDN没有开放性,什么都要审核着实很烦! 下面是我在CSDN十余年耕耘,仅收获了一堆无用的破勋章和一万多粉丝,因为不怎么回消息答疑铁粉很少。下面是我跟CSDN在线客服的对话: 下面是客服回复给我的原文:抱…

Qt - 多线程之线程同步

一、线程为什么要同步 使用两个线程对一个全局变量做累加,从0加到10,所以只要每个线程累加到5就行。代码如下所示: #include <QApplication> #include <QThread> #include <QDebug>// 定义共享资源 int sharedValue = 0;// 定义一个线程类 class MyThread…

el-input 输入框加%号后缀

<el-input><i slot="suffix">%</i> </el-input> 如图学如逆水行舟,不进则退

人工智能之机器学习线代基础——克拉默法则(Cramers Rule)

克拉默法则是一种用于解 线性方程组 的方法,适用于系数矩阵为 方阵 的情况(即未知数的个数与方程的个数相等)。它通过计算行列式直接求解方程组的解。 克拉默法则的优缺点 优点直接性:可以显式地通过行列式计算出解。 理论价值:适合小规模问题,易于理解和验证解的正确性…

CommonsBeanUtils1(基于ysoserial)

环境准备 JDK1.8(8u421) JDK8的版本应该都没什么影响,这里直接以我的镜像为准了、commons-beanutils:commons-beanutils:1.9.2、commons-collections:commons-collections:3.2、javassist:javassist:3.12.0.GA mvn中加入以下依赖: <dependency><groupId>commons-…

【Mastercam 2025下载与安装教程 含补丁】

mastercam 2025是一款专门用于数控加工的软件,广泛应用于航空、汽车、机械制造等领域可以帮助工程师、机械加工师等专业人员高效地进行零件的建模和加工,提高生产效益和质量。 系统要求‌操作系统‌:Windows 7或更高版本,64位操作系统。 ‌处理器‌:CPU频率至少为2GHz。 ‌内…