2010-11-18 16 views
1

私はインポートされた情報を格納するデータベーステーブルを持っています。簡単にするために、のようなその何か:MySQLクエリの最適化

CREATE TABLE `data_import` (
`id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT, 
`amount` DECIMAL(12,2) NULL DEFAULT NULL, 
`payee` VARCHAR(50) NULL DEFAULT NULL, 
`posted` TINYINT(1) NOT NULL DEFAULT 0, 
PRIMARY KEY (`id`), 
INDEX `payee` (`payee`) 
) 

は、私はまた、インポートルールを格納するテーブルを持っている:

CREATE TABLE `import_rules` (
`id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, 
`search` VARCHAR(50) NULL DEFAULT NULL, 
PRIMARY KEY (`id`), 
INDEX `search` (`search`) 
) 

アイデアは、インポートされた各トランザクションのために、クエリは単一のマッチングルールを見つけてみてくださいする必要があるということです - この一致は、data_import.payeeおよびimport_rules.seachフィールドで行われます。これらは両方ともvarcharフィールドなので、クエリを高速化するためにインデックスを作成しました。

これは私がこれまでに思いついたことですが、うまくいくようです。私が望むよりも遅いです。その特定に参加するクエリを停止することが可能である - 上記のクエリは、のために食料調達しないこと

SELECT i.id, i.payee, i.amount, i.posted r.id, r.search 
FROM import_data id 
LEFT JOIN import_rules ir on REPLACE(i.payee, ' ', '') = REPLACE(ir.search, ' ', '') 

ことの一つは、1 = import_data.postedあれば、私はその行のルールを見つける必要がいけないということです行?同様に、受取人がヌルであれば、どちらも参加しないでください。

これを最適化できる方法は他にありますか?私は、テキスト結合を行うことは理想的ではないことを認識しています。

答えて

2

REPLACE()の後に修正された値ではなく、フィールドの値のインデックスを持つため、結合でREPLACE()を使用すると索引が破られている可能性があります。

参加しない場合は、すでにLEFT JOINを使用しているため、一致しない結合の場合はimport_rulesフィールドにNULLが返されます。それを強制するためにWHERE句を追加できるはずです。

3

JOINには、REPLACEを削除することを強くお勧めします。結合の両側にREPLACEを使用すると、両方のテーブルでインデックスを使用する能力が完全になくなります。

  • はあなたがテキストに 列に参加する必要がありは、 ごとに単一のバイトを使用する場合:あなたは(既存のデータおよび/または新しいデータをクレンジングして)REPLACE Sを取り除くことができますと仮定

    あなたがアプリケーション (小さい/より速いインデックスのための)それを可能にする場合、文字の文字セット。

  • それがインデックスの側 に影響を与える(または、ほぼ間違いなく、インデックス 接頭辞を使用)しますようNVARCHAR(N)のように小さな することができますようにしてください。
  • 私はあなたがimport_rules UNIQUEsearchインデックスを作りたい想像 - あなたは唯一 は、1行の結果は、あなたがANDを投げることができる import_data

の行ごとに返さ取得するつもりに確認していますあなたの「WHERE」句に「このケースに参加しない」ルールを適用したい場合は、

LEFT JOIN import_rules ir ON id.payee=ir.search AND id.posted != 1