激情久久久_欧美视频区_成人av免费_不卡视频一二三区_欧美精品在欧美一区二区少妇_欧美一区二区三区的

服務(wù)器之家:專注于服務(wù)器技術(shù)及軟件下載分享
分類導(dǎo)航

Mysql|Sql Server|Oracle|Redis|MongoDB|PostgreSQL|Sqlite|DB2|mariadb|Access|數(shù)據(jù)庫技術(shù)|

服務(wù)器之家 - 數(shù)據(jù)庫 - Mysql - Mysql查詢語句優(yōu)化技巧

Mysql查詢語句優(yōu)化技巧

2020-06-06 17:07鹿偉偉 Mysql

這篇文章主要介紹了Mysql查詢語句優(yōu)化技巧的相關(guān)資料,需要的朋友可以參考下

索引優(yōu)化,查詢優(yōu)化,查詢緩存,服務(wù)器設(shè)置優(yōu)化,操作系統(tǒng)和硬件優(yōu)化,應(yīng)用層面優(yōu)化(web服務(wù)器,緩存)等等。這里的記錄的優(yōu)化技巧更適用于開發(fā)人員,都是從網(wǎng)絡(luò)上收集和自己整理的,主要是查詢語句上面的優(yōu)化,其它層面的優(yōu)化技巧在此不做記錄。

查詢的開銷指標(biāo):

執(zhí)行時間

檢查的行數(shù)

返回的行數(shù)

建立索引的幾個準(zhǔn)則:

(1)、合理的建立索引能夠加速數(shù)據(jù)讀取效率,不合理的建立索引反而會拖慢數(shù)據(jù)庫的響應(yīng)速度。

(2)、索引越多,更新數(shù)據(jù)的速度越慢。

(3)、盡量在采用MyIsam作為引擎的時候使用索引(因為MySQL以BTree存儲索引),而不是InnoDB。但MyISAM不支持

Transcation。

(4)、當(dāng)你的程序和數(shù)據(jù)庫結(jié)構(gòu)/SQL語句已經(jīng)優(yōu)化到無法優(yōu)化的程度,而程序瓶頸并不能順利解決,那就是應(yīng)該考慮使用諸如memcached這樣的分布式緩存系統(tǒng)的時候了。

(5)、習(xí)慣和強迫自己用EXPLAIN來分析你SQL語句的性能。

一、count的優(yōu)化

比如:計算id大于5的城市

?
1
2
select count(*) from world.city where id > ;
select (select count() from world.city) – count() from world.city where id <= ;

a語句當(dāng)行數(shù)超過11行的時候需要掃描的行數(shù)比b語句要多, b語句掃描了6行,此種情況下,b語句比a語句更有效率。當(dāng)沒有where語句的時候直接select count(*) from world.city這樣會更快,因為mysql總是知道表的行數(shù)。

二、避免使用不兼容的數(shù)據(jù)類型

例如float和int、char和varchar、binary和varbinary是不兼容的。數(shù)據(jù)類型的不兼容可能使優(yōu)化器無法執(zhí)行一些本來可以進行的優(yōu)化操作。

在程序中,保證在實現(xiàn)功能的基礎(chǔ)上,盡量減少對數(shù)據(jù)庫的訪問次數(shù);通過搜索參數(shù),盡量減少對表的訪問行數(shù),最小化結(jié)果集,從而減輕網(wǎng)絡(luò)負(fù)擔(dān);能夠分開的操作盡量分開處理,提高每次的響應(yīng)速度;在數(shù)據(jù)窗口使用SQL時,盡量把使用的索引放在選擇的首列;算法的結(jié)構(gòu)盡量簡單;在查詢時,不要過多地使用通配符如 SELECT * FROM T1語句,要用到幾列就選擇幾列如:SELECT COL1,COL2 FROM T1;在可能的情況下盡量限制盡量結(jié)果集行數(shù)如:SELECT TOP 300 COL1,COL2,COL3 FROM T1,因為某些情況下用戶是不需要那么多的數(shù)據(jù)的。不要在應(yīng)用中使用數(shù)據(jù)庫游標(biāo),游標(biāo)是非常有用的工具,但比使用常規(guī)的、面向集的SQL語句需要更大的開銷;按照特定順序提取數(shù)據(jù)的查找。

