目錄
MySQL性能索引的重要性是什麼?
EXPLAIN命令如何幫助提高MySQL性能?
為什麼MySQL不使用任何可能的鍵?
如何優化我的MySQL查詢?
MySQL中主鍵和索引的區別是什麼?
如何在MySQL中創建索引?
MySQL中的複合索引是什麼?
如何在MySQL中刪除索引?
MySQL中聚集索引和非聚集索引的區別是什麼?
MySQL如何選擇要使用的索引?
首頁 後端開發 php教程 用索引提高MySQL性能並解釋

用索引提高MySQL性能並解釋

Feb 08, 2025 pm 12:57 PM

MySQL Performance Boosting with Indexes and Explain

關鍵要點

  • 使用MySQL的EXPLAIN命令分析和優化查詢執行計劃,通過揭示連接類型和索引使用等關鍵信息,確保更高效的數據庫操作。
  • 實施查詢分析來衡量查詢的實際運行時間,從而進行有針對性的優化,以減少執行時間並提高整體性能。
  • 根據EXPLAIN命令的反饋添加合適的索引,重點關注WHERE子句中使用的列,以加快數據檢索速度並提高查詢性能。
  • 對於搜索操作中涉及的列,考慮使用全文索引來優化性能,尤其是在查詢中使用LIKE運算符時。
  • 注意ORDER BYLIMIT組合使用的情況,因為它可能會抵消限制結果的性能優勢,尤其是在沒有有效使用索引的情況下。

數據庫優化通常是提升應用性能的首要關注點,也是最常見的瓶頸。如何衡量和理解需要改進的地方?

一個簡單而有效的工具是查詢分析。啟用分析可以更準確地估計查詢的運行時間。這是一個兩步過程:首先,啟用分析;然後,調用show profiles來獲取查詢運行時間。

假設數據庫中存在以下插入操作(並假設用戶1和圖庫1已創建):

INSERT INTO `homestead`.`images` (`id`, `gallery_id`, `original_filename`, `filename`, `description`) VALUES
(1, 1, 'me.jpg', 'me.jpg', 'A photo of me walking down the street'),
(2, 1, 'dog.jpg', 'dog.jpg', 'A photo of my dog on the street'),
(3, 1, 'cat.jpg', 'cat.jpg', 'A photo of my cat walking down the street'),
(4, 1, 'purr.jpg', 'purr.jpg', 'A photo of my cat purring');
登入後複製
登入後複製
登入後複製
登入後複製
登入後複製

少量數據不會造成問題,但我們可以用它來進行簡單的分析。考慮以下查詢:

SELECT * FROM `homestead`.`images` AS i
WHERE i.description LIKE '%street%';
登入後複製
登入後複製
登入後複製
登入後複製

如果照片條目很多,此查詢將來可能會成為問題。

要獲取此查詢的準確運行時間,可以使用以下SQL:

set profiling = 1;
SELECT * FROM `homestead`.`images` AS i
WHERE i.description LIKE '%street%';
show profiles;
登入後複製

結果如下所示:

Query_Id Duration Query
1 0.00016950 SHOW WARNINGS
2 0.00039200 SELECT * FROM homestead.images AS i WHERE i.description LIKE '%street%' LIMIT 0, 1000
3 0.00037600 SHOW KEYS FROM homestead.images
4 0.00034625 SHOW DATABASES LIKE 'homestead'
5 0.00027600 SHOW TABLES FROM homestead LIKE 'images'
6 0.00024950 SELECT * FROM homestead.images WHERE 0=1
7 0.00104300 SHOW FULL COLUMNS FROM homestead.images LIKE 'id'

show profiles;命令不僅顯示原始查詢的時間,還顯示所有其他查詢的時間,從而可以準確地分析查詢。

如何改進查詢?

可以依靠SQL知識進行改進,或者依靠MySQL的EXPLAIN命令並根據實際信息來提高查詢性能。

