2010-08-15 48 views
3

我在我的表中有一個字段有文本數據類型。這兩個sql查詢的性能有什麼區別?

有以下兩個SQL查詢性能差異:

select * from tablename where fieldname="xyz%"; 
select * from tablename where fieldname="%zyx"; 

如果我們要實現這些查詢的執行,這就是我認爲我們需要做的:

我們必須匹配兩個正則表達式(xyz *和* zyx)。我們將不得不從一開始就檢查字符串字符。

對於第一個查詢,我們必須讀取前三個字符來查看是否有匹配,但對於第二個字符,我們必須閱讀,直到我們得到字符串的結尾以確定匹配是否已經發生。但是,如果我們將字符串的長度存儲在某處,我們可以直接讀取最後三個字符,表現出與第一種情況類似的性能。

我的問題是像mysql和oracle這樣的商業數據庫在執行查詢時的性能是否有差異。

+0

請問,爲什麼你需要匹配這兩個正則表達式? – 2010-08-15 06:44:25

+0

只是一個想法,超越了我的想法。我認爲這是一個非常普遍的用例,我已經說過。 – 2010-08-15 07:21:02

+0

恰恰相反,它是我們非常不尋常的用戶案例。如果你需要這兩個正則表達式,你可以肯定地說他們的數據庫模式是錯誤的。可能是這些數據應該分成不同的列。 – 2010-08-15 07:30:15

回答

4

從您的評論中摘錄:「我只是想知道,如果以比賽開始並且比賽結束時是比賽結果」。

首先 - 請記住,我們不是在尋找匹配字符串的最佳算法。我們正在尋找最佳算法來查找一組N行中的所有匹配字符串。我們想要比'做算法X,N次'做得更好。

如果fieldname沒有被索引,那麼這兩個查詢之間的性能差別很小--SQL引擎只會對字符串的前3個或最後3個字節進行匹配,這只是一個簡單的抵消正確的內存位置的問題。

如果字段名被索引,兩次搜索之間的性能會有很大差異,因爲不是檢查所有N行,而是可以丟棄大部分數據。

即對於「xyz%」版本,我們可以使用二進制搜索。

我們從中間元素開始,這恰好是'彼得'。我們可以在'peter'之前立即丟棄所有內容,並在其餘部分獲得中間元素 - 'samantha',等等,直到我們找到開始'xyz'的條目。

使用「%xyz」版本,我們不能這樣做,因爲ANY字符串可能在最後匹配,我們需要查看每個字符串。

隨着表格尺寸的擴大,這兩種方法之間的差異變大。

爲字段名的反向創建字段/索引的解決方案允許我們再次使用二進制搜索技術。 (在一些數據庫中,實際上可以做到這一點而不創建額外的字段,但通過使用特定的索引類型,虛擬列等)。

這簡化了很多 - 有關數據庫索引實際實現的詳細信息,請查看B樹和B *樹索引。

2

如果fieldname被索引,大多數商業數據庫的可轉換第一個查詢到一個區間檢索

select * from tablename where fieldname>="xyz" and fieldname<"xy{" 

這是非常快的。

+0

第二個呢,它有什麼作用。 – 2010-08-15 07:20:01

+0

btw xyz可能是任何東西。例如,它可能是'2wssdfj,fsf @ sef34'。 – 2010-08-15 07:21:52

+0

@iamrohitbanga這個對話變得越來越抽象。其實沒有人知道你的意思或想要什麼。你能否在一些真實的生活理由上設計一個例子?謝謝 – 2010-08-15 07:32:41

6

所有DB的性能之間肯定存在差異。 如果列索引,第一種情況肯定會更快。

我在我的項目中有類似的實例,用戶也被允許搜索「ends with」(就像你的第二個查詢)。

,因爲這是頻繁使用的操作和查詢速度慢,

  1. 我們增加附加列,其存儲的字段名的反變換表。
  2. 索引此列,每當結束與被搜查,我們在 這個新列:)搜索(通過逆轉原始搜索字符串)

所以你的第二個查詢變爲:

select * from tablename where fieldname_rev="xyz%"; 

這種方法使其與查詢開始一樣快。

+0

@Col。這就是我正在尋找的彈片。 @YoK是在理論或數據庫手冊中的任何地方記錄的。 你能舉出一些這樣的來源嗎?非常感謝。 – 2010-08-15 07:55:27

+0

@iamrohitbanga我不知道它在理論上還是數據庫手冊?但正如我所說,我是從我的項目經驗中寫下來的。我會盡力從某種理論中發現它。 – YoK 2010-08-15 08:15:43

+1

@iamrohitbanga大聲笑,所以你甚至不能告訴你沒有人的幫助下找什麼?你需要努力。知道你想要做什麼總是有幫助 – 2010-08-15 08:36:43

1

是的,有以下兩個查詢之間的區別:

select * from tablename where fieldname LIKE "xyz%"; 
select * from tablename where fieldname LIKE "%zyx"; 
  1. 的等號( 「=」)運算符不允許在SQL通配符 - 你需要使用LIKE
  2. 的查詢是完全不同的
    • 「XYZ%」 將返回記錄中開始與 「XYZ」
    • 「%某某」 將返回記錄中年底與 「XYZ」
  3. 假設在fieldname列存在索引, 「%XYZ」 可以不會使用索引 - 但「xyz%」可以,這意味着它會更快。

在文本中查找子字符串的最快方法是使用全文搜索(FTS) - Oracle和MySQL都有自己的本地功能,並且有像Sphinx和Solr這樣的第三方工具。