搜尋
首頁資料庫mysql教程超詳細匯總mysql優化實踐技巧

這篇文章為大家帶來了關於mysql的相關知識,其中主要總結了二十一個mysql優化的實踐技巧,下面就一起來看一下這二十一個優化技巧,希望對大家有幫助。

超詳細匯總mysql優化實踐技巧

推薦學習:mysql影片教學

#今天,資料庫的操作越來越成為整個應用的效能瓶頸了,這點對於Web 應用尤其明顯。關於資料庫的效能,這不只是 DBA 需要擔心的事,而這更是我們程式設計師需要去關注的事情。當我們去設計資料庫表結構,對操作資料庫時(尤其是查表時的 SQL 語句),我們都需要注意資料運算的效能。這裡,我們不會講過多的 SQL 語句的最佳化,而只是針對 MySQL 這一 Web 應用最多的資料庫。希望下面的這些最佳化技巧對你有用

1.為查詢快取最佳化你的查詢

大多數的 MySQL 伺服器都開啟了查詢快取。這是提高性最有效的方法之一,而且這是由 MySQL 的資料庫引擎處理的。當有很多相同的查詢被執行了多次的時候,這些查詢結果會被放到一個快取中,這樣,後續的相同的查詢就不用操作表而直接存取快取結果了。
這裡最主要的問題是,對程式設計師來說,這個事情是很容易被忽略的。因為,我們某些查詢語句會讓 MySQL 不使用快取。請看下面的範例:

超詳細匯總mysql優化實踐技巧

上面兩個SQL 語句的差異就是CURDATE() ,MySQL 的查詢快取對這個函數不起作用。所以,像 NOW()RAND() 或是其它的諸如此類的 SQL 函數都不會開啟查詢緩存,因為這些函數的傳回是會不定的易變的。所以,你所需要的就是用一個變數來取代 MySQL 的函數,從而開啟快取。

2. EXPLAIN 你的SELECT 查詢

使用EXPLAIN 關鍵字可以讓你知道MySQL 是如何處理你的SQL 語句的。這可以幫你分析你的查詢語句或是表格結構的效能瓶頸。
EXPLAIN 的查詢結果也會告訴你你的索引主鍵被如何利用的,你的資料表是如何被搜尋和排序的…等等,等等。
挑一個你的 SELECT 語句(推薦挑選那個最複雜的,有多表聯接的),把關鍵字 EXPLAIN 加到前面。你可以使用 phpmyadmin 來做這個事。然後,你會看到一張表格。下面的這個範例中,我們忘記加上了group_id 索引,並且有表聯接:

超詳細匯總mysql優化實踐技巧

當我們為group_id 欄位加上索引後:
超詳細匯總mysql優化實踐技巧
我們可以看到,前一個結果顯示搜尋了7883 行,而後一個只是搜尋了兩個表的9 和16 行。查看 rows 列可以讓我們找到潛在的效能問題。

3. 當只要一行資料時使用LIMIT 1 1

當你查詢表的有些時候,你已經知道結果只會有一個結果,但因為你可能需要去fetch 遊標,或是你或許會去檢查回傳的記錄數。
在這種情況下,加上 LIMIT 1 可以增加效能。這樣一樣,MySQL 資料庫引擎會在找到一筆資料後停止搜索,而不是繼續往後查少下一筆符合記錄的資料。
下面的範例,只是為了找一下是否有「中國」的用戶,很明顯,後面的會比前面的更有效率。 (請注意,第一條中是Select *,第二條是Select 1)

超詳細匯總mysql優化實踐技巧

##4 . 為搜尋欄位建立索引

索引不一定就是給主鍵或是唯一的欄位。如果在你的表中,有某個字段你總是要會經常用來做搜索,那麼,請為其建立索引吧

超詳細匯總mysql優化實踐技巧

從上圖你可以看到那個搜尋字串“last_name LIKE 'a%'”,一個是建立了索引,一個是沒有索引,效能差了4倍左右。
另外,你應該也需要知道什麼樣的搜尋是不能使用正常的索引的。例如,當你需要在一篇大的文章中搜尋一個字時,如: “WHERE post_content LIKE ‘%apple%’”,索引可能是沒有意義的。你可能需要使用MySQL 全文索引或是自己做一個索引(比如說:搜尋關鍵字或是Tag 什麼的)

5. 在Join 表的時候使用相同類型的範例

如果你的應用程式有很多JOIN 查詢,你應該確認兩個表中Join 的欄位是被建立索引的。這樣,MySQL 內部會啟動為你優化 Join 的 SQL 語句的機制。
而且,這些被用來 Join 的字段,應該是相同的類型的。例如:如果你要把DECIMAL 欄位和一個 INT 欄位 Join 在一起,MySQL 就無法使用它們的索引。對於那些 STRING 型,還需要有相同的字元集才行。 (兩個表格的字元集有可能不一樣)