EXPLAIN用於獲取查詢執行計劃,即MySQL如何執行查詢。它適用於SELECTDELETEINSERTREPLACEUPDATE語句,並顯示優化器關於語句執行計劃的信息。官方文檔很好地描述了EXPLAIN如何幫助我們:

通過EXPLAIN,您可以看到應該在哪些表中添加索引,以便語句通過使用索引查找行來更快地執行。您還可以使用EXPLAIN來檢查優化器是否以最佳順序連接表。

為了舉例說明EXPLAIN的使用,我們將使用UserManager.php中查找用戶電子郵件的查詢:

INSERT INTO `homestead`.`images` (`id`, `gallery_id`, `original_filename`, `filename`, `description`) VALUES
(1, 1, 'me.jpg', 'me.jpg', 'A photo of me walking down the street'),
(2, 1, 'dog.jpg', 'dog.jpg', 'A photo of my dog on the street'),
(3, 1, 'cat.jpg', 'cat.jpg', 'A photo of my cat walking down the street'),
(4, 1, 'purr.jpg', 'purr.jpg', 'A photo of my cat purring');
登入後複製
登入後複製
登入後複製
登入後複製
登入後複製

要使用EXPLAIN命令,只需在SELECT類型查詢之前添加它:

SELECT * FROM `homestead`.`images` AS i
WHERE i.description LIKE '%street%';
登入後複製
登入後複製
登入後複製
登入後複製

結果如下(向右滾動查看所有內容):

id select_type table partitions type possible_keys key key_len ref rows filtered Extra
1 SIMPLE users NULL const UNIQ_1483A5E9E7927C74 UNIQ_1483A5E9E7927C74 182 const 1 100.00 NULL

這些結果一開始不容易理解,讓我們仔細看看每一個:

  • id:這是SELECT中每個查詢的順序標識符。
  • select_typeSELECT查詢的類型。此字段可以取多個不同的值,因此我們將關注最重要的幾個:
    • SIMPLE:沒有子查詢或聯合的簡單查詢
    • PRIMARYselect位於連接中最外層的查詢中
    • DERIVEDselectfrom中子查詢的一部分
    • SUBQUERY:子查詢中的第一個select
    • UNIONselect是聯合的第二個或後續語句。 完整的select_type字段值列表可以在此處找到。
  • table:行引用的表。
  • type:此字段表示MySQL連接所用表的類型。這可能是EXPLAIN輸出中最重要的字段。它可以指示缺少索引,也可以顯示如何重寫查詢。此字段的可能值如下(從最佳類型到最差類型排序):
    • system:表具有零行或一行。
    • const:表只有一行匹配行,該行已編入索引。這是最快的連接類型。
    • eq_ref:索引的所有部分都由連接使用,並且索引是PRIMARY_KEYUNIQUE NOT NULL
    • ref:對於來自前一張表的每一行組合,都會讀取索引列的所有匹配行。這種類型的連接通常出現在使用=或運算符比較的已編入索引的列中。
    • fulltext:連接使用表的全文索引。
    • ref_or_null:與ref相同,但也包含來自列的NULL值的行。
    • index_merge:連接使用索引列表來生成結果集。 EXPLAINKEY列將包含所使用的鍵。
    • unique_subqueryIN子查詢僅從表中返回一個結果,並使用主鍵。
    • range:使用索引在特定範圍內查找匹配的行。
    • index:掃描整個索引樹以查找匹配的行。
    • ALL:掃描整個表以查找連接的匹配行。這是最差的連接類型,通常表示表上缺少合適的索引。
  • possible_keys:顯示MySQL可用於從表中查找行的鍵。這些鍵在實踐中可能被使用,也可能不被使用。
  • keys:指示MySQL實際使用的索引。 MySQL始終查找可用於查詢的最佳鍵。連接多個表時,它可能會找到一些不在possible_keys中列出但更優的鍵。
  • key_len:指示查詢優化器選擇使用的索引的長度。
  • ref:顯示與key列中命名的索引進行比較的列或常量。
  • rows:列出為生成輸出而檢查的記錄數。這是一個非常重要的指標;檢查的記錄越少越好。
  • Extra:包含其他信息。此列中的Using filesortUsing temporary等值可能表示有問題的查詢。

