如何确定我需要为此多连接多条件查询创建哪个索引?

时间:2016-11-11 16:48:21

标签: mysql indexing

我认为我对如何为复杂查询构建索引缺乏基本的了解。鉴于以下查询,表PHOTOS上的最佳索引是什么?我觉得应该可以知道,而不必做很多试验和错误(相信我,我有...)

这是我目前的索引,它给了我Using index condition; Using temporary; Using filesort。如果可能的话,我想摆脱临时/文件输出位。

testIndex: photoTypeID, photoID, photographerID, shootID, timeAdded

这就是查询(现实中它更复杂,但我已将其剥离到与索引相关的最小相关PHOTOS内容:

SELECT 
SQL_CALC_FOUND_ROWS

PH.photoID

FROM      PHOTOS                PH
JOIN      PHOTO_TYPES           PT  ON  PT.photoTypeID     = PH.photoTypeID
LEFT JOIN PHOTO_LINKS           PL  ON  PL.photoID         = PH.photoID
LEFT JOIN PAYPAL_ITEMS          PI  ON  PI.photoID         = PH.photoID
LEFT JOIN PHOTOGRAPHER_PRODUCTS PP  ON  PP.photographerID  = PH.photographerID

WHERE PH.shootID = 1234

GROUP BY PH.photoID

ORDER BY PH.timeAdded DESC

LIMIT 0, 100;

EXPLAIN输出:

id  select_type     table   type    possible_keys       key             key_len ref             rows    filtered    Extra
1   SIMPLE          PH      ref     PRIMARY,testIndex   testIndex       4   const               80632   100         Using index condition; Using temporary; Using filesort
1   SIMPLE          PT      eq_ref  PRIMARY             PRIMARY         1   PH.photoTypeID      1       100         Using index
1   SIMPLE          PL      ref     photoID             photoID         4   PH.photoID          1       100         Using index
1   SIMPLE          PCI     ref     photoID             photoID         5   PH.photoID,const    1       100         Using index
1   SIMPLE          PP      ref     photographerID      photographerID  4   PH.photographerID   4       100         Using where; Using index

1 个答案:

答案 0 :(得分:0)

我需要一个复合INDEX(shootID, photoID),正如我所描述的in my indexing cookbook

  • shootID=中为WHERE,因此首先出现
  • 由于处理了所有WHERE,我们可以继续......
  • 添加所有GROUP BY,即photoID
  • 但我们必须在此停止,因为ORDER BYGROUP BY不同。

所以...... ORDER BYLIMIT将需要一个临时文件夹。

但是......还有另一个问题(可能):当你JOIN时,(通常)会增加行数。显而易见的'治愈就是做GROUP BY做瘪。但是任何聚合(和SQL_CALC_FOUND_ROWS)都会计算膨胀值。因此,问题是'。

所以......让我们在做JOINs之前尝试计算。可是等等!为什么要加入?你没有从中获取任何东西。而且,由于它们(大多数情况下)是LEFT JOINs,因此您没有使用JOINs进行过滤。

好吧,我无法弄清楚查询的意图,但我会给你一个可能帮助的提示。

SELECT  photoID
    FROM  
    (
        SELECT  SQL_CALC_FOUND_ROWS
                photoID, photoTypeID, photographerID
            FROM  PHOTOS
            WHERE  shootID = 1234
            ORDER BY  PH.timeAdded DESC
            LIMIT  0, 100 
    ) AS PH
    JOIN  PHOTO_TYPES PT  ON PT.photoTypeID = PH.photoTypeID
    LEFT JOIN  PHOTO_LINKS PL  ON PL.photoID = PH.photoID
    LEFT JOIN  PAYPAL_ITEMS PI  ON PI.photoID = PH.photoID
    LEFT JOIN  PHOTOGRAPHER_PRODUCTS PP  ON PP.photographerID = PH.photographerID
    ORDER BY  PH.timeAdded DESC;

该版本需要INDEX(shootID, timeAdded)。它给你正确答案,它应该快得多,不使用tmp或filesort。