天天看點

MySQL學習記錄(四)

之前單獨地學習過MySQL,項目中又有講,作為對之前筆記的補充

Select *from
Join on
Where
Group By
Having
Order by
Limit

From
Join on
Where
Group by
Having
Select
Order by
Limit

FROM ON
JOIN WHERE
GROUP BY    HAVING 
SELECT   ORDER BY
LIMIT

           
左連接配接、右連接配接、内連接配接--LEFT、RIGHT、INNER
------可以延伸出七種JOIN-----加上where及and、or字段
FULL OUTER JOIN -- UNION ALL
           
MySQL學習記錄(四)

資料補充:MySQL 索引及查詢優化

1、索引

1、什麼是索引?

MySQL索引

索引是一種幫助MySQL 高效擷取資料的資料結構。

----是一種為了提高資料擷取速度的資料結構

----主鍵一定是唯一性索引,唯一性索引并不一定就是主鍵。

建立每張表的時候都有個.MYI檔案生成
索引一般都是指B樹(多路搜尋樹,不一定是二叉樹)結構組織的索引---MySQL的索引結構都是B+樹
				---除了B+Tree索引,還有Hash索引、full-text全文索引、R-Tree索引
B-Tree---多路平衡查找樹-----對應一個資料表,一共兩列資料  id及值,最左邊是資料記錄的實體位址--查找速度快

索引類型:單值索引、唯一索引(該字段資料不可重複)、複合索引(建立在多個字段上)
				--ALTER TABLE ..... ADD UNIQUE INDEX .....USING BTREE;
           

2、MySQL索引

索引在存儲引擎層實作的,不是在伺服器層實作的。不同的存儲引擎具有不同的索引類型和實作。

1、B+Tree索引

是大多數 MySQL 存儲引擎的預設索引類型。

因為不再需要進行全表掃描,隻需要對樹進行搜尋即可,是以查找速度快很多。

因為 B+ Tree 的有序性,是以除了用于查找,還可以用于排序和分組。

可以指定多個列作為索引列,多個索引列共同組成鍵。

适用于全鍵值、鍵值範圍和鍵字首查找,其中鍵字首查找隻适用于最左字首查找。如果不是按照索引列的順序進行查找,則無法使用索引。

InnoDB 的 B+Tree 索引分為主索引和輔助索引。主索引的葉子節點 data 域記錄着完整的資料記錄,這種索引方式被稱為聚簇索引。因為無法把資料行存放在兩個不同的地方,是以一個表隻能有一個聚簇索引。

MySQL學習記錄(四)

輔助索引的葉子節點的 data 域記錄着主鍵的值,是以在使用輔助索引進行查找時,需要先查找到主鍵值,然後再到主索引中進行查找。

MySQL學習記錄(四)

2、哈希索引

哈希索引能以 O(1) 時間進行查找,但是失去了有序性:

1、無法用于排序與分組;

2、隻支援精确查找,無法用于部分查找和範圍查找。

InnoDB 存儲引擎有一個特殊的功能叫“自适應哈希索引”,當某個索引值被使用的非常頻繁時,會在 B+Tree 索引之上再建立一個哈希索引,這樣就讓 B+Tree 索引具有哈希索引的一些優點,比如快速的哈希查找。

3、全文索引

MyISAM 存儲引擎支援全文索引,用于查找文本中的關鍵詞,而不是直接比較是否相等。

查找條件使用 MATCH AGAINST,而不是普通的 WHERE。

全文索引使用反向索引實作,它記錄着關鍵詞到其所在文檔的映射。

InnoDB 存儲引擎在 MySQL 5.6.4 版本中也開始支援全文索引。

4、空間資料索引

MyISAM 存儲引擎支援空間資料索引(R-Tree),可以用于地理資料存儲。

空間資料索引會從所有次元來索引資料,可以有效地使用任意次元來進行組合查詢。

必須使用 GIS 相關的函數來維護資料。

3、索引的優點及使用條件

索引的優點:

1、大大減少了伺服器需要掃描的資料行數。
2、幫助伺服器避免進行排序和分組,以及避免建立臨時表
	(B+Tree 索引是有序的,可以用于 ORDER BY 和 GROUP BY 操作。
	臨時表主要是在排序和分組過程中建立,不需要排序和分組,也就不需要建立臨時表)。
3、将随機 I/O 變為順序 I/O(B+Tree 索引是有序的,會将相鄰的資料都存儲在一起)。
           