EXPLAIN輸出格式的完整文檔可以在MySQL官方頁面上找到。

回到我們的簡單查詢:它是一種SIMPLE類型的select,具有const類型的連接。這是我們可能擁有的最佳查詢案例。但是,當我們需要更大更複雜的查詢時會發生什麼?

回到我們的應用程序模式,我們可能想要獲取所有圖庫圖像。我們可能還只想包含描述中包含單詞“cat”的照片。這絕對是我們可以在項目需求中找到的情況。讓我們看看查詢:

INSERT INTO `homestead`.`images` (`id`, `gallery_id`, `original_filename`, `filename`, `description`) VALUES
(1, 1, 'me.jpg', 'me.jpg', 'A photo of me walking down the street'),
(2, 1, 'dog.jpg', 'dog.jpg', 'A photo of my dog on the street'),
(3, 1, 'cat.jpg', 'cat.jpg', 'A photo of my cat walking down the street'),
(4, 1, 'purr.jpg', 'purr.jpg', 'A photo of my cat purring');
登入後複製
登入後複製
登入後複製
登入後複製
登入後複製

在這個更複雜的情況下,我們應該在EXPLAIN中獲得更多信息來分析:

SELECT * FROM `homestead`.`images` AS i
WHERE i.description LIKE '%street%';
登入後複製
登入後複製
登入後複製
登入後複製

這將給出以下結果(向右滾動查看所有單元格):

id select_type table partitions type possible_keys key key_len ref rows filtered Extra
1 SIMPLE users NULL index PRIMARY,UNIQ_1483A5E9BF396750 UNIQ_1483A5E9BF396750 108 NULL 1 100.00 Using index
1 SIMPLE gal NULL ref PRIMARY,UNIQ_F70E6EB7BF396750,IDX_F70E6EB7A76ED395 UNIQ_1483A5E9BF396750 108 homestead.users.id 1 100.00 NULL
1 SIMPLE img NULL ref IDX_E01FBE6A4E7AF8F IDX_E01FBE6A4E7AF8F 109 homestead.gal.id 1 25.00 Using where

讓我們仔細看看,看看我們可以在查詢中改進什麼。

如前所述,首先應該查看的主要列是type列和rows列。目標應該是獲得type列中更好的值,並儘可能減少rows列的值。

第一個查詢的結果是index,這根本不是一個好結果。這意味著我們可能可以改進它。

查看我們的查詢,有兩種方法可以解決它。首先,Users表沒有被使用。我們要么擴展查詢以確保我們正在定位用戶,要么應該完全刪除查詢的用戶部分。它只會增加我們整體性能的複雜性和時間。

INSERT INTO `homestead`.`images` (`id`, `gallery_id`, `original_filename`, `filename`, `description`) VALUES
(1, 1, 'me.jpg', 'me.jpg', 'A photo of me walking down the street'),
(2, 1, 'dog.jpg', 'dog.jpg', 'A photo of my dog on the street'),
(3, 1, 'cat.jpg', 'cat.jpg', 'A photo of my cat walking down the street'),
(4, 1, 'purr.jpg', 'purr.jpg', 'A photo of my cat purring');
登入後複製
登入後複製
登入後複製
登入後複製
登入後複製

所以現在我們得到了完全相同的結果。讓我們看看EXPLAIN

id select_type table partitions type possible_keys key key_len ref rows filtered Extra
1 SIMPLE gal NULL ALL PRIMARY,UNIQ_1483A5E9BF396750 NULL NULL NULL 1 100.00 NULL
1 SIMPLE img NULL ref IDX_E01FBE6A4E7AF8F IDX_E01FBE6A4E7AF8F 109 homestead.gal.id 1 25.00 Using where