超詳細匯總mysql優化實踐技巧

6. 千萬不要ORDER BY RAND()

想打亂回傳的資料行?隨機挑一個資料?真不知道誰發明了這種用法,但很多新手很喜歡這樣用。但你確不了解這樣做有多可怕的效能問題。
如果你真的想把回傳的資料行打亂了,你有 N 種方法可以達到這個目的。這樣使用只讓你的資料庫的效能呈指數級的下降。這裡的問題是:MySQL 會不得不去執行 RAND()函數(很耗 CPU 時間),而且這是為了每一行記錄去記行,然後再對其排序。就算是你用了Limit 1 也無濟於事(因為要排序)

下面的範例是隨機挑一筆記錄:
超詳細匯總mysql優化實踐技巧

#7.避免SELECT *

從資料庫裡讀出越多的數據,那麼查詢就會變得越慢。並且,如果你的資料庫伺服器和 WEB 伺服器是兩台獨立的伺服器的話,這也會增加網路傳輸的負載。所以,你應該養成一個需要什麼就取什麼的好的習慣
超詳細匯總mysql優化實踐技巧

8. 永遠為每個表設定一個ID

我們應該為資料庫裡的每張表都設定一個ID 做為其主鍵,而且最好的是一個INT 型的(建議使用UNSIGNED),並設定上自動增加的AUTO_INCREMENT 標誌。
就算是你 users 表有一個主鍵叫 “email”的字段,你也別讓它成為主鍵。使用 VARCHAR 型別來當主鍵會使用得效能下降。另外,在你的程式中,你應該使用表格的 ID 來建構你的資料結構。
而且,在MySQL 資料引擎下,還有一些操作需要使用主鍵,在這些情況下,主鍵的效能和設定變得非常重要,例如,集群,分區…
在這裡,只有一個情況是例外,那就是“關聯表”的“外鍵”,也就是說,這個表的主鍵,透過若干個別的表的主鍵構成。我們把這個情況叫做「外鍵」。例如:有一個「學生表」有學生的ID,有一個「課表」有課程ID,那麼,「成績表」就是「關聯表」了,其關聯了學生表和課程表,在成績表中,學生ID 和課程ID 叫「外鍵」其共同組成主鍵。

9. 使用 ENUM 而不是 VARCHAR

ENUM 類型是非常快速且緊密的。在實際上,其保存的是 TINYINT,但其外表上顯示為字串。這樣一來,用這個欄位來做一些選項清單變得相當的完美。
如果你有一個字段,例如“性別”,“國家”,“民族”,“狀態”或“部門”,你知道這些字段的取值是有限而且固定的,那麼,你應該使用ENUM而不是VARCHAR
MySQL 也有一個「建議」(見第十條)告訴你怎麼去重新組織你的表格結構。當你有一個 VARCHAR 欄位時,這個建議會告訴你把其改成 ENUM 類型。使用PROCEDURE ANALYSE() 你可以得到相關的建議

10. 從PROCEDURE ANALYSE() 取得建議

PROCEDURE ANALYSE() 會讓MySQL 幫你分析你的欄位和其實際的數據,並會給你一些有用的建議。只有表中有實際的數據,這些建議才會變得有用,因為要做一些大的決定是需要有數據作為基礎的。
例如,如果你建立了一個INT 欄位作為你的主鍵,然而並沒有太多的數據,那麼,PROCEDURE ANALYSE()會建議你把這個欄位的型別改成 MEDIUMINT 。或者你使用了一個 VARCHAR 字段,因為數據不多,你可能會得到一個讓你把它
改成 ENUM 的建議。這些建議,都是可能因為數據不夠多,所以決策做得就不夠準。
phpmyadmin 裡,你可以在查看表格時,點擊「Propose table structure」 來查看這些建議

超詳細匯總mysql優化實踐技巧

一定要注意,這些只是建議,只有當你的表裡的數據越來越多時,這些建議才會變得準確。一定要記住,你才是最終做決定的人

11. 盡可能的使用NOT NULL

除非你有一個很特別的原因去使用NULL 值,你應該總是讓你的欄位保持NOT NULL。這看起來好像有點爭議,請往下看。
首先,問你自己「Empty」和「NULL」有多大的差別(如果是INT,那就是0 和NULL)?如果你覺得它們之間沒有什麼差別,那麼你就不要使用NULL。 (你知道嗎?在Oracle 裡,NULLEmpty 的字串是一樣的!)
不要以為NULL 不需要空間,其需要額外的空間,而且,在你進行比較的時候,你的程式會更複雜。當然,這裡並不是說你就不能使用 NULL 了,現實情況是很複雜的,還是會有些情況下,你需要使用 NULL 值。

