【问题标题】:What is the difference between defining the index as a primary key or in the CREATE INDEX clause?将索引定义为主键或在 CREATE INDEX 子句中有什么区别?
【发布时间】:2018-04-16 09:47:44
【问题描述】:

我正在测试一个包含 5 亿条记录的表的查询。 ID_COMPANY 字段只有值 1(5 亿条记录)。

SQL定义如下:

CREATE TABLE "BIDATA"."CSC_CUSTOMER_PREPAID_BALANCE" 
(   "ID_COMPANY" VARCHAR2(10 BYTE),
    "SEQUENTIAL_MOV" NUMBER(10,0),
    "ID_PAYMENT" NUMBER(10,0)
CONSTRAINT "PK_CSC_CUSTOMER_PREPAID_BAL" PRIMARY KEY ("ID_COMPANY", "SEQUENTIAL_MOV")
  USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS NOLOGGING 
  STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
  PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1
  BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT)
  TABLESPACE "BIDATA_DATOS"  ENABLE
   ) SEGMENT CREATION IMMEDIATE 
  PCTFREE 10 PCTUSED 0 INITRANS 1 MAXTRANS 255 
 NOCOMPRESS LOGGING
  STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
  PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1
  BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT)
  TABLESPACE "BIDATA_DATOS" ;

例如 ID_PAYMENT 字段的 CREATE INDEX 子句

CREATE INDEX "BIDATA"."IDX_ID_PAYMENT" ON "BIDATA"."CSC_CUSTOMER_PREPAID_BALANCE" ("ID_PAYMENT") 
  PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS 
  STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
  PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1
  BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT)
  TABLESPACE "BIDATA_DATOS" ;

我遇到的问题是,在按定义启动查询时,它似乎没有检测到索引 ID_COMPANY,并且显示结果需要超过 15 分钟,但是如果在 WHERE 子句中的查询中添加 ID_COMPANY = '1',不到 10 秒就会显示结果。

我应该删除索引 ID_COMPANY 并将其定义为 CREATE INDEX 吗? 为什么会出现这种时差?

SQL 查询需要> 10 分钟。

SELECT
   COUNT(*)
FROM
  CSC_CUSTOMER_ACCOUNT,
  CSC_CUSTOMER_PREPAID_BALANCE
WHERE

  AND  ( CSC_CUSTOMER_ACCOUNT.ID_ACCOUNT(+)=CSC_CUSTOMER_PREPAID_BALANCE.ID_ACCOUNT AND CSC_CUSTOMER_ACCOUNT.ID_COMPANY(+)=CSC_CUSTOMER_PREPAID_BALANCE.ID_COMPANY  )
  AND  ( CSC_CUSTOMER_PREPAID_BALANCE.ID_ACCOUNT (+)=CSC_RECHARGE_MOBILE.ID_ACCOUNT AND CSC_CUSTOMER_PREPAID_BALANCE.SEQUENTIAL_MOV(+)=CSC_RECHARGE_MOBILE.SEQUENTIAL_MOV  )

SQL 查询耗时

SELECT
   COUNT(*)
FROM

  CSC_CUSTOMER_ACCOUNT,
  CSC_CUSTOMER_PREPAID_BALANCE
WHERE

  AND  ( CSC_CUSTOMER_ACCOUNT.ID_ACCOUNT(+)=CSC_CUSTOMER_PREPAID_BALANCE.ID_ACCOUNT AND CSC_CUSTOMER_ACCOUNT.ID_COMPANY(+)=CSC_CUSTOMER_PREPAID_BALANCE.ID_COMPANY  )
  AND  ( CSC_CUSTOMER_PREPAID_BALANCE.ID_ACCOUNT (+)=CSC_RECHARGE_MOBILE.ID_ACCOUNT AND CSC_CUSTOMER_PREPAID_BALANCE.SEQUENTIAL_MOV(+)=CSC_RECHARGE_MOBILE.SEQUENTIAL_MOV  )
  AND  CSC_CUSTOMER_PREPAID_BALANCE.ID_COMPANY = '1'

QUERY执行计划>10分钟

Execution plan Query > 10

Execution plan Query < 10 seconds

谢谢。

【问题讨论】:

  • 如果没有 where 子句中的 ID_COMPANY,您的查询(可能)在语义上是错误的,因为架构假定可能有多个。
  • 您能否在查询中添加,在索引使用或表扫描方面,它看起来就像索引字段与谓词一样简单,查询将有助于澄清。
  • 在表中只有一个 ID_COMPANY = 1。我添加了一个示例查询,这个查询耗时不到 10 秒,我只包含在 WHERE 子句 ID_COMPANY = '1' 中,我这样做了不明白为什么添加该指令查询会快速显示记录。
  • 这两个查询的执行计划是什么?请编辑您的问题以添加两者。
  • 我已经添加了执行计划。

标签: sql oracle11g ddl


【解决方案1】:

从我从您的问题中可以推断出,您似乎误解了表的索引规则。理想情况下,您不会为主键创建索引,而是相反。即,当您使用主键创建表时,默认情况下它(主键)被 sql 代理视为聚集索引并相应地创建/存储。 更多关于索引和索引类型here

【讨论】:

  • 问题标记为 Oracle。 Oracle 中的主键索引不是“聚集索引”(Oracle 中最接近的是 IOT),它们是普通的唯一索引。
猜你喜欢
  • 1970-01-01
  • 2013-06-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-08-22
  • 2019-07-03
  • 2015-09-18
相关资源
最近更新 更多