簡體   English   中英

MySQL 字符集 & Select 存儲過程中的查詢性能

[英]MySQL Character Set & Select Query Performance in stored procedure

最近我注意到很少有查詢在執行時花費很長時間,進一步檢查發現 MySQL 優化器正在嘗試在Where子句中使用 COLLATE,這會導致性能問題,如果我在沒有 COLLATE 的查詢下運行然后從數據庫中得到快速響應:

 SELECT notification_id FROM notification  
    WHERE ref_table = 2 
    AND ref_id =  NAME_CONST('v_wall_detail_id',_utf8mb4'c37e32fc-b3b5-11ec-befc-02447a44a47c' COLLATE 'utf8mb4_unicode_ci')

MySQL 版本 5.7

Database Character Set: utf8mb4
Column Character set: UTF8 
Column Data Type: CHAR(36) UUID
From PHP in Connection object passing: utf8mb4
Index is applied

This query is written in MySQL stored procedure

顯示創建表

CREATE TABLE `notification` (
  `notification_id` CHAR(36) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL,    
  `title` VARCHAR(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  `created` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,  
  PRIMARY KEY (`notification_id`)
) ENGINE=INNODB DEFAULT CHARSET=utf8mb4

顯示像“coll%”這樣的變量;

collation_connection  utf8_general_ci                                 
collation_database   utf8mb4_unicode_ci                               
collation_server      latin1_swedish_ci                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        

顯示像“char%”這樣的變量;

character_set_client, Connection,Result, System:   utf8
character_set_database      utf8mb4 
character_set_server       latin1                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               
character_set_system       utf8    
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 

任何建議,需要哪些改進才能使我的查詢更快?

該表的字符集是 utf8,所以我猜它的排序規則是 utf8_general_ci 或 utf8_unicode_ci 之一。 你可以這樣檢查:

SELECT collation_name from INFORMATION_SCHEMA.COLUMNS
WHERE table_schema = '...your schema...' AND table_name = 'notification'
  AND column_name = 'ref_id';

您強迫它與具有 utf8mb4 字符集和排序規則的字符串進行比較。 索引是一種排序的數據結構,排序順序取決於列的排序規則。 使用該索引意味着利用排序順序快速查找值,而無需檢查每一行。

當您將該列與具有不同排序規則的字符串進行比較時,MySQL 無法推斷出您的 UUID 常量的排序順序或字符串等效性是兼容的。 所以它必須以困難的方式逐行進行字符串比較。

這不是錯誤,這是排序規則工作的預期方式。 要利用索引,您必須與具有兼容排序規則的字符串進行比較。


我測試發現以下表達式無法使用索引:

不同的字符集,不同的排序規則:

WHERE ref_id = _utf8mb4'c37e32fc-b3b5-11ec-befc-02447a44a47c' COLLATE utf8mb4_general_ci

WHERE ref_id = _utf8mb4'c37e32fc-b3b5-11ec-befc-02447a44a47c' COLLATE utf8mb4_unicode_ci

相同的字符集,不同的排序規則:

WHERE ref_id = _utf8'c37e32fc-b3b5-11ec-befc-02447a44a47c' COLLATE 'utf8_unicode_ci'

以下表達式成功使用索引:

不同字符集,默認排序規則:

WHERE ref_id = _utf8mb4'c37e32fc-b3b5-11ec-befc-02447a44a47c'

相同的字符集,相同的排序規則:

WHERE ref_id = _utf8'c37e32fc-b3b5-11ec-befc-02447a44a47c' COLLATE 'utf8_general_ci'

相同的字符集,默認排序規則:

WHERE ref_id = _utf8'c37e32fc-b3b5-11ec-befc-02447a44a47c'

為了簡化您的環境,我建議您在所有表和 session 中只使用一種字符集和一種排序規則。我建議:

ALTER TABLE notification CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

這將使用指定排序規則的排序順序重建字符串列的索引。

然后使用COLLATE utf8mb4_unicode_ci將兼容,並將使用索引。

PS 在所有情況下,我都省略了 NAME_CONST() function,因為據我所知,它在 WHERE 子句中沒有任何作用。 我不知道你為什么要用它。

這些說明客戶在說什么:

collation_connection  utf8_general_ci
character_set_client, Connection,Result, System:   utf8

要么更改它們,要么更改各個列以匹配它們。

如果您有存儲例程,則需要刪除它們,執行SET NAMES以匹配您選擇的內容,然后重新創建。

由於您使用的是 5.7,因此我建議始終使用utf8mb4utf8mb4_unicode_520_ci

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM