如何优化我的mysql查询以更快地检索数据

时间:2015-12-13 00:29:20

标签: mysql database performance select subquery

我有一个独立的表格,我们通过每周工作插入数据,并在搜索模块中检索数据。

当我执行以下选择查询需要很长时间(大约15秒)时,该表有大约4百万条记录(并且会变大)。我正在使用MySql DB。

SELECT 
    v.venueId,
    (SELECT 
            MIN(totalPerPerson)
        FROM
            PricingArtifact pa
        WHERE
            pa.venueId = v.venueId
                AND pa.mealId IN (SELECT
                    m.mealId
                FROM
                    Meal m,
                    MealDay md
                WHERE
                    m.mealId = md.mealId
                        AND m.mealDeletedAt IS NULL
                        AND md.mealDayDeletedAt IS NULL
                        AND m.venueId = v.venueId)) AS minPrice
FROM
    Venue v

请注意

  • 场地表只有12条记录。
  • 我在pricingArtifact表中有venueId,totalPerPerson的索引。
  • 我尝试加入而不是子查询,并且它给出了相同的结果。
  • 用餐和用餐日表每个记录少于100个。

2 个答案:

答案 0 :(得分:2)

如果您只是寻找场地和每人的最低总数,您可以直接从pricingArtifact下来,而没有实际的Venue作为pricingArtifacts具有场地ID ...除非您也想要场地描述数据。

通过传递属性,如果V.VenueID = PA.VenueID,则可以在不使用场地表的情况下将PA.VenueID连接到M.VenueID。同样,PA.MealID可以直接加入膳食和MealDay表。

现在,您还提到了400万条记录表。您的相关查询(查询min()值perPerson / perVenue是非常昂贵的,因为您已经遇到过,因为它对第一个表中的每个记录执行子查询。您是否真的需要返回所有历史记录,或者是否有一些DATE字段,例如你只关心最后一次的活动......说30天?一旦数据完成,它是否真的改变了?也许保留一个汇总表作为分析定价率的基础。

现在,对于索引。我建议如下。

table            index
PricingArtifact  (venueID, mealID, totalPerPerson )
Meal             (mealID, MealDeletedAt )
MealDay          (mealID, MealDayDeletedAt )


SELECT
      PA.venueID
      MIN( PA.TotalPerPerson ) as VenueMinPerPerson
   from
      PricingArtifact PA
         JOIN meal M
             ON PA.MealID = M.MealID
            AND M.MealDeletedAt IS NULL
         JOIN MealDay MD
             ON PA.MealID = MD.MealID
            AND MD.MealDayDeletedAt Is NULL

答案 1 :(得分:1)

我想你根本不需要加入venue,如果真的只有12个。

SELECT pa.venueID, MIN(PA.TotalPerPerson) as minPrice
FROM PricingArtifact pa
WHERE EXISTS (SELECT 1
              FROM Meal m JOIN
                   MealDay md
                   ON m.mealId = md.mealId
              WHERE m.mealDeletedAt IS NULL AND
                    md.mealDayDeletedAt IS NULL AND
                    pa.mealId = m.mealId
             )
GROUP BY pa.venueId;

对于此查询,您需要Meal(mealId, mealDeletedAt)MealDay(mealId, mealDayDeletedAt)上的索引。

您的查询有一些好奇心:

  • 我通常不会将表达式MIN(totalPerPerson)描述为“MinTotalPrice”。
  • MealMailDayPriceArtifact上的联接都在同一列上。这看起来很奇怪。