1. 程式人生 > >MySql 使用索引進行查詢優化;常用mysql優化

MySql 使用索引進行查詢優化;常用mysql優化

索引有它的缺點:雖然索引大大提高了查詢速度,同時卻會降低更新表的速度,如對錶進行INSERT、UPDATE和DELETE。因為更新表時,MySQL不僅要儲存資料,還要儲存一下索引檔案。建立索引會佔用磁碟空間的索引檔案。一般情況這個問題不太嚴重,但如果你在一個大表上建立了多種組合索引,索引檔案的會膨脹很快。索引只是提高效率的一個因素,如果你的MySQL有大資料量的表,就需要花時間研究建立最優秀的索引,或優化查詢語句。

建索引的幾大原則

1、最左字首匹配原則,非常重要的原則

對於多列索引,總是從索引的最前面欄位開始,接著往後,中間不能跳過。比如建立了多列索引(name,age,sex),會先匹配name欄位,再匹配age欄位,再匹配sex欄位的,中間不能跳過。

mysql會一直向右匹配直到遇到範圍查詢(>、<、between、like)就停止匹配。比如a = 1 and b = 2 and c > 3 and d = 4,如果建立(a,b,c,d)順序的索引,d是用不到索引的,如果建立(a,b,d,c)的索引則都可以用到,a,b,d的順序可以任意調整。

2、儘量選擇區分度高的列作為索引

