简体   繁体   English

JOIN查询非常慢

[英]Very slow JOIN query

I've got a 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

The above is extremely slow as I increase the time period. 随着我增加时间,上述过程极其缓慢。 The above takes about 20 seconds. 以上过程大约需要20秒。

My two table schemas: 我的两个表模式:

`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 has about 1,6 mil rows visit_count大约有visit_count万行

and

orgs has about 14k rows orgs约有1.4万行

Any ideas how I could make this go faster? 有什么想法可以使此过程更快吗?

Edit 编辑

The explain: 解释:

+----+-------------+-------+-------+------------------------------+-----------+---------+------+-------+---------------------------------------------------+
| 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)

Doing address lookups like this is very innefficient. 像这样进行地址查找是非常低效的。 Firstly, you're using a function as a join expression which means you can't use an index, and range queries (particularly on IP addresses) are very innefficient. 首先,您将函数用作联接表达式,这意味着您无法使用索引,并且范围查询(尤其是IP地址)效率很低。

Using the same data type in both tables would help. 在两个表中使用相同的数据类型将有所帮助。 To solve the range lookup problem there are 2 solutions: 要解决范围查找问题,有2个解决方案:

1) instead of having a reference set of arbitrary network ranges, used fixed ranges (eg 255.255.255.0 netmasked) This could be in the form of an:m decomposition between the current tables which would also allow you to keep the differing data types but use indexes. 1)使用固定范围(例如255.255.255.0子网掩码),而不是使用任意范围的网络范围作为参考集,这可以采用当前表之间的an:m分解的形式,这也允许您保留不同的数据类型,但是使用索引。

This a rather kludgy solution. 这是一个相当笨拙的解决方案。

2) Keep the reference set of IP addresses in a geospatial table. 2)将参考IP地址集保留在地理空间表中。 Note that although the address range is a 1-dimensional space, the MySQL Geospatial database only really understands 2-d spaces hence you need to fudge the space a little - this is nicely described here 请注意,尽管地址范围是一维空间,但是MySQL Geospatial数据库仅真正理解二维空间,因此您需要对空间稍加捏造- 此处对此进行了很好的描述

Note that the time range lookup is less affected as the upper and lower bounds of the predicates are bother defined by the same column in the table. 请注意,时间谓词查找受到的影响较小,因为谓词的上下限由表中的同一列定义。

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

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