我們剩下的是ALL類型。雖然ALL可能是最差的連接類型,但也有一些情況下它是唯一的選擇。根據我們的要求,我們想要所有圖庫圖像,因此我們需要搜索整個galleries表。當我們需要表中的所有信息時,索引在嘗試查找表中的特定信息時非常好,但它們幫不了我們。當我們遇到這種情況時,我們必須求助於其他方法,例如緩存。

由於我們正在處理LIKE,我們可以做的最後一個改進是向我們的description字段添加全文索引。這樣,我們可以將LIKE更改為match()並提高性能。更多關於全文索引的信息可以在此處找到。

我們還必須查看兩個非常有趣的情況:應用程序中最新的和相關的功能。這些適用於圖庫,並涉及我們應該注意的一些極端情況:

INSERT INTO `homestead`.`images` (`id`, `gallery_id`, `original_filename`, `filename`, `description`) VALUES
(1, 1, 'me.jpg', 'me.jpg', 'A photo of me walking down the street'),
(2, 1, 'dog.jpg', 'dog.jpg', 'A photo of my dog on the street'),
(3, 1, 'cat.jpg', 'cat.jpg', 'A photo of my cat walking down the street'),
(4, 1, 'purr.jpg', 'purr.jpg', 'A photo of my cat purring');
登入後複製
登入後複製
登入後複製
登入後複製
登入後複製

以上是相關圖庫。

SELECT * FROM `homestead`.`images` AS i
WHERE i.description LIKE '%street%';
登入後複製
登入後複製
登入後複製
登入後複製

以上是最新的圖庫。

乍一看,這些查詢應該非常快,因為它們使用的是LIMIT。在大多數使用LIMIT的查詢中都是這種情況。不幸的是,對於我們和我們的應用程序來說,這些查詢也使用了ORDER BY。因為我們需要在限制查詢之前對所有結果進行排序,所以我們失去了使用LIMIT的優勢。

由於我們知道ORDER BY可能很棘手,讓我們應用我們可靠的EXPLAIN

id select_type table partitions type possible_keys key key_len ref rows filtered Extra
1 SIMPLE gal NULL ALL IDX_F70E6EB7A76ED395 NULL NULL NULL 1 100.00 Using where; Using filesort
1 SIMPLE u NULL eq_ref PRIMARY,UNIQ_1483A5E9BF396750 PRIMARY 108 homestead.gal.id 1 100.00 NULL

以及,

id select_type table partitions type possible_keys key key_len ref rows filtered Extra
1 SIMPLE gal NULL ALL NULL NULL NULL NULL 1 100.00 Using filesort

我們可以看到,對於我們的兩個查詢,我們都有最糟糕的連接類型:ALL

歷史上,MySQL的ORDER BY實現,特別是與LIMIT一起使用時,通常是MySQL性能問題的根源。這種組合也用於大多數具有大型數據集的交互式應用程序。像新註冊用戶和熱門標籤這樣的功能通常使用這種組合。

因為這是一個常見問題,所以我們還應該應用一些常見的解決方案來解決性能問題。

  • 確保我們正在使用索引。在我們的例子中,created_at是一個很好的候選者,因為它是我們正在排序的字段。這樣,我們就可以在不掃描和排序完整結果集的情況下執行ORDER BYLIMIT
  • 按前導表中的列排序。通常,如果ORDER BY按不是連接順序中的第一個表的字段進行排序,則無法使用索引。
  • 不要按表達式排序。表達式和函數不允許ORDER BY使用索引。
  • 注意大的LIMIT值。大的LIMIT值將強制ORDER BY對更多行進行排序。這會影響性能。

當我們同時使用LIMITORDER BY時,這些是我們應該採取的一些措施,以最大限度地減少性能問題。

結論

正如我們所看到的,EXPLAIN對於儘早發現查詢中的問題非常有用。有很多問題只有當我們的應用程序處於生產環境中並且有大量數據或大量訪問者訪問數據庫時才會注意到。如果可以使用EXPLAIN儘早發現這些問題,那麼將來出現性能問題的可能性就小得多。

