SQL优化大或查询

时间:2012-12-14 20:26:49

标签: mysql sql query-optimization

我正在尝试运行查询以查找两个表上多个电话号码列之间的任何匹配,并且花费太长时间(> 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               |
+----+-------------+-------+------+---------------+------+---------+------+-------+----------+----------------------------------------------+

我意识到两个表都没有主键,因为这些只是我需要搜索的列,而是从原始表中提取这些列。但是使用原始表需要更长的时间,因为有更多的数据需要过滤。

我有其他类似的查询可以处理更多数据,所以如果我能在合理的时间内完成这项工作,我可以让其他人同样工作。

2 个答案:

答案 0 :(得分:0)

主键不是优化。您需要的是电话文本字段上的非聚集索引(每列一个索引)。有了这些,您就不需要将数据提取到单独的表中。

答案 1 :(得分:0)

遗留查询很糟糕,抱歉。它是完整的笛卡尔产品。

数据结构无法有效处理此类查询。您在一个表中有3个字段,在另一个表中有4个字段,并尝试确定是否有任何一对匹配。

每个电话列的主键和密钥可能会改进此查询,但不确定,但它可以使删除/插入/更新性能更差。

顺便说一下,你写的是不可能通过可空列索引。这不对。

我只相信激进的解决方案 - 改变数据结构或添加某种带触发器的缓存机制。但这很难。