Original post: http://anothermysqldba.blogspot.com/2014/01/use-your-index-even-with-varchar-char.html
最近,我看到的一個帖子forums.mysql.com網站: 如何快速的搜索結果在300萬記錄?
給出的例子中使用了LIKE'%EED“
這將不採取索引的優勢,會做一個全表掃描。
下面是使用世界數據庫的例子,所以不是300萬條記錄,但只是想顯示它是如何工作的。
為了進一步展示點
上述解釋輸出表明,沒有索引的使用方式。
因此,對於笑著讓我們把一個關鍵的varchar字段。 請注意,我不把一個鍵上的整個範圍的前幾個字符。 這當然取決於你的數據。
所以會這樣,甚至重要嗎?
沒有都不會有問題,因為LIKE'%大壩將迫使完整掃描不論。
注意上面的解釋輸出的差異。 此查詢使用索引。 它不使用名稱作為索引,但它是使用一個索引。 所以你怎麼能走的varchar指數的優勢在哪裡?
上面的查詢將使用name_key指數。
問題的關鍵是在於你有你怎麼寫你的SQL查詢,並確保您運行說明找到的選擇,為您的查詢的最佳指標要小心。
給出的例子中使用了LIKE'%EED“
這將不採取索引的優勢,會做一個全表掃描。
下面是使用世界數據庫的例子,所以不是300萬條記錄,但只是想顯示它是如何工作的。
> explain select * from City where Name LIKE '%dam' \G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: City
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 4188
Extra: Using where
1 row in set (0.01 sec)
[world]> select count(*) FROM City;
+----------+
| count(*) |
+----------+
| 4079 |
+----------+
> select * from City where Name LIKE '%dam';
+------+------------------------+-------------+----------------+------------+
| ID | Name | CountryCode | District | Population
+------+------------------------+-------------+----------------+------------+
| 5 | Amsterdam | NLD | Noord-Holland | 731200 |
| 6 | Rotterdam | NLD | Zuid-Holland | 593321 |
| 1146 | Ramagundam | IND | Andhra Pradesh | 214384 |
| 1318 | Haldwani-cum-Kathgodam | IND | Uttaranchal | 104195 |
| 2867 | Tando Adam | PAK | Sind | 103400 |
| 3122 | Potsdam | DEU | Brandenburg | 128983 |
+------+------------------------+-------------+----------------+------------+
> explain select * from City where Name LIKE '%dam%' \G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: City
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 4188
Extra: Using where
1 row in set (0.00 sec)
> select * from City where Name LIKE '%dam%';
+------+------------------------+-------------+----------------+------------+
| ID | Name | CountryCode | District | Population |
+------+------------------------+-------------+----------------+------------+<
| 5 | Amsterdam | NLD | Noord-Holland | 731200 |
| 6 | Rotterdam | NLD | Zuid-Holland | 593321 |
| 380 | Pindamonhangaba | BRA | São Paulo | 121904 |<
| 625 | Damanhur | EGY | al-Buhayra | 212203 |
| 1146 | Ramagundam | IND | Andhra Pradesh | 214384 |
| 1318 | Haldwani-cum-Kathgodam | IND | Uttaranchal | 104195 |
| 1347 | Damoh | IND | Madhya Pradesh | 95661 |
| 2867 | Tando Adam | PAK | Sind | 103400 |
| 2912 | Adamstown | PCN | – | 42 |
| 3122 | Potsdam | DEU | Brandenburg | 128983 |
| 3177 | al-Dammam | SAU | al-Sharqiya | 482300 |
| 3250 | Damascus | SYR | Damascus | 1347000 |
+------+------------------------+-------------+----------------+------------+<
12 rows in set (0.00 sec)
上述解釋輸出表明,沒有索引的使用方式。
CREATE TABLE `City` (
`ID` int(11) NOT NULL AUTO_INCREMENT,
`Name` char(35) NOT NULL DEFAULT '',
`CountryCode` char(3) NOT NULL DEFAULT '',
`District` char(20) NOT NULL DEFAULT '',
`Population` int(11) NOT NULL DEFAULT '0',
PRIMARY KEY (`ID`),
KEY `CountryCode` (`CountryCode`),
CONSTRAINT `city_ibfk_1` FOREIGN KEY (`CountryCode`) REFERENCES `Country` (`Code`)
) ENGINE=InnoDB
<
因此,對於笑著讓我們把一個關鍵的varchar字段。 請注意,我不把一個鍵上的整個範圍的前幾個字符。 這當然取決於你的數據。
> ALTER TABLE City ADD KEY name_key(`Name`(5));
Query OK, 0 rows affected (0.54 sec)
CREATE TABLE `City` (
`ID` int(11) NOT NULL AUTO_INCREMENT,
`Name` char(35) NOT NULL DEFAULT '',
`CountryCode` char(3) NOT NULL DEFAULT '',
`District` char(20) NOT NULL DEFAULT '',
`Population` int(11) NOT NULL DEFAULT '0',
PRIMARY KEY (`ID`),
KEY `CountryCode` (`CountryCode`),
KEY `name_key` (`Name`(5)),
CONSTRAINT `city_ibfk_1` FOREIGN KEY (`CountryCode`) REFERENCES `Country` (`Code`)
) ENGINE=InnoDB
所以會這樣,甚至重要嗎?
> explain select * from City where Name LIKE '%dam' \G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: City
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 4188
Extra: Using where
1 row in set (0.00 sec)
沒有都不會有問題,因為LIKE'%大壩將迫使完整掃描不論。
> EXPLAIN select * from City where Name LIKE '%dam' AND CountryCode = 'IND' \G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: City
type: ref
possible_keys: CountryCode
key: CountryCode
key_len: 3
ref: const
rows: 341
Extra: Using index condition; Using where
1 row in set (0.00 sec)
注意上面的解釋輸出的差異。 此查詢使用索引。 它不使用名稱作為索引,但它是使用一個索引。 所以你怎麼能走的varchar指數的優勢在哪裡?
> EXPLAIN select * from City where Name LIKE 'Ra%' \G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: City
type: range
possible_keys: name_key
key: name_key
key_len: 5
ref: NULL
rows: 35
Extra: Using where
1 row in set (0.00 sec)
上面的查詢將使用name_key指數。
問題的關鍵是在於你有你怎麼寫你的SQL查詢,並確保您運行說明找到的選擇,為您的查詢的最佳指標要小心。