12.Prepared Statements

Prepared Statements 很像儲存過程,是一種運行在後台的SQL 語句集合,我們可以從使用prepared statements 獲得許多好處,無論是效能問題還是安全性問題
Prepared Statements 可以檢查一些你綁定好的變量,這樣可以保護你的程式不會受到「SQL 注入式」攻擊。當然,你也可以手動地檢查你的這些變量,然而,手動的檢查容易出問題,而且很常會被程式設計師忘了。當我們使用一些framework 或是 ORM 的時候,這樣的問題會好一些。
效能方面,當一個相同的查詢被使用多次的時候,這會為你帶來可觀的效能優勢。你可以給這些 Prepared Statements 定義一些參數,而 MySQL 只會解析一次。
雖然最新版本的 MySQL 在傳輸 Prepared Statements 是使用二進位形式,所以這會使得網路傳輸非常有效率
當然,也有一些情況下,我們需要避免使用 Prepared Statements,因為其不支援查詢快取。但據說版本 5.1 後支援了。
在PHP 要使用prepared statements,你可以查看其使用手冊:mysql擴展或使用資料庫抽象層,如: PDO.

超詳細匯總mysql優化實踐技巧



###########################13 . 無緩衝的查詢#########正常的情況下,當你在當你在你的腳本中執行一個SQL 語句的時候,你的程式會停在那裡直到沒這個SQL 語句返回,然後你的程式再往下繼續執行。你可以使用無緩衝查詢來改變這個行為。 ######mysql_unbuffered_query()### 發送一個 SQL 語句到 MySQL 而不像###mysql_query()###一樣去自動 ###fethch### 和快取結果。這會相當節約很多可觀的內存,尤其是那些會產生大量結果的查詢語句,並且,你不需要等到所有的結果都返回,只需要第一行數據返回的時候,你就可以開始馬上開始工作於查詢結果了。 ### 然而,這會有一些限制。因為你要嘛把所有行都讀走,或是你要在進行下一次的查詢前呼叫 ###mysql_free_result()### 清除結果。而且, ###mysql_num_rows()或 mysql_data_seek()### 將無法使用。所以,是否使用無緩衝的查詢你需要仔細考慮。 ###

14. 把IP 位址存成UNSIGNED INT

很多程式設計師都會建立一個VARCHAR(15) 欄位來存放字串形式的IP 而不是整形的IP。如果你用整形來存放,只需要 4 個字節,而且你可以有定長的字段。而且,這會為你帶來查詢上的優勢,尤其是當你需要使用這樣的 WHERE 條件:IP between ip1 and ip2
我們必需要使用 UNSIGNED INT因為 IP 位址會使用整個 32 位元的無符號整數。
而你的查詢,你可以用INET_ATON() 來把一個字串IP 轉成一個整數,並使用INET_NTOA() 把一個整形轉成一個字串IP。在 PHP 中,也有這樣的函數 ip2long() 和 long2ip()
超詳細匯總mysql優化實踐技巧

15. 固定長度的表會更快

#如果表中的所有欄位都是「固定長度」的,整個表會被認為是“static”或“fixed-length”。例如,表格中沒有以下類型的欄位: VARCHAR,TEXT。只要你包括了其中一個這些字段,那麼這個表就不是「固定長度靜態表」了,這樣,MySQL 引擎會用另一種方​​法來處理。
固定長度的表會提高效能,因為 MySQL 搜尋得會更快一些,因為這些固定的長度是很容易計算下一個資料的偏移量的,所以讀取的自然也會很快。而如果欄位不是定長的,那麼,每次要找下一條的話,就需要程式找到主鍵。
並且,固定長度的表也更容易被快取和重建。不過,唯一的副作用是,固定長度的欄位會浪費一些空間因為定長的欄位無論你用不用,他都是要分配那麼多的空間。

使用「垂直分割」技術(見下一條),你可以分割你的表成為兩個一個是定長的,一個則是不定長的。

16. 垂直分割

「垂直分割」是一種把資料庫中的表按列變成幾張表的方法,這樣可以降低表的複雜度和字段的數目,從而達到優化的目的。 (以前,在銀行做過項目,見過一張表有100 多個字段,很恐怖)

示例一:在Users 表中有一個字段是家庭地址,這個字段是可選字段,相比起,而且你在資料庫操作的時候除了個人資訊外,你並不需要經常讀取或是改寫這個字段。那麼,為什麼不把他放到另外一張表中呢? 這樣會讓你的表有更好的性能,大家想想是不是,大量的時候,我對於用戶表來說,只有用戶ID,用戶名,口令,使用者角色等會被經常使用。小一點的表總是會有好的性愛
能。

