2013-10-09 149 views
2

我有以下代碼,並且在表tblfollowers中只有幾個follower_idusername時加載正常。
但是一旦進入數千人,它的載入真的很慢。
有沒有更好的方法來寫這個?SQL緩慢加載時間

我在它加入的字段上添加了索引,這似乎沒有什麼區別。

$scheduler->render_table("events 
    LEFT JOIN tblfollowers ON events.id_user = tblfollowers.username 
    WHERE events.status ='active' 
     AND((tblfollowers.follower_id)='$test') OR ((events.id_user) ='$test') 
    GROUP BY events.event_id, events.event_name, events.user_name, events.id_user, events.time, events.details, events.location, events.dresscode 
    ORDER BY events.timestamp DESC" 
    ,"event_id","start_date, start_date,event_name,details"); 
$scheduler->render_sql("SELECT event_id, start_date, end_date, event_name, details 
         FROM events "); 

下面是這個查詢的解釋:

 
1 SIMPLE events ALL NULL NULL NULL NULL 1593 Using where; Using temporary; Using filesort  
1 SIMPLE tblfollowers ref PRIMARY PRIMARY 
4 dbhappps.events.id_user 17 Using where; Using index  

下面是表

塊引用

表活動:

event_id int(11) Primary Unique Index  
event_name varchar(400) 
user_name varchar(155) 
id_user int(11) Primary Unique Index 
start_date datetime 
end_date datetime 
details varchar(700) 
location varchar(255) 
dresscode varchar(255) 
timestamp timestamp on update CURRENT_TIMESTAMP 

塊引用

tblfollowers:

username int(11) primary 
follower_id int(11) primary 
timestamp timestamp on update CURRENT_TIMESTAMP 

如何加快這個查詢呢?

+0

你能更好地解釋你的表模式。具體來說,提供有關您的索引的信息 –

+0

@MikeBrant表中沒有索引。有一次,我在id_user和event_id上有一個索引,但正如你在下面看到的那樣,答案是索引會減慢上傳時間。如果你看看我做的最底部,並在查詢中進行EXPLAIN SELECT,那麼你可以看到那個結果 – Steven

+0

沒有你的索引,你正在做全表掃描。是索引會增加加載時間,但這是你付出的代價。另請看「(tblfollowers.follower_id)='$ test')或((events.id_user)='$ test')」。將id_user檢查移到where子句可能不是更好嗎? – crafter

回答

1

完全透露:我不知道PHP。

但是,嘗試拆分查詢並使用UNION將它重新組合在一起。我認爲這是通過阻止使用你的索引來殺死你的表現的OR。這是我認爲你的查詢看起來像PHP之外的東西。

SELECT event_id 
    , start_date 
    , end_date 
    , event_name 
    , details 
    FROM events 
    LEFT JOIN tblfollowers 
    ON events.id_user = tblfollowers.username 
WHERE events.status ='active' 
    AND tblfollowers.follower_id = '$test' 
UNION 
SELECT event_id 
    , start_date 
    , end_date 
    , event_name 
    , details 
    FROM events 
WHERE id_user = '$test' 
+0

哇!這絕對解決了這個問題。現在我必須弄清楚如何將你所做的事情整合到PHP文件中。從10秒到0.0283秒。感謝一堆! – Steven

2

你只需要兩個字段在group by(如果電場event_id是主鍵,你只需要場。
有GROUP BY考慮較少字段應該讓你的查詢速度更快。
你應該只有把功能獨立的領域在group by,列出功能相關的領域有非荒謬和浪費時間。
幸運的MySQL不要求你做到這一點。

$scheduler->render_table("events 
    LEFT JOIN tblfollowers ON events.id_user = tblfollowers.username 
    WHERE events.status ='active' 
    AND '$test' IN (tblfollowers.follower_id, events.id_user) <<-- maybe faster 
    GROUP BY events.event_id, events.id_user <<-- only include unique key fields 
    ORDER BY events.timestamp DESC" 
,"event_id","start_date, start_date,event_name,details"); 
$scheduler->render_sql("SELECT event_id, start_date, end_date, event_name, details 
         FROM events "); 

這裏看到更多的信息:http://rpbouman.blogspot.com/2007/05/debunking-group-by-myths.html

爲什麼慢?
沒有tblfollowers和events的表定義很難說。

使用說明
如果你想看看那裏的瓶頸,把一個EXPLAIN在選擇前,貼在你的問題的結果。

$scheduler->render_sql("EXPLAIN SELECT event_id, start_date, end_date, event_name, details 
         FROM events "); 

後跟蹤指標並不能幫助
使用輸出explain告知你的決定,增加索引減慢你的插入和更新,以及醃您的磁盤使用情況。

+0

這兩個表在事件中都有int(11)用於username,follower_id和id_user。查詢仍然運行緩慢,所以我不知道除了卷之外的交易。但是這個數量並不是很大,我預計這個延遲。 – Steven

+0

聽起來像硬盤失敗。一個破損的扇區可以減慢查詢速度,從小秒到小時。嘗試將設置移到另一臺計算機或硬盤上。 – Johan

+0

並說明了這一點。停止幻想這個問題並開始測量。 – Johan

1

這主要是一個會減慢查詢速度的臨時文件。 EXPLAIN中的temporary這個詞意味着每次運行此查詢時,MySQL服務器都必須創建一個臨時表。雖然它很小,但它保存在內存中,因此速度相對較快。當它變得足夠大時,它將移動到磁盤並使查詢運行速度非常慢。

何時使用臨時表?它在MySQL Reference Manual – Optimizing Database Structure中有很好的描述。在你的情況下,它必須發生,因爲你按timestamp字段排序,GROUP BY子句中沒有包含該字段。

接下來,你是否真的需要通過所有這些字段進行分組?由於您正在按events表的主鍵進行分組,所以將另一個event的字段分組是沒有意義的。嘗試執行此查詢:

$scheduler->render_table("events 
    LEFT JOIN tblfollowers ON events.id_user = tblfollowers.username 
    WHERE events.status = 'active' 
    AND tblfollowers.follower_id = '$test' 
    OR events.id_user = '$test' 
    GROUP BY events.event_id, events.timestamp 
    ORDER BY events.timestamp DESC" 
, "event_id", "start_date, start_date, event_name, details"); 

編輯:順便說一句,你沒忘了把周圍的狀況的括號? AND優先於OR

WHERE events.status ='active' 
     AND (tblfollowers.follower_id='$test' OR events.id_user='$test') 

這樣對我來說似乎更符合邏輯。

+0

好吧,這似乎沒有任何工作,所以也許我可以解釋我正在試圖完成查詢。這些問題始於我向1500名追隨者添加了1500名追隨者。我正在嘗試獲取由id_user 50發佈的所有事件以及tblfollowers中follower_id 50所發生的任何事件。 – Steven

+0

它在我的原始示例中的括號中。 – Steven

+0

嘗試在'timestamp'字段中添加'INDEX' - 必須避免臨時表。順便說一句,查詢運行了多久?1593x17行不能太多,即使對於磁盤上的文件... – Dmitry

0

很難說沒有創建表語句。

對於該組和按順序。 如果event_id不是主節點,則可以通過在event_id,timestamp desc上添加複合索引來看到一些改進。如果按event_id排序,可以接受timestamp desc,這會爲您節省一些時間。通過這種重新排序,組會進行隱式排序,從而減慢速度。按event_id分組,時間戳ASC然後通過時間戳DESC進行排序可能會遇到該排序的最差情況。

如果event_id是主要的,則在時間戳DESC上添加索引將創建event_id和timstamp DESC的組合索引。