區分度的公式是count(distinct col)/count(*),表示欄位不重複的比例,比例越大我們掃描的記錄數越少,唯一鍵的區分度是1,而一些狀態、性別欄位可能在大資料面前區分度就是0,那可能有人會問,這個比例有什麼經驗值嗎?使用場景不同,這個值也很難確定,一般需要join的欄位我們都要求是0.1以上,即平均1條掃描10條記錄。(比如,我們會選擇學號做索引,而不會選擇性別來做索引。

3、=和in可以亂序

比如a = 1 and b = 2 and c = 3 建立(a,b,c)索引可以任意順序,mysql的查詢優化器會幫你優化成索引可以識別的形式。

4、索引列不能參與計算,保持列“乾淨”

比如from_unixtime(create_time) = ’2014-05-29’就不能使用到索引,原因很簡單,b+樹中存的都是資料表中的欄位值,但進行檢索時,需要把所有元素都應用函式才能比較,顯然成本太大。所以語句應該寫成create_time = unix_timestamp(’2014-05-29’);

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


比如:Flistid+1>‘2000000608201108010831508721‘。原因很簡單,假如索引列參與計算的話,那每次檢索時,都會先將索引計算一次,再做比較,顯然成本太大。

5、儘量的擴充套件索引,不要新建索引

比如表中已經有a的索引,現在要加(a,b)的索引,那麼只需要修改原來的索引即可。

6. 索引不會包含有NULL值的列

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

7. 使用短索引

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

8. 索引列排序

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

9. like語句操作

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

最後總結一下,MySQL只對以下操作符才使用索引:<,<=,=,>,>=,between,in,以及某些時候的like(不以萬用字元%或_開頭的情形)。而理論上每張表裡面最多可建立16個索引,不過除非是資料量真的很多,否則過多的使用索引也不是那麼好玩的,比如我剛才針對text型別的欄位建立索引的時候,系統差點就卡死了。

使用索引優化查詢

使用索引的典型場景

1、匹配全值

對索引中所有列都指定具體值,即對索引中的所有列都有等值匹配的條件。

#設定組合索引(rental_date,inventory_id,customer_id)為唯一索引。
EXPLAIN 
SELECT 
  * 
FROM
  rental 
WHERE rental_date = '2005-05-25 17:22:10' 
  AND inventory_id = 373 
  AND customer_id = 343 ;

這裡寫圖片描述

2、匹配值的範圍查詢

對索引的值能夠進行範圍查詢。

#設定索引idx_fk_customer_id(customer_id)
EXPLAIN 
SELECT 
  * 
FROM
  rental 
WHERE customer_id >= 373 
  AND customer_id < 400 ;

這裡寫圖片描述

型別type為range說明優化器選擇範圍查詢,索引key為idx_fk_customer_id說明優化器選擇索引idx_fk_customer_id來加速訪問,Extra為using where說明優化器除了利用索引加速訪問外,還需要根據索引回表查詢資料。

3、匹配最左字首

僅僅使用索引中的最左邊列進行查詢。比如組合索引(col1,col2,col3)能夠被col1,col1+col2,col1+col2+col3的等值查詢利用到的。

#建立索引idx_payment_date(payment_date,amount,last_update);
EXPLAIN 
SELECT 
  * 
FROM
  payment 
WHERE payment_date = '2006-02-14 15:16:03' 
  AND last_update = '2006-02-15 22:12:32' ;

這裡寫圖片描述

從結果可以看出利用了索引,但又row為182行,所有隻使用了部分索引。

EXPLAIN 
SELECT 
  * 
FROM
  payment 
WHERE amount = 3.98 
  AND last_update = '2006-02-15' ;

這裡寫圖片描述

從結果看出,這次查詢沒有利用索引,進行了全表查詢。

4、僅對索引進行查詢

當查詢列都在索引欄位中。即select中的列都在索引中。

EXPLAIN 
SELECT 
  last_update 
FROM
  payment 
WHERE payment_date = '2005-08-19 21:21:47' 
  AND amount = 4.99 ;

這裡寫圖片描述

extra部分Using index,說明不需要通過索引回表,Using index就是平時說的覆蓋索引掃描(即找到索引,就找到了要查詢的結果,不用再回表查找了)。

5、匹配列字首

僅僅使用索引的第一列,並且只包含索引第1列的開頭部分進行查詢。

#建立索引idx_title_desc_part(title(10),description(20));
EXPLAIN 
SELECT 
  title 
FROM
  film_text 
WHERE title LIKE 'AFRICAN%' ;

這裡寫圖片描述

6、索引部分等值匹配,部分範圍匹配

EXPLAIN 
SELECT 
  inventory_id 
FROM
  rental 
WHERE rental_date = '2006-02-14 15:16:03' 
  AND customer_id >= 300 
  AND customer_id <= 400 ;

這裡寫圖片描述

type=ref,說明使用了索引。key為idx_rental_date說明優化器選擇使用索引加速查詢,同時由於只查詢索引欄位inventory_id,故Extra部分有using index,表示查詢使用了覆蓋索引掃描。

7、若列名是索引,則使用column_name is null就會使用索引

EXPLAIN 
SELECT 
  * 
FROM
  payment 
WHERE rental_id IS NULL ;

這裡寫圖片描述

索引存在但不能使用索引的典型場景

1、以%開頭的like查詢

EXPLAIN 
SELECT 
  * 
FROM
  actor 
WHERE last_name LIKE '%NI%' ;

這裡寫圖片描述

因為B-Tree索引的結構,所以以%開頭的查詢自然沒法使用索引。InnoDB的表都是聚簇表,一般索引都會比表小,掃描索引比掃描表更快,而InnoDB表上二級索引idx_last_name實際上儲存欄位last_name和主鍵actor_id,故先掃描二級索引idx_last_name獲得滿足條件last_name like '%NI%'的主鍵actor_id列表,之後根據主鍵回表去檢索記錄,這樣避免了全表掃面演員表actor產生的大量IO請求

#優化
EXPLAIN 
SELECT 
  * 
FROM
  (SELECT 
    actor_id 
  FROM
    actor 
  WHERE last_name LIKE '%NI%') a,
  actor b 
WHERE a.actor_id = b.actor_id ;

這裡寫圖片描述

2、資料型別出現隱式轉化,不會使用索引

EXPLAIN 
SELECT 
  * 
FROM
  actor 
WHERE last_name = 1 ;

這裡寫圖片描述

#使用索引
EXPLAIN 
SELECT 
  * 
FROM
  actor 
WHERE last_name = '1' ;

這裡寫圖片描述

3、組合索引,不滿足最左原則,不使用符合索引

EXPLAIN 
SELECT 
  * 
FROM
  payment 
WHERE amount = 3.98 
  AND last_update = '2006-02-15 22:12:32' ;

這裡寫圖片描述

4、估計使用索引比全表掃描還慢,則不要使用索引

update film_text set title=concat('S',title);

如查詢以“S”開頭的標題的電影,返回記錄比例比較大,mysql預估索引掃描還不如全表掃描。

EXPLAIN 
SELECT 
  * 
FROM
  film_text 
WHERE title LIKE 'S%' ;

這裡寫圖片描述

5、用or分割條件,若or前後只要有一個列沒有索引,就都不會用索引

EXPLAIN 
SELECT 
  * 
FROM
  payment 
WHERE customer_id = 203 
  OR amount = 3.96 ;

這裡寫圖片描述

應儘量避免在where子句中使用or來連線條件,否則將導致引擎放棄使用索引而進行全表掃描,如:
低效:select * from t_credit_detail where Flistid = '2000000608201108010831508721' or Flistid = '10000200001';

可以用下面這樣的查詢代替上面的 or 查詢:
高效:select from t_credit_detail where Flistid = '2000000608201108010831508721' union all select from t_credit_detail where Flistid = '10000200001';

6 使用!= 或 <> 操作符時

儘量避免使用!= 或 <>操作符,否則資料庫引擎會放棄使用索引而進行全表掃描。使用>或<會比較高效。

select * from t_credit_detail where Flistid != '2000000608201108010831508721'\G

7 對欄位進行null值判斷

應儘量避免在where子句中對欄位進行null值判斷,否則將導致引擎放棄使用索引而進行全表掃描,如:
低效:select * from t_credit_detail where Flistid is null ;

可以在Flistid上設定預設值0,確保表中Flistid列沒有null值,然後這樣查詢:
高效:select * from t_credit_detail where Flistid =0;

避免select *

在解析的過程中,會將'*' 依次轉換成所有的列名,這個工作是通過查詢資料字典完成的,這意味著將耗費更多的時間。

所以,應該養成一個需要什麼就取什麼的好習慣。

優化子查詢

使用連線查詢(join)代替子查詢可以提高查詢效率。

MySQL4.1版開始支援子查詢(一個查詢的結果作為另一個select子句的條件),子查詢雖然靈活但執行效率不高,因為使用子查詢時,MySQL需要為內層查詢語句的查詢結果建立一個臨時表,然後外層查詢語句從臨時表中查詢記錄,查詢完畢後 再撤銷這些臨時表,因此子查詢的速度會相應的受到影響。而連線查詢不需要建立臨時表其查詢速度快於子查詢!

優化插入記錄的速度

innoDB引擎的表常見的優化方法

(1)、禁用唯一性檢查

插入資料時,MySQL會對插入的記錄進行唯一性校驗。這種唯一性校驗會降低插入記錄的速度。為了降低這種情況對查詢速度的影響可以在插入記錄之前禁用唯一性檢查,等到記錄插入完畢後再開啟。

Set  unique_check=0; 開啟唯一性檢查的語句如下:set  unique_checks=1;

(2)、禁用外來鍵檢查

插入資料之前禁止對外來鍵的檢查,資料插入完成之後再恢復對外來鍵的檢查。

Set foreign_key_checks=0; 恢復外來鍵檢查:set foreign_key_checks=1;

(3)、禁止自動提交

插入資料之前禁止事務的自動提交,資料匯入之後,執行恢復自動提交操作。

禁止自動提交的語句 set autocommit=0;恢復自動提交:set autocommit=1;

Myisam引擎表常見的優化方法

(1)、禁用索引 alter table table_name disable keys

            匯入資料  loading the data

    開啟索引 alter table table_name enable keys

(2)禁用唯一性檢查

(3)使用批量插入

(4)當需要批量匯入資料時,使用load data infile

優化insert語句

1. 一條SQL語句插入多條資料。
常用的插入語句如:

1234INSERTINTO`insert_table`(`datetime`,`uid`,`content`,`type`)VALUES('0','userid_0','content_0',0);INSERTINTO`insert_table`(`datetime`,`uid`,`content`,`type`)VALUES('1','userid_1','content_1',1);

修改成:

12INSERTINTO`insert_table`(`datetime`,`uid`,`content`,`type`)VALUES('0','userid_0','content_0',0),('1','userid_1','content_1',1);

修改後的插入操作能夠提高程式的插入效率。這裡第二種SQL執行效率高的主要原因是合併後日志量(MySQL的binlog和innodb的事務讓日誌)減少了,降低日誌刷盤的資料量和頻率,從而提高效率。通過合併SQL語句,同時也能減少SQL語句解析的次數,減少網路傳輸的IO。
這裡提供一些測試對比資料,分別是進行單條資料的匯入與轉化成一條SQL語句進行匯入,分別測試1百、1千、1萬條資料記錄。

2. 在事務中進行插入處理。

把插入修改成:

1234567START TRANSACTION;INSERTINTO`insert_table`(`datetime`,`uid`,`content`,`type`)VALUES('0','userid_0','content_0',0);INSERTINTO`insert_table`(`datetime`,`uid`,`content`,`type`)VALUES('1','userid_1','content_1',1);...

相關推薦

MySql 使用索引進行查詢優化常用mysql優化

索引有它的缺點:雖然索引大大提高了查詢速度,同時卻會降低更新表的速度,如對錶進行INSERT、UPDATE和DELETE。因為更新表時,MySQL不僅要儲存資料,還要儲存一下索引檔案。建立索引會佔用磁碟空間的索引檔案。一般情況這個問題不太嚴重,但如果你在一個大表上建立了多種組

MySQL索引查詢優化總結

存儲 一行 -1 type 一定的 關鍵技術 表示 智能 string類型 一個簡單的對比測試 前面的案例中,c2c_zwdb.t_file_count表只有一個自增id,FFileName字段未加索引的sql執行情況如下: 在上圖中,type=all,key=nul

MySQL------索引、叢集、儲存原理、優化查詢

1. MySQL資料庫儲存的原理: 儲存過程是一個可程式設計的函式,它在資料庫中建立並儲存。它可以有SQL語句和一些特殊的控制結構組成。當希望在不同的應用程式或平臺上執行相同的函式,或者封裝特定功能時,儲存過程是非常有用的。資料庫中的儲存過程可以看做是對程式設計中面向物件方法的模擬。它允

MySQL 索引查詢優化總結

本文由雲+社群發表 文章《MySQL查詢分析》講述了使用MySQL慢查詢和explain命令來定位mysql效能瓶頸的方法,定位出效能瓶頸的sql語句後,則需要對低效的sql語句進行優化。本文主要討論MySQL索引原理及常用的sql查詢優化。 一個簡單的對比測試 前面的案例中,c2c_zwdb

由淺入深探究mysql索引結構原理、效能分析與優化

第一部分:基礎知識 第二部分:MYISAM和INNODB索引結構 1、 簡單介紹B-tree B+ tree樹 2、 MyisAM索引結構 3、 Annode索引結構 4、 MyisAM索引與InnoDB索引相比較 第三部分:MYSQL優化 1、表資料型別選擇 2、sql語句優化 (1)     最左字首

資料庫適當新增索引進行查詢優化

新增索引: 顯示資料表的已經添加了索引的欄位 show index from m3u8_content; 用explain檢測效能,語句為:explain select count(*) from m3u8_content where status=8; type由al

nodejs 利用對mysql資料庫進行查詢和插入資料

nodejs對資料庫的操作是比較簡單的。下面看一個對laughter庫操作: 這是專案檔案結構圖: config.js的配置如下: //資料庫配置檔案 module.exports = { mysql: {

mysql資料庫建立索引mysql索引總結----mysql 索引型別以及建立mysql_建立索引的優缺點

因為欣賞所以轉載: http://www.cnblogs.com/cy163/archive/2008/10/27/1320798.html http://www.cnblogs.com/lihuiyong/p/5623191.html ht

JDBC java對MySQL資料庫進行查詢操作,並把查詢的結果輸出

Resultset中的所有資料都可以通過getString()方法取得 String是可以接收表中的任意型別列的內容,所以在以下的程式中全部都使用getString()接收 package JDBC;

MySQL索引原理及慢查詢優化(轉)

範圍 很難 等於 right 事件 原理 插入 jpg 個人網站 轉自:美團點評技術團隊http://tech.meituan.com/mysql-index.html MySQL憑借著出色的性能、低廉的成本、豐富的資源,已經成為絕大多數互聯網公司的首選關系型數據庫。雖然性

數據查詢優化mysql索引

between 如果 哪些 isa 綜合 ring 信息 xpl xxx 為什麽要建立索引: 索引用於快速找出在某個列中有一特定值的行。不使用索引,MySQL必須從第1條記錄開始然後讀完整個表直到找出相關的行,還需要考慮每次讀入數據頁的IO開銷。而如果采取索引,則可以根據索

MySQL索引原理及慢查詢優化-zz

`` 原理 並不是 計劃 ora 實的 birt 總計 war https://tech.meituan.com/mysql-index.html MySQL憑借著出色的性能、低廉的成本、豐富的資源,已經成為絕大多數互聯網公司的首選關系型數據庫。雖然性能出色,但所謂“好馬配

mysql:索引原理與慢查詢優化

一個 mark index out 般的 test output 都是 records 一 介紹 二 索引的原理 三 索引的數據結構 三 MySQL索引管理 四 測試索引 五 正確使用索引 六 查詢優化神器-explain 七 慢查詢優化的基本步驟 八 慢日誌管理 九 參

MySQL索引原理以及查詢優化

地址 存儲引擎 想要 方式 聯合 執行 圖書 解決 範圍查詢 一、介紹 1.什麽是索引? 一般的應用系統,讀寫比例在10:1左右,而且插入操作和一般的更新操作很少出現性能問題,在生產環境中,我們遇到最多的,也是最容易出問題的,還是一些復雜的查詢操作,因此對查詢語句的優化顯然

mysql 使用索引進行分頁優化

MySQL大資料量分頁查詢方法及其優化 ---方法1: 直接使用資料庫提供的SQL語句 ---語句樣式: MySQL中,可用如下方法: SELECT * FROM 表名稱 LIMIT M,N ---適應場景: 適用於資料量較少的情況(元組百/千級) ---原因/缺點: 全表掃描,速度會很慢 且

MySQL定位慢查詢以及索引優化

(一)定位慢查詢 1.通過explain,可以檢視sql語句的執行情況(比如查詢的表,使用的索引以及mysql在表中找到所需行的方式等),一般情況下,基本可以通過explain,主要是通過其查詢行的方式和查詢行數確定問題,因為全表掃描很浪費時間,佔用cpu。 2.通過show pr

MySQL - - 索引原理與慢查詢優化

詳解 limit 性能 取出 平衡 獲取數據 目的 官方文檔 百度 目錄 索引介紹 索引方法 索引類型 聚合索引和輔助索引 測試索引 正確使用索引 組合索引 註意事項 查詢計劃 慢日誌查詢 大數據量分頁優化 EXPLAIN 詳解 1, 索引介紹 需求: 一般的應用系

Mysql 索引 與 多表查詢效能優化

最近做專案需要用到Luence Whoosh,要定時從資料庫中索引出資料來供檢索,但是在索引中設計多表查詢,速度較慢,因為強迫症,想要做效能優化,因此把Mysql的核心又翻出來研究一遍。 關於MySQL索引的好處,如果正確合理設計並且使用索引的MySQL是一輛蘭博基尼的話,那麼

mysql分頁查詢優化(索引延遲關聯)

對於web後臺報表匯出是一種常見的功能點,實際對應服務後端即資料庫的排序分頁查詢。如下示例為公司商戶積分報表匯出其中一個sql ,當大批量的匯出請求進入時候,mysql的cpu急劇上升瞬間有拖垮庫的風險。 SELECT * FROM coupons.cp_score_log WHERE

41 MYSQL 索引和慢查詢優化

一 .索引mysql 索引 b+tree本質:通過不斷地縮小想要獲取資料的範圍來篩選出最終想要的結果,同時把隨機的事件變成順序的事件,也就是說,有了這種索引機制,我們可以總是用同一種查詢方式來鎖定資料。索引注意的問題: 1. 索引欄位要儘量小,訪問磁碟查詢時,儘量減少io 2.索引 選 區別度