Mysql優化技巧

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

建立索引的幾個準則:

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

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

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

(4)、當你的程序和數據庫結構/SQL語句已經優化到無法優化的程度,而程序瓶頸并不能順利解決,那就是應該考慮使用諸如memcached這樣的分布式緩存系統的時候了。

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


1count的優化

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


(1). select count(*) from world.city where id > 5;

(2). select (select count() from world.city) – count() from world.city where id <= 5;


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


2避免使用不兼容的數據類型

例如float和int、char和varchar、binary和varbinary是不兼容的。數據類型的不兼容可能使優化器無法執行一些本來可以進行的優化操作。


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


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

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

SELECT * FROM T1 WHERE F1/2=100 應改為: SELECT * FROM T1 WHERE F1=100*2


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

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


5盡量使用數字型字段

一部分開發人員和數據庫管理人員喜歡把包含數值信息的字段設計為字符型,這會降低查詢和連接的性能,并會增加存儲開銷。這是因為引擎在處理查詢和連接回逐個比較字符串中每一個字符,而對于數字型而言只需要比較一次就夠了。


6合理使用EXISTS,NOT EXISTS子句

如下所示:

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

(2). SELECT SUM(T1.C1) FROM T1WHERE EXISTS(SELECT * FROM T2 WHERE T2.C2=T1.C2)


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

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


7能夠用BETWEEN的就不要用IN


8能夠用DISTINCT的就不用GROUP BY


9盡量不要用SELECT INTO語句。SELECT INTO 語句會導致表鎖定,阻止其他用戶訪問該表


10必要時強制查詢優化器使用某個索引

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)

則查詢優化器將會強行利用索引IX_ProcessID 執行查詢。


11消除對大型表行數據的順序存取

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

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

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

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

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


12盡量避免在索引過的字符數據中,使用非打頭字母搜索。這也使得引擎無法利用索引

見如下例子:

SELECT * FROM T1 WHERE NAME LIKE ‘%L%’

SELECT * FROM T1 WHERE SUBSTING(NAME,2,1)=’L’

SELECT * FROM T1 WHERE NAME LIKE ‘L%’

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


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

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

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

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

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

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

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


14能用UNION ALL就不要用UNION

UNION ALL不執行SELECT DISTINCT函數,這樣就會減少很多不必要的資源

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

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


15字段數據類型優化

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

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

(3). 優先使用定長型


16關于大數據量limit分布的優化(當偏移量特別大時,limit效率會非常低)

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


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


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


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);


17程序中如果一次性對同一個表插入多條數據

比如以下語句:


insert into person(name,age) values(‘xboy’, 14);


insert into person(name,age) values(‘xgirl’, 15);


insert into person(name,age) values(‘nia’, 19);


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


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


18不要在選擇的欄位上放置索引,這是無意義的。應該在條件選擇的語句上合理的放置索引,比如where,order by

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


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


19ORDER BY語句的MySQL優化

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


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


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


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


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


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


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


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


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


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


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


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


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

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/386062.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/386062.shtml
英文地址,請注明出處:http://en.pswp.cn/news/386062.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【工作經驗分享】不會真有人覺得mybatis很難學吧

什么是自旋鎖和互斥鎖&#xff1f; 由于CLH鎖是一種自旋鎖&#xff0c;那么我們先來看看自旋鎖是什么&#xff1f; 自旋鎖說白了也是一種互斥鎖&#xff0c;只不過沒有搶到鎖的線程會一直自旋等待鎖的釋放&#xff0c;處于busy-waiting的狀態&#xff0c;此時等待鎖的線程不會…

華為面試題

技術面試&#xff1a; java&#xff1a; java學了幾年&#xff0c;看過什么書&#xff0c;有沒有看過thinking in java這本書 java的公共父類是什么&#xff0c;object類中有什么方法 object中有個hashcode方法&#xff0c;這個方法是用來做什么的&#xff0c; equal 與 的區…

【工作經驗分享】這些新技術你們都知道嗎

前言 近年來&#xff0c;微服務架構(Microservices Architecture)已經成為一種主流的軟件開發方法論&#xff0c;所謂微服務( Microservices ),就是一些具有足夠小的粒度、能夠相互協作且自治的服務體系。 微服務架構基于分布式系統&#xff0c;同時借助了面向服務架構和企業服…

京東面試題(JAVA)

京東17號一面問題與回答情況&#xff08;Java崗&#xff09; 作者&#xff1a;牛客190525號 Q1: HashMap的原理, 以及HashMap如何擴充bucket的大小 A1: 原理答上來了&#xff0c;如何擴容瞎答的&#xff0c;之前不知道擴容之后已經哈希的MapEntry如何處理&#xff0c;當時就…

【微信小程序】使用Hystrix的插件機制

前言 在本篇文章開始前&#xff0c;我想想來回答一個問題&#xff1a;我為什么要寫這一篇關于面試的文章&#xff1f; 原因有三&#xff1a;第一&#xff0c;我想為每一個為夢想時刻準備著的”有心人“盡一份自己的力量&#xff0c;提供一份高度精華的Java面試清單&#xff1…

大話數據結構——數據結構緒論

數據&#xff1a;描述客觀事物的符號&#xff0c;是計算機可以操作的對象&#xff0c;是能被計算機識別&#xff0c;并輸入給計算機處理的符號集合。 有兩個要素&#xff1a; 可以輸入到計算機中能被計算機程序處理 數據元素&#xff1a;組成數據的基本單位&#xff0c;也就…

【微信小程序】目前最全的《Java面試題及解析》

