我有一个sql查询来随机选择1200个转发的转发推文,至少转发50次,而tweetDate应该比4千万条记录早4天。我下面粘贴的查询有效,但需要40分钟,那么该查询的版本是否更快?
SELECT
originalTweetId, Count(*) as total, tweetContent, tweetDate
FROM
twitter_gokhan2.tweetentities
WHERE
originalTweetId IS NOT NULL
AND originalTweetId <> - 1
AND isRetweet = true
AND (tweetDate < DATE_ADD(CURDATE(), INTERVAL - 4 DAY))
GROUP BY originalTweetId
HAVING total > 50
ORDER BY RAND()
limit 0 , 1200;
---------------------------------------------------------------
Table creation sql is like:
CREATE TABLE `tweetentities` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`tweetId` bigint(20) NOT NULL,
`tweetContent` varchar(360) DEFAULT NULL,
`tweetDate` datetime DEFAULT NULL,
`userId` bigint(20) DEFAULT NULL,
`userName` varchar(100) DEFAULT NULL,
`retweetCount` int(11) DEFAULT '0',
`keyword` varchar(500) DEFAULT NULL,
`isRetweet` bit(1) DEFAULT b'0',
`isCompleted` bit(1) DEFAULT b'0',
`applicationId` int(11) DEFAULT NULL,
`latitudeData` double DEFAULT NULL,
`longitude` double DEFAULT NULL,
`originalTweetId` bigint(20) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `index` (`originalTweetId`),
KEY `index3` (`applicationId`),
KEY `index2` (`tweetId`),
KEY `index4` (`userId`),
KEY `index5` (`userName`),
KEY `index6` (`isRetweet`),
KEY `index7` (`tweetDate`),
KEY `index8` (`originalTweetId`),
KEY `index9` (`isCompleted`),
KEY `index10` (`tweetContent`(191))
) ENGINE=InnoDB AUTO_INCREMENT=41501628 DEFAULT CHARSET=utf8mb4$$
答案 0 :(得分:1)
当然,您总结了巨大的个记录,然后将它们随机化。这种事情很难快速发展。回到开始的时候会让事情变得更糟。在空条件下搜索只会破坏它。
如果您希望合理地执行此操作,则必须摆脱IS NOT NULL
选择。否则,它将表现不佳。
但是,让我们试着找到一个合理的解决方案。首先,让我们得到我们需要的originalTweetId
值。
SELECT MIN(id) originalId,
MIN(tweetDate) tweetDate,
originalTweetId,
Count(*) as total
FROM twitter_gokhan2.tweetentities
WHERE originalTweetId <> -1
/*AND originalTweetId IS NOT NULL We have to leave this out for perf reasons */
AND isRetweet = true
AND tweetDate < CURDATE() - INTERVAL 4 DAY
AND tweetDate > CURDATE() - INTERVAL 30 DAY /*let's add this, if we can*/
GROUP BY originalTweetId
HAVING total >= 50
此摘要查询为我们提供了每个主题推文的数据库中最低的ID号和日期。
为了让它快速运行,我们需要一个复合索引(originalTweetId,isRetweet,tweetDate,id)。该查询将在tweetDate上对该索引进行范围扫描,其速度与您希望的速度一样快。调试此查询,无论是为了正确性还是性能,然后继续。
现在进行随机化。让我们用尽可能少的数据来做这件事,以避免分类大量的东西。
SELECT originalTweetId, tweetDate, total, RAND() AS randomOrder
FROM (
SELECT MIN(id) originalId,
MIN(tweetDate) tweetDate
originalTweetId,
Count(*) as total
FROM twitter_gokhan2.tweetentities
WHERE originalTweetId <> -1
/*AND originalTweetId IS NOT NULL We have to leave this out for perf reasons */
AND isRetweet = true
AND tweetDate < CURDATE() - INTERVAL 4 DAY
AND tweetDate > CURDATE() - INTERVAL 30 DAY /*let's add this, if we can*/
GROUP BY originalTweetId
HAVING total >= 50
) AS retweets
ORDER BY randomOrder
LIMIT 1200
大。现在我们以随机顺序列出了1200条推文ID和日期。现在我们来看看内容。
SELECT a.originalTweetId, a.total, b.tweetContent, a.tweetDate
FROM (
/* that whole query above */
) AS a
JOIN twitter_gokhan2.tweetentities AS b ON (a.id = b.id)
ORDER BY a.randomOrder
看看这是怎么回事?使用复合索引来执行摘要,并使用最少量的数据执行此操作。然后进行随机化,然后获取所需的额外数据。
答案 1 :(得分:0)
您通过选择4天以上的每条记录来选择大量记录....
由于查询需要花费大量时间,为什么不使用在后台重复运行的独立脚本来准备结果....
你或许可以假设如果它是转发,那么originalTweetId不能为null / -1
答案 2 :(得分:0)
只是为了澄清......你真的是想要查询所有OLDER而不是4天吗?
AND (tweetDate < DATE_ADD(CURDATE(), INTERVAL - 4 DAY))
或者......你的意思是你只想在最近4天内汇总最近的TWEETS。对我来说,2年前发生的推文对于当前的事件来说毫无价值......如果是这样的话,你可能会更好地改为
AND (tweetDate >= DATE_ADD(CURDATE(), INTERVAL - 4 DAY))
答案 3 :(得分:0)
看看这是不是比40分钟快一点:
首先在没有注释行的情况下进行测试,然后重新添加它们以比较性能影响。 (特别是ORDER BY RAND()
被认为是可怕的)
SELECT
originalTweetId,
total,
-- tweetContent, -- may slow things somewhat
tweetDate
FROM (
SELECT
originalTweetId,
COUNT(*) AS total,
-- tweetContent, -- may slow things somewhat
MIN(tweetDate) AS tweetDate,
MAX(isRetweet) AS isRetweet
FROM twitter_gokhan2.tweetentities
GROUP BY originalTweetId
) AS t
WHERE originalTweetId > 0
AND isRetweet
AND tweetDate < DATE_ADD(CURDATE(), INTERVAL - 4 DAY)
AND total > 50
-- ORDER BY RAND() -- very likely to slow performance,
-- test with and without...
LIMIT 0, 1200;
PS - originalTweetId应该有希望索引