繁体   English   中英

JOIN查询非常慢

[英]Very slow JOIN query

我有一个查询:

EXPLAIN 
SELECT i.ipStart, i.ipEnd, i.descr 
FROM orgs i 
JOIN visit_count v 
on inet_aton(v.ipaddress) BETWEEN i.ipStart and i.ipEnd
WHERE v.last_visit BETWEEN '2014-10-10' AND '2014-10-22' 
AND v.user_id = 1

随着我增加时间,上述过程极其缓慢。 以上过程大约需要20秒。

我的两个表模式:

`visit_count` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `visitCount` int(11) NOT NULL,
  `user_id` int(11) NOT NULL,
  `cookieId` varchar(50) NOT NULL,
  `ipaddress` varchar(50) NOT NULL,
  `last_visit` datetime NOT NULL,
  PRIMARY KEY (`id`),
  KEY `cookieId` (`cookieId`),
  KEY `user_id` (`user_id`),
  KEY `last_visit` (`last_visit`),
  KEY `user_id_2` (`user_id`,`last_visit`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;


`orgs` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `ipStart` bigint(100) DEFAULT NULL,
  `ipEnd` bigint(100) DEFAULT NULL,
  `land` varchar(250) DEFAULT NULL,
  `descr` varchar(250) DEFAULT NULL,
  `ipStartRead` varchar(250) DEFAULT NULL,
  `ipEndRead` varchar(250) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `ipStart` (`ipStart`,`ipEnd`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

visit_count大约有visit_count万行

orgs约有1.4万行

有什么想法可以使此过程更快吗?

编辑

解释:

+----+-------------+-------+-------+------------------------------+-----------+---------+------+-------+---------------------------------------------------+
| id | select_type | table | type  | possible_keys                | key       | key_len | ref  | rows  | Extra                                             |
+----+-------------+-------+-------+------------------------------+-----------+---------+------+-------+---------------------------------------------------+
   1   SIMPLE        v       range   user_id,last_visit,user_id_2   user_id_2         9   NULL     357   Using index condition
   1   SIMPLE        i       ALL     NULL                           NULL        NULL      NULL   22068   Using where; Using join buffer (Block Nested Loop)

像这样进行地址查找是非常低效的。 首先,您将函数用作联接表达式,这意味着您无法使用索引,并且范围查询(尤其是IP地址)效率很低。

在两个表中使用相同的数据类型将有所帮助。 要解决范围查找问题,有2个解决方案:

1)使用固定范围(例如255.255.255.0子网掩码),而不是使用任意范围的网络范围作为参考集,这可以采用当前表之间的an:m分解的形式,这也允许您保留不同的数据类型,但是使用索引。

这是一个相当笨拙的解决方案。

2)将参考IP地址集保留在地理空间表中。 请注意,尽管地址范围是一维空间,但是MySQL Geospatial数据库仅真正理解二维空间,因此您需要对空间稍加捏造- 此处对此进行了很好的描述

请注意,时间谓词查找受到的影响较小,因为谓词的上下限由表中的同一列定义。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM