2012-11-28 29 views
1

假設我有一個包含100列和100萬行的訂單表。它在OrderID和FK約束StoreID - > Store.StoreID上有一個PK。上述爲什麼在MySQL中查詢需要很長時間,即使有LIMIT子句?

1)select * from 'Order' order by OrderID desc limit 10;

需要幾毫秒。

2)select * from 'Order' o join 'Store' s on s.StoreID = o.StoreID order by OrderID desc limit 10;

這在某種程度上可能需要長達許多秒。我添加的內部聯接越多,速度就越慢。

3)select OrderID, column1 from 'Order' o join 'Store' s on s.StoreID = o.StoreID order by OrderID desc limit 10;

這似乎加速執行起來,通過限制我們選擇列。

有幾點,我不明白在這裏,如果有人更熟悉與MySQL(或一般rmdb查詢執行)可以啓發我,真的很感激。

查詢1很快,因爲它只是一個反向查找的PK和DB只需要返回遇到的前10行。

我不明白爲什麼查詢2應該永遠採取。操作不應該一樣嗎?即通過PK得到前10行並且然後與其他表加入。由於存在FK約束,因此可以保證滿足關係。所以DB不需要加入超過必要的行數,然後修剪結果,對吧?除非FK約束允許空FK?在這種情況下,我猜左連接會比內連接快得多嗎?

最後,我猜查詢3只是更快,因爲在這些不必要的連接中使用較少的列?但爲什麼查詢執行時需要其他列加入?它不應該只是首先使用PK加入,然後獲得10列的列嗎?

謝謝!

+0

如果你有一個有100列的表格,那麼表格的設計就會出錯。作爲一個經驗法則,RDBMS擅長使用細長的表格,只要您可以應用明智的btree索引即可。 – gview

+0

雖然很容易指出不好的設計,但不會簡單地從頭開始編寫所有的東西,或者在獲得第一個機會時重新設計/重寫。 =) – Xerion

+0

Xerion:事實上,指出一個糟糕的設計並不容易 - 如果是的話,會有更少的糟糕設計。它實際上需要了解關係數據庫背後的基本概念,以及有效設計模式的一些經驗。然而,我不需要那些人說,當你規定你有一個100列以上的桌子時,那種設計是完全錯誤的。我知道它可能不是你的設計,你可能無法改變它,但你也被畫到了一個角落,在這個角落裏,容易和高性能的東西都不是。 – gview

回答

2

我的理解是,在發生任何join之後,mysql引擎會應用limit

http://dev.mysql.com/doc/refman/5.0/en/select.htmlThe HAVING clause is applied nearly last, just before items are sent to the client, with no optimization. (LIMIT is applied after HAVING.)

編輯:您可以嘗試使用此查詢趁PK速度。

select * from (select * from 'Order' order by OrderID desc limit 10) o join 'Store' s on s.StoreID = o.StoreID;

+0

除了在答案中的可讀性/格式化之外,最終的查詢正是我所建議的...... – DRapp

+0

酷,這是一個不錯的訣竅。 – Xerion

2

你所有的例子都要求現有的表的表掃描,所以沒有人會比在何種程度上的MySQL可以緩存數據或結果或多或少的高性能。你的一些查詢有順序或連接標準,它們可以純粹的利用索引來提高連接過程的效率,但是,這仍然不同於具有一組觸發索引使用的標準。

限制不是一個標準 - 一旦確定了結果集,它可以被認爲是過濾。一旦結果集準備就緒,您就可以節省客戶端上的時間,而不是在服務器上。

真的,讓你正在尋找的答案,唯一的辦法就是去熟悉: EXPLAIN EXTENDED your_sql_statement

EXPLAIN會告訴你多少行正在看着由MySQL,以及對輸出無論是否使用任何索引。

相關問題