範例二: 你有一個叫 “last_login” 的字段,它會在每次使用者登入時更新。但是,每次更新時會導致該表的查詢快取被清空。所以,你可以把這個欄位放到另一個表中,這樣就不會影響你對用戶 ID,用戶名,用戶角色的不停地讀取了,因為查詢快取會幫你增加很多效能。

另外,你需要注意的是,這些被分出去的字段所形成的表,你不會經常性地去Join 他們,不然的話,這樣的性能會比不分割時還要差,而且,會是極數級的下降

17.拆分大的DELETE 或INSERT 語句

如果你需要在一個在線的網站上去執行一個大的DELETEINSERT 查詢,你需要非常小心,要避免你的操作讓你的整個網站停止相應。因為這兩個操作是會鎖表的,表一鎖住了,別的操作都進不來了。
Apache 會有很多的子行程或執行緒。所以,其工作起來相當有效率,而我們的伺服器也不希望有太多的子進程,線程和資料庫鏈接,這是極大的佔伺服器資源的事情,尤其是內存。
如果你把你的表鎖上一段時間,比如30 秒鐘,那麼對於一個有很高訪問量的站點來說,這30 秒所積累的訪問進程/線程,數據庫鏈接,打開的文件數,可能不只讓你泊WEB 服務Crash,還可能會讓你的整台伺服器馬上掛了。
所以,如果你有一個大的處理,你定你一定把其拆分,使用 LIMIT 條件是一個好的方法。下面是一個範例:

超詳細匯總mysql優化實踐技巧

18.越小的列會越快

對於大多數的資料庫引擎來說,硬碟操作可能是最重大的瓶頸。所以,把你的資料變得緊湊會對這種情況非常有幫助,因為這減少了對硬碟的存取。
參考 MySQL 的文檔 Storage Requirements 查看所有的資料類型。
如果一個表只會有幾列罷了(比如說字典表,配置表),那麼,我們就沒有理由使用INT 來做主鍵,使用MEDIUMINT, SMALLINT#或者更小的TINYINT 會比較經濟一點。如果你不需要記錄時間,使用 DATE 要比 DATETIME 好很多。
當然,你也需要留夠足夠的擴充空間,不然,你日後來做這個事,你會死的很難看,參看Slashdot 的例子(2009 年11 月06 日),一個簡單的ALTER TABLE 語句花了3 個多小時,因為裡面有一千六百萬個資料。

19. 選擇正確的儲存引擎

在 MySQL 中有兩個儲存引擎 MyISAM 和 InnoDB,每個引擎都有優點和缺點。酷殼以前文章《MySQL: InnoDB 還是 MyISAM?》討論和這個事情。
MyISAM 適合於一些需要大量查詢的應用,但其對於有大量寫入操作並不是很好。甚至你只是需要 update 一個字段,整個表都會被鎖起來,而別的進程,就算是讀進程都無法操作直到讀取操作完成。另外,MyISAM 對於 SELECT COUNT(*)這類的計算是超快無比的。
InnoDB 的趨勢會是一個非常複雜的儲存引擎,對於一些小的應用,它會比MyISAM 還慢。他是它支援「行鎖」 ,於是在寫操作比較多的時候,會更優秀。並且,他也支援更多的高階應用,例如:事務。

20. 使用一個物件關係映射器(Object Relational Mapper)

使用ORM (Object Relational Mapper),你能夠得到可靠的性能增漲。一個ORM 可以做的所有事情,也能被手動的寫出來。但是,這需要一個高級專家。
ORM 的最重要的是“Lazy Loading”,也就是說,只有在需要的去取值的時候才會去真正的去做。但你也需要小心這種機制的副作用,因為這很有可能會因為要去創建很多很多小的查詢反而會降低效能。
ORM 還可以把你的 SQL 語句打包成一個事務,這會比單獨執行他們快得多。
目前,個人最喜歡的PHP 的ORM 是:Doctrine

#21. 小心“ 永久連結”

“永久連結”的目的是用來減少重新建立MySQL 連結的次數。當一個連結被創建了,它會永遠處於連線的狀態,就算是資料庫操作已經結束了。而且,自從我們的 Apache 開始重複使用它的子進程後——也就是說,下一次的 HTTP 請求會重複使用 Apache 的子進程,並重複使用相同的 MySQL 連結。
在理論上來說,這聽起來非常的好。但是從個人經驗(也是大多數人的)上來說,這個功能製造出來的麻煩事更多。因為,你只有有限的連結數,記憶體問題,檔案句柄數,等等。
而且,Apache 運行在極端並行的環境中,會創造出很多很多的了進程。這就是為什麼這種「永久連結」的機制運作地不好的原因。在你決定要使用「永久連結」之前,你需要好好地考慮一下你的整個系統的架構

