需要有关优化SQL查询的帮助

时间:2011-06-28 08:28:50

标签: mysql sql query-optimization

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

用户访问特定的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;

请注意我已经尝试过内连接而不是subselect但是这不起作用。即,以下查询不会返回与上述查询相同的结果。

SELECT DISTINCT(ts.SOURCE_URL), COUNT(ts.SOURCE_URL) CATCOUNT FROM topsources ts INNER JOIN topsources tsi ON ts.USER_ID = tsi.USER_ID AND tsi.SOURCE_URL = ? WHERE ts.SOURCE_URL <> ? AND ts.CATEGORY_URL = ? GROUP BY ts.SOURCE_URL ORDER BY ts.CATCOUNT DESC

2 个答案:

答案 0 :(得分:4)

IN子选择未在MySQL中进行优化。 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 :(得分:1)

这迫切需要正常化。你真正需要的是像

这样的网址表
id | url
1  | http://....

然后在你的topsources表中

id | url_id
1  | 1

然后你的DISTINCT(url_id)应该明显加快。