大家好犬缨,我是IT修真院上海分院碎节,一枚正直純潔善良的如剛?cè)腴T的Java程序員阻塑,今天試著給大家分享一下Select*from table的弊端
sql執(zhí)行流程機(jī)制:
1.客戶端發(fā)送一條查詢給服務(wù)器轻姿。
2.服務(wù)器先檢查查詢緩存臭笆,如果命中了緩存,則立刻返回存儲(chǔ)在緩存中的結(jié)果市咆。否則進(jìn)入下一階段汉操。
3。服務(wù)器端進(jìn)行SQL解析蒙兰,預(yù)處理磷瘤,再由優(yōu)化器生成對(duì)應(yīng)的執(zhí)行計(jì)劃
4。MySql根據(jù)優(yōu)化器生成的執(zhí)行計(jì)劃搜变,調(diào)用存儲(chǔ)引擎的API執(zhí)行查詢采缚。
5。返回結(jié)果給客戶端挠他。
具體用法:
-- 檢索單個(gè)列
SELECT prod_name FROM products;
-- 檢索多個(gè)列
SELECT prod_id, prod_name, prod_price FROM products;
-- 檢索所有的列
SELECT * FROM products;
-- 檢索不同的值
select distinct vend_id from products;
-- 限制結(jié)果 (MYSQL)
SELECT prod_name FROM products;
select prod_name from products limit 5;
select prod_name from products limit 3 offset 0; -- 從第0行開始扳抽,檢索3行
select prod_name from products limit 0, 3; -- 從第0行開始,檢索3行
問題分析:
1殖侵,數(shù)據(jù)庫需要知道*等于什么贸呢,查數(shù)據(jù)字典(進(jìn)行數(shù)據(jù)庫設(shè)計(jì)的時(shí)候,對(duì)數(shù)據(jù)庫元素進(jìn)行的解釋說明)拢军,這在分析階段就會(huì)增大開銷(實(shí)際上,ORACLE在解析的過程中, 會(huì)將’*’ 依次轉(zhuǎn)換成所有的列名, 這個(gè)工作是通過查詢數(shù)據(jù)字典完成的, 這意味著將耗費(fèi)更多的時(shí)間)楞陷。
2,select *最大的問題是可能會(huì)多出一些不用的列茉唉,這就杜絕了索引覆蓋的可能性固蛾,導(dǎo)致查詢的成本幾何級(jí)增高(索引覆蓋:就是select的數(shù)據(jù)列只用從索引中就能夠取得,不必從數(shù)據(jù)表中讀取赌渣,換句話說查詢列要被所使用的索引覆蓋魏铅。)
3,網(wǎng)絡(luò)開銷坚芜,不需要的字段會(huì)增加數(shù)據(jù)傳輸?shù)臅r(shí)間览芳,在本地客戶端連的是本地mysql服務(wù)器,TCP協(xié)議傳輸數(shù)據(jù)會(huì)增加額外的時(shí)間鸿竖;數(shù)據(jù)量越大這種這種劣勢(shì)就會(huì)越明顯沧竟;如果db和客戶端不在同一臺(tái)機(jī)器铸敏,比如鏈接到阿里云,那這種開銷就更加明顯
4悟泵,從另外一個(gè)相似的角度來看杈笔;就是查詢進(jìn)行的時(shí)候,多取了不必要的列糕非,數(shù)據(jù)字段比較多蒙具,mysql并不是把所有結(jié)果全部得到后再進(jìn)行一次性保存,而是每次分配一塊大小的內(nèi)存空間保存結(jié)果集朽肥,使用完后禁筏,接著再分配一個(gè)這樣的塊,如果還不不夠衡招,接著再分配一個(gè)塊篱昔,依此類推,也就是說始腾,有可能在一次查詢中mysqI要進(jìn)行多次內(nèi)存分配的操作州刽,頻繁操作內(nèi)存都是要耗費(fèi)時(shí)間的。
5浪箭,mysql拿到一條命令穗椅,會(huì)去解析命令、優(yōu)化查詢奶栖,然后去存儲(chǔ)引擎執(zhí)行查找房待,Select*數(shù)據(jù)庫會(huì)解析更多的 對(duì)象,字段驼抹,權(quán)限,屬性相關(guān)拜鹤,在 SQL 語句復(fù)雜框冀,會(huì)對(duì)數(shù)據(jù)庫造成沉重的負(fù)擔(dān)。選擇了實(shí)際不會(huì)用到的額外的列敏簿,就會(huì)導(dǎo)致優(yōu)化和效率問題明也。
6,原則上講作為有著良好編程習(xí)慣的程序員惯裕,也不應(yīng)該獲取自己不需要的東西温数,若是執(zhí)行select*,以后表結(jié)構(gòu)修改了蜻势,如原表加減了某些列撑刺,對(duì)代碼影響也很大。(源程序就會(huì)報(bào)錯(cuò)握玛,因?yàn)榱袛?shù)不對(duì)應(yīng)够傍。)
7甫菠,當(dāng)然,若是你想在SELECT子句中列出所有的COLUMN時(shí),使用動(dòng)態(tài)SQL列引用 ‘*’ 倒是是一個(gè)方便的方法冕屯,毫無疑問寂诱!對(duì)于一次性的查詢來說,使用Select *沒有任何問題安聘,不過要避免將它作為應(yīng)用開發(fā)代碼的一部分痰洒。程序員可能在代碼中編寫SQL來選擇數(shù)據(jù),并放入宿主變量字段浴韭。使用Select *時(shí)丘喻,必須為表中的每一列分別寫一個(gè)宿主變量。倘若表少了一列囱桨,或者表中增加了一個(gè)新列呢仓犬?如果發(fā)生這種情況,就需要調(diào)整源代碼舍肠。為了避免這種可能性搀继,首先就不要使用Select *。
索引拓展:
1翠语,唯一索引怎么判斷列唯一:先建立唯一索引叽躯, MySQL會(huì)在有新記錄插入數(shù)據(jù)表時(shí),自動(dòng)檢查新記錄的這個(gè)字段的值是否已經(jīng)在某個(gè)記錄的這個(gè)字段里出現(xiàn)過了肌括;如果是点骑,MySQL將拒絕插入那條新記錄。也就是說谍夭,唯一索引可以保證數(shù)據(jù)記錄的唯一性黑滴。事實(shí)上,在許多場(chǎng)合紧索,人們創(chuàng)建唯一索引的目的往往不是為了提高訪問速度袁辈,而只是為了避免數(shù)據(jù)出現(xiàn)重復(fù)。(唯一索引的異常珠漂,時(shí)由數(shù)據(jù)庫判斷晚缩,一次 insert 即可,然后程序捕獲異常處理)
最好是判斷一下媳危,插入之前先看看有沒有相同的記錄荞彼;當(dāng)然,不做判斷直接插入也是可以的待笑,如果沒異常,插入成功;如果捕捉到異常签夭,根據(jù)異常的類型齐邦,判斷有重復(fù)記錄,做出對(duì)應(yīng)業(yè)務(wù)處理第租。(去?SqlServer?官方要編號(hào)列表呀措拇。然后你的服務(wù)器維護(hù)這樣一個(gè)列表,就可以判斷哪種因素的原因了)
2慎宾,緩存機(jī)制的查看
show variables like "%cache";
show status like "%qcache%";
參考鏈接:
http://www.cnblogs.com/xinye/p/3823461.html
https://www.zhihu.com/question/37777220
http://bbs.csdn.net/topics/390302591?page=1#post-393091122
http://blog.csdn.net/wujizkm/article/details/50497642
http://blog.csdn.net/beauty_1991/article/details/51160072
http://blog.csdn.net/li563868273/article/details/51254907
今天的分享就到這里啦丐吓,剛學(xué)沒多久,水平不夠趟据,歡迎大家指正券犁,拍磚~
我的邀請(qǐng)碼:15686104,或者你可以直接點(diǎn)擊此鏈接http://www.jnshu.com/login/1/15686104