#22.sql優化之索引優化

1.獨立的列

在進行查詢時,索引列不能是表達式的一部分,也不能是函數的參數,否則無法使用索引。
例如下面的查詢不能使用 actor_id 欄位的索引:

#这是错误的SELECT actor_id FROM sakila.actor WHERE actor_id + 1 = 5;

最佳化方式:可以將表達式、函數操作移到等號右側。如下:

SELECT actor_id FROM sakila.actor WHERE actor_id  = 5 - 1;

2.多列索引

在需要使用多個列作為條件進行查詢時,使用多列索引比使用多個單列索引效能更好。
例如下面的語句中,最好把actor_idfilm_id 設定為多列索引。猿輔導有題,詳見鏈接,可以讓理解更深刻。

SELECT film_id, actor_ id FROM sakila.film_actorWHERE actor_id = 1 AND film_id = 1;

3.索引列的順序

讓選擇性最強的索引列放在前面。
索引的選擇性是指:不重複的索引值和記錄總數的比值。最大值為 1,此時每個記錄都有唯一的索引與其對應。選擇性越高,每個記錄的區分度越高,查詢效率也越高。

例如下面顯示的結果中 customer_id 的選擇性比 staff_id 更高,因此最好把 customer_id 欄位放在多列索引的前面。

SELECT COUNT(DISTINCT staff_id)/COUNT(*) AS staff_id_selectivity,
COUNT(DISTINCT customer_id)/COUNT(*) AS customer_id_selectivity,
COUNT(*)
FROM payment;

#结果如下
staff_id_selectivity: 0.0001
customer_id_selectivity: 0.0373
COUNT(*): 16049

4.前綴索引

對於 BLOB、TEXT 和 VARCHAR 類型的列,必須使用前綴索引,只索引開始的部分字元。

前綴長度的選取需要根據索引選擇性來決定。

5.覆盖索引

索引包含所有需要查询的字段的值。具有以下优点:

1.索引通常远小于数据行的大小,只读取索引能大大减少数据访问量。
2.一些存储引擎(例如 MyISAM)在内存中只缓存索引,而数据依赖于操作系统来缓存。因此,只访问索引可以不使用系统调用(通常比较费时)。
3.对于 InnoDB 引擎,若辅助索引能够覆盖查询,则无需访问主索引。

6.优先使用索引,避免全表扫描

mysql在使用like进行模糊查询的时候把%放后面,避免开头模糊查询
因为mysql在使用like查询的时候只有使用后面的%时,才会使用到索引。

如:’%ptd_’ 和 ‘%ptd_%’ 都没有用到索引;而 ‘ptd_%’ 使用了索引。

#进行全表查询,没有用到索引
EXPLAIN SELECT * FROM `user` WHERE username LIKE '%ptd_%';
EXPLAIN SELECT * FROM `user` WHERE username LIKE '%ptd_';

#有用到索引
EXPLAIN SELECT * FROM `user` WHERE username LIKE 'ptd_%';

再比如:经常用到的查询数据库中姓张的所有人:

SELECT * FROM `user` WHERE username LIKE '张%';

7.尽量避免使用in 和not in,会导致数据库引擎放弃索引进行全表扫描。

比如:

SELECT * FROM t WHERE id IN (2,3)SELECT * FROM t1 WHERE username IN (SELECT username FROM t2)

优化方式:如果是连续数值,可以用between代替。如下:

SELECT * FROM t WHERE id BETWEEN 2 AND 3

如果是子查询,可以用exists代替。如下:

SELECT * FROM t1 WHERE EXISTS (SELECT * FROM t2 WHERE t1.username = t2.username)

8.尽量避免使用or,会导致数据库引擎放弃索引进行全表扫描

如:

SELECT * FROM t WHERE id = 1 OR id = 3

优化方式:可以用union代替or。如下:

SELECT * FROM t WHERE id = 1UNIONSELECT * FROM t WHERE id = 3

9.尽量避免进行null值的判断,会导致数据库引擎放弃索引进行全表扫描

SELECT * FROM t WHERE score IS NULL

优化方式:可以给字段添加默认值0,对0值进行判断。如下:

SELECT * FROM t WHERE score = 0

10.尽量避免在where条件中等号的左侧进行表达式、函数操作,会导致数据库引擎放弃索引进行全表扫描

同第1个,单独的列;

SELECT * FROM t2 WHERE score/10 = 9SELECT * FROM t2 WHERE SUBSTR(username,1,2) = 'li'

