0

2つのテーブルの複数の電話番号列の間で一致するものを見つけるためにクエリを実行しようとしていますが、時間がかかりすぎています(> 5分)。これは、データが可能な限りフィルタリングされているためです。合計行数を減らすために、両方のテーブルから検索できる実際の列をそれぞれのテーブルに分けました。

これは私が継承したレガシーアプリケーションからのものです。

クエリ

select count(b.bid) 
from customers_with_phone c,buyers_orders_with_phone b 
where 
   (b.hphone=c.pprim or b.hphone=c.phome or b.hphone=c.pwork or b.hphone=c.pother) 
or (b.wphone=c.pprim or b.wphone=c.phome or b.wphone=c.pwork or b.wphone=c.pother) 
or (b.cphone=c.pprim or b.cphone=c.phome or b.cphone=c.pwork or b.cphone=c.pother) 
group by b.bid;

テーブル

mysql> show columns from customers_with_phone;
+--------+---------+------+-----+---------+-------+
| Field  | Type    | Null | Key | Default | Extra |
+--------+---------+------+-----+---------+-------+
| pnum   | int(11) | YES  |     | NULL    |       |
| pprim  | text    | YES  |     | NULL    |       |
| phome  | text    | YES  |     | NULL    |       |
| pwork  | text    | YES  |     | NULL    |       |
| pother | text    | YES  |     | NULL    |       |
+--------+---------+------+-----+---------+-------+

mysql> show columns from buyers_orders_with_phone;
+--------+------+------+-----+---------+-------+
| Field  | Type | Null | Key | Default | Extra |
+--------+------+------+-----+---------+-------+
| bid    | text | YES  |     | NULL    |       |
| hphone | text | YES  |     | NULL    |       |
| wphone | text | YES  |     | NULL    |       |
| cphone | text | YES  |     | NULL    |       |
+--------+------+------+-----+---------+-------+

説明

+----+-------------+-------+------+---------------+------+---------+------+-------+----------+----------------------------------------------+
| id | select_type | table | type | possible_keys | key  | key_len | ref  | rows  | filtered | Extra                                        |
+----+-------------+-------+------+---------------+------+---------+------+-------+----------+----------------------------------------------+
|  1 | SIMPLE      | b     | ALL  | NULL          | NULL | NULL    | NULL |  8673 |   100.00 | Using where; Using temporary; Using filesort |
|  1 | SIMPLE      | c     | ALL  | NULL          | NULL | NULL    | NULL | 75931 |   100.00 | Using where; Using join buffer               |
+----+-------------+-------+------+---------------+------+---------+------+-------+----------+----------------------------------------------+

これらは検索する必要のある列のみであり、元のテーブルからこれらの列を抽出したため、どちらのテーブルにも主キーがないことに気付きました。ただし、元のテーブルを使用すると、フィルタリングするデータがはるかに多いため、さらに時間がかかります。

これに似た他のクエリがあり、より多くのデータで機能するため、これを妥当な時間内に機能させることができれば、他のクエリも同様に機能させることができます。

4

2 に答える 2

0

A primary key is not a optimazation. What you need are non clustered index on your telephone text fields (one index per column). With these, you won't need to extract your data to seperate tables.

于 2012-12-14T20:38:57.600 に答える
0

従来のクエリはひどいものです。申し訳ありません。完全デカルト積です。

データ構造は、そのようなクエリを効果的に処理できません。1 つのテーブルに 3 つのフィールドがあり、別のテーブルに 4 つのフィールドがあり、いずれかのペアが一致するかどうかを調べようとします。

おそらくすべての電話番号列の主キーとキーにより、このクエリが改善される可能性がありますが、確かではありませんが、削除/挿入/更新のパフォーマンスが低下する可能性があります。

ところで、null可能な列でインデックスを作成することは不可能だと書いています。それは正しくありません。

データ構造を変更するか、トリガーを使用して何らかのキャッシュメカニズムを追加するという根本的な解決策しか信じられません。しかし、それは難しいです。

于 2012-12-15T00:17:21.360 に答える