1.基礎架構:一條sql查詢語句是如何執行的?
mysql> select * from T where ID=10;
2.基礎架構:一條sql更新語句是如何執行的?
mysql> update T set c=c+1 where ID=2;
redo log
(1)存儲引擎的日志,InnoDB特有的;
(2)物理日志
(3)循環寫,空間固定會用完;
binlog
(1)server端日志,所有引擎都有;
(2)邏輯日志
(3)追加寫,文件寫到一定大小,切換下一個,並不會覆蓋之前的日志;
redolog的寫入拆分成兩個步驟:prepare和commit
redo log 和binlog都可以用於表示事務的提交狀態,兩階段提交是為了維持這兩個狀態一致。
恢復:
注:正常執行redolog commit;崩潰恢復的時候可以接受redolog prepare並且binglog完整
3.事務隔離
MyISAM不支持事務,InnoDB 支持事務
讀未提交:別人改數據的事務尚未提交,我在我的事務中也能讀到。
讀已提交:別人改數據的事務已經提交,我在我的事務中才能讀到。
可重復讀:別人改數據的事務已經提交,我在我的事務中也不去讀。(對賬的例子)
串行:我的事務尚未提交,別人就別想改數據。
https://blog.csdn.net/changhenshui1990/article/details/77161401
4.索引(上)
索引---目錄:提供數據查詢的效率
(1)哈希表:適合等值查詢的場景
缺點:范圍查找比較麻煩
哈希沖突:鏈表(兩個key生成的N一樣)
(2)有序數組:等值查找,范圍查詢性能都很好、只適合靜態存儲引擎
缺點:更新比較麻煩
(3)二叉搜索樹:每個節點的左兒子小於父節點,父節點又小於右兒子
InnoDB的索引模型
B+樹索引模型
mysql> create table T(
id int primary key,
k int not null,
name varchar(16),
index (k))engine=InnoDB;
索引類型:主建索引、非主建索引
主建索引的葉子節點存儲:整行數據(聚簇索引),主建索引只要搜索id這個B+ Tree就可以拿到數據
非主建索引葉子節點:主建的值(二級索引),普通索引先搜索索引拿到主建值,再到主建索引搜索一次(回表)
索引維護:
一個數據頁滿了,按照B+Tree算法,新增加一個數據頁,叫做頁分裂,會導致性能下降。空間利用率降低大概50%。當相鄰的兩個數據頁利用率很低的時候會做數據頁合並,合並的過程是分裂過程的逆過程。
性能和存儲上來考慮,自增主建往往是更合理的選擇;遞增插入,追加,不會觸發葉子節點分裂。
業務字段用作主建:(1)只有一個索引(2)該索引必須唯一索引。-------------------------直接將這個索引設置成主建,避免每次查詢搜索兩棵樹。
5.索引(下)
(1)覆蓋索引:select ID from T where k betwe 3 and 5 不需要回表(回到主鍵索引樹搜索的過程,成為回表)
(2)前綴索引
(3)索引下推
總結:
1、覆蓋索引:如果查詢條件使用的是普通索引(或是聯合索引的最左原則字段),查詢結果是聯合索引的字段或是主鍵,不用回表操作,直接返回結果,減少IO磁盤讀寫讀取正行數據
2、最左前綴:聯合索引的最左 N 個字段,也可以是字符串索引的最左 M 個字符
3、聯合索引:根據創建聯合索引的順序,以最左原則進行where檢索,比如(age,name)以age=1 或 age= 1 and name=‘張三’可以使用索引,單以name=‘張三’ 不會使用索引,考慮到存儲空間的問題,還請根據業務需求,將查找頻繁的數據進行靠左創建索引。
4、索引下推:like 'hello%’and age >10 檢索,MySQL5.6版本之前,會對匹配的數據進行回表查詢。5.6版本后,會先過濾掉age<10的數據,再進行回表查詢,減少回表率,提升檢索速度
6.數據庫鎖——行鎖,表鎖
鎖:並發
(1)全局鎖:對整個數據庫實例加鎖,全庫數據備份的時候用;(InnoDB采用事務,可重復讀可以支持;不支持事務的引擎不能夠實現,采用FTWRL) FTWRL——保證只讀
(2)表級鎖:表鎖、元數據鎖;
(3)行級鎖:InnoDB(行鎖)、MyIsAM(不支持行鎖)
7.索引選擇——唯一索引,普通索引
8.給字符串字段加索引
前綴索引
mysql> alter table SUser add index index1(email);
或
mysql> alter table SUser add index index2(email(6));
使用前綴索引,定義好長度,就可以做到既節省空間,又不用額外增加太多的查詢成本
前綴索引對覆蓋索引的影響:
其他方式: 倒序存儲、hash字段
9.mysql "抖"了一下
WAL:先寫日志,再寫磁盤
刷臟頁(flush)
(1)InnoDB的redo log滿了的時候
(2)內存不夠用了,先將臟頁寫到磁盤
(3)mysql系統空閑的時候
(4)mysql正常關閉的時候
10.數據刪除,表文件大小不變
InnoDB:表結構(.frm)定義和數據(.ibd)。
delete 命令其實只是把記錄的位置,或者數據頁標記為“可復用”,但磁盤文件的大小是不會變的。----空洞
重建表可以收縮空間
11.count(*)的實現
MyISAM:一個表的總行數存在了磁盤上
InnoDB:把數據一行一行地從引擎里面讀出來,然后累加
count(字段)<count(主建id)<count(1)約等於count(*)
12.order by的原理
(1)全字段排序:
缺點:
1.造成sort_buffer中存放不下很多數據,因為除了排序字段還存放其他字段,對sort_buffer的利用效率不高
2.當所需排序數據量很大時,會有很多的臨時文件,排序性能也會很差
優點:MySQL認為內存足夠大時會優先選擇全字段排序,因為這種方式比rowid 排序避免了一次回表操作
(2)rowId排序
優點:更好的利用內存的sort_buffer進行排序操作,盡量減少對磁盤的訪問
缺點:回表的操作是隨機IO,會造成大量的隨機讀,不一定就比全字段排序減少對磁盤的訪問
13.mysql隨機消息
mysql> select word from words order by rand() limit 3;
14.邏輯相同的sql語句性能相差很大
(1)條件字段函數
mysql> select count(*) from tradelog where month(t_modified)=7;
如果對字段做了函數計算,就用不上索引了,這是 MySQL 的規定。
對索引字段做函數操作,可能會破壞索引值的有序性,因此優化器就決定放棄走樹搜索功能。
mysql> select count(*) from tradelog where
-> (t_modified >= '2016-7-1' and t_modified<'2016-8-1') or
-> (t_modified >= '2017-7-1' and t_modified<'2017-8-1') or
-> (t_modified >= '2018-7-1' and t_modified<'2018-8-1');
(2)隱式類型轉換
mysql> select * from tradelog where tradeid=110717;
相當於 mysql> select * from tradelog where CAST(tradid AS signed int) = 110717;
對索引字段做函數操作,優化器會放棄走樹搜索功能。
(3)隱式字符串編碼轉換
15.查一行數據也很慢
(1)查詢長時間不返回:等MDL鎖、等flush、等行鎖
(2)查詢慢:沒有加索引,需要全表掃描;
16.幻讀
間隙鎖
17.mysql如何保證數據不丟失
18.mysql主備一致:binlog歸檔
binlog的格式:
(1)statement
(2)row
(3)mixed
19.mysql如何保證高可用
主備(寫數據)、主從(讀數據)------一主多從
20.mysql讀寫分離
21.join
select * from t1 straight_join t2 on (t1.b=t2.b) where t2.id<=50;
select * from t2 straight_join t1 on (t1.b=t2.b) where t2.id<=50;
第二條語句更好,小表作為驅動表;
22.分區表
CREATE TABLE `t` (
`ftime` datetime NOT NULL,
`c` int(11) DEFAULT NULL,
KEY (`ftime`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
PARTITION BY RANGE (YEAR(ftime))
(PARTITION p_2017 VALUES LESS THAN (2017) ENGINE = InnoDB,
PARTITION p_2018 VALUES LESS THAN (2018) ENGINE = InnoDB,
PARTITION p_2019 VALUES LESS THAN (2019) ENGINE = InnoDB,
PARTITION p_others VALUES LESS THAN MAXVALUE ENGINE = InnoDB);
insert into t values('2017-4-1',1),('2018-4-1',1);
索引參考:https://blog.csdn.net/tongdanping/article/details/79878302
https://www.cnblogs.com/yuyue2014/p/3662005.html
http://blog.codinglabs.org/articles/theory-of-mysql-index.html