2015-10-08 55 views
6

在MySQL手冊中有一個關於index hinting的頁面,它提到您可以爲查詢的特定部分指定索引提示。索引作用域在Mysql中如何工作?

您可以通過向提示添加FOR子句來指定索引提示的範圍。這爲優化器爲查詢處理的各個階段選擇執行計劃提供了更精細的控制。要僅影響MySQL決定如何在表中查找行以及如何處理連接時使用的索引,請使用FOR JOIN。要影響對行進行排序或分組的索引使用情況,請使用FOR ORDER BYFOR GROUP BY

但是,關於這是如何工作的或者它在MySQL優化器中實際做了什麼的信息很少。在實踐中,實際上改善任何事情似乎都是微不足道的。

下面是測試查詢,什麼解釋說,有關查詢:

SELECT 
    `property`.`primary_id` AS `id` 
FROM `California` `property` 

USE INDEX FOR JOIN (`Zipcode Bedrooms`) 
USE INDEX FOR ORDER BY (`Zipcode Bathrooms`) 

INNER JOIN `application_zipcodes` `az` 
    ON `az`.`application_id` = '18' 
    AND `az`.`zipcode` = `property`.`zipcode` 

WHERE `property`.`city` = 'San Jose' 
AND `property.`zipcode` = '95133' 
AND `property`.property_type` = 'Residential' 
AND `property`.`style` = 'Condominium' 
AND `property`.`bedrooms` = '3' 
ORDER BY `property`.`bathrooms` ASC 
LIMIT 15 
; 

解釋:

EXPLAIN SELECT `property`.`primary_id` AS `id` FROM `California` `property` USE INDEX FOR JOIN (`Zipcode Bedrooms`) USE INDEX FOR ORDER BY (`Zipcode Bathrooms`) INNER JOIN `application_zipcodes` `az` ON `az`.`application_id` = '18' AND `az`.`zipcode` = `property`.`zipcode` WHERE `property`.`city` = 'San Jose' AND `property.`zipcode` = '95133' AND `property`.property_type` = 'Residential' AND `property`.`style` = 'Condominium' AND `property`.`bedrooms` = '3' ORDER BY `property`.`bathrooms` ASC LIMIT 15\g 
+------+-------------+----------+--------+---------------+---------+---------+------------------------------------+------+----------------------------------------------------+ 
| id | select_type | table | type | possible_keys | key  | key_len | ref        | rows | Extra            | 
+------+-------------+----------+--------+---------------+---------+---------+------------------------------------+------+----------------------------------------------------+ 
| 1 | SIMPLE  | Property | ref | Zip Bed  | Zip Bed | 17  | const,const      | 2364 | Using index condition; Using where; Using filesort | 
| 1 | SIMPLE  | az  | eq_ref | PRIMARY  | PRIMARY | 7  | const,Property.zipcode    | 1 | Using where; Using index       | 
+------+-------------+----------+--------+---------------+---------+---------+------------------------------------+------+----------------------------------------------------+ 
2 rows in set (0.01 sec) 

所以,總結我基本上不知道該指數範圍是怎樣來使用,因爲當我添加或刪除行USE INDEX FOR ORDER BY (Zipcode Bathrooms)時,這似乎不起作用。

回答

1

我還沒有弄清楚如何使用多個提示。根據SELECT,MySQL幾乎不會使用多於一個索引。我知道的唯一例外是「索引合併」,這與您的示例中不相關。

優化器通常專注於爲WHERE子句找到一個好的索引。如果它完全覆蓋了WHERE,沒有任何「範圍」,則它會檢查是否有GROUP BYORDER BY字段以正確的順序使用。如果它可以處理所有的WHERE, GROUP BY, and ORDER BY,那麼它實際上可以優化LIMIT(但不是OFFSET)。

如果優化程序不能使用所有的WHERE,它可能會到達ORDER BY,希望避免ORDER BY另外需要的「文件」。

這些都不允許不同子句的不同索引。一個提示可能會鼓勵使用上面的一個案例(上圖)而不是另一個;我不知道。

請勿使用utf8作爲郵編;它使事情變得比必要的更大(每個字符3個字節)。一般來說,縮小表格大小有助於提高性能。或者,如果您有一個龐大的數據集,它可能會幫助我們完成大量工作。 (避免I/O非常重要。)

Bathrooms不是很有選擇性;即使可能,也沒有太多的收穫。

az.application_id是查詢中的大猴子扳手;它是什麼?

+0

從本質上講,它是一種使我有一個郵編列表之間的一對多關係的方法。 [你實際上評論過我遇到的問題,並且這個結果似乎是最快的結果。](http:// stackoverflow。com/questions/32256402/sql-performance-using-or-is-slow-in-when-using-order-by)如果使用正確的索引,此問題中的查詢實際上相當快,但優化程序試圖挑錯,造成一個文件夾。我也無法刪除任何索引,因爲它們都是用於排序的目的。 – Dbeazy

+0

無法再次編輯我最後的評論。你說,'浴室不是非常有選擇性的;即使有可能,也沒有什麼可以獲得的。「雖然在where語句的情況下這是事實,但它是很多行,因此將它用作order by的索引要比當使用「臥室」上的索引。也想要說明的是,我也嘗試過使用一個巨大的Union All作爲郵編,而且速度確實很快,但是除了我自己以外,其他開發者都需要管理它,所以我認爲與目前相比,不值得。 – Dbeazy