這樣寫sql避免索引失效

       合理地對數據表加索引可以大大加快數據的訪問效率,但索引也不是對任何查詢都有效,如果sql的結構不當,也會發生索引失效。所以爲避免採坑,寫下此文,作爲記錄。下面的例子是在mysql中創建的一張表,建表語句如下:

CREATE TABLE `user_info` (
  `id` bigint(32) NOT NULL,
  `name` varchar(32) DEFAULT NULL,
  `age` int(3) DEFAULT NULL,
  `address` varchar(32) DEFAULT NULL,
  `nick_name` varchar(32) DEFAULT NULL,
  `role_id` bigint(32) DEFAULT NULL,
  `create_time` date DEFAULT NULL,
  `update_time` date DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

一、儘量選擇複合索引

        在對錶創建索引時,如果可以使用複合索引,儘量使用複合索引而不是單列索引,理由如下。現創建的一個複合索引:

CREATE INDEX idx_name_age_status ON user(name, age, status);

        這裏創建了一個名爲idx_name_age_status的複合索引,索引涉及到三個字段。在mysql中,這一個索引實際上相當於三個索引,分別是name、 name + age、 name + age + stauts,那麼在使用name或name + age或name + age + stauts進行查詢時,都會使索引生效。而如果分別給三個字段三個單列索引,在查詢這張表時條件中有這三個字段,數據庫會選擇一個最優的單列索引,而不會使用全部三個索引。

 

二、最左前綴法

        使用到複合索引時,注意最左前綴法,也就是查詢的條件需要從索引的最左列開始,並且不跳過中間列,才能使索引發揮最好的效果。現在創建這樣的索引:

CREATE INDEX idx_name_age_status ON user(name, age, status);

        使用name或name + age或name + age + status進行查詢能使索引生效;使用單個查詢條件age或status或者age + status 進行查詢不會使索引生效;使用name + stauts進行查詢只有name字段的索引生效。

 

三、使用複合索引時範圍查詢右邊的列索引不會生效

        三個字段在同一個複合索引中,如果查詢條件中用到了範圍查詢,範圍查詢後面的索引不再生效比如創建如下索引:

CREATE INDEX idx_name_age_status ON user(name, age, status);

        使用這三個字段作爲查詢條件,處於中間的age如果用到了範圍查詢,則status上的索引不會生效。

-- name + age + nick_name索引生效
SELECT * FROM user_info WHERE name = '張三' AND age = 22 AND nick_name = '三兒';
-- age用到了範圍查詢,僅name + age索引生效
SELECT * FROM user_info WHERE name = '張三' AND age > 22 AND nick_name = '三兒';

 

四、在索引列上進行運算操作後,索引將失效

        在索引列上進行運算操作後,索引將失效。比如有這樣一個索引:

CREATE INDEX idx_name ON user_info(name);

        直接以name作爲條件查詢索引是生效的,如果在name上使用函數會導致索引失效,比如這樣:

SELECT * FROM user_info WHERE substring(name, 1, 2) = '夏侯';

 

五、模糊匹配不生效的情況

        查詢條件中的模糊條件,如果是以%開頭,不走索引,比如

SELECT * FROM user_info WHERE name like '%三兒%';    -- 不走索引

        或者

SELECT * FROM user_info WHERE name like '%三兒';    -- 不走索引

        以上兩種寫法都不會走索引,下面這種寫法索引是有效的

SELECT * FROM user_info WHERE name like '三兒%';    -- 走索引

 

六、字符串沒加引號,索引失效

        查詢時字符串如果沒加引號,索引失效。

        在mysql中,假設有一個字段名是name,類型爲VARCHAR,使用name作爲條件查詢。此時忘記給name的值加上引號,就像這樣:

SELECT * FROM user_info WHERE name = 12;    -- name爲VARCHAR類型

        此時name條件查詢的值是12,mysql是可以執行的,如果這裏寫一個name = 張三,mysql不能執行。雖然這條語句可以執行,並且如果數據表中有name值爲12的數據也是可以查出來的。但是,它不會走索引。  

 

七、作爲條件的索引字段位於or兩側,導致該索引失效

      name字段上有索引,所以這樣查肯定是走索引的。

SELECT * FROM user_info WHERE name = '張三';

        在這張表中另外有一列nick_name,不管這一字段有沒有加索引,下面這一個語句都不會走索引

SELECT * FROM user_info WHERE name = '張三' OR nick_name = '頑皮';

 

八、儘量不使用SELECT *,最好只查詢索引列

        儘量使用覆蓋索引,也就是儘量只查詢索引列,比如複合索引如下:

CREATE INDEX idx_name_age_status ON user(name, age, status);

       使用SELECT * FROM user_info WHERE name = '張三' AND age = 12 AND status = 1進行查詢,索引自然會生效,但是效率肯定不如SELECT name, age, status FROM user_info WHERE name = '張三' AND age = 12 AND status = 1,這在數據量大的時候可以看出來。

       另外,儘量不要寫SELECT * FROM user_info這樣的語句,SELECT後面只跟需要用到的列是好的選擇。

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