如何优化这个MySQL查询?

时间:2011-08-29 10:28:40

标签: mysql sql

我有一个查询,它使用大量的聚合函数来为每个项目(相册)构建数据。这些数据至关重要,需要存在。目前,查询单独执行大约需要1.5秒,这太长了。

我已经创建了这些函数,因为有很多查询都需要进行这些计算,所以将它们分成它们自己的函数以便于代码可维护性是有意义的。否则,每当条件发生变化时,就会有5个或更多的地方去寻找并进行更改。

我真的很想知道如何才能更快地完成此查询。很明显,聚合函数是罪魁祸首,因为如果我用简单的SELECT *替换它们,它会在大约0.1秒内运行。

我唯一能想到的是删除聚合函数并为需要聚合的每个项执行内部联接/子查询。你可以想象,我真的不想这样做,因为它需要重构其他地方的负载,并使代码维护非常混乱。

有什么建议吗?谢谢!

SELECT
fnAlbumGetNumberOfPhotos(albumId,1,0, 100) AS albumNumberOfPhotos,
fnLikeGetCount(1, 3, album.albumId) AS albumLikeCount,
fnGetAlbumPhotoViewCount(albumId) AS albumNumberOfPhotoViews,
fnLikeGetDoesUserLikeDislike(1, 3, album.albumId, 100) AS albumDoesUserLike,
fnObjectTagGetObjectTags(3, albumId) AS albumTags
FROM 
album
WHERE 0 = 0 
-- AND insert additional filters here
LIMIT 0,15

这些函数都是简单的聚合函数,例如:

CREATE DEFINER=`root`@`%` FUNCTION `fnAlbumGetNumberOfPhotos`(_albumId int, _photoIsActive tinyint, _photoIsDisabled tinyint, _userId int) RETURNS int(11)
BEGIN

  DECLARE outNumberOfPhotos int DEFAULT 0;
  DECLARE _userRoleId int DEFAULT 0;

  SET _userRoleId = (SELECT userRoleId FROM user WHERE userId = _userId);


  SET outNumberOfPhotos =
  (
    SELECT COUNT(*) AS outNumberOfPhotos
    FROM photo
    WHERE photoAlbumId = _albumId
    AND photoIsDisabled = _photoIsDisabled
    AND photoIsActive = _photoIsActive
    AND (photoPublishDate <= Now() || photoCSI = _userId || _userRoleId = 2)
  );

  RETURN outNumberOfPhotos;

END $$

1 个答案:

答案 0 :(得分:2)

当sql优化器为任何查询构建执行计划时,它会将查询拆分为单个操作,然后使用它们进行操作。不幸的是,函数是sql优化器的“黑盒子” - 它不知道该函数内部是什么,并假设函数调用是一个奇异的操作。 如果性能对您的查询至关重要:

  1. 重新检查表上的索引
  2. INLINE您的函数调用 - 在这种情况下,查询优化器可以构建 基于索引的最佳执行计划
  3. 而不是p.2你可以使用VIEW(当然,如果可能的话) - 他们 对优化器来说是透明的。
  4. 希望这个帮助