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

How to optimize my mysql query to retrieve data faster

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

当我执行以下 select 查询时,table 有大约 400 万条记录(并且会变得更大),它需要很长时间(大约 15 秒)。我正在使用 MySql 数据库。

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

请注意

如果您只查找场地和每人的最低总数,您可以直接从 pricingArtifact 向下执行此操作,而无需实际场地,因为 pricingArtifact 具有 venueID...除非您也需要场地描述数据。

通过传递 属性,如果 V.VenueID = PA.VenueID,则 PA.VenueID 可以连接到 M.VenueID 而无需使用地点table。同样,PA.MealID 可以直接加入 meal 和 MealDay tables。

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

现在,对于索引。我会提出以下建议。

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

我想你根本不需要连接到 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 上的联接都在同一列上。好像很奇怪。