2010-07-28 130 views
2

最近我有這個question,一切正常,直到我把它發送到我的服務器在DreamHost。如何提高此查詢的性能?

下面的查詢似乎需要太長的時間來執行,我不知道爲什麼這麼多行一次處理。在我的本地服務器中,相同的查詢在0.3秒內執行完畢。

SELECT feed_entries . * 
FROM feed_entries 
WHERE 
id 
IN (

SELECT e.id 
FROM feed_entries AS e 
INNER JOIN feeds AS f ON e.feed_id = f.id 
INNER JOIN entries_categorias AS ec ON ec.entry_id = e.id 
INNER JOIN categorias AS c ON ec.categoria_id = c.id 
WHERE 
e.deleted =0 
AND 
c.slug 
IN ('entenda', 'google') 
GROUP BY e.id 
HAVING COUNT(DISTINCT ec.id) =2 

) 
ORDER BY date DESC 
LIMIT 1 

這是我從支持團隊收到的消息:

嗯,它看起來像該查詢 鎖定由於這些其他查詢 像這樣的加工6.5百萬 記錄,持續11秒。

# Query_time: 11.639269 Lock_time: 0.000192 Rows_sent: 2 Rows_examined: 
6509098 
use desenvolvimentistas; 
SET timestamp=1280325753; 
SELECT `e`.*, `f`.`titulo` AS `feedTitulo`, `f`.`url` AS `feedUrl` FROM 
`feed_entries` AS `e` 
INNER JOIN `feeds` AS `f` ON e.feed_id =f.id WHERE (e.id IN (SELECT 
`e`.`id` FROM `feed_entries` AS `e` 
INNER JOIN `feeds` AS `f` ON e.feed_id =f.id 
INNER JOIN `entries_categorias` AS `ec` ON ec.entry_id =e.id 
INNER JOIN `categorias` AS `c` ON ec.categoria_id =c.id WHERE (e.deleted 
=0) AND (e.id NOT IN ('', '', '842', '853', '774', '878')) AND 
(e.imagem145x145 =1) AND (c.slug IN('destaque-2')) GROUP BY `e`.`id` 
HAVING (COUNT(DISTINCT ec.id) =1))) ORDER BY `e`.`date` DESC LIMIT 4; 

有可能的查詢需要在本地計算機是 空閒的0.3秒到 運行,但因爲它是在 一次運行查詢150這是在我們的服務器上 緩慢,並且每一個正在處理 1530萬條記錄。

我有我們的MySQL管理員看了看 它,他說,這是相當低效 和感到驚訝的是 數據庫甚至訪問,因爲 查詢沒有這麼鎖定。他說 表示數據庫將被禁用,如果 它繼續這種方式並導致 服務器問題。他說你應該修復所檢查的行或者獲得一個MySQL PS,儘管mysql ps不會修復 它,而是隻會阻止 數據庫被禁用。

下面是該查詢:

# Query_time: 25.944779 Lock_time: 0.000176 Rows_sent: 0 Rows_examined: 
15378209 
use desenvolvimentistas; 
SELECT `feed_entries`.* FROM `feed_entries` WHERE (id IN (SELECT `e`.`id` 
FROM `feed_entries` AS `e` INNER JOIN `feeds` AS `f` ON e.feed_id =f.id 
INNER JOIN `entries_categorias` AS `ec` ON ec.entry_id =e.id INNER JOIN 
`categorias` AS `c` ON ec.categoria_id =c.id WHERE (e.deleted =0) AND 
(c.slug IN('entenda','google')) GROUP BY `e`.`id` HAVING (COUNT(DISTINCT 
ec.id) =2))) ORDER BY `date` DESC LIMIT 1; 

這裏是另一個需要被固定:

# Query_time: 27.010857 Lock_time: 0.000165 Rows_sent: 0 Rows_examined: 
15382750 
use desenvolvimentistas; 
SET timestamp=1280325706; 
SELECT `e`.*, `f`.`titulo` AS `feedTitulo`, `f`.`url` AS `feedUrl` FROM 
`feed_entries` AS `e` 
INNER JOIN `feeds` AS `f` ON e.feed_id =f.id WHERE (e.id IN (SELECT 
`e`.`id` FROM `feed_entries` AS `e` 
INNER JOIN `feeds` AS `f` ON e.feed_id =f.id 
INNER JOIN `entries_categorias` AS `ec` ON ec.entry_id =e.id 
INNER JOIN `categorias` AS `c` ON ec.categoria_id =c.id WHERE (e.deleted 
=0) AND (c.slug IN('manchete', 'google')) GROUP BY `e`.`id` HAVING 
(COUNT(DISTINCT ec.id) =2))) ORDER BY `e`.`date` DESC LIMIT 4;7:18 

回答

1

理想情況下,每個問題的一個查詢請 - 您可以詢問的問題數量沒有限制,並且可以最大限度地減少與每個單獨查詢相關的顫音。

我重新寫你的第一個查詢爲:

SELECT t.* 
    FROM feed_entries t 
    WHERE EXISTS(SELECT NULL 
        FROM feed_entries AS e 
        JOIN feeds AS f ON e.feed_id = f.id 
        JOIN entries_categorias AS ec ON ec.entry_id = e.id 
        JOIN categorias AS c ON ec.categoria_id = c.id 
       WHERE e.deleted = 0 
        AND c.slug IN ('entenda', 'google') 
        AND e.id = t.id 
       GROUP BY e.id 
       HAVING COUNT(DISTINCT ec.id) = 2) 
ORDER BY date DESC 
    LIMIT 1 

指數在連接標準使用的列在最低限度,如果沒有的話。

我看到一條關於正在運行的查詢的150條評論 - 您能否詳細說明一下?

+0

因爲他命令它,但只取得最好的結果,是否有一個好的建議可以有'日期'的索引? – 2010-07-28 15:44:54

+0

@Neil Trodden:是的,但是[MySQL對分配索引的空間有限制(MyISAM爲1,000,InnoDB爲767)](http://dev.mysql.com/doc/refman/5.0/en/create-index .html)所以JOIN標準是我的首要任務,然後看看我能做些什麼來覆蓋索引。 – 2010-07-28 15:59:19

+0

謝謝,我減少了150個查詢的數量並定義了索引。也發現了其他的錯誤。現在可以了。 – 2010-08-03 16:12:23

1

嗯,我會檢查的第一件事是,你有託管服務器上的正確索引。有時候,人們在遷移數據庫時會忘記移動它們。

1

你總是可以緩存它;-)

+0

我已經有緩存。但是這個錯誤需要修正,我的表格不超過一千行。他說有一個查詢處理了一千五百萬個數據。 – 2010-07-28 16:34:22

0

我會嘗試創建一個查詢從內一個。 然後將生成的id手動添加到外部(其中((1,2,3,4,5)中的id))。 儘管這不會自動提高性能,但至少知道發生了什麼。

他們描述問題的方式,甚至可能是內循環針對從外循環檢查的每個單個記錄進行測試,這將通過該方法來修復。儘管我認爲MySQL會很聰明,但不能自行處理。