这是查询
SELECT * FROM ProductReviews
INNER JOIN RatingActions USING(RatingActionID)
LEFT JOIN ProductRatingVotes USING(RatingActionID)
WHERE ProductReviews.ProductID="200129" AND ProductReviewStatus="1"
ORDER BY RatingActionTimestamp DESC;
这是执行计划
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: ProductReviews
type: ref
possible_keys: FK_ProductReview_ProductID,FK_ProductReviews_RatingActionID
key: FK_ProductReview_ProductID
key_len: 4
ref: const
rows: 1
Extra: Using where; Using temporary; Using filesort
*************************** 2. row ***************************
id: 1
select_type: SIMPLE
table: ProductRatingVotes
type: ref
possible_keys: FK_ProductRatingVotes_RatingActionID
key: FK_ProductRatingVotes_RatingActionID
key_len: 4
ref: scart.ProductReviews.RatingActionID
rows: 1
Extra:
*************************** 3. row ***************************
id: 1
select_type: SIMPLE
table: RatingActions
type: eq_ref
possible_keys: PRIMARY
key: PRIMARY
key_len: 4
ref: scart.ProductReviews.RatingActionID
rows: 1
Extra:
3 rows in set (0.00 sec)
虽然它正在扫描一行,但是using temporary
会杀死它,并且需要3-4秒才能完成(一个非常繁忙的服务器;在我的本地主机上0.004秒,这仍然比版本慢6倍没有订单)。
据我了解,using temporary
是由order by
列不在第一个表格中的事实引起的。
有没有办法优化此查询,还是应该将Timestamp复制到ProductReviews表中?
UPDATE 表:
CREATE TABLE `ProductReviews` (
`ProductReviewID` int(10) unsigned NOT NULL AUTO_INCREMENT,
`ProductID` int(10) unsigned NOT NULL DEFAULT '0',
`RatingActionID` int(10) unsigned NOT NULL DEFAULT '0',
`ProductReviewText` text NOT NULL,
`ProductReviewStatus` tinyint(3) unsigned NOT NULL DEFAULT '0',
PRIMARY KEY (`ProductReviewID`),
KEY `FK_ProductReview_ProductID` (`ProductID`),
KEY `FK_ProductReviews_RatingActionID` (`RatingActionID`),
CONSTRAINT `FK_ProductReviews_RatingActionID` FOREIGN KEY (`RatingActionID`) REFERENCES `ratingactions` (`RatingActionID`) ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT `FK_ProductReview_ProductID` FOREIGN KEY (`ProductID`) REFERENCES `products` (`ProductID`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=66 DEFAULT CHARSET=utf8
CREATE TABLE `ratingactions` (
`RatingActionID` int(10) unsigned NOT NULL AUTO_INCREMENT,
`RatingActionTimestamp` int(10) unsigned NOT NULL DEFAULT '0',
`CustomerID` int(10) unsigned DEFAULT NULL,
`RatingActionIPAddress` int(10) unsigned NOT NULL DEFAULT '0',
`RatingActionInputName` varchar(255) NOT NULL DEFAULT '',
PRIMARY KEY (`RatingActionID`),
KEY `FK_RatingActions_CustomerID` (`CustomerID`),
CONSTRAINT `FK_RatingActions_CustomerID` FOREIGN KEY (`CustomerID`) REFERENCES `customers` (`CustomerID`) ON DELETE SET NULL ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=142 DEFAULT CHARSET=utf8
CREATE TABLE `ProductRatingVotes` (
`ProductRatingVoteID` int(10) unsigned NOT NULL AUTO_INCREMENT,
`ProductID` int(10) unsigned NOT NULL DEFAULT '0',
`RatingActionID` int(10) unsigned NOT NULL DEFAULT '0',
`ProductRatingVoteValue` tinyint(3) unsigned NOT NULL DEFAULT '0',
`ProductRatingVoteStatus` tinyint(3) unsigned NOT NULL DEFAULT '0',
PRIMARY KEY (`ProductRatingVoteID`),
KEY `FK_ProductRatingVotes_ProductID` (`ProductID`),
KEY `FK_ProductRatingVotes_RatingActionID` (`RatingActionID`),
CONSTRAINT `FK_ProductRatingVotes_ProductID` FOREIGN KEY (`ProductID`) REFERENCES
`products` (`ProductID`) ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT `FK_ProductRatingVotes_RatingActionID` FOREIGN KEY
(`RatingActionID`) REFERENCES `ratingactions` (`RatingActionID`) ON
DELETE CASCADE ON UPDATE CASCADE )
ENGINE=InnoDB AUTO_INCREMENT=142
DEFAULT CHARSET=utf8
答案 0 :(得分:1)
请改为尝试:
SELECT /*STRAIGHT_JOIN*/ ProductReviews.ProductID, RatingActionTimestamp
FROM ratingactions
join ProductReviews USING(RatingActionID)
LEFT JOIN ProductRatingVotes USING(RatingActionID)
WHERE ProductReviews.ProductID=200129 AND ProductReviewStatus=1
order by RatingActionTimestamp desc;
这应该消除使用临时和使用filesort的额外步骤。如果没有,请尝试取消注释STRAIGHT_JOIN。
答案 1 :(得分:1)
所有其他明显不起作用的东西,我会提供以下内容...将产品评论移动到from中的第一个位置作为选择/来自...然后应用连接
SELECT STRAIGHT_JOIN
PR.ProductID,
RA.RatingActionTimestamp
FROM
( select PR1.ProductID,
PR1.RatingActionID
FROM ProductReviews PR1
WHERE
PR1.ProductID = 200129
AND PR1.ProductReviewStatus = 1 ) PR
JOIN rating actions RA
on PR.RatingActionID = RA.RatingActionID
LEFT JOIN ProductRatingVotes PRV
on PR.RatingActionID = PRV.RatingActionID
order by
RA.RatingActionTimestamp desc;
这样,它应该以您期望的单行开始内部查询,然后加入评级操作。产品评论FIRST,获取相关产品的合格条目,然后继续加入评级评级行动的评级表...
答案 2 :(得分:0)
似乎其中一个表包含TEXT或BLOB字段,并且ORDER BY被强制使用磁盘进行排序。解决方案可能是在没有子查询中的字段的情况下进行排序,并再次与其余列连接。