索引的使用條件:

1、對于非常小的表、大部分情況下簡單的全表掃描比建立索引更高效;
2、對于中到大型的表,索引就非常有效;
3、但是對于特大型的表,建立和維護索引的代價将會随之增長。
	這種情況下,需要用到一種技術可以直接區分出需要查詢的一組資料,而不是一條記錄一條記錄地比對,例如可以使用分區技術。
           

2、Explain關鍵字:

将SQL語句執行過程中MySQL引擎的執行參數陳列出來
---可以模拟執行SQL語句,通過模拟執行的參數,知道MySQL怎麼處理SQL語句,
	分析查詢語句或表結構的性能瓶頸,進一步優化SQL。
用法:在SQL語句前加上EXPLAIN關鍵字

作用:---可以得知以下資訊:
	表的讀取順序
	資料讀取操作的操作類型
	哪些索引可以使用
	哪些索引被實際使用
	表之間的引用
	每張表有多少行被優化器查詢

EXPLAIN得到的參數概念:

id:
	--EXPLAIN中的辨別,表示select查詢的序列号,包含一組數字,表示查詢順序
	--說明每個對象(表)的執行順序,id越大執行越早,id越小執行越晚,id一樣的按照從前到後的順序執行
select_type:
	--是指查詢方式的類型、查詢類型
	---主查詢PRIMARY、子查詢SUBQUERY、簡單查詢SIMPLE(單表--無傷大雅)、
		聯合查詢UNION(union all)、衍生表查詢DERIVED(假表、虛拟表、衍生表)
table:
	--查詢所涉及到的表,真實存在的表或者衍生表
type:
	--索引使用情況的類型--說本次查詢所使用到的索引類型,如果沒有用到索引則為ALL
	--速度優劣由最好到最差:
		system(系統常量,寫死在程式中--const特例)
		>const(記錄在表中的常量,從表中比對一下)
		>eq_ref(關聯别的表--唯一性索引掃描,對每個索引鍵,表中隻有一條記錄與之比對--主鍵)
		(前三個要求過高,過于特殊)
		>ref(索引不是單獨用的,關聯别的表--有一個表提供資料----非唯一性索引掃描,傳回比對每個單獨值的所有行)
		>range(範圍索引,使用索引樹上的範圍)
		>index(查詢的東西正好在索引上,也是讀全表,但是index是從索引中讀取的)
		(盡量到達上面三種級别,加快速度)
		>ALL (沒有用到索引,周遊全表找到比對的行)

		 
possible_keys:
	--在多表關聯時,可能用到的索引(一般是兩張表的所有索引)
	--可能應用到這張表中的索引,一個或者多個,查詢到的索引不一定被查詢實際使用。
key:
	--實際使用的索引。如果為NULL,則沒有使用索引
key_len:
	--被用到的索引的長度
	--所使用的的索引的果實越短,查詢越快
	----int:4、Varchar:3位元組(utf-8)*20(字段長度)+1(null)+2(varchar的存儲長度)=63
ref:
	--兩張表在索引關聯查詢時所關聯的索引字段是什麼---兩表聯合查詢聯合索引是什麼
	--type為ref時,這裡的顯示所關聯的表的名字
rows:
	--查詢字段表中的資料數量
	--根據表統計資訊及索引選用情況,大緻估算出找到所需記錄所需要讀取的行數
Extra:
	--包含不适合在其他列中顯示但是重要的額外資訊
	--using filesort檔案内排序(檢索到的結果不符合order by)及using temporary(臨時空間)盡量不要出現,出現說明效率低
           

3、索引優化(幾十萬條以下都差不多)

MySQL學習記錄(四)

原則:—避免索引失效

1、全值比對我最愛—用上所有的組合索引—key_len優先級低于ref

–全值比對我最愛

–最左字首要遵守

2、最佳左字首法則–如果索引了多列,查詢從索引的最左前列開始并且不跳過索引中的列。

–帶頭大哥不能死,中間兄弟不能斷

3、不在索引列上做任何操作(計算、函數、類型轉換),會導緻索引失效轉向全表掃描。

–索引列上少計算

4、存儲引擎不能使用索引中範圍條件右邊的列。

–範圍之後全失效

5、盡量使用覆寫索引(隻通路索引的查詢(索引列和查詢列一緻)),減少select *

– 覆寫索引不寫 *

