oracle联合主键 索引,关于复合主键查询时使用索引研究
當數據庫創建表時,每個表只能有一個主鍵,但是如果想讓多個列都成為主鍵時,就要用到復合主鍵。
一、主鍵唯一約束
我們知道當某列為主鍵時,Oracle會自動將此列創建唯一約束。也就是說不允許有相同的值出現。
如:
CREATE TABLE T
(
ID NUMBER,
NAME VARCHAR2(10),
constraint t_pk primary key (ID)
);
table T 已創建。
INSERT INTO T VALUES(1,'A');
1 行已插入。
insert into T VALUES(1,'B');
SQL 錯誤: ORA-00001: 違反唯一約束條件 (TEST.T_PK)
復合主鍵創建的約束指的是不允許三個值都重復的數據插入
如:
CREATE TABLE T
(
ID1 NUMBER,
ID2 NUMBER,
ID3 NUMBER,
NAME VARCHAR2(10),
constraint t_pk primary key (ID1,ID2,ID3)
);
table T 已創建。
INSERT INTO T VALUES(1,1,1,'A');
1 行已插入。
INSERT INTO T VALUES(1,1,2,'B');
1 行已插入。
INSERT INTO T VALUES(1,2,1,'A');
1 行已插入。
INSERT INTO T VALUES(1,1,2,'B');
SQL 錯誤: ORA-00001: 違反唯一約束條件 (TEST.T_PK)
二、主鍵索引
當創建主鍵時Oracle會自動創建索引。
如:
CREATE TABLE T1
(
ID NUMBER,
NAME VARCHAR2(10),
CONSTRAINT T1_PK PRIMARY KEY (ID)
);
...插入部分數據...
SELECT * FROM T1 WHERE id = 10;
查看Oracle的解釋計劃
很明顯Oracle使用了索引來查詢。
而當執行一下查詢時由于沒有索引列,所以使用的是全表掃描查詢。
SELECT * FROM T1 where name = 'A';
SELECT * FROM T1 ;
當創建復合索引時包含全部索引列時Oracle會以索引方式進行查詢。
SELECT * FROM T WHERE ID1 = 2 AND ID2 = 3 AND ID3 = 1;
當條件包含部分索引列時會發生兩種情況。我們重新創建一張表REPOLICYSHARE,向表內插入500000行數據。
CREATE TABLE REPOLICYSHARE
(
POLICYNO?? VARCHAR2(22),
DANGERNO?? NUMBER(8,0),
REPOLICYNO VARCHAR2(22) NOT NULL,
STARTDATE DATE,
CLASSCODE???? VARCHAR2(4),
RISKCODE????? VARCHAR2(4),
COMCODE?????? VARCHAR2(10) NOT NULL,
REINSMODE???? VARCHAR2(3) NOT NULL,
TREATYNO????? VARCHAR2(10) NOT NULL,
TREATYSECTION VARCHAR2(12),
SHARERATE???? NUMBER(9,6),
CURRENCY????? VARCHAR2(3),
REAMOUNT????? NUMBER(14,2),
REPREMIUM???? NUMBER(14,2),
EXCHRATECNY?? NUMBER(12,8),
ACCPAYDATE DATE NOT NULL,
TREATYFLAG VARCHAR2(1) NOT NULL,
PAYDATE DATE NOT NULL,
STATDATE DATE,
CONSTRAINT PK_MID_R_REPOLICYSHARE PRIMARY KEY (REPOLICYNO,
COMCODE, TREATYNO, ACCPAYDATE, PAYDATE, TREATYFLAG,
CURRENCY)
);
由建表語句我們能看出此表的所因為復合索引,并且由REPOLICYNO, COMCODE, TREATYNO, ACCPAYDATE, PAYDATE, TREATYFLAG, CURRENCY等列構成。
當where條件包含REPOLICYNO, COMCODE, TREATYNO列時。使用的是索引查詢。
SELECT POLICYNO
FROM REPOLICYSHARE
WHERE REPOLICYNO = 'PO0520062458001329'
AND COMCODE????? = '2458800605'
AND TREATYNO???? = 'OP2006ZL';
當where條件包含COMCODE, TREATYNO列時。使用的是全表掃描查詢。
SELECT POLICYNO
FROM REPOLICYSHARE
WHERE COMCODE????? = '2458800605'
AND TREATYNO???? = 'OP2006ZL';
為什么同樣是部分列,但查詢形式卻不一樣呢?
這是因為復合索引實用的條件為當where條件中存在復合索引的第一列時,才使用索引。也就是說第二個查詢語句中沒有包含REPOLICYNO所以Oracle沒有使用復合索引。至于為什么必須有第一列,個人認為由于Oracle默認是使用B*樹索引,而B樹的復合索引指向的是第一列的元素索引,如果不包括第一列則無法找到索引源頭從而無法使用索引。
如上圖所示,如果不包含第一列則Oracle無法找到索引的start位置進而無法使用索引。
三、使用什么樣的索引
我們可以從前幾個查詢語句看出索引對于查詢速度的重要性。
所以要想使
SELECT POLICYNO
FROM REPOLICYSHARE
WHERE COMCODE????? = '2458800605'
AND TREATYNO???? = 'OP2006ZL';
語句查詢更快,就要建立索引。
但是問題也出現了,是創建復合索引查詢更快,還是還是單獨建立索引查詢更快,還是一樣快呢?
首先我們為每個列創建索引
CREATE INDEX INX_REPOLICYSHARE_COMCODE ON REPOLICYSHARE(COMCODE);
CREATE INDEX INX_REPOLICYSHARE_TREATYNO ON REPOLICYSHARE(TREATYNO);
然后執行SQL語句查看執行時間,并查看Oracle的解釋計劃。
提取50行的運行時間為:0.452秒
解釋計劃:
刪除剛剛建立的索引并創建復合索引。
DROP INDEX INX_REPOLICYSHARE_COMCODE;
DROP INDEX INX_REPOLICYSHARE_TREATYNO;
CREATE INDEX INX_REPOLICYSHARE ON REPOLICYSHARE(COMCODE,TREATYNO);
然后執行SQL語句查看執行時間,并查看Oracle的解釋計劃。
提取50行的運行時間為:0.067秒
解釋計劃:
結果很明顯,復合索引要快于單獨建立索引。
總結
以上是生活随笔為你收集整理的oracle联合主键 索引,关于复合主键查询时使用索引研究的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 非好学校科班出身的程序员,该如何快速提升
- 下一篇: word2vec学习+使用介绍