MySQL 多列索引優化小記

2021-07-29 14:35:14 字數 2141 閱讀 1690

mysql 5.6.30

由於爬蟲抓取的資料不斷增多,這兩天在不斷對資料庫以及查詢語句進行優化,其中乙個表結構如下:

create

table

`news*****_article` (

`id`

varchar(50) not

null comment '編號',

`title`

varchar(190) not

null comment '標題',

`author`

varchar(255) default

null comment '作者',

`date`

date

null

default

null comment '發表時間',

`content` longtext comment '正文',

`status` tinyint(4) default

'0',

primary

key (`id`),

key`idx_status_date` (`status`,`date`)

) engine=innodb default charset=utf8mb4 comment='文章表';

根據業務需要,新增了idx_status_date索引,在執行下面這個 sql 時特別耗時:

select id, title, status, date

from article where status > -2

anddate = '2016-01-07';

根據觀察,每天新增的資料大概在2500條以內,本以為這裡指定了具體某天的日期'2016-01-07',實際需要掃瞄的資料量應該在2500條以內才對,但實際並非如此:

實際共掃瞄了185589條資料,遠遠高於預估的2500條,且實際執行時間都將近3秒鐘:

這是為什麼呢?

idx_status_date (status, date)改為idx_status (status)後,檢視 mysql 執行計畫:

可以看到將多列索引改為單列索引後,執行計畫要掃瞄的資料總量沒有任何變化。結合多列索引遵循最左字首原則,推測上面的查詢語句只使用了idx_status_date最左邊的status的索引。

翻了下《高效能mysql》找到了下面這段話,證實了我的想法:

如果查詢中有某個列的範圍查詢,則其右邊所有列都無法使用索引優化查詢。例如有查詢where last_name = 'smith' and first_name like 'j%' and dob = '1976-12-23',這個查詢只能使用索引的前兩列,因為這裡like是乙個範圍條件(但是伺服器可以把其餘列用於其他目的)。如果範圍查詢列值的數量有限,那麼可以通過使用多個等於條件來代替範圍條件。

因此,這裡解決思路有兩種:

優化後的執行計畫:

實際執行結果:

當人們談論索引的時候,如果沒有特別指明型別,那麼多半說的是b-tree索引,它使用b-tree資料結構來儲存資料。我們使用術語「b-tree」,是因為 mysql 在create table和其他語句中也使用該關鍵字。不過,底層的儲存引擎也可能使用不同的儲存結構。innodb使用的是b+tree。

假如有如下資料表:

create

table people (

last_name varchar(50) not

null,

first_name varchar(50) not

null,

dob date

notnull,

gender enum('m', 'f') not

null,

key(last_name, first_name, dob)

);

mysql多列索引 MySQL的多列索引

什麼是索引?索引用來快速地尋找那些具有特定值的記錄,所有mysql索引都以b 樹的形式儲存。如果沒有索引,執行查詢時mysql必須從第乙個記錄開始掃瞄整個表的所有記錄,直至找到符合要求的記錄。表裡面的記錄數量越多,這個操作的代價就越高。如果作為搜尋條件的列上已經建立了索引,mysql無需掃瞄任何記錄...

MySql多列索引

多列索引 多列索引就是將多個列作為乙個索引,在乙個多列b tree索引中,索引列的順序意味著索引首先按照最左列進行排序,然後第二列第三列等等。所以可以按照公升序或者降序進行掃瞄,以滿足精確符合列順序的order by,group by和distinct等子句,所以,多列索引的順序至關重要,key 列...

mysql多列索引

1,資料庫每次查詢只能使用乙個索引 2,假設資料 表t a,b,c rowid 為物理位置 rowid a b c 1 1 1 1 2 2 1 13 3 2 2 14 4 1 3 3 5 2 3 12 6 1 2 5 7 2 3 9 8 1 2 2 9 1 3 6 10 2 2 11 11 2 2 ...