技術分享 | OceanBase 使用全局索引的必要性

作者:楊濤濤

資深數據庫專家,專研 MySQL 十餘年。擅長 MySQL、PostgreSQL、MongoDB 等開源數據庫相關的備份恢復、SQL 調優、監控運維、高可用架構設計等。目前任職於愛可生,爲各大運營商及銀行金融企業提供 MySQL 相關技術支持、MySQL 相關課程培訓等工作。

本文來源:原創投稿

* 愛可生開源社區出品,原創內容未經授權不得隨意使用,轉載請聯繫小編並註明來源。

OceanBase 從索引和主表的關係來講,有兩種索引:局部索引和全局索引。
局部索引等價於我們通常說的本地索引,與主表的數據結構保持一對一的關係。局部索引沒有單獨分區的概念,一般來講,主表的分區方式決定局部索引的分區方式,也就是說假設主表有10個分區,那麼對於每個分區來講,都有一個對應的局部索引。
全局索引區別於局部索引,與主表數據結構保持一對多、多對多的關係,全局索引主要應用於分區表。對於分區表來講,一個非分區全局索引對應主表的多個分區;一個分區全局索引也對應主表的多個分區,同時主表每個分區也對應多個全局索引的索引分區。
引入全局索引的目標就是彌補局部索引在數據過濾上的一些不足,比如避免分區表的全分區掃描,把過濾條件下壓到匹配的表分區中。
針對查詢過濾條件來講,局部索引和全局索引的簡單使用場景總結如下:
1. 帶分區鍵的查詢,適合用局部索引。這也是分區表設計的初衷,以過濾條件來反推分區表的設計。

比如語句:select  * from p1 where id = 9;id 爲分區鍵,可以直接定位到具體的表分區partitions(p9),僅需掃描一行記錄。

<mysql:5.6.25:ytt>explain select  * from p1 where id = 9\G
*************************** 1. row ***************************
Query Plan: ==================================
|ID|OPERATOR |NAME|EST. ROWS|COST|
----------------------------------
|0 |TABLE GET|p1  |1        |46  |
==================================

Outputs & filters: 
-------------------------------------
0 - output([p1.id], [p1.r1], [p1.r2]), filter(nil), 
access([p1.id], [p1.r1], [p1.r2]), partitions(p9)

1 row in set (0.005 sec)

2. 不帶分區鍵的查詢有兩個考慮方向,主要在於能否克服全局索引的缺點:全局索引勢必會帶來查詢的分佈式執行!

(1)表的併發寫不大,可以考慮用全局索引。

(2)表的併發寫很大,用全局索引與否就有待商榷, 可以根據當前的業務模型做個壓力測試,取一個折中點。

比如以下語句, 全局索引 idx_r2_global 基於非分區字段 r2 ,執行計劃如下:算子1需要去底層各個節點分佈式掃描(DISTRIBUTED TABLE SCAN)。
<mysql:5.6.25:ytt>explain select * from p1 where r2 = 30\G
*************************** 1. row ***************************
Query Plan: =============================================================

|ID|OPERATOR               |NAME             |EST. ROWS|COST|
-------------------------------------------------------------

|0 |TABLE LOOKUP           |p1               |101      |395 |

|1 | DISTRIBUTED TABLE SCAN|p1(idx_r2_global)|101      |48  |
=============================================================
...
3. 對於需要在非主鍵、非分區鍵的字段上建立唯一索引的業務來講,可以有兩個考慮方向:

(1)給這個字段創建局部索引,但是需要帶上完整的分區鍵。不推薦這種方式,一來是需要更改過濾條件,增加分區鍵;二來增加索引本身的數據冗餘。

比如在 MySQL 租戶下創建這樣的索引會報錯:

<mysql:5.6.25:ytt>create unique index udx_r1 on p1(r1) local;
ERROR 1503 (HY000): A UNIQUE INDEX must include all columns in the table's partitioning function

如果創建本地索引,則需要加上完整分區鍵:

<mysql:5.6.25:ytt>create unique index udx_r1_local on p1(r1,id) local;
Query OK, 0 rows affected (3.012 sec)
(2)給這個字段創建全局索引,不需要帶上完整的分區鍵。強烈推薦的方式!
<mysql:5.6.25:ytt>create unique index udx_r1_global on p1(r1) global;
Query OK, 0 rows affected (1.950 sec)
本文關鍵字: #全局索引# #本地索引#

文章推薦:

一款功能全面的 MySQL Shell 插件

使用 SQL 語句來簡化 show engine innodb status 的結果解讀

OceanBase 在 Ubuntu 平臺部署

關於SQLE

愛可生開源社區的 SQLE 是一款面向數據庫使用者和管理者,支持多場景審覈,支持標準化上線流程,原生支持 MySQL 審覈且數據庫類型可擴展的 SQL 審覈工具。

SQLE 獲取
類型 地址
版本庫 https://github.com/actiontech/sqle
文檔 https://actiontech.github.io/sqle-docs-cn/
發佈信息 https://github.com/actiontech/sqle/releases
數據審覈插件開發文檔 https://actiontech.github.io/sqle-docs-cn/3.modules/3.7_auditplugin/auditplugin_development.html

提交有效pr,高質量issue,將獲贈面值200-500元(具體面額依據質量而定)京東卡以及愛可生開源社區精美周邊!

更多關於 SQLE 的信息和交流,請加入官方QQ交流羣:637150065...

本文分享自微信公衆號 - 愛可生開源社區(ActiontechOSS)。
如有侵權,請聯繫 [email protected] 刪除。
本文參與“OSC源創計劃”,歡迎正在閱讀的你也加入,一起分享。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章