三、索引字段上進行運算會使索引失效

盡量避免在WHERE子句中對字段進行函數(shù)或表達式操作,這將導(dǎo)致引擎放棄使用索引而進行全表掃描。如:

?
1
SELECT * FROM T1 WHERE F1/2=100 應(yīng)改為: SELECT * FROM T1 WHERE F1=100*2

四、避免使用!=或<>、IS NULL或IS NOT NULL、IN ,NOT IN等這樣的操作符

因為這會使系統(tǒng)無法使用索引,而只能直接搜索表中的數(shù)據(jù)。例如: SELECT id FROM employee WHERE id != “B%” 優(yōu)化器將無法通過索引來確定將要命中的行數(shù),因此需要搜索該表的所有行。在in語句中能用exists語句代替的就用exists.

五、盡量使用數(shù)字型字段

一部分開發(fā)人員和數(shù)據(jù)庫管理人員喜歡把包含數(shù)值信息的字段

設(shè)計為字符型,這會降低查詢和連接的性能,并會增加存儲開銷。這是因為引擎在處理查詢和連接回逐個比較字符串中每一個字符,而對于數(shù)字型而言只需要比較一次就夠了。

六、合理使用EXISTS,NOT EXISTS子句

如下所示:

?
1
2
SELECT SUM(T1.C1) FROM T1 WHERE (SELECT COUNT(*)FROM T2 WHERE T2.C2=T1.C2>0)
SELECT SUM(T1.C1) FROM T1WHERE EXISTS(SELECT * FROM T2 WHERE T2.C2=T1.C2)

兩者產(chǎn)生相同的結(jié)果,但是后者的效率顯然要高于前者。因為后者不會產(chǎn)生大量鎖定的表掃描或是索引掃描。如果你想校驗表里是否存在某條紀(jì)錄,不要用count(*)那樣效率很低,而且浪費服務(wù)器資源。可以用EXISTS代替。如:

?
1
IF (SELECT COUNT() FROM table_name WHERE column_name = ‘xxx')可以寫成:IF EXISTS (SELECT FROM table_name WHERE column_name = ‘xxx')

七、 能夠用BETWEEN的就不要用IN

八、 能夠用DISTINCT的就不用GROUP BY

九、盡量不要用SELECT INTO語句

SELECT INTO 語句會導(dǎo)致表鎖定,阻止其他用戶訪問該表

十、 必要時強制查詢優(yōu)化器使用某個索引

?
1
2
SELECT * FROM T1 WHERE nextprocess = 1 AND processid IN (8,32,45) 改成:
SELECT * FROM T1 (INDEX = IX_ProcessID) WHERE nextprocess = 1 AND processid IN (8,32,45)

則查詢優(yōu)化器將會強行利用索引IX_ProcessID 執(zhí)行查詢。

十一、消除對大型表行數(shù)據(jù)的順序存取

盡管在所有的檢查列上都有索引,但某些形式的WHERE子句強迫優(yōu)化器使用順序存取。如:

?
1
SELECT * FROM orders WHERE (customer_num=104 AND order_num>1001) OR order_num=1008

解決辦法可以使用并集來避免順序存取:

?
1
SELECT * FROM orders WHERE customer_num=104 AND order_num>1001 UNION SELECT * FROM orders WHERE order_num=1008

這樣就能利用索引路徑處理查詢。【jacking 數(shù)據(jù)結(jié)果集很多,但查詢條件限定后結(jié)果集不大的情況下,后面的語句快】

十二、盡量避免在索引過的字符數(shù)據(jù)中,使用非打頭字母搜索。

這也使得引擎無法利用索引

見如下例子:

?
1
2
3
SELECT * FROM T1 WHERE NAME LIKE ‘%L%'
SELECT * FROM T1 WHERE SUBSTING(NAME,2,1)='L'
SELECT * FROM T1 WHERE NAME LIKE ‘L%'