优化方式:可以将表达式、函数操作移动到等号右侧。如下:

SELECT * FROM t2 WHERE score = 10*9SELECT * FROM t2 WHERE username LIKE 'li%'

11.当数据量大时,避免使用where 1=1的条件。通常为了方便拼装查询条件,我们会默认使用该条件,数据库引擎会放弃索引进行全表扫描

SELECT * FROM t WHERE 1=1

优化方式用代码拼装sql时进行判断,没where加where,有where加and。
索引的好处:建立索引后,查询时不会扫描全表,而会查询索引表锁定结果。
索引的缺点:在数据库进行DML操作的时候,除了维护数据表之外,还需要维护索引表,运维成本增加。
应用场景:数据量比较大,查询字段较多的情况。

索引规则:

1.选用选择性高的字段作为索引,一般unique的选择性最高;
2.复合索引:选择性越高的排在越前面。(左前缀原则);
3.如果查询条件中两个条件都是选择性高的,最好都建索引;

23.SQL优化之查询优化

1.使用Explain进行分析

Explain 用来分析 SELECT 查询语句,开发人员可以通过分析 Explain 结果来优化查询语句。

比较重要的字段有:

select_type : 查询类型,有简单查询、联合查询、子查询等;
key : 使用的索引;
rows : 扫描的行数;

2.优化数据访问

1.减少请求的数据量

只返回必要的列:最好不要使用 SELECT * 语句。
只返回必要的行:使用 LIMIT 语句来限制返回的数据。
缓存重复查询的数据:使用缓存可以避免在数据库中进行查询,特别在要查询的数据经常被重复查询时,缓存带来的查询性能提升将会是非常明显的。

2.减少服务器端扫描的行数

最有效的方式是使用索引来覆盖查询。

3.重构查询方式

1.切分大查询

一个大查询如果一次性执行的话,可能一次锁住很多数据、占满整个事务日志、耗尽系统资源、阻塞很多小的但重要的查询。

2.分解大连接查询

将一个大连接查询分解成对每一个表进行一次单表查询,然后在应用程序中进行关联,这样做的好处有:

讓快取更有效率:對於連線查詢,如果其中一個表格發生變化,那麼整個查詢快取就無法使用。而分解後的多個查詢,即使其中一個表發生變化,對其它表的查詢快取依然可以使用。
分解成多個單表查詢,這些單表查詢的快取結果更可能被其它查詢使用到,從而減少冗餘記錄的查詢。
減少鎖定競爭;
在應用程式層進行連接,可以更容易對資料庫進行拆分,從而更容易做到高效能和可伸縮。
查詢本身效率也可能會有所提升。例如下面的範例中,使用 IN() 代替連接查詢,可以讓 MySQL 按照 ID 順序進行查詢,這可能比隨機的連接更有效率。

SELECT * FROM tab
JOIN tag_post ON tag_post.tag_id=tag.id
JOIN post ON tag_post.post_id=post.id
WHERE tag.tag='mysql';

SELECT * FROM tag WHERE tag='mysql';
SELECT * FROM tag_post WHERE tag_id=1234;
SELECT * FROM post WHERE post.id IN (123,456,567,9098,8904);

24.分析查询语句

