Oracle同義詞、索引、分區

同義詞:是現有對象的一個別名數據庫

  1. 簡化SQL語句
  2. 隱藏對象的名稱和全部者
  3. 提供對對象的公共訪問

同義詞共有兩種類型數組

  1. 私有同義詞只能在其模式內訪問,且不能與當前模式的對象同名
  2. 公有同義詞可被全部的數據庫用戶訪問

Oracle同義詞使用注意事項安全

  • 使用同義詞前,要得到同義詞對應對象的訪問權限
  • 同名狀況
  1. 對象與私有同義詞不能同名
  2. 對象與共有同義詞同名時,數據庫優先選擇對象做爲目標
  3. 私有同義詞與共有同義詞同名時,數據庫優先選擇私有同義詞做爲目標

 

/*
===========================================================
|          將訪問員工表的權限授予A_oe用戶
============================================================
*/   
GRANT SELECT ON employee TO A_oe;


--以A_oe用戶登陸   
SELECT * FROM A_hr.employee;

--是否有更好的解決方案?

 

/*
===========================================================
|         在訂單表中,只容許當前員工查看本身的訂單記錄
============================================================
*/
--當前用戶A_oe
--得到create view權限

CREATE OR REPLACE VIEW v_myOrders
AS
SELECT * 
  FROM orders 
 WHERE sales_rep_id=(SELECT empno
                       FROM employee 
                      WHERE ename=(SELECT USER FROM dual));

SELECT * FROM v_myOrders;

 

/*
===========================================================
|         在員工表中,普通職員只容許看姓名、部門列
============================================================
*/
--當前用戶A_hr
CREATE OR REPLACE VIEW v_employee
AS
SELECT empno,ename,e.deptno,dname 
  FROM employee e INNER JOIN dept d 
    ON e.deptno=d.deptno;

 

/*
===========================================================
|          建立私有同義詞
============================================================
*/
CREATE OR REPLACE SYNONYM emp FOR employee;
/*
===========================================================
|          建立公有同義詞
============================================================
*/     
CREATE PUBLIC SYNONYM employee FOR A_hr.employee;

GRANT SELECT ON employee TO A_oe;   
----以A_oe用戶登陸   
--SELECT * FROM A_hr.employee;
SELECT * FROM employee;
/*
===========================================================
|          刪除同義詞
============================================================
*/   
DROP SYNONYM emp; 
DROP PUBLIC SYNONYM employee; 
/*
===========================================================
|          其餘用戶均可以訪問A_hr用戶下的employee表
============================================================
*/   
GRANT SELECT ON A_hr.employee TO public;
CREATE PUBLIC SYNONYM employee FOR A_hr.employee;
--以其餘用戶登陸
SELECT * FROM employee;

 

索引less

  • 索引是與表關聯的可選結構,一種快速訪問數據的途徑
  • 索引分類

1.B樹索引:標準索引,默認是爲非惟一索引函數

1.2.性能

--建立B樹索引
CREATE INDEX idx_emp_department
       ON employee(deptno);

 

2.反向鍵索引:一般創建在值連續增加的列上測試

  與常規B樹索引相反,反向鍵索引在保持列順序的同時反轉索引列的字節spa

 

/*
===========================================================
|          爲employee表建立索引
============================================================
*/
-- 主鍵列建立反向鍵索引
CREATE UNIQUE INDEX idx_empno ON employee(empno) REVERSE;

ALTER TABLE employee 
ADD CONSTRAINT PK_empno 
               PRIMARY KEY(empno) USING INDEX ix_empno;

3.位圖索引:適用於低基數列3d

  使用bitmap數組進行存儲日誌

 

--建立位圖索引
CREATE BITMAP INDEX idx_emp_job
       ON employee(job);

 

索引管理

  • 將正常索引修改爲反向鍵索引:加上PEBUILD NOREVERSE;
  • 將反向鍵索引修改爲正常索引:加上PEBUILD REVERSE;
  • 正常狀況下,通常用ALTER INDEX index_reverse_empno REBUILD;

 

--建立組合索引
CREATE INDEX idx_emp_name
       ON employee(last_name,first_name);

 

/*
===========================================================
|          主鍵列建立反向鍵索引
============================================================
*/
CREATE UNIQUE INDEX idx_empno ON employee(empno) REVERSE;

ALTER TABLE employee ADD CONSTRAINT PK_empno PRIMARY KEY(empno) USING INDEX idx_empno;

select * FROM employee WHERE empno=7900;

 

  • 頻繁搜索、排序、分組的列能夠做爲索引
  • 常常用做鏈接的列(主鍵、外鍵)可做爲索引
  • 將索引放在一個單獨的表空間中
  • 使用NOLOGGING子句可減小日誌信息
  • 按期重建索引
  • 僅包含幾個不一樣值的列建議使用位圖索引
  • 不要在僅包含幾行的表中建立索引

 

什麼時候刪除索引?

  (1)應用程序再也不須要索引

  (2)執行批量加載前

  (3)索引已損壞

什麼時候重建索引?

  (1)表遷移至新表空間後

  (2)索引中已包含不少已刪除項

  (3)需將現有的正常索引轉換成反向鍵索引

 分區表

  • 容許用戶將一個表分紅多個分區
  • 用戶能夠執行查詢,只訪問表中的特定分區
  • 將不一樣的分區存儲在不一樣的磁盤,提升訪問性能和安全性
  • 能夠獨立地備份和恢復每一個分區

範圍分區:以表中的一個列或一組列的值的範圍分區

