當前位置:首頁 » 數據倉庫 » 雲資料庫數組索引通配符
擴展閱讀
webinf下怎麼引入js 2023-08-31 21:54:13
堡壘機怎麼打開web 2023-08-31 21:54:11

雲資料庫數組索引通配符

發布時間: 2022-11-21 14:04:53

1. mysql索引類型解釋

索引分單列索引和組合索引。單列索引,即一個索引只包含單個列,一個表可以有多個單列索引,但這不是組合索引。組合索引,即一個索包含多個列。
MySQL索引類型包括:
(1)普通索引
這是最基本的索引,它沒有任何限制。它有以下幾種創建方式:
◆創建索引
CREATE INDEX indexName ON mytable(username(length));
如果是 CHAR,VARCHAR類型,length可以小於欄位實際長度;如果是BLOB和TEXT類型,必須指定 length,下同。
◆修改表結構
ALTER mytable ADD INDEX [indexName] ON (username(length))
◆ 創建表的時候直接指定
CREATE TABLE mytable( ID INT NOT NULL, username VARCHAR(16) NOT NULL, INDEX [indexName] (username(length)) );
刪除索引的語法:
DROP INDEX [indexName] ON mytable;
(2)唯一索引
它與前面的普通索引類似,不同的就是:索引列的值必須唯一,但允許有空值。如果是組合索引,則列值的組合必須唯一。它有以下幾種創建方式:
◆創建索引
CREATE UNIQUE INDEX indexName ON mytable(username(length))
◆修改表結構
ALTER mytable ADD UNIQUE [indexName] ON (username(length))
◆創建表的時候直接指定
CREATE TABLE mytable( ID INT NOT NULL, username VARCHAR(16) NOT NULL, UNIQUE [indexName] (username(length)) );
(3)主鍵索引
它是一種特殊的唯一索引,不允許有空值。一般是在建表的時候同時創建主鍵索引:
CREATE TABLE mytable( ID INT NOT NULL, username VARCHAR(16) NOT NULL, PRIMARY KEY(ID) );
當然也可以用 ALTER 命令。記住:一個表只能有一個主鍵。
(4)組合索引
為了形象地對比單列索引和組合索引,為表添加多個欄位:
CREATE TABLE mytable( ID INT NOT NULL, username VARCHAR(16) NOT NULL, city VARCHAR(50) NOT NULL, age INT NOT NULL );
為了進一步榨取MySQL的效率,就要考慮建立組合索引。就是將 name, city, age建到一個索引里:
ALTER TABLE mytable ADD INDEX name_city_age (name(10),city,age);
建表時,usernname長度為 16,這里用 10。這是因為一般情況下名字的長度不會超過10,這樣會加速索引查詢速度,還會減少索引文件的大小,提高INSERT的更新速度。
如果分別在 usernname,city,age上建立單列索引,讓該表有3個單列索引,查詢時和上述的組合索引效率也會大不一樣,遠遠低於我們的組合索引。雖然此時有了三個索引,但MySQL只能用到其中的那個它認為似乎是最有效率的單列索引。
建立這樣的組合索引,其實是相當於分別建立了下面三組組合索引:
usernname,city,age usernname,city usernname
為什麼沒有 city,age這樣的組合索引呢?這是因為MySQL組合索引「最左前綴」的結果。簡單的理解就是只從最左面的開始組合。並不是只要包含這三列的查詢都會用到該組合索引,下面的幾個SQL就會用到這個組合索引:
SELECT * FROM mytable WHREE username="admin" AND city="鄭州" SELECT * FROM mytable WHREE username="admin"
而下面幾個則不會用到:
SELECT * FROM mytable WHREE age=20 AND city="鄭州" SELECT * FROM mytable WHREE city="鄭州"
(5)建立索引的時機
到這里我們已經學會了建立索引,那麼我們需要在什麼情況下建立索引呢?一般來說,在WHERE和JOIN中出現的列需要建立索引,但也不完全如此,因為MySQL只對<,<=,=,>,>=,BETWEEN,IN,以及某些時候的LIKE才會使用索引。例如:
SELECT t.Name FROM mytable t LEFT JOIN mytable m ON t.Name=m.username WHERE m.age=20 AND m.city='鄭州'
此時就需要對city和age建立索引,由於mytable表的 userame也出現在了JOIN子句中,也有對它建立索引的必要。
剛才提到只有某些時候的LIKE才需建立索引。因為在以通配符%和_開頭作查詢時,MySQL不會使用索引。例如下句會使用索引:
SELECT * FROM mytable WHERE username like'admin%'
而下句就不會使用:
SELECT * FROM mytable WHEREt Name like'%admin'
因此,在使用LIKE時應注意以上的區別。
(6)索引的不足之處
上面都在說使用索引的好處,但過多的使用索引將會造成濫用。因此索引也會有它的缺點:
◆雖然索引大大提高了查詢速度,同時卻會降低更新表的速度,如對表進行 INSERT、UPDATE和DELETE。因為更新表時,MySQL不僅要保存數據,還要保存一下索引文件。
◆建立索引會佔用磁碟空間的索引文件。一般情況這個問題不太嚴重,但如果你在一個大表上創建了多種組合索引,索引文件的會膨脹很快。
索引只是提高效率的一個因素,如果你的 MySQL有大數據量的表,就需要花時間研究建立最優秀的索引,或優化查詢語句。
(7)使用索引的注意事項
使用索引時,有以下一些技巧和注意事項:
◆索引不會包含有NULL值的列
只要列中包含有NULL值都將不會被包含在索引中,復合索引中只要有一列含有 NULL值,那麼這一列對於此復合索引就是無效的。所以我們在資料庫設計時不要讓欄位的默認值為NULL。
◆使用短索引
對串列進行索引,如果可能應該指定一個前綴長度。例如,如果有一個CHAR(255)的列,如果在前10個或20個字元內,多數值是惟一的,那麼就不要對整個列進行索引。短索引不僅可以提高查詢速度而且可以節省磁碟空間和I/O操作。
◆索引列排序
MySQL查詢只使用一個索引,因此如果 where子句中已經使用了索引的話,那麼order by中的列是不會使用索引的。因此資料庫默認排序可以符合要求的情況下不要使用排序操作;盡量不要包含多個列的排序,如果需要最好給這些列創建復合索引。
◆like語句操作
一般情況下不鼓勵使用like操作,如果非使用不可,如何使用也是一個問題。like 「%aaa%」 不會使用索引而like 「aaa%」可以使用索引。
◆不要在列上進行運算
select * from users where YEAR(adddate)<2007;
將在每個行上進行運算,這將導致索引失效而進行全表掃描,因此我們可以改成
select * from users where adddate<『2007-01-01』;
◆不使用NOT IN和<>操作
以上,就對其中MySQL索引類型進行了介紹。
轉自:http://www.zbite.com/?action-viewthread-tid-33491

