重写这个子查询?

时间:2010-10-04 21:33:19

标签: sql mysql database query-optimization

我正在尝试构建一个新表,以便在另一个表中不包含现有表中的值(但显然包含以下检查)。以下是我的表结构:

mysql> explain t1;
+-----------+---------------------+------+-----+---------+-------+
| Field     | Type                | Null | Key | Default | Extra |
+-----------+---------------------+------+-----+---------+-------+
| id        | int(11)             | YES  |     | NULL    |       | 
| point     | bigint(20) unsigned | NO   | MUL | 0       |       | 
+-----------+---------------------+------+-----+---------+-------+

mysql> explain whitelist;
+-------------+---------------------+------+-----+---------+----------------+
| Field       | Type                | Null | Key | Default | Extra          |
+-------------+---------------------+------+-----+---------+----------------+
| id          | bigint(20) unsigned | NO   | PRI | NULL    | auto_increment | 
| x           | bigint(20) unsigned | YES  |     | NULL    |                | 
| y           | bigint(20) unsigned | YES  |     | NULL    |                | 
| geonetwork  | linestring          | NO   | MUL | NULL    |                | 
+-------------+---------------------+------+-----+---------+----------------+

我的查询如下:

SELECT point 
  FROM t1 
 WHERE EXISTS(SELECT source 
                FROM whitelist 
               WHERE MBRContains(geonetwork, GeomFromText(CONCAT('POINT(', t1.point, ' 0)'))));

说明:

    +----+--------------------+--------------------+-------+-------------------+-----------+---------+------+------+--------------------------+
| id | select_type        | table              | type  | possible_keys     | key       | key_len | ref  | rows | Extra                    |
+----+--------------------+--------------------+-------+-------------------+-----------+---------+------+------+--------------------------+
|  1 | PRIMARY            | t1                 | index | NULL              | point     | 8       | NULL | 1001 | Using where; Using index | 
|  2 | DEPENDENT SUBQUERY | whitelist          | ALL   | _geonetwork       | NULL      | NULL    | NULL | 3257 | Using where              | 
+----+--------------------+--------------------+-------+-------------------+-----------+---------+------+------+--------------------------+

查询在t1中执行1000条记录需要6秒钟,这对我来说是不可接受的。如果我没有要加入的列,如何使用连接重写此查询(或者如果存在的话,可能是更快的方式)?在最坏的情况下,即使是存储过程也是可以接受的。我的目标是最终创建一个包含来自t1的条目的新表。有什么建议吗?

2 个答案:

答案 0 :(得分:1)

除非查询优化器失败,否则WHERE EXISTS构造应该与具有GROUP子句的连接产生相同的计划。看看优化MBRContains(geonetwork, GeomFromText(CONCAT('POINT(', t1.point, ' 0)')))),这可能是您的查询一直花费的地方。我没有这方面的建议,但这是用JOIN编写的查询:

Select t1.point
from t1
join whitelist on MBRContains(whitelist.geonetwork, GeomFromText(CONCAT('POINT(', t1.point, ' 0)'))))
group by t1.point
;

或者让t1中的点不在白名单中:

Select t1.point
from t1
left join whitelist on MBRContains(whitelist.geonetwork, GeomFromText(CONCAT('POINT(', t1.point, ' 0)'))))
where whitelist.id is null
;

答案 1 :(得分:0)

这似乎是对t1进行去正规化可能有益的情况。添加值为GeomFrmTxt的{​​{1}}列可以加快您已有的查询速度。