2013-07-07 48 views
0

我有以下查詢:指數具有複雜MySQL查詢

SELECT venues.venue_name, count(distinct checkin.user_id) AS total_count, category_id 
    FROM checkin 
    INNER JOIN venues ON checkin.internal_venue_id = venues.venue_primary_id 
    WHERE checkin.item_id = '3783' 
    and is_category_valid = 1 and created_at >= DATE_SUB('2013-07-07 12:35:06', INTERVAL 5 DAY) 
    GROUP BY checkin.internal_venue_id 
    ORDER BY total_count DESC 
    LIMIT 10; 

我與此查詢所需的索引掙扎。是否正確的索引:

checkin: (internal_venue_id, item_id, is_category_valid, created_at, user_id) 

或者是否有另一個更理想的查詢路徑?

回答

0

您建議的索引是相關的。

但是,沒有像「正確」或「最佳」索引本身這樣的東西,您需要考慮表的完整結構以及基數。例如,is_category_valid = 1有多少記錄(按比例)?如果大多數記錄符合這個條件,那麼這個字段上的索引幾乎沒有用處。

其基本思想是按照「重要性」的順序包含列,也就是說首先在最具有區分性的列上。例如,如果大多數類別都是「有效」的,我會將列is_category_valid推到索引的末尾。

(有,出現在GROUP BYORDER BY條款列的例外,但你已經知道這一點,所以它看起來是)

你應該看看查詢執行計劃(EXPLAIN SELECT [your query here]),看看如何該查詢被處理。嘗試各種組合,看看哪一個更好。請記住,當你的數據集發展時,今天的「最佳」指數可能會變得不那麼理想。

0

RandomSeed有非常好的觀點。對於您所遇到的問題,我會嘗試根據您要求的最小粒度來優化索引。在這種情況下,您正在特定查找給定的「item_ID」。將它移動到索引的前端位置。然後,我會根據結果期望的粒度將其他標準或羣組作爲下一個考慮。你有Is_Category_Valid和Created_At ..我期望,因爲大多數類別將是有效的,我會在第二個位置created_at。這基本上是指出索引可以跳轉到項目ID 3783,並在其中,去創建日期2013-07-07(通過Date_sub少於5天)。在這一點上,我將在小組中通過對指數的標準,最終的有效

index (item_id, created_at, interval_venue_id, is_category_valid) 

但是,每個查詢是不同的,你需要看最快的方式獲取數據的粒度級別..並且有一個覆蓋索引(如果可能的話)可以防止需要轉到原始頁面數據級別,這有助於提高速度。

+0

所以你不會包含user_id作爲索引的一部分? – gregavola

+0

@gregavola,對不起,把它放在最後,因爲它只是你想要的一個「額外」列,並且不符合查詢中標準的位置或組的順序。 – DRapp

+0

是的,但我是通過該列的計數(distinct user_id)進行排序。如果這個範圍很高? – gregavola