首先,mysql的查詢流程大體是:mysql
mysql客戶端經過協議與mysql服務器建鏈接,發送查詢語句,先檢查查詢緩存,若是命中,直接返回結果,不然進行語句解析,也就是說,在解析查詢以前,服務器會先訪問查詢緩存(query cache)——它存儲SELECT語句以及相應的查詢結果集。若是某個查詢結果已經位於緩存中,服務器就不會再對查詢進行解析、優化、以及執行。它僅僅將緩存中的結果返回給用戶便可,這將大大提升系統的性能。sql
語法解析器和預處理:首先mysql經過關鍵字將SQL語句進行解析,並生成一顆對應的「解析樹」。mysql解析器將使用mysql語法規則驗證和解析查詢;預處理器則根據一些mysql規則進一步檢查解析數是否合法。shell
查詢優化器當解析樹被認爲是合法的了,而且由優化器將其轉化成執行計劃。一條查詢能夠有不少種執行方式,最後都返回相同的結果。優化器的做用就是找到這其中最好的執行計劃。。緩存
而後,mysql默認使用的BTREE索引,而且一個大體方向是:不管怎麼折騰sql,至少在目前來講,mysql最多隻用到表中的一個索引。服務器
#查看mysql存儲引擎 show engines;
#查看mysql當前默認的存儲引擎 show variables like '%storage_engine%';
對比項 | MyISAM | InnoDB |
---|---|---|
外鍵 | 只緩存索引,不緩存真實數據 | 不只緩存索引還要緩存真實數據,對內存要求較高,並且內存大小對性能有決定性的影響 |
事務 | 不支持 | 支持 |
行表鎖 | 表鎖,即便操做一條記錄也會鎖住整個表,不適合高併發的操做 | 行鎖,操做時只鎖某一行,不對其它行有影響,適合高併發的操做 |
緩存 | 只緩存索引,不緩存真實數據 | 不只緩存索引還要緩存真實數據,對內存要求較高,並且內存大小對性能有決定性的影響 |
關注點 | 性能 | 事務 |
默認安裝 | 是 | 是 |
默認使用 | 否 | 是 |
自帶系統表使用 | 是 | 否 |
(1)索引失效架構
(2)關聯查詢太多join併發
(3)服務器調優及各個參數設置高併發
CREATE TABLE `t_dept` ( `id` INT(11) NOT NULL AUTO_INCREMENT, `deptName` VARCHAR(30) DEFAULT NULL, `address` VARCHAR(40) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=INNODB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; CREATE TABLE `t_emp` ( `id` INT(11) NOT NULL AUTO_INCREMENT, `name` VARCHAR(20) DEFAULT NULL, `age` INT(3) DEFAULT NULL, `deptId` INT(11) DEFAULT NULL, empno int not null, PRIMARY KEY (`id`), KEY `idx_dept_id` (`deptId`) #CONSTRAINT `fk_dept_id` FOREIGN KEY (`deptId`) REFERENCES `t_dept` (`id`) ) ENGINE=INNODB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; INSERT INTO t_dept(deptName,address) VALUES('華山','華山'); INSERT INTO t_dept(deptName,address) VALUES('丐幫','洛陽'); INSERT INTO t_dept(deptName,address) VALUES('峨眉','峨眉山'); INSERT INTO t_dept(deptName,address) VALUES('武當','武當山'); INSERT INTO t_dept(deptName,address) VALUES('明教','光明頂'); INSERT INTO t_dept(deptName,address) VALUES('少林','少林寺'); INSERT INTO t_emp(NAME,age,deptId,empno) VALUES('風清揚',90,1,100001); INSERT INTO t_emp(NAME,age,deptId,empno) VALUES('嶽不羣',50,1,100002); INSERT INTO t_emp(NAME,age,deptId,empno) VALUES('令狐沖',24,1,100003); INSERT INTO t_emp(NAME,age,deptId,empno) VALUES('洪七公',70,2,100004); INSERT INTO t_emp(NAME,age,deptId,empno) VALUES('喬峯',35,2,100005); INSERT INTO t_emp(NAME,age,deptId,empno) VALUES('滅絕師太',70,3,100006); INSERT INTO t_emp(NAME,age,deptId,empno) VALUES('周芷若',20,3,100007); INSERT INTO t_emp(NAME,age,deptId,empno) VALUES('張三丰',100,4,100008); INSERT INTO t_emp(NAME,age,deptId,empno) VALUES('張無忌',25,5,100009); INSERT INTO t_emp(NAME,age,deptId,empno) VALUES('韋小寶',18,null,100010);
#全部門派的人員信息(A、B兩表共有) SELECT * FROM t_dept INNER JOIN t_emp ON t_dept.`id` = t_emp.`deptId`; #列出全部用戶,並顯示其機構信息 (A的全集) SELECT * FROM t_emp LEFT JOIN t_dept ON t_emp.`deptId`=t_dept.`id`; #列出全部門派 (B的全集) SELECT * FROM t_dept # 全部不入門派的人員 (A的獨有) SELECT * FROM t_emp LEFT JOIN t_dept ON t_emp.`deptId`=t_dept.`id` WHERE t_emp.`deptId` IS NULL #全部沒人入的門派 (B的獨有) SELECT * FROM t_dept LEFT JOIN t_emp ON t_dept.`id`=t_emp.`deptId` WHERE t_emp.`deptId` IS NULL #列出全部人員和機構的對照關係(AB全有) #MySQL Full Join的實現 由於MySQL不支持FULL JOIN,下面是替代方法 #left join + union(可去除重複數據)+ right join SELECT * FROM t_emp A LEFT JOIN t_dept B ON A.deptId = B.id UNION SELECT * FROM t_emp A RIGHT JOIN t_dept B ON A.deptId = B.id #列出全部沒入派的人員和沒人入的門派(A的獨有+B的獨有) SELECT * FROM t_emp LEFT JOIN t_dept ON t_emp.`deptId`=t_dept.`id` WHERE t_emp.`deptId` IS NULL UNION SELECT * FROM t_dept LEFT JOIN t_emp ON t_dept.`id`=t_emp.`deptId` WHERE t_emp.`deptId` IS NULL