我們的應用程序擁有所有需要的索引,並且速度很快,但我們現在知道,每當我們需要檢查性能提升時,我們總是可以求助於EXPLAIN和索引。

關於MySQL性能索引的常見問題解答(FAQ)

MySQL性能索引的重要性是什麼?

MySQL性能索引對於優化數據庫性能至關重要。它們通過根據已編入索引的列中的值快速訪問數據表中的行,顯著加快數據檢索操作。如果沒有索引,MySQL將不得不遍歷表中的每一行才能找到相關的行,這可能會非常耗時,尤其對於大型數據庫而言。

EXPLAIN命令如何幫助提高MySQL性能?

MySQL中的EXPLAIN命令是一個強大的工具,它提供有關MySQL如何執行查詢的信息。它顯示讀取表的順序、執行的讀取操作類型、可選擇的索引以及要檢查的估計行數。這些信息可以幫助開發人員優化查詢並提高數據庫性能。

為什麼MySQL不使用任何可能的鍵?

MySQL不使用任何可能的鍵可能有幾個原因。一個原因可能是優化器估計使用索引需要掃描表的大部分,並決定表掃描會更快。另一個原因可能是WHERE子句中的列與索引中的列不匹配。

如何優化我的MySQL查詢?

有幾種方法可以優化MySQL查詢。一種方法是有效地使用索引。索引可以顯著加快數據檢索速度。但是,它們會減慢數據修改操作(如INSERTUPDATEDELETE)的速度。因此,找到平衡點非常重要。另一種方法是使用EXPLAIN命令來了解MySQL如何執行查詢並查找潛在的瓶頸。

MySQL中主鍵和索引的區別是什麼?

MySQL中的主鍵是一種索引。主鍵是表中行的唯一標識符。它強制執行列或列組合的唯一性,並確保列或列組合不包含NULL值。另一方面,索引是一種數據結構,它可以提高數據檢索操作的速度。它可以應用於任何列或列的組合。

如何在MySQL中創建索引?

可以使用CREATE INDEX語句在MySQL中創建索引。語法如下:CREATE INDEX index_name ON table_name (column1, column2, …);。這將在指定表的指定列上創建一個索引。

MySQL中的複合索引是什麼?

複合索引,也稱為多列索引,是一個包含多列的索引。在MySQL中,複合索引最多可以包含16列,但已編入索引的列的總大小不能超過767字節。

如何在MySQL中刪除索引?

可以使用DROP INDEX語句在MySQL中刪除索引。語法如下:DROP INDEX index_name ON table_name;。這將從指定的表中刪除指定的索引。

MySQL中聚集索引和非聚集索引的區別是什麼?

聚集索引決定表中數據的物理順序。每個表只能有一個聚集索引。另一方面,非聚集索引不會更改表中數據的物理順序。相反,它維護一個指向數據行的單獨數據結構(索引),從而允許更快地檢索數據。

MySQL如何選擇要使用的索引?

MySQL使用基於成本的優化器來選擇要使用的索引。優化器會估計不同查詢執行計劃的成本,並選擇成本最低的計劃。成本是根據要讀取的行數、磁盤查找次數、CPU成本和內存使用情況等因素來估計的。

以上是用索引提高MySQL性能並解釋的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

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

AI Clothes Remover

AI Clothes Remover

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

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

熱門話題

Java教學
1664
14
CakePHP 教程
1421
52
Laravel 教程
1315
25
PHP教程
1266
29
C# 教程
1239
24
PHP和Python:比較兩種流行的編程語言 PHP和Python:比較兩種流行的編程語言 Apr 14, 2025 am 12:13 AM

PHP和Python各有優勢,選擇依據項目需求。 1.PHP適合web開發,尤其快速開發和維護網站。 2.Python適用於數據科學、機器學習和人工智能,語法簡潔,適合初學者。

