2017-02-19 83 views
0

我有以下查詢,它總是使整個網站下載下來的,原因是其的「等待表級鎖」:MySQL的性能:一個大的查詢總是卡住/慢

/*IPS\Patterns\_ActiveRecordIterator::count:246*/ SELECT SQL_CALC_FOUND_ROWS forums_posts . * , forums_topics . * 
FROM `forums_posts` 
LEFT JOIN `forums_topics` ON forums_posts.topic_id = forums_topics.tid 
LEFT JOIN `core_permission_index` ON core_permission_index.app = 'forums' 
AND core_permission_index.perm_type = 'forum' 
AND core_permission_index.perm_type_id = forums_topics.forum_id 
LEFT JOIN `forums_forums` ON forums_topics.forum_id = forums_forums.id 
WHERE (
NULLIF(forums_topics.moved_to, '') IS NULL 
) 
AND (
forums_forums.password IS NULL 
OR (
(
FIND_IN_SET(2, forums_forums.password_override) 
) 
) 
) 
AND (
forums_forums.can_view_others =1 
OR forums_topics.starter_id IS NULL 
) 
AND forums_forums.min_posts_view <=0 
AND queued =0 
AND forums_topics.approved =1 
AND (
(
(
FIND_IN_SET(2, perm_2) 
) 
) 
OR perm_2 = '*' 
) 
ORDER BY post_date DESC 
LIMIT 185725 , 25 

有什麼我可以做改善這個查詢的性能,而不是殺死進程/等待10分鐘直到它完成?

+0

那是因爲[SQL_CALC_FOUND_ROWS](http://stackoverflow.com/questions/186588/which-is-fastest-select-sql-calc-found-rows-from-table-or-select-count) – Fal

回答

0

如果這是一個「爬蟲」,正在打開你的網站,你真的必須擺脫OFFSET的使用。或者獲取一些過濾器來防止有效的DOS(拒絕服務)攻擊。至少告訴搜索機器人,以避免您的網站。 (這可能是簡單的答案。)

讓我們變得真實。 LIMIT 185725 , 25 - 這是第7429頁。你真的穿過那麼多頁嗎?

你有那麼多行,但沒有方便的方式來「搜索」或「鞏固」數據?

其他問題:

OR是昂貴的 - 它可以防止索引使用

LEFT JOIN往往需要尋找到「正確」的表,但快樂的時候無所不有。這可能比普通的JOIN更糟糕。 (然而,業務邏輯可能需要它。)

由於查詢的複雜性,SQL_CALC_FOUND_ROWS可能需要幾乎與獲取所有沒有LIMIT的行一樣長的時間。注意搜索引擎過去常常說「約180,000」的結果,然後甚至放棄了這一結果。也許你的應用程序應該這樣做。

當然有一個更簡單的方法來做NULLIF(forums_topics.moved_to, '') IS NULL

你使用什麼引擎表?如果使用MyISAM,切換到InnoDB;那可能會擺脫「表級鎖定」。

0

請檢查表類型是InnoDB。如果是MyISAM,則將其轉換爲InnoDB。 MyISAM無法讀取表中的數據,而其他某個線程/查詢正在更新該表中的任何行。它使用表級鎖。

InnoDB使用MVCC在UPDATE/INSERT/DELETE更新表時啓用SELECT。