MySQL架構(gòu)如下:
創(chuàng)新互聯(lián)建站提供成都網(wǎng)站設計、成都網(wǎng)站制作、外貿(mào)網(wǎng)站建設、網(wǎng)頁設計,品牌網(wǎng)站建設,廣告投放平臺等致力于企業(yè)網(wǎng)站建設與公司網(wǎng)站制作,10多年的網(wǎng)站開發(fā)和建站經(jīng)驗,助力企業(yè)信息化建設,成功案例突破超過千家,是您實現(xiàn)網(wǎng)站建設的好選擇.
我們寫的sql語句通過client對接MYSQL的連接層,然后有查詢緩存,語法解析器,優(yōu)化器,生成最終執(zhí)行計劃,然后去查詢插件式存儲引擎,如InnoDB等。我們的數(shù)據(jù)是通過存儲引擎來和物理設備交互的。
B TREE 索引是有序排列的。所以在執(zhí)行 ORDER BY 操作時,可以使用索引來避免使用額外的排序操作。
即使 ORDER BY 沒有精確地與索引相匹配,只要所有索引未使用的部分和所有 ORDER BY 中額外的列在 WHERE 子句中是一個常量。如果索引不包含查詢中訪問的索引列,只有當索引訪問效率高于其他訪問模式時才使用索引。
這里的無法使用索引是指不使用索引進行排序( ORDER BY )操作。但是仍然可能使用索引來檢索和 WHERE 子句匹配的行
如果 ORDER BY 無法使用索引,MySQL會執(zhí)行文件排序( filesort )操作:讀取表中的每一行并進行排序。 filesoft 可以被視為是語句執(zhí)行過程中的額外排序操作。
為了獲取 filesort 操作的內(nèi)存,優(yōu)化器分配固定的 sort_buffer_size 大小的內(nèi)存。 sort_buffer_size 是會話級的,可以動態(tài)修改。
如果結(jié)果集太大,內(nèi)存容納不下全部結(jié)果, filesort 操作會使用臨時磁盤文件。一些類型的查詢特別適合使用內(nèi)存 filesort 操作。例如:優(yōu)化器可以使用內(nèi)存 filesort 來
SELECT ... FROM single_table ... ORDER BY non_index_column [DESC] LIMIT [M,]N;
對于未使用 filesort 的 ORDER BY ,可以降低 max_length_for_sort_data 的值來觸發(fā)文件排序。(max_length_for_sort_data過高可能導致磁盤活動較高但CPU利用率較低)
要提高 ORDER BY 的性能,檢查是否能否使用索引,來避免額外的排序操作,如果無法使用索引,嘗試以下策略:
可以通過 EXPLIAN 查看 ORDER BY 是否使用了索引:
sort_mode 值提供了關于排序緩沖區(qū)中元組內(nèi)容的信息:
EXPLAIN 無法區(qū)分 filesort 是否在內(nèi)存中執(zhí)行??梢酝ㄟ^優(yōu)化器跟蹤輸出來查看 filesort 的內(nèi)存使用。查看 filesort_priority_queue_optimization
1.一條查詢語句如何執(zhí)行?
2.一條更新語句如何執(zhí)行?
3.innodb的redolog是什么?
4.什么是寫緩沖
5.寫緩沖一定好嗎?
6.什么情況會引發(fā)刷臟頁
關于一條mysql查詢語句在mysql中的執(zhí)行流程
如select name from test where id=10;
1.連接器---先與mysql服務端連接器建立連接,若查詢緩存命中則直接返回 (查詢緩存的弊端:查詢緩存的失效非常頻繁,只要有對一個表的更新,這個表上所有的查詢緩存都會被清空。)
2.分析器---詞法分析告訴服務端你要干什么(我要找 test表中id為10的名字) ( 其中sql語法錯誤在這塊暴露 )
3.優(yōu)化器---服務端會思考該怎么執(zhí)行最優(yōu)(索引的選擇)
4.執(zhí)行器---檢查用戶對庫對表的權(quán)限
5.存儲引擎--存儲數(shù)據(jù),提供讀寫接口
以update a set name=1 where id=1;
主要區(qū)別在于在查詢到數(shù)據(jù)之后(select name from a where id=1),如果是innodb引擎它會進行日志的兩階段提交:
1.開啟事務,寫入redolog(innodb引擎特有),并更新內(nèi)存
3.寫入binlog,提交事務,commit
我們知道m(xù)ysql數(shù)據(jù)存儲包含內(nèi)存與磁盤兩個部分,innodb是按數(shù)據(jù)頁(通常為16k)從磁盤讀取到內(nèi)存中的(剩余操作在內(nèi)存中執(zhí)行),當要更新數(shù)據(jù)時,若目標數(shù)據(jù)的數(shù)據(jù)頁剛好在內(nèi)存中,則直接更新。不在呢?
將這個更新操作(也可能是插入) 緩存在change buffer中 (redolog也會記錄這個change buffer操作)等到下一次查詢要用到這些數(shù)據(jù)時,再執(zhí)行這些操作,改變數(shù)據(jù)(稱為合并操作記錄稱為merge)。
innodb_change_buffer_max_size
innodb_change_buffering
先介紹兩個概念
因為redolog是環(huán)形日志,當redolog寫滿時,就需要“擦掉”開頭的一部分數(shù)據(jù)來達到循環(huán)寫,這里的擦掉指,指將redolog日志的checkpoint位置從 CP推進到CP‘ ,同時將兩點之間的臟頁刷到磁盤上(flush操作),此時系統(tǒng)要停止所有的更新操作(防止更新操作丟失)
1.系統(tǒng)內(nèi)存不足。當要讀取新的內(nèi)存頁時就要淘汰一些數(shù)據(jù)頁,如果淘汰的正好是臟頁,就要執(zhí)行一次flush操作
2.Mysql認為系統(tǒng)處于“空閑狀態(tài)”
3.正常關閉Mysql
上述后兩者場景(系統(tǒng)空閑和正常關閉)對于性能都沒太大影響。
當為第一種redolog寫滿時,系統(tǒng)無法執(zhí)行更新操作,所有操作都會堵塞
當為第二種內(nèi)存不夠用時,如果淘汰臟頁太多,影響mysql響應時間
后兩者刷臟頁會影響性能,所以Mysql需要有刷臟頁控制策略,可以從以下幾個設置項考慮
1.設置innodb_io_capacity告訴innodb所在主機的IO能力
你的問題太泛泛了,“MYSQL的程序”你指的是什么?是MYSQL的 存儲過程??您最好是具體問題具體問,你這樣提問的話大家都不知道你想要什么!
mysql soure example.sql里的soure寫錯了應該是source!!!!example.sql是你實現(xiàn)先編輯好的文本內(nèi)容,內(nèi)容可以是創(chuàng)建一個數(shù)據(jù)庫,然后再數(shù)據(jù)庫下建立一個或多個數(shù)據(jù)表,再往表里插入一些記錄??!然后再寫個存儲過程完成一些簡單的功能,比如把A表里的內(nèi)容插入到B表等等(可以加內(nèi)容存在就修改不存在就插入等判斷)?。〗⒁粋€.SQL文件就是為了方便??!隨便舉個例子:在D盤根目錄下用記事本建立個example.sql文件,內(nèi)容如下:
CREATE database name ;
use name;
CREATE TABLE a (
user_id int(11) DEFAULT NULL,
name char(11) DEFAULT NULL,
UNIQUE KEY USER_ID (user_id)
);
insert into a (user_id,name) values (1,'aaa'),(2,'bbb');
CREATE TABLE b (
user_id int(11) DEFAULT NULL,
name char(11) DEFAULT NULL,
UNIQUE KEY USER_ID (user_id)
);
insert into b (user_id,name) values (1,'xxx'),(3,'ccc');
DELIMITER $$
DROP PROCEDURE IF EXISTS qq$$
CREATE PROCEDURE qq()
begin
declare p_user_id varchar(6);
declare p_name varchar(6);
declare cursor_flag int default 0;
declare user_nrb cursor for select user_id,name from a;
declare continue handler for sqlstate '02000' set cursor_flag = 1;
open user_nrb;
repeat
fetch user_nrb into p_user_id,p_name;
if not cursor_flag then
if not exists (select * from b where user_id=p_user_id) then
insert into b(user_id,name)values(p_user_id,p_name);
else
update b set name=p_name where user_id=p_user_id;
end if;
end if;
until cursor_flag end repeat;
close user_nrb;
end$$
DELIMITER ;
順序是建立名為name的數(shù)據(jù)庫,其下建立倆表A和B,為A表插入用戶1和2,為B表插入用戶1,3?。≡俳⒚麨镼Q的存儲過程,功能是把a表的用戶導入到B表,如果A的用戶號再B里沒有直接插入,如果A里的用戶號已經(jīng)在B表里了那就改變B表里相應用戶的名字?。〈蟾攀沁@么個過程?。≡贛YSQL自帶的客戶端導入剛才建立的example.sql文件,順序是:開始——程序——MYSQL——MYSQL SERVER5.1——MYSQL COMMAND LINE CLIENT 窗口里輸入ROOT用戶密碼在光標處輸入source d:\example.sql!!最后再執(zhí)行存儲過程,敲call qq;回車?。?!
驗證方法是敲select * from b;回車??!可以發(fā)現(xiàn)B表由本來插入的2條記錄變成3條記錄,而且用戶1的名字也從xxx變成aaa了?。。?!
希望對你有幫助!另外最重要的是MYSQL有一些很好的圖形界面客戶端工具,不用這個DOS界面的東西,下載個sqlyog什么的軟件裝上,基本一啟動就會用了的東西!在SQLYOG的界面直接把example.sql里的內(nèi)容復制過來粘貼后按F5鍵運行即可?。?!
如果查詢緩存沒有命中,那么SQL請求會進入分析器,分析器是用來分辨SQL語句的執(zhí)行目的,其執(zhí)行過程大致分為兩步:
表1 語法分析關鍵字然后再通過語法規(guī)則解析,判斷輸入的SQL 語句是否滿足MySQL語法,并且生成圖5的語法樹。由SQL語句生成的四個單詞中,識別出兩個關鍵字,分別是select 和from。根據(jù)MySQL的語法Select 和 from之間對應的是fields 字段,下面應該掛接username;在from后面跟隨的是Tables字段,其下掛接的是userinfo。
優(yōu)化器的作用是對SQL進行優(yōu)化,生成最有的執(zhí)行方案。如圖6所示,前面提到的SQL解析器通過語法分析和語法規(guī)則生成了SQL語法樹。這個語法樹作為優(yōu)化器的輸入,而優(yōu)化器(黃色的部分)包含了邏輯變換和代價優(yōu)化兩部分的內(nèi)容。在優(yōu)化完成以后會生成SQL執(zhí)行計劃作為整個優(yōu)化過程的輸出,交給執(zhí)行器在存儲引擎上執(zhí)行。
所處的位置如上圖所示,這節(jié)的重點在優(yōu)化器中的邏輯變換和代價優(yōu)化上。
邏輯變換也就是在關系代數(shù)基礎上進行變換,其目的是為了化簡,同時保證SQL變化前后的結(jié)果一致,也就是邏輯變化并不會帶來結(jié)果集的變化。其主要包括以下幾個方面:
這樣講概念或許有些抽象,通過圖7 來看看邏輯變化如何在SQL中執(zhí)行的吧。
如圖7所示,從上往下共有4個步驟:
1. 針對存在的SQL語句,首先通過“否定消除”,去掉條件判斷中的“NOT”。語句由原來的“or”轉(zhuǎn)換成“and”,并且大于小于符號進行變號。藍色部分為修改前的SQL,紅色是修改以后的SQL。2. 等值傳遞,這一步很好理解分別降”t2.a=9” 和”t2.b=5”分別替換掉SQL中對應的值。3. 接下來就是常量表達式計算,將“5+7”計算得到“12”。4. 最后是常量表達式計算后的化簡,將”9=10”化簡為”true”帶入到最終的SQL表達式中完成優(yōu)化。
代價優(yōu)化是用來確定每個表,根據(jù)條件是否應用索引,應用哪個索引和確定多表連接的順序等問題。為了完成代價優(yōu)化,需要找到一個代價最小的方案。因此,優(yōu)化器是通過基于代價的計算方法來決定如何執(zhí)行查詢的(Cost-based Optimization)。簡化的過程如下:
這里將配置操作的代價分為MySQL 服務層和MySQL 引擎層,MySQL 服務層主要是定義CPU的代價,而MySQL 引擎層主要定義IO代價。MySQL 5.7 引入了兩個系統(tǒng)表mysql.server_cost和mysql.engine_cost來分別配置這兩個層的代價。如下:MySQL 服務層代價保存在表server_cost中,其具體內(nèi)容如下:
由上可以看出創(chuàng)建臨時表的代價是很高的,尤其是內(nèi)部的myisam或innodb臨時表。MySQL 引擎層代價保存在表engine_cost中,其具體內(nèi)容如下:
目前io_block_read_cost和memory_block_read_cost默認值均為1,實際生產(chǎn)中建議酌情調(diào)大memory_block_read_cost,特別是對普通硬盤的場景。MySQL會根據(jù)SQL查詢生成的查詢計劃中對應的操作從上面兩張代價表中查找對應的代價值,并且進行累加形成最終執(zhí)行SQL計劃的代價。再將多種可能的執(zhí)行計劃進行比較,選取最小代價的計劃執(zhí)行。
當分析器生成查詢計劃,并且經(jīng)過優(yōu)化器以后,就到了執(zhí)行器。執(zhí)行器會選擇執(zhí)行計劃開始執(zhí)行,但在執(zhí)行之前會校驗請求用戶是否擁有查詢的權(quán)限,如果沒有權(quán)限,就會返回錯誤信息,否則將會去調(diào)用MySQL引擎層的接口,執(zhí)行對應的SQL語句并且返回結(jié)果。例如SQL:“SELECT * FROM userinfo WHERE username = 'Tom';“假設 “username“ 字段沒有設置索引,就會調(diào)用存儲引擎從第一條開始查,如果碰到了用戶名字是” Tom“, 就將結(jié)果集返回,沒有查找到就查看下一行,重復上一步的操作,直到讀完整個表或者找到對應的記錄。需要注意SQL語句的執(zhí)行順序并不是按照書寫順序來的,順序的定義會在分析器中做好,一般是按照如下順序:
如果命中的記錄比較多,應用會從MySql Server一批批獲取數(shù)據(jù)
本文從MySQL中SQL語句的執(zhí)行過程作為切入點,首先介紹了查詢請求的執(zhí)行流程,其中將MySQL的處理分為MySQL Server層和MySQL存儲引擎層。通過介紹SQL語句的流轉(zhuǎn),引出了后面要介紹的5大組件,他們分別是:連接器、查詢緩存、分析器、優(yōu)化器、執(zhí)行器。后面的內(nèi)容中對每個組件進行了詳細的介紹。連接器,負責身份認證和權(quán)限鑒別;查詢緩存,將查詢的結(jié)果集進行緩存,提高查詢效率;分析器,對SQL語句執(zhí)行語法分析和語法規(guī)則,生成語法樹和執(zhí)行計劃;優(yōu)化器,包括邏輯變換和代價優(yōu)化;執(zhí)行器,在檢查用戶權(quán)限以后對數(shù)據(jù)進行逐條查詢,整個過程遵守SQL語句的執(zhí)行順序。
文章名稱:mysql是怎么執(zhí)行的,一條sql語句在mysql中如何執(zhí)行的
標題來源:http://aaarwkj.com/article34/dsiecse.html
成都網(wǎng)站建設公司_創(chuàng)新互聯(lián),為您提供微信公眾號、動態(tài)網(wǎng)站、自適應網(wǎng)站、企業(yè)建站、外貿(mào)建站、電子商務
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)