星期一, 12月 26, 2005

MySQL 到 SQL Server 的轉換

上週提到,使用 MySQL 全文檢索遇到的效能困境。

想起從前曾用過 Microsoft SQL Server 的全文檢索功能,而當初的感覺還不錯,所以就打算將雛型的資料庫改用 SQL Server 2000,來比對是否真的是 MySQL 的問題。

不過,字元編碼的問題又再度出現:MySQL 支援 UTF-8,但不支援 UTF-16 的字元編碼。M$ SQL Server 則正好相反,支援 UTF-16,卻不支援 UTF-8。當下嘆了口氣:看來,轉碼的功夫是省不了的...

找了幾個資料庫轉換的工具軟體,都無法在資料庫之間正確轉碼,所以就只好自己動手寫程式。不過,SQL Server 的 drivers 似乎很奇怪,大五碼(big-5)的字元可以正確地轉譯到 nvarchar 或者 ntext,但其他字元怎麼都會變成問號呢?

明明覺得「一定有辦法解決」,但怎麼總是有某個地方不對勁?又是一番冗長的手冊閱讀、網路搜尋、以及嘗試錯誤過程。頗幸運地,最後終於找到正確的轉碼方式了。

轉譯的過程,用到了 PHP COM 模組的 CP_UTF8 codepage,以及 SQL Server 指令的 "N" prefix。我想,這應該就是所謂的「know how」吧:明明知道必然有解,而最終也證明這個解相當簡單,但如果缺乏這個 know how,就怎麼也做不出來。

5 則留言:

被掛掉的阿尼 提到...

即然你已經轉了就算了
不然本來想如果效能真的不能忍受, 在mysql裡開二個isam table(就是一個table本身就是isam, 而不是指定索引欄位, 如果mysql沒有isam table也只是浪費空間), 一個是(單字, 文章), 一個是(雙字, 文章). 應該可以很快的做初級過濾

tu 提到...

全文檢索的麻煩,就是應該有基本 Boolean queries 的能力:除了可以檢索出「可能含有數個詞彙之一的文件」外,還要處理「負詞彙」(也就是說,應該要有能力可以檢索出「不含某些字詞的文件」)。

如果要直接用關聯式資料庫實作,那光是 query processing 就很麻煩,而且效能應該不會很好(用 n-gram 來建立數個 tables 也不是不行啦,但總覺得麻煩)。所以,能夠用現成的資料庫是最好的。

被掛掉的阿尼 提到...

呵, 這是資料庫理論裡一個典型的問題, 叫self-join. 例如有一個isam table x(單字, 文章, 位置), 那大部份的檢索都可以寫進去 (有utm的感覺). 例如我要找蜥蜴, 那可以寫成 select * from (select * from x where 單字='蜥' as T1), (select * from x where 單字='蜴' as T2) where t1.文章 = t2.文章 and t1.位置+1 = t2.位置
我真的試過幾個常用的database, 用當時我不是有一台跑os2的pc, 結果db2比其他快很多. 不是因為os2的關係, 而是db2真的有花工夫在這上面. 在db2的教學書上, 還有教怎麼用sql做旅行規劃

tu 提到...

阿尼所說的,應該就是利用關聯式資料庫來實作 inverted file(全文索引)的方法吧。

關聯式資料庫背後有頗堅實的集合論基礎,因此在理論上,要換成 SQL commands 來做集合的處理,應該是不會有問題的。

但全文檢索的麻煩,除了將 user query 翻譯為資料庫指令外,對於 Boolean queries 的 OR 與 NOT 效能,也常常不能忽視。(因為有限集合的「OR」與「NOT」天生就很吃計算資源。)

例如,這樣的檢索條件「廣福 大湖 -金廣福」是要搜尋「含有『廣福』或『大湖』,但不含『金廣福』」的文件,用傳統的資料庫搜尋就很傷效能。(當然也可以做優化處理啦,但花這些力氣去做,總覺得不甚舒服。)

所以,如果有現成的全文檢索支援,那不是更好嗎?

被掛掉的阿尼 提到...

SQL有差集啦
不過你還是去試一試google desktop的api吧, 試完再報告一下