0

私は2つのテーブルを持っています:

辞書- 約 36,000 語を収録

CREATE TABLE IF NOT EXISTS `dictionary` (
  `word` varchar(255) NOT NULL,
  PRIMARY KEY (`word`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

データ- 約 100,000 行が含まれます

CREATE TABLE IF NOT EXISTS `datas` (
  `ID` int(11) NOT NULL AUTO_INCREMENT,
  `hash` varchar(32) NOT NULL,
  `data` varchar(255) NOT NULL,
  `length` int(11) NOT NULL,
  `time` int(11) NOT NULL,
  PRIMARY KEY (`ID`),
  UNIQUE KEY `hash` (`hash`),
  KEY `data` (`data`),
  KEY `length` (`length`),
  KEY `time` (`time`)
) ENGINE=InnoDB  DEFAULT CHARSET=latin1 AUTO_INCREMENT=105316 ;

datasdataに1つ以上の単語が含まれている行をすべて選択したいと思います。

これは大きな課題であることを理解しています。可能な限りすべての組み合わせでこれらの行をすべて一致させる必要があるため、最適な最適化が必要です。

以下のクエリを試しましたが、何年もハングアップしています。

SELECT      `datas`.*, `dictionary`.`word`
FROM        `datas`, `dictionary`
WHERE       `datas`.`data` LIKE CONCAT('%', `dictionary`.`word`, '%')
AND         LENGTH(`dictionary`.`word`) > 3
ORDER BY    `length` ASC
LIMIT       15

また、左結合と、like ステートメントを指定した on 句を使用して、上記と同様のことを試しました。

4

3 に答える 3

1

これは実際には簡単な問題ではありません。実行しようとしているのは全文検索と呼ばれるものであり、リレーショナル データベースはそのようなタスクに最適なツールではありません。これがある種のコア機能である場合は、Sphinx Search Serverなど、この種の操作専用のソリューションの使用を検討してください。

これが「ミッション クリティカル」なシステムでない場合は、別のものを試すことができます。data.data 列はそれほど長くないことがわかります。そのため、タスク専用の構造を作成し、運用中に維持し続けることができます。たとえば、テーブルを作成します。

dictionary_datas (
    datas_id FK (datas.id),
    word FK (dictionary.word)
)

データまたはディクショナリ テーブルを挿入、削除、または単に変更するたびに、どの datas_id にどの単語が含まれているか (基本的に多対多の関係) の情報をそこに配置して、dictionary_datas を更新します。もちろん、パフォーマンスが低下するため、システムのトランザクション負荷が高い場合は、定期的にこれを行う必要があります。たとえば、毎晩午前 3 時に実行される Cron ジョブを配置し、テーブルを実現します。タスクを簡素化するために、フラグ TO_CHECK を DATAS テーブルに追加し、そこに 1 を持つレコードのデータのみを実体化できます (dictionary_datas を実体化した後、値を 0 に切り替えます)。ちなみに、DICTIONARY テーブルを更新した後は、DATAS テーブル全体を更新することを忘れないでください。36 000 と 100 000 は、データ処理の観点からは大きな数字ではありません。

このテーブルを取得したら、次のようにクエリを実行できます。

SELECT datas_id, count(*) AS words_num FROM dictionary_datas GROUP BY datas_id HAVING count(*) > 3;

クエリを高速化する (ただし、更新を低速化する) には、列 datas_id、word (正確にその順序で) に複合インデックスを作成できます。データを定期的に更新する場合は、データを更新するよりも更新前にインデックスを削除し、更新後に最後にインデックスを作成する必要があります。この方法の方が高速です。

于 2012-09-15T15:27:13.243 に答える
0

あなたの問題を理解できたかどうかはわかりませんが、これで解決できると思います。また、人々は正規表現が好きではないと思いますが、これは、値が複数の単語を持つ列を選択するのに役立ちます。

SELECT * FROM データ WHERE データ REGEXP "([az] )+"

于 2012-09-15T15:36:22.123 に答える
0

これを試しましたか?

 select *
 from dictionary, datas
 where position(word,data) > 0 
 ;

これは非常に非効率的ですが、あなたにとっては十分かもしれません。ここにフィドルがあります。

パフォーマンスを向上させるには、テキスト列にテキスト検索インデックスを配置してから、 の代わりに関数DATAを使用してみてください。CONTAINSPOSITION

于 2014-02-03T06:08:40.837 に答える