即使NAME字段建有索引,前兩個查詢依然無法利用索引完成加快操作,引擎不得不對全表所有數(shù)據(jù)逐條操作來完成任務(wù)。而第三個查詢能夠使用索引來加快操作,不要習(xí)慣性的使用 ‘%L%'這種方式(會導(dǎo)致全表掃描),如果可以使用`L%'相對來說更好;

十三、雖然UPDATE、DELETE語句的寫法基本固定,但是還是對UPDATE語句給點建議

(1). 盡量不要修改主鍵字段。

(2). 當(dāng)修改VARCHAR型字段時,盡量使用相同長度內(nèi)容的值代替。

(3). 盡量最小化對于含有UPDATE觸發(fā)器的表的UPDATE操作。

(4). 避免UPDATE將要復(fù)制到其他數(shù)據(jù)庫的列。

(5). 避免UPDATE建有很多索引的列。

(6). 避免UPDATE在WHERE子句條件中的列。

十四、能用UNION ALL就不要用UNION

UNION ALL不執(zhí)行SELECT DISTINCT函數(shù),這樣就會減少很多不必要的資源

在跨多個不同的數(shù)據(jù)庫時使用UNION是一個有趣的優(yōu)化方法,UNION從兩個互不關(guān)聯(lián)的表中返回數(shù)據(jù),這就意味著不會出現(xiàn)重復(fù)的行,同時也必須對數(shù)據(jù)進行排序,我們知道排序是非常耗費資源的,特別是對大表的排序。

UNION ALL可以大大加快速度,如果你已經(jīng)知道你的數(shù)據(jù)不會包括重復(fù)行,或者你不在乎是否會出現(xiàn)重復(fù)的行,在這兩種情況下使用UNION ALL更適合。此外,還可以在應(yīng)用程序邏輯中采用某些方法避免出現(xiàn)重復(fù)的行,這樣UNION ALL和UNION返回的結(jié)果都是一樣的,但UNION ALL不會進行排序。

十五、字段數(shù)據(jù)類型優(yōu)化

(1). 避免使用NULL類型:NULL對于大多數(shù)數(shù)據(jù)庫都需要特殊處理,MySQL也不例外,它需要更多的代碼,更多的檢查和特殊的索引邏輯,有些開發(fā)人員完全沒有意識到,創(chuàng)建表時NULL是默認(rèn)值,但大多數(shù)時候應(yīng)該使用NOT NULL,或者使用一個特殊的值,如0,-1作為默認(rèn)值。

(2). 盡可能使用更小的字段,MySQL從磁盤讀取數(shù)據(jù)后是存儲到內(nèi)存中的,然后使用cpu周期和磁盤I/O讀取它,這意味著越小的數(shù)據(jù)類型占用的空間越小,從磁盤讀或打包到內(nèi)存的效率都更好,但也不要太過執(zhí)著減小數(shù)據(jù)類型,要是以后應(yīng)用程序發(fā)生什么變化就沒有空間了。修改表將需要重構(gòu),間接地可能引起代碼的改變,這是很頭疼的問題,因此需要找到一個平衡點。

(3). 優(yōu)先使用定長型

十七、關(guān)于大數(shù)據(jù)量limit分布的優(yōu)化(當(dāng)偏移量特別大時,limit效率會非常低)

附上一個提高limit效率的簡單技巧,在覆蓋索引(覆蓋索引用通俗的話講就是在select的時候只用去讀取索引而取得數(shù)據(jù),無需進行二次select相關(guān)表)上進行偏移,而不是對全行數(shù)據(jù)進行偏移。可以將從覆蓋索引上提取出來的數(shù)據(jù)和全行數(shù)據(jù)進行聯(lián)接,然后取得需要的列,會更有效率,看看下面的查詢:

?
1
mysql> select film_id, description from sakila.film order by title limit 50, 5;

如果表非常大,這個查詢最好寫成下面的樣子:

?
1
2
mysql> select film.film_id, film.description from sakila.film
inner join(select film_id from sakila.film order by title liimit 50,5) as film usinig(film_id);