通过对查询语句的分析,可以了解查询语句执行的情况,找出查询语句执行的瓶颈,从而优化查询语句。mysql中提供了EXPLAIN语句和DESCRIBE语句,用来分析查询语句。
EXPLAIN语句的基本语法如下:
EXPLAIN [EXTENDED] SELECT select_options;
使用EXTENED关键字,EXPLAIN语句将产生附加信息。select_options是select语句的查询选项,包括from where子句等等。
执行该语句,可以分析EXPLAIN后面的select语句的执行情况,并且能够分析出所查询的表的一些特征。
例如:EXPLAIN SELECT * FROM user;
查询结果进行解释说明:
a、id:select识别符,这是select的查询序列号。
b、select_type:标识select语句的类型。
它可以是以下几种取值:
b1、SIMPLE(simple)表示简单查询,其中不包括连接查询和子查询。
b2、PRIMARY(primary)表示主查询,或者是最外层的查询语句。
b3、UNION(union)表示连接查询的第2个或者后面的查询语句。
b4、DEPENDENT UNION(dependent union)连接查询中的第2个或者后面的select语句。取决于外面的查询。
b5、UNION RESULT(union result)连接查询的结果。
b6、SUBQUERY(subquery)子查询的第1个select语句。
b7、DEPENDENT SUBQUERY(dependent subquery)子查询的第1个select,取决于外面的查询。
b8、DERIVED(derived)导出表的SELECT(FROM子句的子查询)。
c、table:表示查询的表。
d、type:表示表的连接类型。
下面按照从最佳类型到最差类型的顺序给出各种连接类型。
d1、system,该表是仅有一行的系统表。这是const连接类型的一个特例。
d2、const,数据表最多只有一个匹配行,它将在查询开始时被读取,并在余下的查询优化中作为常量对待。const表查询速度很快,因为它们只读一次。const用于使用常数值比较primary key或者unique索引的所有部分的场合。
例如:EXPLAIN SELECT * FROM user WHERE id=1;
d3、eq_ref,对于每个来自前面的表的行组合,从该表中读取一行。当一个索引的所有部分都在查询中使用并且索引是UNIQUE或者PRIMARY KEY时候,即可使用这种类型。eq_ref可以用于使用“=”操作符比较带索引的列。比较值可以为常量或者一个在该表前面所读取的表的列的表达式。
例如:EXPLAIN SELECT * FROM user,db_company WHERE user.company_id = db_company.id;
d4、ref对于来自前面的表的任意行组合,将从该表中读取所有匹配的行。这种类型用于所以既不是UNION也不是primaey key的情况,或者查询中使用了索引列的左子集,即索引中左边的部分组合。ref可以用于使用=或者操作符的带索引的列。
d5、ref_or_null,该连接类型如果ref,但是如果添加了mysql可以专门搜索包含null值的行,在解决子查询中经常使用该连接类型的优化。
d6、index_merge,该连接类型表示使用了索引合并优化方法。在这种情况下,key列包含了使用的索引的清单,key_len包含了使用的索引的最长的关键元素。
d7、unique_subquery,该类型替换了下面形式的in子查询的ref。是一个索引查询函数,可以完全替代子查询,效率更高。
d8、index_subquery,该连接类型类似于unique_subquery,可以替换in子查询,但是只适合下列形式的子查询中非唯一索引。
d9、range,只检索给定范围的行,使用一个索引来选择行。key列显示使用了那个索引。key_len包含所使用索引的最长关键元素。当使用=,,>,>=,,between或者in操作符,用常量比较关键字列时,类型为range。
d10、index,该连接类型与all相同,除了只扫描索引树。着通常比all快,引文索引问价通常比数据文件小。
d11、all,对于前面的表的任意行组合,进行完整的表扫描。如果表是第一个没有标记const的表,这样不好,并且在其他情况下很差。通常可以增加更多的索引来避免使用all连接。
e、possible_keys:possible_keys欄位指出mysql能使用那個索引在該表中找到行。如果該列是null,則沒有相關的索引。在這種情況下,可以透過檢查where子句看它是否引起某些欄位或適合索引的欄位來提高查詢效能。如果是這樣,可以建立適合的索引來提高查詢的效能。
f、key:表示查詢實際使用到的索引,如果沒有選擇索引,該列的值是null,要強制mysql使用或忽略possible_key列中的索引,在查詢中使用force index、use index或ignore index
g、key_len:表示mysql選擇索引欄位依照位元組計算的長度,如果健是null,則長度為null。注意透過key_len值可以確定mysql將實際使用一個多列索引中的幾個欄位。
h、ref:表示使用那個欄位或常數或索引一起來查詢記錄。
i、rows:顯示mysql在表中進行查詢必須檢查的行數。
j、Extra:該列mysql在處理查詢時的詳細資訊。

推薦學習:mysql影片教學

#

以上是超詳細匯總mysql優化實踐技巧的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述
本文轉載於:CSDN。如有侵權,請聯絡admin@php.cn刪除
如何識別和優化MySQL中的慢速查詢? (慢查詢日誌,performance_schema)如何識別和優化MySQL中的慢速查詢? (慢查詢日誌,performance_schema)Apr 10, 2025 am 09:36 AM

要優化MySQL慢查詢,需使用slowquerylog和performance_schema:1.啟用slowquerylog並設置閾值,記錄慢查詢;2.利用performance_schema分析查詢執行細節,找出性能瓶頸並優化。

MySQL和SQL:開發人員的基本技能MySQL和SQL:開發人員的基本技能Apr 10, 2025 am 09:30 AM

MySQL和SQL是開發者必備技能。 1.MySQL是開源的關係型數據庫管理系統,SQL是用於管理和操作數據庫的標準語言。 2.MySQL通過高效的數據存儲和檢索功能支持多種存儲引擎,SQL通過簡單語句完成複雜數據操作。 3.使用示例包括基本查詢和高級查詢,如按條件過濾和排序。 4.常見錯誤包括語法錯誤和性能問題,可通過檢查SQL語句和使用EXPLAIN命令優化。 5.性能優化技巧包括使用索引、避免全表掃描、優化JOIN操作和提升代碼可讀性。

