2010-02-03 84 views
1

我们有一个关于mysql的表来记录我们网站的所有访问者。该结构如下所示MySQL查询问题 - 计数查询使用大量的CPU

 
    CREATE TABLE `tblvisitors` (
     `visitorURL` longtext, 
     `visitorDatetime` datetime DEFAULT NULL, 
     `visitorIP` varchar(255) DEFAULT NULL, 
     `visitorID` int(10) NOT NULL AUTO_INCREMENT, 
     `visitorUser` varchar(255) DEFAULT NULL, 
     `visitorShow` varchar(50) DEFAULT NULL, 
     `visitorIPcaption` varchar(255) DEFAULT NULL, 
     `visitorIPRange` varchar(255) DEFAULT NULL, 
     PRIMARY KEY (`visitorID`), 
     KEY `INDEXDT` (`visitorDatetime`), 
     KEY `INDEXIP` (`visitorIP`) 
    ) ENGINE=MyISAM DEFAULT CHARSET=latin1; 

表有现在超过500万分的记录。

我们每半秒执行一次INSERT操作,每半秒执行一次SELECT操作,其中涉及visitorURL列上的CRITERIA和COUNT字段的Select。

查询是:

 
    SELECT COUNT(visitorURL) FROM tblVisitors 
     WHERE visitorURL='http://mihirdarji.com/something' 

这将拍摄的CPU使用率90%与8 GB内存的8核心服务器。

MySQL管理器显示很多连接上面的查询等待执行。

任何建议将受到欢迎。

解释计划说

 
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | 
| 1 | SIMPLE | tblVIsitors | ALL | NULL | NULL | NULL | NULL | 4293277 | Using where | 

回答

1
  1. 先上visitorURL
  2. 创建索引仅次于COUNT一些静态SELECT COUNT(1) FROM tblVisitors WHERE visitorURL=...
+0

-visitorURL是longtext我不确定索引是否可以工作 - 将尝试使用静态东西 – Mihir 2010-02-03 07:59:51

+0

您可以肯定地在长文本上添加索引:“对于BLOB和TEXT列上的索引,必须指定一个索引前缀长度”c.f.http://dev.mysql.com/doc/refman/5.0/en/blob.html – 2010-02-03 20:13:18

0

你有没有在这个表上定义的索引?如果不是,您应该在visitorURL栏中确定make an index。您当前的查询需要全表扫描,这需要很长时间。但是,如果使用简单索引(因为唯一字符串的数量与表中的记录数量相似),索引长文本字符串可能会提高所需速度。因此,在这种情况下,全文索引可能是更好的选择。这将要求您使用特殊的"full-text search functions"

+0

我会尝试并发送更新,如果成功 – Mihir 2010-02-03 08:01:11

+0

全文不允许我匹配确切的URL,我可以以某种方式匹配吗? – Mihir 2010-02-03 10:16:07

+0

所以问题是,你在这个'visitorURL'字段中存储了什么?它是HTTP引用者还是它是你的网站之一?我只是想,有多少不同的值可以在这一列 – naivists 2010-02-03 11:53:01

0

visitorIp是否真的需要varchar(255)?

+0

是的,它是必需的 – Mihir 2010-02-03 08:00:25

+0

啊,我现在看到。你匹配了其他列的长度。 – rrrfusco 2010-02-03 14:52:07

0

运行该query

+0

像其他人一样,需要在visitorURL上创建索引,'possible_keys'为'null': 如果此列为NULL,则有没有相关指标。在这种情况下,您可以通过检查WHERE子句来检查是否引用某些适合索引的列或列,从而提高查询的性能。如果是这样,请创建一个适当的索引,并再次使用EXPLAIN检查查询 – 2010-02-03 08:40:34

+1

thnx,但将在此类查询中使用全文索引帮助 – Mihir 2010-02-03 10:15:08

1

而不是索引URL列,您可以将URL的散列值存储在单独的varchar列和索引中并查询该值。但是无论你做什么,你都需要一个你正在计算的列的索引。另请参阅MyIsam keycache设置,以确保尽可能有效地处理索引。