間隔分區:實現範圍分區的自動化(在11g纔出現的)

  • INTERVAL表明「間隔」,按照後面括號中的低谷已間隔添加分區
  • NUMTOYMINTERVAL(n,'interval_unit')函數
  1. 將n轉換成interval_unit所指定的值
  2. inter_unit能夠爲:YEAR,MONTH
  • 表分區容許將一個表劃分紅幾部分,以改善大型應用系統的性能
  • 表分區對用戶是透明的,即應用程序能夠不知道表已被分區

 1.建立範圍分區

/*
===========================================================
|          建立範圍分區表
============================================================
*/
CREATE TABLE sales_range1
(sales_id   NUMBER NOT NULL,
 product_id   VARCHAR2(5),
 sales_date   DATE,
 sales_cost   NUMBER(10),
 areacode    VARCHAR2(5)
)
partition by range(sales_date)
(partition part1 values less than (to_date('2011/01/01','yyyy/mm/dd')) TABLESPACE tp_orders,
 partition part2 values less than (to_date('2012/01/01','yyyy/mm/dd')),  
 partition part3 values less than (to_date('2013/01/01','yyyy/mm/dd')),  
 partition part4 values less than (to_date('2014/01/01','yyyy/mm/dd'))
);

 

--查詢分區狀況
SELECT table_name,partition_name 
  FROM user_tab_partitions 
 WHERE table_name=UPPER('sales_range1');

 

--插入數據
insert into sales_range1 values (1000,'p1',to_date('2011-01-01','yyyy-mm-dd'),1000,'A1');

 

--查詢數據

select * from sales_range1 PARTITION (part2);

2.分區表的管理

/*
===========================================================
|          分區表的管理
============================================================
*/

--查詢分區狀況
SELECT table_name,partition_name 
  FROM user_tab_partitions 
 WHERE table_name=UPPER('sales_range1');

SELECT * FROM sales_range1 PARTITION (part1);--11前
SELECT * FROM sales_range1 PARTITION (part2);--12前
SELECT * FROM sales_range1 PARTITION (part3);--13前
SELECT * FROM sales_range1 PARTITION (part4);--14前

 

--插入數據
INSERT INTO sales_range1 VALUES (2000,'p1',to_date('2014-01-01','yyyy-mm-dd'),1000,'A1');

 

--添加分區
ALTER TABLE sales_range1 ADD PARTITION part5 VALUES LESS THAN (to_date('2015-01-01','yyyy-mm-dd'));
ALTER TABLE sales_range1 ADD PARTITION part6  VALUES LESS THAN (MAXVALUE);

SELECT * FROM sales_range1 PARTITION (part5);--15前

 

--刪除分區
ALTER TABLE sales_range1 DROP PARTITION part5  

SELECT * FROM sales_range1 WHERE sales_id=2000;

 

--移動分區
ALTER TABLE sales_range1 MOVE PARTITION part1 TABLESPACE tp_sales_bak;
--表空間只讀後測試插入數據,失敗。
INSERT INTO sales_range1 VALUES (3000,'p1',to_date('2009-01-01','yyyy-mm-dd'),1000,'A1');

 

--表空間
CREATE TABLESPACE tp_sales_bak 
       DATAFILE 'd:\data\tp_sales_bak.dbf' SIZE 100M;      
ALTER USER A_oe QUOTA UNLIMITED ON tp_sales_bak;

 

--移動完表空間後將表空間設置爲只讀
ALTER TABLESPACE tp_sales_bak READ ONLY;

ALTER TABLESPACE tp_sales_bak READ WRITE;

3.間隔分區表

/*
===========================================================
|          間隔分區表
============================================================
*/
CREATE TABLE sales_interval1
(sales_id   NUMBER NOT NULL,
 product_id   VARCHAR2(5),
 sales_date   DATE,
 sales_cost   NUMBER(10),
 areacode    VARCHAR2(5)
)
PARTITION BY RANGE(sales_date)
INTERVAL(NUMTOYMINTERVAL(1,'YEAR'))
(PARTITION part1 VALUES LESS THAN (to_date('2011/01/01','yyyy/mm/dd')))

 

--查詢分區狀況
SELECT table_name,partition_name,tablespace_name 
FROM user_tab_partitions 
WHERE table_name=UPPER('sales_interval1');

INSERT INTO sales_interval1 VALUES (1000,'p1',SYSDATE,2000,'A2');

SELECT * FROM sales_interval1 PARTITION (SYS_P142);

 

--現有表建立新表
CREATE TABLE sales_interval2
PARTITION BY RANGE(sales_date)
INTERVAL(NUMTOYMINTERVAL(1,'YEAR'))
(PARTITION part1 VALUES LESS THAN (to_date('2011/01/01','yyyy/mm/dd')))
AS SELECT * FROM sales;

4.現有表建立範圍分區表

/*
===========================================================
|          現有表建立範圍分區表
============================================================
*/

CREATE TABLE sales
(sales_id   NUMBER NOT NULL,
 product_id   VARCHAR2(5),
 sales_date   DATE,
 sales_cost   NUMBER(10),
 areacode    VARCHAR2(5)
)

CREATE TABLE sales_range2
partition by range(sales_date)
(partition part1 values less than (to_date('2011/01/01','yyyy/mm/dd')),
 partition part2 values less than (to_date('2012/01/01','yyyy/mm/dd')),  
 partition part3 values less than (to_date('2013/01/01','yyyy/mm/dd')),  
 partition part4 values less than (to_date('2014/01/01','yyyy/mm/dd'))
)
as select * from sales;

--問題1 2014/01/01的數據落在哪一個分區?
--問題2 2015年的數據落在哪一個分區?

--2個解決辦法:一個是添加分區;一個是建立間隔分區

相關文章
相關標籤/搜索