6、mysql在使用不等于(!=、>、<)的時候有時候無法使用索引會導緻全表掃描。

7、null及not null也盡量不要有。

8、like以通配符開頭(%…),導緻mysql索引失效會變成全表掃描的操作。----比對時左側盡量不要模糊

–like百分寫最右

9、字元串不加單引号也會導緻索引失效。

–VAR引号不可丢

10、少用or,用它連接配接會導緻索引失效。

–不等空值還有OR

如何注意索引優化?

1、SQL語句的優化,充分利用索引
2、建立資料結構時,要盡量考慮到索引的使用,
	複合索引在建立和使用時,盡量考慮在使用者應用查詢時,常用的排序方向和字段組合順序。
           

4、資料庫函數(使用者資料庫函數導入大的測試資料–上百萬級别)

plsql---首創于oracle的一種擴充sql語言,PL/SQL是Oracle資料庫對SQL語句的擴充。---SQL的程式化語言
	--運作在oracle内部的一個類似js腳本的語言
	--有傳回值的叫函數;
	--沒有傳回值的叫存儲過程(執行一些列的複雜的資料庫操作,如自動生成表資料,如對多張表的關聯增删改查)
           

設定參數log_bin_trust_function_creators為true

-------其實就是在Navicat中寫函數,表示各種

建立函數----------------随機生成字元串函數、生成随機數字-部門編号

建立存儲過程----------插入部門、調用函數—生成部門、員工參數(部門編号起始值,最大值)

5、資料庫鎖(如何防止庫存超賣)

如何解決庫存超賣現象?

在高并發的情況下,多個人同時搶購同一庫存時,由于資料庫的讀寫操作可以并行執行的原因,會導緻修改庫存時,庫存不足出現超賣現象。
---redis解決:分布式鎖、lua腳本、Redisson
---mysql解決:用鎖将查詢庫存的操作和寫入庫存的操作互斥
	(1)悲觀鎖解決庫存問題:
		在select時,将select語句加入一個行鎖,與更新庫存是語句互斥,可以保證在查詢庫存時庫存不被修改。
	(2)樂觀鎖解決庫存問題:
		在select時,加入一個版本字段,每次更新,同時查詢和更新版本字段,如果版本字段發生變化,則SQL語句不會執行成功。
		Select kc,version from sku_info where sku_id = ?----查詢兩個字段
		Update sku_info set kc = kc - 1, version = version + 1 where sku_id = ? and version = version
           

MyISAM–查詢用—不存在事務—基本已經淘汰

InnoDB資料庫引擎–事務型–支援行鎖、表鎖----三種鎖指行鎖、表鎖、頁鎖

表鎖

在偏讀型資料庫中使用表鎖----如MyISAM

–很少用表鎖–安全–

Lock table 表名

Unlock tables

寫鎖和讀鎖阻塞(讀寫互斥),讀與讀共享,寫和寫阻塞(寫寫互斥)

行鎖

------行鎖支援事務----沒有行鎖就沒有事務

------沒開啟事務就是預設送出—開啟事務後送出需要手動commit

------行鎖可以讓讀讀互斥,可以避免在查詢到庫存時,庫存已經被修改的情況發生

-----update自帶行鎖—事務

-----在無索引操作時,注意鎖的更新(行鎖更新表鎖)

--- 如何鎖定一行?--加上一個行鎖
-----查詢加上行鎖for update ,避免查詢和更新同時發生,導緻讀到的庫存數量發生不可重複讀的錯誤
set autocommit = 0;
select kc from product where productname = '電腦' for update
update product set kc = kc - 1 where productname = '電腦'
commit
           

間隙鎖

當使用範圍條件不是相等條件檢索資料時,并請求共享或排他鎖時,InnoDB會給符合條件的已有資料記錄的索引項加鎖。

對于鍵值在條件範圍内但是并不存在的記錄叫作“間隙”(GAP)

InnoDB也會對這個間隙加鎖–這種鎖機制就是間隙鎖(Next-Key鎖)

可能會鎖定一個并不存在的記錄。

可能也會導緻鎖的更新,危害别的資料。—是以查詢時盡量不使用範圍條件檢索

頁鎖

開銷和加鎖時間介于表鎖和行鎖之間,會出現死鎖;

鎖定粒度介于表鎖和行鎖之間,并發度一般。

資料庫的死鎖

----多線程死鎖

形成了一種因果關系,死循環。—彼此占用了對方的解鎖的鑰匙