說明PHP中的安全密碼散列(例如,password_hash,password_verify)。為什麼不使用MD5或SHA1? 說明PHP中的安全密碼散列(例如,password_hash,password_verify)。為什麼不使用MD5或SHA1? Apr 17, 2025 am 12:06 AM

在PHP中,應使用password_hash和password_verify函數實現安全的密碼哈希處理,不應使用MD5或SHA1。1)password_hash生成包含鹽值的哈希,增強安全性。 2)password_verify驗證密碼,通過比較哈希值確保安全。 3)MD5和SHA1易受攻擊且缺乏鹽值,不適合現代密碼安全。

PHP行動:現實世界中的示例和應用程序 PHP行動:現實世界中的示例和應用程序 Apr 14, 2025 am 12:19 AM

PHP在電子商務、內容管理系統和API開發中廣泛應用。 1)電子商務:用於購物車功能和支付處理。 2)內容管理系統:用於動態內容生成和用戶管理。 3)API開發:用於RESTfulAPI開發和API安全性。通過性能優化和最佳實踐,PHP應用的效率和可維護性得以提升。

什麼是HTTP請求方法(獲取,發布,放置,刪除等),何時應該使用? 什麼是HTTP請求方法(獲取,發布,放置,刪除等),何時應該使用? Apr 09, 2025 am 12:09 AM

HTTP請求方法包括GET、POST、PUT和DELETE,分別用於獲取、提交、更新和刪除資源。 1.GET方法用於獲取資源,適用於讀取操作。 2.POST方法用於提交數據,常用於創建新資源。 3.PUT方法用於更新資源,適用於完整更新。 4.DELETE方法用於刪除資源,適用於刪除操作。

PHP:網絡開發的關鍵語言 PHP:網絡開發的關鍵語言 Apr 13, 2025 am 12:08 AM

PHP是一種廣泛應用於服務器端的腳本語言,特別適合web開發。 1.PHP可以嵌入HTML,處理HTTP請求和響應,支持多種數據庫。 2.PHP用於生成動態網頁內容,處理表單數據,訪問數據庫等,具有強大的社區支持和開源資源。 3.PHP是解釋型語言,執行過程包括詞法分析、語法分析、編譯和執行。 4.PHP可以與MySQL結合用於用戶註冊系統等高級應用。 5.調試PHP時,可使用error_reporting()和var_dump()等函數。 6.優化PHP代碼可通過緩存機制、優化數據庫查詢和使用內置函數。 7

解釋self ::,parent ::和static :: in php oop中的區別。 解釋self ::,parent ::和static :: in php oop中的區別。 Apr 09, 2025 am 12:04 AM

在PHPOOP中,self::引用當前類,parent::引用父類,static::用於晚靜態綁定。 1.self::用於靜態方法和常量調用,但不支持晚靜態綁定。 2.parent::用於子類調用父類方法,無法訪問私有方法。 3.static::支持晚靜態綁定,適用於繼承和多態,但可能影響代碼可讀性。

PHP如何安全地上載文件? PHP如何安全地上載文件? Apr 10, 2025 am 09:37 AM

PHP通過$\_FILES變量處理文件上傳,確保安全性的方法包括:1.檢查上傳錯誤,2.驗證文件類型和大小,3.防止文件覆蓋,4.移動文件到永久存儲位置。

PHP類型提示如何起作用,包括標量類型,返回類型,聯合類型和無效類型? PHP類型提示如何起作用,包括標量類型,返回類型,聯合類型和無效類型? Apr 17, 2025 am 12:25 AM

PHP類型提示提升代碼質量和可讀性。 1)標量類型提示:自PHP7.0起,允許在函數參數中指定基本數據類型,如int、float等。 2)返回類型提示:確保函數返回值類型的一致性。 3)聯合類型提示:自PHP8.0起,允許在函數參數或返回值中指定多個類型。 4)可空類型提示:允許包含null值,處理可能返回空值的函數。

See all articles