十八、程序中如果一次性對同一個表插入多條數(shù)據(jù)

比如以下語句:

?
1
2
3
insert into person(name,age) values(‘xboy', 14);
insert into person(name,age) values(‘xgirl', 15);
insert into person(name,age) values(‘nia', 19);

把它拼成一條語句執(zhí)行效率會更高.

?
1
insert into person(name,age) values(‘xboy', 14), (‘xgirl', 15),(‘nia', 19);

十九、不要在選擇的欄位上放置索引,這是無意義的。

應(yīng)該在條件選擇的語句上合理的放置索引,比如where,order by

?
1
SELECT id,title,content,cat_id FROM article WHERE cat_id = 1;

上面這個語句,你在id/title/content上放置索引是毫無意義的,對這個語句沒有任何優(yōu)化作用。但是如果你在外鍵cat_id上放置一個索引,那作用就相當(dāng)大了。

二十、ORDER BY語句的MySQL優(yōu)化

(1). ORDER BY + LIMIT組合的索引優(yōu)化。如果一個SQL語句形如:

?
1
SELECT [column1],[column2],…. FROM [TABLE] ORDER BY [sort] LIMIT [offset],[LIMIT];

這個SQL語句優(yōu)化比較簡單,在[sort]這個欄位上建立索引即可。

(2). WHERE + ORDER BY + LIMIT組合的索引優(yōu)化,形如:

?
1
SELECT [column1],[column2],…. FROM [TABLE] WHERE [columnX] = [VALUE] ORDER BY [sort] LIMIT [offset],[LIMIT];

這個語句,如果你仍然采用第一個例子中建立索引的方法,雖然可以用到索引,但是效率不高。更高效的方法是建立一個聯(lián)合索引(columnX,sort)

(3). WHERE + IN + ORDER BY + LIMIT組合的索引優(yōu)化,形如:

?
1
SELECT [column1],[column2],…. FROM [TABLE] WHERE [columnX] IN ([value1],[value2],…) ORDER BY [sort] LIMIT [offset],[LIMIT];

這個語句如果你采用第二個例子中建立索引的方法,會得不到預(yù)期的效果(僅在[sort]上是using index,WHERE那里是using where;using filesort),理由是這里對應(yīng)columnX的值對應(yīng)多個。

目前哥還木有找到比較優(yōu)秀的辦法,等待高手指教。

(4).WHERE+ORDER BY多個欄位+LIMIT,比如:

?
1
SELECT * FROM [table] WHERE uid=1 ORDER x,y LIMIT 0,10;

對于這個語句,大家可能是加一個這樣的索引:(x,y,uid)。但實際上更好的效果是(uid,x,y)。這是由MySQL處理排序的機制造成的。

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 中国fx性欧美xxxx | 久久精品国产99久久6动漫亮点 | 欧美一区二区三区久久久久久桃花 | 国产一级aa大片毛片 | 久色网站 | 91成人免费看片 | 久久免费视频精品 | 99这里有精品 | 日本最新免费二区三区 | 久久人人97超碰国产公开结果 | 日日狠狠久久 | 石原莉奈日韩一区二区三区 | 国产手机av在线 | 精品呦女 | 国产在线精品一区二区三区不卡 | 九九精品免费 | 成人一级黄色片 | 沉沦的校花奴性郑依婷c到失禁 | 综合网日日天干夜夜久久 | 青青操国产 | 中文在线国产 | 麻豆小视频在线观看 | 国产一区在线免费 | 久久久久久久久日本理论电影 | 羞羞视频入口 | 一区二区三区黄色 | 精品国产一区二区三区四 | 12av毛片| 久久久成人精品 | 一级影片在线观看 | 午夜丰满少妇高清毛片1000部 | 91久久91久久精品免观看 | 黄在线看| 国产一级做a爰片在线看 | 黄色7777| 日本高清在线免费 | 中文字幕在线播放视频 | 91免费版在线观看 | 成人网在线观看 | 国产一区二区三区四区精 | 国产午夜免费视频 |