ゆるいテキスト検索   ぬこ@横浜(@nuko_yokohama)
自己紹介   名前:ぬこ@横浜 仕事:ラーメンレビュー副業:某通信系SI会社勤務最近、(誰得な)PostgreSQL拡張に     はまってます。
誰得                ?  つくったものxml_fdw:XMLファイルを   SQLで検索するFDW ksj:漢数字で演算する型
第1章ntext EXTENSION
TEXT型検索に おける問題
ヴェスパ問題
「ヴェ」と「ベ」はだいたい一緒じゃん!(ベスパじゃ)いかんのか?
カヲル君問題
なんで「ヲ」なんだよっ!「エヴァンゲリヲン」もだけど。 「カオル君」「エヴァンゲリオン」で       検索しても「カヲル君」や「エヴァンゲリヲン」が      ヒットしない
全角英数字問題
俺は全角英数字が大嫌いなんだよ! 全角英数字は同じ意味の半角英数字とマッチしない・・・
半角カタカナ問題
半角カタカナを使う奴は地獄の火の中に投げ込まれるべきである     同じ意味の全角カタカナとマッチしない・・・
ねことネコ問題
にゃー                        ニャー     「ねこ」も「ネコ」も  全く同じように可愛いのだが      TEXT型では      SELECT ねこ = ネコ           ⇒false      trueでい...
typo問題
人はtypoをするものである。しかしTEXT型ではtypoがあると     ヒットしない。SELECT ダライアス = ダライアヌ          ⇒false   だいたいあってるから  trueでいいじゃんかよ!
とまあ、いろいろ 不満点はある
ここから本題
ゆるい評価を行う   TEXT型⇒ ntext型を作成
ntext EXTENSION feature ・全角数字/半角数字の正規化比較・全角/半角・大/小英字の正規化比較・ひらがな/全角カタカナ/半角カタカナの        正規化比較     ・正規化SQL関数      ・近似比較演算(多少の...
ntextデモ
でも(実        行コ   ストが)                  お高いTEXT型と                      ん   でしょ?ntext型の性能比較
環境Lets note CF-SX2 (メモリ8G、SSD) CentOS 6.2 on VMWare/Windows8           PostgreSQL 9.2      configurationはデフォルト測定はpgbenchカス...
モデル・検索対象テーブルはserial型と text/ntext型のカラムで構成・10文字の長さを持つデータを        10000件挿入・pgbenchで4種類のSELECTを         1000回実行      ・同時実行数は1
測定結果
スループット   text型         text型          ntext型        ntext型         ntext型         (SeqScan)     (IndexScan)    (=検索,      ...
pgbench による tps 測定(スループット)                                                                 text 型                         ...
pgbench による tps 測定(平均レスポンス時間)ひらがな                                                                                         ...
要するに
風が語りかけます遅い、遅すぎる(ntext型が)
textと相対比較するとかなり遅い・・・●でも、絶対値で見れば正規化も思ったよ り遅くはない●インデクスをきちんと張ればそれなり●近似検索も予想よりはマシ●ただし、CPUはゴリゴリ使うので、同時 実行数が多くなると厳しいかも。
TEXT型検索における残課題
送り仮名問題
戦前の送り仮名法と  戦後改定された送り仮名法で   送り仮名の方式が違う。しかも、それが混在しているのが現状「問合せ」「問い合わせ」「問合わせ」(近似検索である程度はカバーできるが・・・)
ニャ問題(拗音と直音)
ニャロメ「バニャニャ・・・!」 「ニャ」=「ナ」と正規化すべきか    最後まで悩んだ・・・。(現版ではニャ⇒ナ変換は未サポート)
拗音→直音正規化をやりすぎると  「きゃりーぱみゅぱみゅ」       ↓   「かりーぱむぱむ」 ここまでやるのはやりすぎ?
ニャルラトホテプ問題 (別名:表記ゆれすぎ問題)
(」・                ω   ・)」う    ナイアーラトテップ                         ー!                            (/・                        ...
シソーラスの導入?              ,,,,,,,,,,,,,,,,,,,,             /": : : : : : : : \           /-─-,,,_: : : : : : : : :\          ...
補足
正規化と近似検索相当 (あとシソーラス)は、    実は既にある。   正規化:textsearch_ja   シソーラス:textsearch近似検索:pg_trgmのsimilarity関数近似検索:contrib/fuzzystrmatch
教訓・・・      r ‐、      | ○ |         r‐‐、     _,;ト - イ、      ∧l☆│∧   良い子の諸君!    (⌒`    ⌒ヽ   /,、,,ト.-イ/,、 l      |ヽ   ~~⌒γ ⌒ ...
第2章近似検索拡張
正規化/近似検索と  全文検索連携  pg_trgm+正規化textsearch+近似検索
pg_trgm+正規化
pg_trgmでは正規化検索は不可
どうする?
pg_trgm機能と 正規化関数の組み合わせでOK
【pg_trgmのみ】SELECT id, data FROM testWHERE data LIKE%PostgreSQL%;【pg_trgm+正規化組み込み】SELECT id, data FROM testWHERE pg_ntext_n...
デモ
正規化組み込み前   「ラーメン」では「らーめん」や「ラーメン」が    ヒットしない。  (´・ω・`) ショボーン
正規化組み込み後  「ラーメン」でも「らーめん」や「ラーメン」が    ヒットした。  (`・ω・´) シャキーン
正規化+pg_trgm  簡単かつそれなりに有効
textsearch+近似検索
textsearchでは近似検索は不可
ぬこは激怒した。必ず、かの杓子定規のtextsearchをユルくしなければならぬと決意した。ぬこにはPostgreSQL内部がわからぬ。ぬこは、ただのユーザである。SQLを書き、psqlと遊んで暮して来た。けれども検索結果に対しては、人一倍に敏...
「フィロストラトスでございます。貴方のお友達セリヌンティウス様の弟子でご  ざいます。」(走れメロスより)「フィロストラス」(一文字抜けてる)「センヌリティウス」(微妙に?違う)  のキーワードで引っ掛けたい。   ※ textsearch単体...
どうする?
一筋縄ではいかない textsearch自体の   改造が必要     決してスマートな    方法ではないが・・・
HOOKポイントの追加 HOOK関数の実装  HOOKの有効化
HOOKとは?    フック(Hook)とは、 特定の場面で呼び出される処理を、ユーザが定義した処理に置き換える機能 ex. auto_explain, pg_statsinfo,      SE-PostgreSQL, ・・・
なぜHOOKを使う?HOOKにすることで、近似検索ロジック     を差し替え可能にする。ex. 自前の関数、pg_trgmのsimilarity()     相当の関数の組込みなど。
HOOKポイントの追加 backend/util/adt/tsvector_op.cここでtextsearchの @@ 演算子を実装 その関数内にHOOKポイントを追加
Postg                                                              reS   QL 9                                             ...
HOOK関数の実装 近似評価関数の実装   _PG_init()
【ts_compare/tsearch_hook.c】・・・extern void _PG_init(void);/*  * TsearchCompare_hook  * Custom approx compare function  */st...
HOOKの有効化 postgresql.confの設定shared_preload_libraries  PostgreSQLの再起動
HOOKの有効化【postgresql.conf】# - Other Defaults -#dynamic_library_path = $libdir#local_preload_libraries = shared_preload_libr...
デモ
近似検索組み込み前「センヌリティウス」では「セリヌンティウス」が    ヒットしない。  (´・ω・`) ショボーン
近似検索組み込み後「センヌリティウス」でも「セリヌンティウス」が    ヒットした。  (`・ω・´) シャキーン
近似検索+textsearch ちょっと邪道だが 結構使えないか?
さいごに
ニッチす              ぎて無                  理か 試作したtextsearch                       な・・・評価関数のHOOKをコミュニティに提案する価値はあるか?
ご清聴ありがとうございました
Upcoming SlideShare
Loading in …5
×

ゆるいテキスト検索

3,295 views

Published on

自作の正規化EXTENSION ntextと全文検索との組み合わせの説明

Published in: Technology
0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total views
3,295
On SlideShare
0
From Embeds
0
Number of Embeds
59
Actions
Shares
0
Downloads
19
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide

ゆるいテキスト検索

  1. 1. ゆるいテキスト検索 ぬこ@横浜(@nuko_yokohama)
  2. 2. 自己紹介 名前:ぬこ@横浜 仕事:ラーメンレビュー副業:某通信系SI会社勤務最近、(誰得な)PostgreSQL拡張に はまってます。
  3. 3. 誰得 ? つくったものxml_fdw:XMLファイルを SQLで検索するFDW ksj:漢数字で演算する型
  4. 4. 第1章ntext EXTENSION
  5. 5. TEXT型検索に おける問題
  6. 6. ヴェスパ問題
  7. 7. 「ヴェ」と「ベ」はだいたい一緒じゃん!(ベスパじゃ)いかんのか?
  8. 8. カヲル君問題
  9. 9. なんで「ヲ」なんだよっ!「エヴァンゲリヲン」もだけど。 「カオル君」「エヴァンゲリオン」で 検索しても「カヲル君」や「エヴァンゲリヲン」が ヒットしない
  10. 10. 全角英数字問題
  11. 11. 俺は全角英数字が大嫌いなんだよ! 全角英数字は同じ意味の半角英数字とマッチしない・・・
  12. 12. 半角カタカナ問題
  13. 13. 半角カタカナを使う奴は地獄の火の中に投げ込まれるべきである 同じ意味の全角カタカナとマッチしない・・・
  14. 14. ねことネコ問題
  15. 15. にゃー ニャー 「ねこ」も「ネコ」も 全く同じように可愛いのだが TEXT型では SELECT ねこ = ネコ ⇒false trueでいいじゃんかよ!
  16. 16. typo問題
  17. 17. 人はtypoをするものである。しかしTEXT型ではtypoがあると ヒットしない。SELECT ダライアス = ダライアヌ ⇒false だいたいあってるから trueでいいじゃんかよ!
  18. 18. とまあ、いろいろ 不満点はある
  19. 19. ここから本題
  20. 20. ゆるい評価を行う TEXT型⇒ ntext型を作成
  21. 21. ntext EXTENSION feature ・全角数字/半角数字の正規化比較・全角/半角・大/小英字の正規化比較・ひらがな/全角カタカナ/半角カタカナの 正規化比較 ・正規化SQL関数 ・近似比較演算(多少のtypoがあっても同じと評価) ・btree index対応
  22. 22. ntextデモ
  23. 23. でも(実 行コ ストが) お高いTEXT型と ん でしょ?ntext型の性能比較
  24. 24. 環境Lets note CF-SX2 (メモリ8G、SSD) CentOS 6.2 on VMWare/Windows8 PostgreSQL 9.2 configurationはデフォルト測定はpgbenchカスタムクエリモード
  25. 25. モデル・検索対象テーブルはserial型と text/ntext型のカラムで構成・10文字の長さを持つデータを 10000件挿入・pgbenchで4種類のSELECTを 1000回実行 ・同時実行数は1
  26. 26. 測定結果
  27. 27. スループット text型 text型 ntext型 ntext型 ntext型 (SeqScan) (IndexScan) (=検索, (=検索, (/=検索, SeqScan) IndexScan) SeqScan)tps 207.364 742.217 30.964 169.894 29.875平均レスポン text型 text型 ntext型 ntext型 ntext型ス時間 (SeqScan) (IndexScan) (=検索, (=検索, (/=検索, SeqScan) IndexScan) SeqScan)半角数字 1.155 0.070 7.472 1.145 7.822全角数字 1.231 0.067 8.362 1.230 8.651半角英字 1.152 0.071 7.966 2.145 8.297ひらがな 1.234 0.067 8.429 1.311 8.692
  28. 28. pgbench による tps 測定(スループット) text 型 (SeqScan) text 型 (IndexScan) ntext 型tps ( = 検索 , SeqScan ) ntext 型 ( = 検索 , IndexScan ) ntext 型 ( /= 検索 , SeqScan ) 0 100 200 300 400 500 600 700 800
  29. 29. pgbench による tps 測定(平均レスポンス時間)ひらがな text 型 (SeqScan)半角英字 text 型 (IndexScan) ntext 型 ( = 検索 , SeqScan ) ntext 型 ( = 検索 , IndexScan )全角数字 ntext 型 ( /= 検索 , SeqScan )半角数字 0.000 1.000 2.000 3.000 4.000 5.000 6.000 7.000 8.000 9.000 10.000
  30. 30. 要するに
  31. 31. 風が語りかけます遅い、遅すぎる(ntext型が)
  32. 32. textと相対比較するとかなり遅い・・・●でも、絶対値で見れば正規化も思ったよ り遅くはない●インデクスをきちんと張ればそれなり●近似検索も予想よりはマシ●ただし、CPUはゴリゴリ使うので、同時 実行数が多くなると厳しいかも。
  33. 33. TEXT型検索における残課題
  34. 34. 送り仮名問題
  35. 35. 戦前の送り仮名法と 戦後改定された送り仮名法で 送り仮名の方式が違う。しかも、それが混在しているのが現状「問合せ」「問い合わせ」「問合わせ」(近似検索である程度はカバーできるが・・・)
  36. 36. ニャ問題(拗音と直音)
  37. 37. ニャロメ「バニャニャ・・・!」 「ニャ」=「ナ」と正規化すべきか 最後まで悩んだ・・・。(現版ではニャ⇒ナ変換は未サポート)
  38. 38. 拗音→直音正規化をやりすぎると 「きゃりーぱみゅぱみゅ」 ↓ 「かりーぱむぱむ」 ここまでやるのはやりすぎ?
  39. 39. ニャルラトホテプ問題 (別名:表記ゆれすぎ問題)
  40. 40. (」・ ω ・)」う ナイアーラトテップ ー! (/・ ω・ )/に ゃー ナイアーラソテップ ! ナイアルラトホテップ ニャルラトテップ ニャルラトホテプ これは、同一の神性の名前・・・機械的正規化ではどうにもならんかも (近似検索でも厳しいかも?)
  41. 41. シソーラスの導入?              ,,,,,,,,,,,,,,,,,,,,             /": : : : : : : : \           /-─-,,,_: : : : : : : : :\          /     -,,,: : : : : : : :i          /、      /: : : : : : : : i     ________         r-、 ,,,,,,,,,,、 /: : : : : : : : : :i    /         L_, ,   、 \: : : : : : : : :i   / シソーラスを使ったら         /●) (●>   |: :__,=-、: / <   負けかなと思ってる        l イ  -     |:/ tbノノ    \        l ,`-=-\     `l ι;/      \  会社員(??歳・男性)        ヽトェ-ェェ-:)     -r          ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄         ヾ=-     / /     ____ヽ::::...   / ::::|  / ̄ ::::::::::::::l `──   :::|
  42. 42. 補足
  43. 43. 正規化と近似検索相当 (あとシソーラス)は、 実は既にある。 正規化:textsearch_ja シソーラス:textsearch近似検索:pg_trgmのsimilarity関数近似検索:contrib/fuzzystrmatch
  44. 44. 教訓・・・      r ‐、      | ○ |         r‐‐、     _,;ト - イ、      ∧l☆│∧   良い子の諸君!    (⌒`    ⌒ヽ   /,、,,ト.-イ/,、 l      |ヽ   ~~⌒γ ⌒ ) r⌒ `!´ `⌒) いい拡張を思いついた!と思っても   │ ヽー―^ー-  ( ⌒γ ⌒~~ /  大抵それは「先人が思いついた」ものだ   │  〉    |│  |`ー^ー― r |    │ /───| |  |/ |  l  ト、 |  類似の拡張がないか調べてから   |  irー-、 ー ,} |    /     i    作るんだぞ!   | /   `X´ ヽ    /   入  |
  45. 45. 第2章近似検索拡張
  46. 46. 正規化/近似検索と 全文検索連携 pg_trgm+正規化textsearch+近似検索
  47. 47. pg_trgm+正規化
  48. 48. pg_trgmでは正規化検索は不可
  49. 49. どうする?
  50. 50. pg_trgm機能と 正規化関数の組み合わせでOK
  51. 51. 【pg_trgmのみ】SELECT id, data FROM testWHERE data LIKE%PostgreSQL%;【pg_trgm+正規化組み込み】SELECT id, data FROM testWHERE pg_ntext_normalize(data::ntext)::text LIKEpg_ntext_normalize(%PostgreSQL%)::text; に )の代わり もOK omalize( alize()で text_n ja_norm pg_n h_jaの arc textse
  52. 52. デモ
  53. 53. 正規化組み込み前 「ラーメン」では「らーめん」や「ラーメン」が ヒットしない。 (´・ω・`) ショボーン
  54. 54. 正規化組み込み後 「ラーメン」でも「らーめん」や「ラーメン」が ヒットした。 (`・ω・´) シャキーン
  55. 55. 正規化+pg_trgm 簡単かつそれなりに有効
  56. 56. textsearch+近似検索
  57. 57. textsearchでは近似検索は不可
  58. 58. ぬこは激怒した。必ず、かの杓子定規のtextsearchをユルくしなければならぬと決意した。ぬこにはPostgreSQL内部がわからぬ。ぬこは、ただのユーザである。SQLを書き、psqlと遊んで暮して来た。けれども検索結果に対しては、人一倍に敏感であった。
  59. 59. 「フィロストラトスでございます。貴方のお友達セリヌンティウス様の弟子でご ざいます。」(走れメロスより)「フィロストラス」(一文字抜けてる)「センヌリティウス」(微妙に?違う) のキーワードで引っ掛けたい。 ※ textsearch単体では無理
  60. 60. どうする?
  61. 61. 一筋縄ではいかない textsearch自体の 改造が必要 決してスマートな 方法ではないが・・・
  62. 62. HOOKポイントの追加 HOOK関数の実装 HOOKの有効化
  63. 63. HOOKとは? フック(Hook)とは、 特定の場面で呼び出される処理を、ユーザが定義した処理に置き換える機能 ex. auto_explain, pg_statsinfo, SE-PostgreSQL, ・・・
  64. 64. なぜHOOKを使う?HOOKにすることで、近似検索ロジック を差し替え可能にする。ex. 自前の関数、pg_trgmのsimilarity() 相当の関数の組込みなど。
  65. 65. HOOKポイントの追加 backend/util/adt/tsvector_op.cここでtextsearchの @@ 演算子を実装 その関数内にHOOKポイントを追加
  66. 66. Postg reS QL 9 .2 .3の場【backend/util/adt/tsvector_op.c】 合int (*TsearchCompare_hook) (char* a, char* b, int len) = NULL; // add bynuko・・・ if (TsearchCompare_hook == NULL) { cmp = memcmp(a, b, Min(lena, lenb)); } else { // Custom Compare Hook Functoin Call cmp = (*TsearchCompare_hook) (a, b, Min(lena, lenb)); }・・・ else if ((TsearchCompare_hook == NULL) && cmp == 0 &&lena != lenb) // modify by nuko { cmp = (lena < lenb) ? -1 : 1; }
  67. 67. HOOK関数の実装 近似評価関数の実装 _PG_init()
  68. 68. 【ts_compare/tsearch_hook.c】・・・extern void _PG_init(void);/* * TsearchCompare_hook * Custom approx compare function */static intTsearchCompareApprox(char* a, char* b, int len){・・・実際の近似評価用のコード}・・・/* * Module initialization function */void_PG_init(void){ /* activate hook module is loaded */ TsearchCompare_hook = TsearchCompareApprox;}
  69. 69. HOOKの有効化 postgresql.confの設定shared_preload_libraries PostgreSQLの再起動
  70. 70. HOOKの有効化【postgresql.conf】# - Other Defaults -#dynamic_library_path = $libdir#local_preload_libraries = shared_preload_libraries = ts_compare_approx
  71. 71. デモ
  72. 72. 近似検索組み込み前「センヌリティウス」では「セリヌンティウス」が ヒットしない。 (´・ω・`) ショボーン
  73. 73. 近似検索組み込み後「センヌリティウス」でも「セリヌンティウス」が ヒットした。 (`・ω・´) シャキーン
  74. 74. 近似検索+textsearch ちょっと邪道だが 結構使えないか?
  75. 75. さいごに
  76. 76. ニッチす ぎて無 理か 試作したtextsearch な・・・評価関数のHOOKをコミュニティに提案する価値はあるか?
  77. 77. ご清聴ありがとうございました

×