2011-06-28 211 views
0

我非常需要帮助,在高流量网站上,过去6个月中一直引起很多悲痛的查询。我是一名能够编写简单SQL查询的前端开发人员,因此我无法自行解决此问题。该查询现在经常因缺少内存或CPU或VPS上其他查询的干扰而锁定mysql数据库。我升级了硬件,但单靠这一点无法解决问题。因此,以下是对查询尝试执行的操作的描述:需要帮助来优化SQL查询

用户访问特定URL(例如the_source_url)。应用程序试图获取其他用户(他们也访问过the_source_url)早些时候访问过的相关source_urls,按最频繁访问次数最少访问次数排序。基本上,应用程序试图找到具有类似兴趣的用户并显示他们以前访问的其他页面。

这是“复杂的查询”,我写我年轻的时候/愚蠢的网站没有流量:

SELECT DISTINCT(SOURCE_URL), COUNT(SOURCE_URL) CATCOUNT 
    FROM topsources 
WHERE SOURCE_URL <> ? 
    AND USER_ID IN (SELECT DISTINCT(USER_ID) 
        FROM topsources WHERE SOURCE_URL = ?) 
GROUP BY SOURCE_URL ORDER BY CATCOUNT DESC 

这是表结构:

`topsources` (
    `USER_ID` varchar(255) NOT NULL, 
    `DATE_AND_HOUR` varchar(255) NOT NULL, 
    `UPDATED_TIME` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, 
    `ITEM_ID` int(11) NOT NULL, 
    `SOURCE_URL` varchar(100) NOT NULL, 
    `FEED_PAGE_URL` varchar(255) NOT NULL, 
    `CATEGORY_URL` varchar(100) NOT NULL, 
    `REFERRER` varchar(2048) DEFAULT NULL, 
    PRIMARY KEY (`USER_ID`,`DATE_AND_HOUR`(30),`ITEM_ID`), 
    KEY `USER_ID` (`USER_ID`), 
    KEY `FEED_PAGE_URL` (`FEED_PAGE_URL`), 
    KEY `SOURCE_URL` (`SOURCE_URL`), 
    KEY `CATEGORY_URL` (`CATEGORY_URL`) 
) ENGINE=MyISAM DEFAULT CHARSET=utf8; 

请注意,我已经尝试了内部连接而不是子选择,但这不起作用。即,下面的查询不返回与上述查询相同的结果。

​​3210
+0

当您使用GROUP BY时,不要使用DISTINCT。 – niktrs

回答

4

IN subselects没有在MySQL中优化。而不是执行子选择,然后选择outser,MySQL为外部选择匹配的每一行执行子选择。因此,IN子句中的子查询应该用连接替换。以下是查询的更快版本:

SELECT DISTINCT(SOURCE_URL), COUNT(SOURCE_URL) CATCOUNT 
FROM topsources 
INNER JOIN 
(SELECT DISTINCT(USER_ID) 
       FROM topsources WHERE SOURCE_URL = ?) as t 
ON (topsources.USER_ID = t.USER_ID) 
WHERE SOURCE_URL <> ? 
GROUP BY SOURCE_URL ORDER BY CATCOUNT DESC 
+1

上面的代码是MySQL如何解释原始查询或建议改进的示例吗? –

+0

仔细阅读:由于MySQL处理子查询的方式(如上所述),IN子句中的子查询必须替换为连接。因此重写的查询是一个建议的改进 –

+0

对不起,我不是无礼的意思。我不确定你最初想传达什么。感谢您清理它。 –

1

这是要求正常化的要求。你真正需要的是一个链接表像

id | url 
1 | http://.... 

然后在你的topsources表

id | url_id 
1 | 1 

然后你DISTINCT(url_id)应显著更快。