2. 資料庫中怎麼建立索引

1.資料庫中的索引分為兩種類型,分別是普通索引、唯一索引。下面讓我們來分別介紹一下這...
2.第一種是普通索引,CREATE INDEX indexName ON mytable(...
3.第二種是唯一索引,它與普通索引是類似的,但也存在不同之處,不同之處在於索引列的值...
4.以上三張圖分別為創建索引、修改表結構、創建表時直接指定的數據。而且還有四種方式來...
5.第一種方式:ALTER TABLE tbl_name ADD PRIMARY KEY (...

3. 資料庫索引有哪幾種怎樣建立索引

  • 種類:

1、按照索引列值的唯一性,索引可分為唯一索引和非唯一索引;

  • 非唯一索引:

create index 索引名 on 表名(列名) tablespace表空間名;

  • 唯一索引:

建立主鍵或者唯一約束時會自動在對應的列上建立唯一索引;

2、索引列的個數:單列索引和復合索引;

3、按照索引列的物理組織方式。

  • 索引的創建格式:

CREATEUNIUQE|BITMAPINDEX<schema>.<index_name>ON<schema>.<table_name>(<column_name>|<expression>ASC|DESC,<column_name>|<expression>ASC|DESC,...)TABLESPACE<tablespace_name>STORAGE<storage_settings>LOGGING||COMPRESS<nn>NOSORT|REVERSEPARTITION|GLOBALPARTITION<partition_setting>

使用USER_IND_COLUMNS查詢某個TABLE中的相應欄位索引建立情況

使用DBA_INDEXES/USER_INDEXES查詢所有索引的具體設置情況。

在Oracle中的索引可以分為:B樹索引、點陣圖索引、反向鍵索引、基於函數的索引、簇索引、全局索引、局部索引等,下面逐一講解:

一、B樹索引:

最常用的索引,各葉子節點中包括的數據有索引列的值和數據表中對應行的ROWID,簡單的說,在B樹索引中,是通過在索引中保存排過續的索引列值與相對應記錄的ROWID來實現快速查詢的目的。其邏輯結構如圖:

可以保證無論用戶要搜索哪個分支的葉子結點,都需要經過相同的索引層次,即都需要相同的I/O次數。

B樹索引的創建示例:

create index ind_t on t1(id);

注1:索引的針對欄位創建的,相同欄位不能創建一個以上的索引;

注2:默認的索引是不唯一的,但是也可以加上unique,表示該索引的欄位上沒有重復值(定義unique約束時會自動創建);

注3:創建主鍵時,默認在主鍵上創建了B樹索引,因此不能再在主鍵上創建索引。

二、點陣圖索引:

有些欄位中使用B樹索引的效率仍然不高,例如性別的欄位中,只有「男、女」兩個值,則即便使用了B樹索引,在進行檢索時也將返回接近一半的記錄。

所以當欄位的基數很低時,需要使用點陣圖索引。(「低」的標準是取值數量 < 行數*1%)

反向鍵索引是一種特殊的B樹索引,在存儲構造中與B樹索引完全相同,但是針對數值時,反向鍵索引會先反向每個鍵值的位元組,然後對反向後的新數據進行索引。例如輸入2008則轉換為8002,這樣當數值一次增加時,其反向鍵在大小中的分布仍然是比較平均的。

反向鍵索引的創建示例:

createindex ind_t on t1(id) reverse;

註:鍵的反轉由系統自行完成。對於用戶是透明的。

四、基於函數的索引:

有的時候,需要進行如下查詢:select * from t1 where to_char(date,'yyyy')>'2007';

但是即便在date欄位上建立了索引,還是不得不進行全表掃描。在這種情況下,可以使用基於函數的索引。其創建語法如下:

create index ind_t on t1(to_char(date,'yyyy'));

註:簡單來說,基於函數的索引,就是將查詢要用到的表達式作為索引項。

五、全局索引和局部索引:

這個索引貌似很復雜,其實很簡單。總得來說一句話,就是無論怎麼分區,都是為了方便管理。

具體索引和表的關系有三種:

1、局部分區索引:分區索引和分區表1對1

2、全局分區索引:分區索引和分區表N對N

3、全局非分區索引:非分區索引和分區表1對N

創建示例:

首先創建一個分區表

createtable student

(

stuno number(5),

sname vrvhar2(10),

deptno number(5)

)

partition by hash (deptno)

(

partition part_01 tablespace A1,

partition part_02 tablespace A2

);

創建局部分區索引(1v1):

create index ind_t on student(stuno)

local(

partition part_01 tablespace A2,

partition part_02 tablespace A1

);--local後面可以不加

創建全局分區索引(NvN):

create index ind_t on student(stuno)

globalpartition by range(stuno)

(

partition p1 values less than(1000) tablespace A1,

partition p2 values less than(maxvalue) tablespace A2

);--只可以進行range分區

創建全局非分區索引(1vN)

createindex ind_t on student(stuno) GLOBAL;

4. 如何正確合理的建立MYSQL資料庫索引

如何正確合理的建立MYSQL資料庫索引

索引是快速搜索的關鍵。MySQL索引的建立對於MySQL的高效運行是很重要的。下面介紹幾種常見的MySQL索引類型。

在資料庫表中,對欄位建立索引可以大大提高查詢速度。假如我們創建了一個 mytable表:

CREATE TABLE mytable( ID INT NOT NULL, username VARCHAR(16) NOT NULL
); 我們隨機向裡面插入了10000條記錄,其中有一條:5555, admin。

在查找username="admin"的記錄 SELECT * FROM mytable WHERE
username='admin';時,如果在username上已經建立了索引,MySQL無須任何掃描,即准確可找到該記錄。相反,MySQL會掃描所有記錄,即要查詢10000條記錄。

索引分單列索引和組合索引。單列索引,即一個索引只包含單個列,一個表可以有多個單列索引,但這不是組合索引。組合索引,即一個索包含多個列。

MySQL索引類型包括:

(1)普通索引

這是最基本的索引,它沒有任何限制。它有以下幾種創建方式:

◆創建索引

CREATE INDEX indexName ON mytable(username(length));
如果是CHAR,VARCHAR類型,length可以小於欄位實際長度;如果是BLOB和TEXT類型,必須指定 length,下同。

◆修改表結構

ALTER mytable ADD INDEX [indexName] ON (username(length))

◆創建表的時候直接指定

CREATE TABLE mytable( ID INT NOT NULL, username VARCHAR(16) NOT NULL,
INDEX [indexName] (username(length)) ); 刪除索引的語法:

DROP INDEX [indexName] ON mytable;

(2)唯一索引

它與前面的普通索引類似,不同的就是:索引列的值必須唯一,但允許有空值。如果是組合索引,則列值的組合必須唯一。它有以下幾種創建方式:

◆創建索引

CREATE UNIQUE INDEX indexName ON mytable(username(length))

◆修改表結構

ALTER mytable ADD UNIQUE [indexName] ON (username(length))

◆創建表的時候直接指定

CREATE TABLE mytable( ID INT NOT NULL, username VARCHAR(16) NOT NULL,
UNIQUE [indexName] (username(length)) );

(3)主鍵索引

它是一種特殊的唯一索引,不允許有空值。一般是在建表的時候同時創建主鍵索引:

CREATE TABLE mytable( ID INT NOT NULL, username VARCHAR(16) NOT NULL,
PRIMARY KEY(ID) ); 當然也可以用 ALTER 命令。記住:一個表只能有一個主鍵。

(4)組合索引

為了形象地對比單列索引和組合索引,為表添加多個欄位:

CREATE TABLE mytable( ID INT NOT NULL, username VARCHAR(16) NOT NULL,
city VARCHAR(50) NOT NULL, age INT NOT NULL );
為了進一步榨取MySQL的效率,就要考慮建立組合索引。就是將 name, city, age建到一個索引里:

ALTER TABLE mytable ADD INDEX name_city_age (name(10),city,age);
建表時,usernname長度為 16,這里用
10。這是因為一般情況下名字的長度不會超過10,這樣會加速索引查詢速度,還會減少索引文件的大小,提高INSERT的更新速度。

如果分別在
usernname,city,age上建立單列索引,讓該表有3個單列索引,查詢時和上述的組合索引效率也會大不一樣,遠遠低於我們的組合索引。雖然此時有了三個索引,但MySQL只能用到其中的那個它認為似乎是最有效率的單列索引。

建立這樣的組合索引,其實是相當於分別建立了下面三組組合索引:

usernname,city,age usernname,city usernname 為什麼沒有
city,age這樣的組合索引呢?這是因為MySQL組合索引「最左前綴」的結果。簡單的理解就是只從最左面的開始組合。並不是只要包含這三列的查詢都會用到該組合索引,下面的幾個SQL就會用到這個組合索引:

SELECT * FROM mytable WHREE username="admin" AND city="鄭州" SELECT * FROM
mytable WHREE username="admin" 而下面幾個則不會用到:

SELECT * FROM mytable WHREE age=20 AND city="鄭州" SELECT * FROM mytable WHREE
city="鄭州"

(5)建立索引的時機

到這里我們已經學會了建立索引,那麼我們需要在什麼情況下建立索引呢?一般來說,在WHERE和JOIN中出現的列需要建立索引,但也不完全如此,因為MySQL只對<,<=,=,>,>=,BETWEEN,IN,以及某些時候的LIKE才會使用索引。例如:

SELECT t.Name FROM mytable t LEFT JOIN mytable m ON t.Name=m.username
WHERE m.age=20 AND m.city='鄭州'
此時就需要對city和age建立索引,由於mytable表的userame也出現在了JOIN子句中,也有對它建立索引的必要。

剛才提到只有某些時候的LIKE才需建立索引。因為在以通配符%和_開頭作查詢時,MySQL不會使用索引。例如下句會使用索引:

SELECT * FROM mytable WHERE username like'admin%' 而下句就不會使用:

SELECT * FROM mytable WHEREt Name like'%admin' 因此,在使用LIKE時應注意以上的區別。

(6)索引的不足之處

上面都在說使用索引的好處,但過多的使用索引將會造成濫用。因此索引也會有它的缺點:

◆雖然索引大大提高了查詢速度,同時卻會降低更新表的速度,如對表進行INSERT、UPDATE和DELETE。因為更新表時,MySQL不僅要保存數據,還要保存一下索引文件。

◆建立索引會佔用磁碟空間的索引文件。一般情況這個問題不太嚴重,但如果你在一個大表上創建了多種組合索引,索引文件的會膨脹很快。

索引只是提高效率的一個因素,如果你的MySQL有大數據量的表,就需要花時間研究建立最優秀的索引,或優化查詢語句。

(7)使用索引的注意事項

使用索引時,有以下一些技巧和注意事項:

◆索引不會包含有NULL值的列

只要列中包含有NULL值都將不會被包含在索引中,復合索引中只要有一列含有NULL值,那麼這一列對於此復合索引就是無效的。所以我們在資料庫設計時不要讓欄位的默認值為NULL。

◆使用短索引

對串列進行索引,如果可能應該指定一個前綴長度。例如,如果有一個CHAR(255)的列,如果在前10個或20個字元內,多數值是惟一的,那麼就不要對整個列進行索引。短索引不僅可以提高查詢速度而且可以節省磁碟空間和I/O操作。

◆索引列排序

MySQL查詢只使用一個索引,因此如果where子句中已經使用了索引的話,那麼order
by中的列是不會使用索引的。因此資料庫默認排序可以符合要求的情況下不要使用排序操作;盡量不要包含多個列的排序,如果需要最好給這些列創建復合索引。

◆like語句操作

一般情況下不鼓勵使用like操作,如果非使用不可,如何使用也是一個問題。like 「%aaa%」 不會使用索引而like
「aaa%」可以使用索引。

◆不要在列上進行運算

select * from users where YEAR(adddate)<2007;
將在每個行上進行運算,這將導致索引失效而進行全表掃描,因此我們可以改成

select * from users where adddate<『2007-01-01』;

◆不使用NOT IN和<>操作

以上,就對其中MySQL索引類型進行了介紹。

5. wos資料庫的基本使用方法中,通配符*表示什麼意思

應該是和其他資料庫中的用法相同,
「*」為通配符,表示查找FROM中所指出關系的所有屬性的值。

6. 雲上MongoDB常見索引問題及最優索引規則大全

本文干貨較多,建議收藏學習。先將文章結構速覽奉上:

一、背景

二、MongoDB執行計劃

2.1 queryPlanner信息

2.2 executionStats信息

2.3 allPlansExecution信息

三、雲上用戶建索引常見問題及優化方法

3.1 等值類查詢常見問題及優化方法

3.1.1 同一類查詢創建多個索引問題

3.1.2 多欄位等值查詢組合索引順序非最優

3.1.3 最左原則包含關系引起的重復索引

3.1.4 唯一欄位和其他欄位組合引起的無用重復索引

3.2 非等值類查詢常見問題及優化方法

3.2.1 非等值組合查詢索引不合理創建

3.2.2 等值+非等值組合查詢索引欄位順序不合理

3.2.3 不同類型非等值查詢優先順序問題

3.3 OR類查詢常見問題及優化方法

3.3.1 普通OR類查詢優化方法

3.3.2 復雜OR類查詢優化方法

3.4 SORT類排序查詢常見問題及優化方法

3.4.1 單欄位正反序排序查詢引起的重復索引

3.4.2 多欄位排序查詢正反序問題引起索引無效

3.4.3 等值查詢+多欄位排序組合查詢

3.4.4 等值查詢+非等值查詢+SORT排序查詢

3.4.5 OR+SORT組合排序查詢

3.5 無用索引優化方法

四、MongoDB不同類型查詢最優索引總結

騰訊雲MongoDB當前已服務於 游戲 、電商、社交、教育、新聞資訊、金融、物聯網、軟體服務、 汽車 出行、音視頻等多個行業。

騰訊MongoDB團隊在配合用戶分析問題過程中,發現 雲上用戶存在如下索引共性問題 ,主要集中在如下方面:

本文 重點分析總結騰訊雲上用戶索引創建不合理相關的問題 ,通過本文可以學習到MongoDB的以下知識點:

本文總結的 《最優索引規則創建大全》 不僅僅適用於MongoDB,很多規則 同樣適用於MySQL等關系型資料庫

判斷索引選擇及不同索引執行傢伙信息可以通過explain操作獲取, MongoDB通過explain來獲取SQL執行過程信息 ,當前持續explain的請求命令包含以下幾種:

aggregate, count, distinct, find, findAndModify, delete, mapRece, and update。

詳見explain官網鏈接:

https://docs.MongoDB.com/manual/reference/command/explain/

explain可以攜帶以下幾個參數信息,各參數信息功能如下:

2.1 queryPlanner信息

獲取MongoDB查詢優化器選擇的最優索引和拒絕掉的非最優索引,並給出各個候選索引的執行階段信息,queryPlanner輸出信息如下:

queryPlanner輸出主要包括如下信息:

parsedQuery信息

內核對查詢條件進行序列化,生成一棵expression tree信息,便於候選索引查詢匹配。

winningPlan信息

rejectedPlans信息

輸出信息和winningPlan類似,記錄這些拒絕掉索引的執行stage信息。

2.2 executionStats信息

explain的executionStats參數除了提供上面的queryPlanner信息外,還提供了最優索引的執行過程信息,如下:

上面是通過executionStats獲取執行過程的詳細信息,其中欄位信息較多,平時分析索引問題最常用的幾個欄位如下:

executionStats輸出欄位較多,其他欄位將在後續《MongoDB內核index索引模塊實現原理》中進行進一步說明。

在實際分析索引問題是否最優的時候,主要查看以下三個統計項:

executionStats.totalKeysExamined

executionStats.totalDocsExamined

executionStats .nReturned

如果存在以下情況則說明索引存在問題,可能索引不是最優的:

1. executionStats.totalKeysExamine遠大於executionStats .nReturned

2. executionStats. totalDocsExamined遠大於executionStats .nReturned

2.3 allPlansExecution信息

allPlansExecution參數對應輸出信息和executionStats輸出信息類似,只是多了所有候選索引(包括reject拒絕的非最優索引)的執行過程,這里不再詳述。

2.4 總結

從上面的幾個explain執行計劃參數輸出信息可以看出,各個參數的功能各不相同,總結如下:

queryPlanner

輸出索引的候選索引,包括最優索引及其執行stage過程(winningPlan)+其他非最優候選索引及其執行stage過程。

注意: queryPlanner沒有真正在表中執行整個SQL,只做了查詢優化器獲取候選索引過程,因此可以很快返回。

executionStats

相比queryPlanner參數,executionStats會記錄查詢優化器根據所選最優索引執行SQL的整個過程信息,會真正執行整個SQL。

allPlansExecution

和executionStats類似,只是多了所有候選索引的執行過程。

在和用戶一起優化騰訊雲上MongoDB集群索引過程中,以及和頭部用戶的交流中發現很多用戶對如何創建最優索引有較為嚴重的錯誤認識,並且很多是絕大部分用戶的共性問題,因此在本文中將這些問題匯總如下:

3.1 等值類查詢常見問題及優化方法

如下三個查詢:

用戶創建了如下3個索引:

{a:1, b:1, c:1}

{b:1, a:1, c:1}

{c:1, a:1, b:1}

實際上這3個查詢屬於同一類查詢,只是查詢欄位順序不一樣,因此只需創建任一個索引即可滿足要求。驗證過程如下:

從上面的expalin輸出可以看出,3個查詢都走向了同一個索引。

例如test表有多條數據,每條數據有3個欄位,分別為a、b、c。其中a欄位有10種取值,b欄位有100種取值,c欄位有1000種取值,稱為各個欄位值的 「區分度」

用戶查詢條件為db.test.find({"a":"xxx", "b":"xxx", "c":"xxx"}),創建的索引為{a:1, b:1, c:1}。如果只是針對這個查詢,該查詢可以創建a,b,c三欄位的任意組合,並且其SQL執行代價一樣,通過hint強制走不通索引,驗證過程如下:

從上面的執行計劃可以看出,多欄位等值查詢各個欄位的組合順序對應執行計劃代價一樣。絕大部分用戶在創建索引的時候,都是直接按照查詢欄位索引組合對應欄位。

但是,單就這一個查詢,這里有個不成文的建議,把區分度更高的欄位放在組合索引左邊,區分度低的欄位放到右邊。這樣做有個好處,資料庫組合索引遵從最左原則,就是當其他查詢裡面帶有區分度最高的欄位時,就可以快速排除掉更多不滿足條件的數據。

例如用戶有如下兩個查詢:

用戶創建了如下兩個索引:

{b:1, c:1}

{a:1,b:1,c:1}

這兩個查詢中,查詢2中包含有查詢1中的欄位,因此可以用一個索引來滿足這兩個查詢要求,按照最左原則,查詢1欄位放左邊即可,該索引可以優化為:b,c欄位索引+a欄位索引,b,c欄位順序可以根據區分排序,加上c欄位區分度比b高,則這兩個查詢可以合並為一個{c:1, b:1, a:1}。兩個查詢可以走同一個索引驗證過程如下:

從上面輸出可以看出,這兩個查詢都走了同一個索引。

例如用戶有以下兩個查詢:

用戶為這兩個查詢創建了兩個索引,{a:1, b:1}和{a:1, c:1},但是a欄位取值是唯一的,因此這兩個查詢中a以外的欄位無用,一個{a:1}索引即可滿足要求。

3.2 非 等值類查詢常見索引錯誤創建方法及如何創建最優索引

假設用戶有如下查詢:

a,c兩個欄位都是非等值查詢,很多用戶直接添加了{a:1, c:1}索引,實際上多個欄位的非等值查詢,只有最左邊的欄位才能走索引,例如這里只會走a欄位索引,驗證過程如下:

從上面執行計劃可以看出,索引數據掃描了10行(也就是a欄位滿足a:{$gte:1}條件的數據多少),但是實際上只返回了4條滿足{a:{$gte:1}, c:{$lte:1}}條件的數據,可以看出c欄位無法做索引。

同理,當查詢中包含多個欄位的范圍查詢的適合,除了最左邊第一個欄位可以走索引,其他欄位都無法走索引。因此,上面例子中的查詢候選索引為{a:1}或者{b:1}中任何一個就可以了,組合索引中欄位太多會佔用更多存儲成本、同時佔用更多IO資源引起寫放大。

例如下面查詢:

如上查詢,d欄位為非等值查詢,e欄位為等值查詢,很多用戶遇到該類查詢直接創建了{d:1, e:1}索引,由於d欄位為非等值查詢,因此e欄位無法走索引,驗證過程如下:

從上面驗證過程可以看出,等值類和非等值類組合查詢對應組合索引,最優索引應該優先把等值查詢放到左邊,上面查詢對應最優索引{e:1, d:1}

前面用到的非等值查詢操作符只提到了比較類操作符,實際上非等值查詢還有其他操作符。常用非等值查詢包括:$gt、$gte、$lt、$lte、$in、$nin、$ne、$exists、$type等,這些非等值查詢在絕大部分情況下存在如下優先順序:

從上到下優先順序更高,例如下面的查詢:

如上,該查詢等值部分查詢最優索引{a:1, b:1}(假設a區分度比b高);非等值部分,因為$in操作符優先順序最高,排他性更好,加上多個欄位非等值查詢只會有一個欄位走索引,因此非等值部分最優索引為{g:1}。

最終該查詢最優索引為:」等值部分最優索引」與」非等值部分最優索引」拼接,也就是{a:1,b:1, g:1}

3.3 OR類查詢常見索引錯誤創建方法及如何創建最優索引

例如下面的OR查詢:

該查詢很多用戶直接創建了{b:1, d:1, c:1, a:1},用戶創建該索引後,發現用戶還是全表掃描。

OR類查詢需要給數組中每個查詢添加索引,例如上面or數組中實際包含{ b: 0, d:0 }和 {"c":1, "a":{$gte:4}}查詢,需要創建兩個查詢的最優索引,也就是{b:1, d:1}和{c:1, a:1},執行計劃驗證過程如下(該測試表總共10條數據):

從上面執行計劃可以看出,如果該OR類查詢走{b:1, d:1, c:1, a:1}索引,則實際上做了全表掃描。如果同時創建{b:1, d:1}、{c:1, a:1}索引,則直接走兩個索引,其執行key和doc掃描行數遠遠小於全表掃描。

這里在提升一下OR查詢難度,例如下面的查詢:

上面的查詢可以轉換為如下兩個查詢:

如上圖,查詢1拆分後的兩個查詢2和查詢3組成or關系,因此對應最優索引需要創建兩個,分表是:{f:1, g:1, b:1, d:1} 和 {f:1, g:1, b:1, d:1}。對應執行計劃如下:

同理,不管怎麼增加難度,OR查詢最終可轉換為多個等值、非等值或者等值與非等值組合類查詢,通過如上變換最終可以起到舉一反三的作用。

說明:這個例子中可能在一些特殊數據分布場景,最優索引也可能是{f:1, g:1}或者{f:1, g:1, b:1, d:-1}或者{ f:1, g:1, c:1, a:1},這里我們只考慮大部分通用場景。

3.4 SORT類排序查詢常見索引錯誤創建方法及如何創建最優索引

例如用戶有以下兩個查詢:

這兩個查詢都不帶條件,排序方式不一樣,因此很多創建了兩個索引{a:1}和{a:-1},實際上這兩個索引中的任何一個都可以滿足兩種查詢要求,驗證過程如下:

假設有如下查詢:

其中a欄位為正序,b欄位為反序排序,很多用戶直接創建{a:1, b:1}索引,這時候b欄位內容就存在內存排序情況。多欄位排序索引,如果沒有攜帶查詢條件,則最優索引即為排序欄位對應索引,這里切記保持每個欄位得正反序和sort完全一致,否則可能存在部分欄位內存排序的情況,執行計劃驗證過程如下:

例如如下查詢:

該類查詢很多人直接創建{a:1, b:1, c:1, d:1},結果造成內存排序。這種組合查詢最優索引=「多欄位等值查詢最優索引_多欄位排序類組合最優索引」,例如該查詢:

{ "a" : 3, "b" : 1}等值查詢假設a區分度比b高,則對應最優索引為:{a:1, b:1}

{ c:-1, d:1}排序類查詢最優索引保持正反序一致,也就是:{ c:-1, d:1}

因此整個查詢就是這兩個查詢對應最優索引拼接,也就是{a:1, b:1, c:-1, d:1},對應執行計劃過程驗證如下:

假設有下面的查詢:

騰訊雲很多用戶看到該查詢直接創建{a:1, b:1, c:1, d:-1, e:1}索引,發現存在內存排序。等值+非等值+sort排序組合查詢,由於非等值查詢右邊的欄位不能走索引,因此如果把d, e放到c的右邊,則d,e欄位索引無效。

等值+非等值+sort排序最優索引組合欄位順序為:等值_sort排序_非等值,因此上面查詢最優索引為:{a:1, b:1, d:-1, e:1, c:1}。執行計劃驗證過程如下:

例如如下查詢:

上面組合很多人直接創建{b:1, d:1, c:1, a:1, e:1},該索引創建後還是會掃表和內存排序,實際上OR+SORT組合查詢可以轉換為下面兩個查詢:

所以這個復雜查詢就可以拆分為等值組合查詢+sort排序查詢,拆分為上面的兩個查詢,這樣我們只需要同時創建查詢2和查詢3對應最優索引即可。該查詢最終拆分後對應最優索引需要添加如下兩個:

{b:1, d:1, e:-1}和{c:1, a:1, e:-1}

非最優索引和最優索引執行計劃驗證過程如下:

OR+SORT類查詢,最終可以《參考前面的OR類查詢常見索引錯誤創建方法》把OR查詢轉換為多個等值、非等值或者等值與非等值組合查詢,然後與sort排序對應索引欄位拼接。例如下面查詢:

拆分後的兩個查詢組成or關系,如下:

如上,查詢1 = or: [查詢2, 查詢3],因此只需要創建查詢2和查詢3兩個最優索引即可滿足查詢1要求,查詢2和查詢3最優索引可以參考前面《or類查詢常見索引錯誤創建方法》,該查詢最終需要創建如下兩個索引:

{f:1, g:1, b:1, d:1, e:-1}和{ f:1, g:1, c:1, a:1, e:-1}

說明:這個例子中可能在一些特殊數據分布場景,最優索引也可能是{f:1, g:1}或者{f:1, g:1, b:1, d:1, e:-1}或者{ f:1, g:1, c:1, a:1, e:-1},這里我們只考慮通用場景。

3.5 避免創建太多無用索引及無用索引分析方法

在騰訊雲上,我們還發現另外一個問題,很多實例存在大量無用索引,無用索引會引起以下問題:

存儲成本增加

沒增加一個索引,MongoDB內核就會創建一個index索引文件,記錄該表的索引數據,造成存儲成本增加。

影響寫性能

用戶沒寫入一條數據,就會在對應索引生成一條索引KV,實現索引與數據的一一對應,索引KV數據寫入Index索引文件過程加劇寫入負載。

影響讀性能

MongoDB內核查詢優化器原理是通過候選索引快速定位到滿足條件的數據,然後采樣評分。如果滿足條件的候選索引越多,整個評分過程就會越長,增加內核選擇最優索引的流程。

下面以一個真實線上實例為例,說明如何找出無用索引:

MongoDB默認提供有索引統計命令來獲取各個索引命中的次數,該命令如下:

該聚合輸出中的幾個核心指標信息如下表:

上表中的ops代表命中次數,如果命中次數為0或者很小,說明該索引很少被選為最優索引使用,因此可以認為是無用索引,可以考慮刪除。

說明:

本文總結的《最優索引規則大全》中的規則適用於絕大部分查詢場景,但是一些特殊數據分布場景可能會有一定偏差,請根據實際數據分布進行查詢計劃分析。

DBbrain for MongoDB

最後,本文中所介紹的優化原理即將集成到騰訊雲DBbrain for MongoDB的智能索引推薦(規則+代價計算)功能中,屆時可幫助用戶一鍵優化索引,無需親自反復推敲驗證,歡迎體驗。

騰訊雲MongoDB當前服務於 游戲 、電商、社交、教育、新聞資訊、金融、物聯網、軟體服務等多個行業;MongoDB團隊(簡稱CMongo)致力於對開源MongoDB內核進行深度研究及持續性優化(如百萬庫表、物理備份、免密、審計等),為用戶提供高性能、低成本、高可用性的安全資料庫存儲服務。後續持續分享MongoDB在騰訊內部及外部的典型應用場景、踩坑案例、性能優化、內核模塊化分析。

叮咚買菜自建MangoDB上騰訊雲實踐

7. 資料庫建立索引怎麼利用索引查詢

1.合理使用索引
索引是資料庫中重要的數據結構,它的根本目的就是為了提高查詢效率。現在大多數的資料庫產品都採用IBM最先提出的ISAM索引結構。
索引的使用要恰到好處,其使用原則如下:
在經常進行連接,但是沒有指定為外鍵的列上建立索引,而不經常連接的欄位則由優化器自動生成索引。
在頻繁進行排序或分組(即進行group by或order by操作)的列上建立索引。
在條件表達式中經常用到的不同值較多的列上建立檢索,在不同值少的列上不要建立索引。比如在雇員表的「性別」列上只有「男」與「女」兩個不同值,因此就無必要建立索引。如果建立索引不但不會提高查詢效率,反而會嚴重降低更新速度。
如果待排序的列有多個,可以在這些列上建立復合索引(compound index)。
使用系統工具。如Informix資料庫有一個tbcheck工具,可以在可疑的索引上進行檢查。在一些資料庫伺服器上,索引可能失效或者因為頻繁操作而 使得讀取效率降低,如果一個使用索引的查詢不明不白地慢下來,可以試著用tbcheck工具檢查索引的完整性,必要時進行修復。另外,當資料庫表更新大量 數據後,刪除並重建索引可以提高查詢速度。
(1)在下面兩條select語句中:
SELECT * FROM table1 WHERE field1<=10000 AND field1>=0;
SELECT * FROM table1 WHERE field1>=0 AND field1<=10000;
如果數據表中的數據field1都>=0,則第一條select語句要比第二條select語句效率高的多,因為第二條select語句的第一個條件耗費了大量的系統資源。
第一個原則:在where子句中應把最具限制性的條件放在最前面。
(2)在下面的select語句中:
SELECT * FROM tab WHERE a=… AND b=… AND c=…;
若有索引index(a,b,c),則where子句中欄位的順序應和索引中欄位順序一致。
第二個原則:where子句中欄位的順序應和索引中欄位順序一致。
——————————————————————————
以下假設在field1上有唯一索引I1,在field2上有非唯一索引I2。
——————————————————————————
(3) SELECT field3,field4 FROM tb WHERE field1='sdf' 快
SELECT * FROM tb WHERE field1='sdf' 慢[/cci]
因為後者在索引掃描後要多一步ROWID表訪問
(4) SELECT field3,field4 FROM tb WHERE field1>='sdf' 快
SELECT field3,field4 FROM tb WHERE field1>'sdf' 慢
因為前者可以迅速定位索引。
(5) SELECT field3,field4 FROM tb WHERE field2 LIKE 'R%' 快
SELECT field3,field4 FROM tb WHERE field2 LIKE '%R' 慢,
因為後者不使用索引。
(6) 使用函數如:
SELECT field3,field4 FROM tb WHERE upper(field2)='RMN'不使用索引。
如果一個表有兩萬條記錄,建議不使用函數;如果一個表有五萬條以上記錄,嚴格禁止使用函數!兩萬條記錄以下沒有限制。
(7) 空值不在索引中存儲,所以
SELECT field3,field4 FROM tb WHERE field2 IS[NOT] NULL不使用索引。
(8) 不等式如
SELECT field3,field4 FROM tb WHERE field2!='TOM'不使用索引。
相似地,
SELECT field3,field4 FROM tb WHERE field2 NOT IN('M','P')不使用索引。
(9) 多列索引,只有當查詢中索引首列被用於條件時,索引才能被使用。
(10) MAX,MIN等函數,使用索引。
SELECT max(field2) FROM tb 所以,如果需要對欄位取max,min,sum等,應該加索引。
一次只使用一個聚集函數,如:
SELECT 「min」=min(field1), 「max」=max(field1) FROM tb
不如:SELECT 「min」=(SELECT min(field1) FROM tb) , 「max」=(SELECT max(field1) FROM tb)
(11) 重復值過多的索引不會被查詢優化器使用。而且因為建了索引,修改該欄位值時還要修改索引,所以更新該欄位的操作比沒有索引更慢。
(12) 索引值過大(如在一個char(40)的欄位上建索引),會造成大量的I/O開銷(甚至會超過表掃描的I/O開銷)。因此,盡量使用整數索引。 Sp_estspace可以計算表和索引的開銷。
(13) 對於多列索引,ORDER BY的順序必須和索引的欄位順序一致。
(14) 在sybase中,如果ORDER BY的欄位組成一個簇索引,那麼無須做ORDER BY。記錄的排列順序是與簇索引一致的。
(15) 多表聯結(具體查詢方案需要通過測試得到)
where子句中限定條件盡量使用相關聯的欄位,且盡量把相關聯的欄位放在前面。
SELECT a.field1,b.field2 FROM a,b WHERE a.field3=b.field3
field3上沒有索引的情況下:
對a作全表掃描,結果排序
對b作全表掃描,結果排序
結果合並。
對於很小的表或巨大的表比較合適。
field3上有索引
按照表聯結的次序,b為驅動表,a為被驅動表
對b作全表掃描
對a作索引范圍掃描
如果匹配,通過a的rowid訪問
(16) 避免一對多的join。如:
SELECT tb1.field3,tb1.field4,tb2.field2 FROM tb1,tb2 WHERE tb1.field2=tb2.field2 AND tb1.field2=『BU1032』 AND tb2.field2= 『aaa』
不如:
declare @a varchar(80)
SELECT @a=field2 FROM tb2 WHERE field2=『aaa』
SELECT tb1.field3,tb1.field4,@a FROM tb1 WHERE field2= 『aaa』
(16) 子查詢
用exists/not exists代替in/not in操作
比較:
SELECT a.field1 FROM a WHERE a.field2 IN(SELECT b.field1 FROM b WHERE b.field2=100)
SELECT a.field1 FROM a WHERE EXISTS( SELECT 1 FROM b WHERE a.field2=b.field1 AND b.field2=100)
SELECT field1 FROM a WHERE field1 NOT IN( SELECT field2 FROM b)
SELECT field1 FROM a WHERE NOT EXISTS( SELECT 1 FROM b WHERE b.field2=a.field1)
(17) 主、外鍵主要用於數據約束,sybase中創建主鍵時會自動創建索引,外鍵與索引無關,提高性能必須再建索引。
(18) char類型的欄位不建索引比int類型的欄位不建索引更糟糕。建索引後性能只稍差一點。
(19) 使用count(*)而不要使用count(column_name),避免使用count(DISTINCT column_name)。
(20) 等號右邊盡量不要使用欄位名,如:
SELECT * FROM tb WHERE field1 = field3
(21) 避免使用or條件,因為or不使用索引。
2.避免使用order by和group by字句。
因為使用這兩個子句會佔用大量的臨時空間(tempspace),如果一定要使用,可用視圖、人工生成臨時表的方法來代替。
如果必須使用,先檢查memory、tempdb的大小。
測試證明,特別要避免一個查詢里既使用join又使用group by,速度會非常慢!
3.盡量少用子查詢,特別是相關子查詢。因為這樣會導致效率下降。
一個列的標簽同時在主查詢和where子句中的查詢中出現,那麼很可能當主查詢中的列值改變之後,子查詢必須重新查詢一次。查詢嵌套層次越多,效率越低,因此應當盡量避免子查詢。如果子查詢不可避免,那麼要在子查詢中過濾掉盡可能多的行。
4.消除對大型錶行數據的順序存取
在 嵌套查詢中,對表的順序存取對查詢效率可能產生致命的影響。
比如採用順序存取策略,一個嵌套3層的查詢,如果每層都查詢1000行,那麼這個查詢就要查詢 10億行數據。
避免這種情況的主要方法就是對連接的列進行索引。
例如,兩個表:學生表(學號、姓名、年齡……)和選課表(學號、課程號、成績)。如果兩個 表要做連接,就要在「學號」這個連接欄位上建立索引。
還可以使用並集來避免順序存取。盡管在所有的檢查列上都有索引,但某些形式的where子句強迫優化器使用順序存取。
下面的查詢將強迫對orders表執行順序操作:
SELECT * FROM orders WHERE (customer_num=104 AND order_num>1001) OR order_num=1008
雖然在customer_num和order_num上建有索引,但是在上面的語句中優化器還是使用順序存取路徑掃描整個表。因為這個語句要檢索的是分離的行的集合,所以應該改為如下語句:
SELECT * FROM orders WHERE customer_num=104 AND order_num>1001
UNION
SELECT * FROM orders WHERE order_num=1008
這樣就能利用索引路徑處理查詢。
5.避免困難的正規表達式
MATCHES和LIKE關鍵字支持通配符匹配,技術上叫正規表達式。但這種匹配特別耗費時間。例如:SELECT * FROM customer WHERE zipcode LIKE 「98_ _ _」
即使在zipcode欄位上建立了索引,在這種情況下也還是採用順序掃描的方式。如果把語句改為SELECT * FROM customer WHERE zipcode >「98000」,在執行查詢時就會利用索引來查詢,顯然會大大提高速度。
另外,還要避免非開始的子串。例如語句:SELECT * FROM customer WHERE zipcode[2,3] >「80」,在where子句中採用了非開始子串,因而這個語句也不會使用索引。
6.使用臨時表加速查詢
把表的一個子集進行排序並創建臨時表,有時能加速查詢。它有助於避免多重排序操作,而且在其他方面還能簡化優化器的工作。例如:
SELECT cust.name,rcvbles.balance,……other COLUMNS
FROM cust,rcvbles
WHERE cust.customer_id = rcvlbes.customer_id
AND rcvblls.balance>0
AND cust.postcode>「98000」
ORDER BY cust.name
如果這個查詢要被執行多次而不止一次,可以把所有未付款的客戶找出來放在一個臨時文件中,並按客戶的名字進行排序:
SELECT cust.name,rcvbles.balance,……other COLUMNS
FROM cust,rcvbles
WHERE cust.customer_id = rcvlbes.customer_id
AND rcvblls.balance>;0
ORDER BY cust.name
INTO TEMP cust_with_balance
然後以下面的方式在臨時表中查詢:
SELECT * FROM cust_with_balance
WHERE postcode>「98000」
臨時表中的行要比主表中的行少,而且物理順序就是所要求的順序,減少了磁碟I/O,所以查詢工作量可以得到大幅減少。
注意:臨時表創建後不會反映主表的修改。在主表中數據頻繁修改的情況下,注意不要丟失數據。
7.用排序來取代非順序存取
非順序磁碟存取是最慢的操作,表現在磁碟存取臂的來回移動。SQL語句隱藏了這一情況,使得我們在寫應用程序時很容易寫出要求存取大量非順序頁的查詢。

8. Excel 數組公式,想要使用通配符應該怎麼辦

在EXECL中查找和替換中通配符有如下含義:
1、?代表任意單個字元;
2、*代表任意多個字元;
3、如果要替換通配符本身,需要在其前面加~;
4、 在EXCEL中不支持正則類通配符。