開頭 在找工作的過程中&#xff0c;對于 Redis 技術知識的掌握已經成為必須的技能。美團面試常常就會被問到Redis相關知識&#xff0c;而這次我就差點倒在了美團3面&#xff0c;面試官連問我以下幾個Redis的問題&#xff0c;然后就卡殼了… redis了解嗎&#xff1f;你說說怎么…

大話數據結構——算法

算法&#xff1a;算法是解決特定問題求解步驟的描述&#xff0c;在計算機中表現為指令的有限序列&#xff0c;并且每條指令表示一個或多個操作。 為什么把數據結構和算法一起說&#xff1f; 想想羅密歐與朱麗葉&#xff0c;梁山伯和祝英臺&#xff0c;少了一個你總會覺得奇怪…

java線上培訓班學費一般多少,成長路線圖

前言 眾所皆知的&#xff0c;Linux的核心原型是1991年由托瓦茲(Linus Torvalds)寫出來的&#xff0c;但是托瓦茲為何可以寫出Linux這個操作系統?為什么它要選擇386的計算機來開發?為什么Linux的發展可以這么迅速?又為什么Linux是免費的?以及目前為何有這么多的 Linux版本(…

將visio的圖片插入latex(png格式轉換成eps格式圖片)

EPS和PDF轉換工具&#xff1a;http://www.xdowns.com/tag.asp?keywordEPS%D7%AApdf 這個軟件親測可以轉換&#xff0c;但是&#xff0c;仍然不能插入latex中&#xff0c;就像之前曾嘗試強制改變后綴名轉成eps一樣&#xff0c;效果是不佳的。 樓主的圖是在visio上畫的&#x…

java線程池使用實戰,太牛了!

前言 今天這篇文章中簡單介紹一下一個 Java 程序員必知的 Linux 的一些概念以及常見命令。 如果文章有任何需要改善和完善的地方&#xff0c;歡迎在評論區指出&#xff0c;共同進步&#xff01;筆芯&#xff01; 正式開始 Linux 之前&#xff0c;簡單花一點點篇幅科普一下操作…

大數據基礎技術和應用

大數據概述 數據的表現形式&#xff1a; 線下數據信息化&#xff1a;數據庫、文字記錄、照片……互聯網-移動互聯網&#xff1a;網頁數據、用戶行為記錄、數字圖像……傳感器&#xff1a;設備監控、智能家居、攝像頭…… 大數據的4V特征&#xff1a; 大量化&#xff08;Vol…

java線程池參數面試題,附贈復習資料

前言 作為同時具備高性能、高可靠和高可擴展性的典型鍵值數據庫&#xff0c;Redis不僅功能強大&#xff0c;而且穩定&#xff0c;理所當然地成為了大型互聯網公司的首選。 眾多大廠在招聘的時候&#xff0c;不僅會要求面試者能簡單地使用Redis&#xff0c;還要能深入地理解底…

Hadoop 大數據平臺架構與實踐

初識Hadoop Hadoop是一個開源的分布式存儲分布式計算平臺。 Hadoop核心組成部分&#xff1a; HDFS&#xff1a;分布式文件系統&#xff0c;存儲海量的數據。MapReduce&#xff1a;并行處理框架&#xff0c;實現任務分解和調度。 Hadoop可以用來做什么&#xff1f; 搭建大型…

java線程池有幾種,講的太透徹了

前言 該文檔在Github上收獲40Kstar的Java面試神技&#xff08;這贊數&#xff0c;質量多高就不用我多說了吧&#xff09;非常全面&#xff0c;包涵Java基礎、Java集合、JavaWeb、Java異常、OOP、IO與NIO、反射、注解、多線程、JVM、MySQL、MongoDB、Spring全家桶、計算機網絡、…

HIVE入門

Hive概述 什么是 Hive&#xff1f; * Hive 是建立在 Hadoop HDFS 上的數據庫倉庫基礎建構 * Hive 可以用來進行數據庫提取轉化加載&#xff08;ETL&#xff09; * Hive 定義了簡單的類似 SQL 查詢語言&#xff0c;稱為 HQL&#xff0c;它允許熟悉 SQL 的用戶查詢數據 * Hi…

java線程面試題博客園,超詳細

簡介 HikariCP 是用于創建和管理連接&#xff0c;利用“池”的方式復用連接減少資源開銷&#xff0c;和其他數據源一樣&#xff0c;也具有連接數控制、連接可靠性測試、連接泄露控制、緩存語句等功能&#xff0c;另外&#xff0c;和 druid 一樣&#xff0c;HikariCP 也支持監控…

java編寫斐波那契數列,實戰案例

前言 提到插件&#xff0c;相信大家都知道&#xff0c;插件的存在主要是用來改變或者增強原有的功能&#xff0c;MyBatis中也一樣。然而如果我們對MyBatis的工作原理不是很清楚的話&#xff0c;最好不要輕易使用插件&#xff0c;否則的話如果因為使用插件導致了底層工作邏輯被…

用戶畫像

用戶畫像&#xff1a;標簽化、 用標簽描述用戶行為 用戶畫像&#xff1a;動態信息數據 用戶行為產生的數據&#xff1a;注冊、瀏覽、點擊、購買、簽收、評價 比較重要的行為&#xff1a;購買商品、瀏覽商品、放入購物車、關注商品 用戶畫像的用途&#xff1a;分類統計&…

java編程代寫有哪些平臺,學習路線+知識點梳理

前言 今天剛好有空&#xff0c;跟大家聊聊如何學好算法進大廠。 前兩天一個讀者和我說&#xff0c;他堅持刷算法題2個月&#xff0c;薪資翻番去了他夢寐以求的大廠&#xff0c;期間面字節跳動還遇到了原題…其實據我所知目前國內的大廠和一些獨角獸&#xff0c;已經越來越效仿…