ORACLE存儲過程獲取索引信息-轉為MySQL索引創建語句
背景:因為在使用DataPipeline做數據同步(oracle到TiDB[語法與MySQL基本一致的數據庫])的時候發現oracle數據庫的索引是沒有被一起同步過來的,在查詢數據的時候會很慢,所以需要手動在TiDB中創建索引,這個就很麻煩啦.... 如果一個一個的手工創建,且oracle那邊沒有辦法直接將索引創建語句導出,表多且每張表的索引也很多,這種情況下,我們還是寫個存儲過程 獲取oracle表的索引信息,在存儲過程里直接拼湊為TiDB(MySQL)的索引創建語句。
關於ORACLE的索引信息:
1.查看當前表的索引信息
select * from user_indexes where table_name='tablename' ; -- 將tablename替換為你的表名就即可 ,也可以不指定表名,直接查詢出所有表的索引信息
2. 根據索引名稱,查詢到表的索引列信息
select * from user_ind_columns where index_name=upper('I1PBASEPAPER'); -- I1PBASEPAPER是上面那條語句查詢出來的 INDEX_NAME 值
3.一條sql語句查詢出索引相關信息 ,將tablename替換為需要的表名即可
select a.index_name , a.table_name , a.column_name ,b.index_type ,b.uniqueness FROM all_ind_columns a, all_indexes b WHERE a.index_name=b.index_name AND a.table_name = upper('tablename') ORDER BY a.table_name, a.index_name, a.column_position ;
4.來咯,上重點啦,存儲過程 取出oracle表中的所有索引並且拼湊為MYSQL的索引創建腳本輸出
思路很簡單,借用上面的查詢索引語句,循環取出我們要的索引信息(索引名稱,索引類型(唯一/非唯一),索引所屬的表名),然后手動拼湊sql即可
需要注意的點:
唯一索引需要單獨判斷
組合索引寫法有點不一樣,需要單獨拼接
先來一段簡單的,看看索引信息(第一段for里面的in (T1APL,tablename2)指定表名信息即可,多張表用逗號分割)
declare begin for curidx in (select index_name,TABLE_NAME from user_indexes where table_name in('T1APL','tablename2')) loop dbms_output.put('索引:【表:'||curidx.TABLE_NAME||', 索引: '||curidx.index_name||', 索引列:'); for curidxcol in (select * from user_ind_columns where index_name=upper(curidx.index_name)) loop dbms_output.put_line(curidxcol.column_name||'】'); end loop; end loop; end;
執行上面的語句,我們會看到類似下面的數據輸出,這里組合索引列輸出會有點亂,下面的腳本會統一整理,這里只做索引基本信息獲取然后迭代出來的演示
5.來咯,放大招啦哈哈哈哈,實實在在的使用的腳本:(你只需要替換你的tablename即可使用啦)
declare idx_cnt int(10) ; -- 用於保存索引列的數量 begin for curidx in (select index_name,table_name,uniqueness from user_indexes where table_name in('tablename','T1APL')) loop select count(*) into idx_cnt from user_ind_columns where index_name=upper(curidx.index_name); if idx_cnt >1 -- 組合索引 then if curidx.uniqueness = 'UNIQUE' then -- 判斷是否為 唯一索引如果是就在創建索引的時候添加 unique 關鍵字 dbms_output.put('ALTER TABLE or_lifepro.'||curidx.table_name||' add '||curidx.uniqueness||' index '||curidx.index_name||' ('); else dbms_output.put('ALTER TABLE or_lifepro.'||curidx.table_name||' add index '||curidx.index_name||'('); end if; for curidxcol in (select * from user_ind_columns where index_name=upper(curidx.index_name)) loop idx_cnt := idx_cnt -1; -- 當前循環每執行一次,變量次數減1 if idx_cnt=0 -- 當前循環為最后一次循環時 使用括號結束索引創建語句 then dbms_output.put_line(curidxcol.column_name||');'); else dbms_output.put(curidxcol.column_name||','); end if; end loop; else -- 單列索引 for curidxcol in (select * from user_ind_columns where index_name=upper(curidx.index_name)) loop if curidx.uniqueness = 'UNIQUE' then -- 判斷是否為 唯一索引如果是就在創建索引的時候添加 unique 關鍵字 dbms_output.put_line('ALTER TABLE or_lifepro.'||curidx.table_name||' add '||curidx.uniqueness||' index '||curidx.index_name||'('||curidxcol.column_name||');'); else dbms_output.put_line('ALTER TABLE or_lifepro.'||curidx.table_name||' add index '||curidx.index_name||'('||curidxcol.column_name||');'); end if; end loop; end if; end loop; end;
在PLSQL里面執行腳本(注意這個腳本中我添加了庫名前綴 or_lifepro[這是我TiDB里面的庫名],可以看自己喜好選擇修改為你的庫名或者刪除哦)
執行結果如下圖:我們可以看到這里的組合索引都是正常的輸出哦,且唯一索引也都加了UNIQUE關鍵字
到這里我們的ORACLE索引轉換為MySQL就執行完了,接下來將輸出里面的內容復制到MySQL數據庫中執行一遍即可啦!!!
關於MySQL的索引信息
1.mysql查看表索引語句
show index from tablename;
2.添加索引
ALTER table table_name ADD INDEX index_name (column1,column2,column3); -- 添加組合索引
ALTER table table_name ADD INDEX index_name (columnname); -- 添加普通索引
ALTER table table_name ADD UNIQUE INDEX index_name (columnname); -- 添加唯一索引
3.分析表,使得索引生效
analyze table tablename;
4.批量刪除mysql表索引
先將表索引信息刪除語句拼湊好,執行如下sql,更改你的tablename即可
SELECT i.TABLE_NAME, i.COLUMN_NAME, i.INDEX_NAME, CONCAT('ALTER TABLE ',i.TABLE_NAME,' DROP INDEX ',i.INDEX_NAME,' ;') FROM INFORMATION_SCHEMA.STATISTICS i where i.TABLE_NAME='tablename' ;