描述MySQL異步主奴隸複製過程。描述MySQL異步主奴隸複製過程。Apr 10, 2025 am 09:30 AM

MySQL異步主從復制通過binlog實現數據同步,提升讀性能和高可用性。 1)主服務器記錄變更到binlog;2)從服務器通過I/O線程讀取binlog;3)從服務器的SQL線程應用binlog同步數據。

mysql:簡單的概念,用於輕鬆學習mysql:簡單的概念,用於輕鬆學習Apr 10, 2025 am 09:29 AM

MySQL是一個開源的關係型數據庫管理系統。 1)創建數據庫和表:使用CREATEDATABASE和CREATETABLE命令。 2)基本操作:INSERT、UPDATE、DELETE和SELECT。 3)高級操作:JOIN、子查詢和事務處理。 4)調試技巧:檢查語法、數據類型和權限。 5)優化建議:使用索引、避免SELECT*和使用事務。

MySQL:數據庫的用戶友好介紹MySQL:數據庫的用戶友好介紹Apr 10, 2025 am 09:27 AM

MySQL的安裝和基本操作包括:1.下載並安裝MySQL,設置根用戶密碼;2.使用SQL命令創建數據庫和表,如CREATEDATABASE和CREATETABLE;3.執行CRUD操作,使用INSERT,SELECT,UPDATE,DELETE命令;4.創建索引和存儲過程以優化性能和實現複雜邏輯。通過這些步驟,你可以從零開始構建和管理MySQL數據庫。

InnoDB緩衝池如何工作,為什麼對性能至關重要?InnoDB緩衝池如何工作,為什麼對性能至關重要?Apr 09, 2025 am 12:12 AM

InnoDBBufferPool通過將數據和索引頁加載到內存中來提升MySQL數據庫的性能。 1)數據頁加載到BufferPool中,減少磁盤I/O。 2)臟頁被標記並定期刷新到磁盤。 3)LRU算法管理數據頁淘汰。 4)預讀機制提前加載可能需要的數據頁。

MySQL:初學者的數據管理易用性MySQL:初學者的數據管理易用性Apr 09, 2025 am 12:07 AM

MySQL適合初學者使用,因為它安裝簡單、功能強大且易於管理數據。 1.安裝和配置簡單,適用於多種操作系統。 2.支持基本操作如創建數據庫和表、插入、查詢、更新和刪除數據。 3.提供高級功能如JOIN操作和子查詢。 4.可以通過索引、查詢優化和分錶分區來提升性能。 5.支持備份、恢復和安全措施,確保數據的安全和一致性。

與MySQL中使用索引相比,全表掃描何時可以更快?與MySQL中使用索引相比,全表掃描何時可以更快?Apr 09, 2025 am 12:05 AM

全表掃描在MySQL中可能比使用索引更快,具體情況包括:1)數據量較小時;2)查詢返回大量數據時;3)索引列不具備高選擇性時;4)複雜查詢時。通過分析查詢計劃、優化索引、避免過度索引和定期維護表,可以在實際應用中做出最優選擇。

See all articles

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

AI Hentai Generator

AI Hentai Generator

免費產生 AI 無盡。

熱門文章

R.E.P.O.能量晶體解釋及其做什麼(黃色晶體)
3 週前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳圖形設置
3 週前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您聽不到任何人,如何修復音頻
3 週前By尊渡假赌尊渡假赌尊渡假赌
WWE 2K25:如何解鎖Myrise中的所有內容
3 週前By尊渡假赌尊渡假赌尊渡假赌

熱工具

mPDF

mPDF

mPDF是一個PHP庫,可以從UTF-8編碼的HTML產生PDF檔案。原作者Ian Back編寫mPDF以從他的網站上「即時」輸出PDF文件,並處理不同的語言。與原始腳本如HTML2FPDF相比,它的速度較慢,並且在使用Unicode字體時產生的檔案較大,但支援CSS樣式等,並進行了大量增強。支援幾乎所有語言,包括RTL(阿拉伯語和希伯來語)和CJK(中日韓)。支援嵌套的區塊級元素(如P、DIV),

SublimeText3 Linux新版

SublimeText3 Linux新版

SublimeText3 Linux最新版

MantisBT

MantisBT

Mantis是一個易於部署的基於Web的缺陷追蹤工具,用於幫助產品缺陷追蹤。它需要PHP、MySQL和一個Web伺服器。請查看我們的演示和託管服務。

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

Safe Exam Browser

Safe Exam Browser

Safe Exam Browser是一個安全的瀏覽器環境,安全地進行線上考試。該軟體將任何電腦變成一個安全的工作站。它控制對任何實用工具的訪問,並防止學生使用未經授權的資源。