我有一个独立的表格,我们通过每周工作插入数据,并在搜索模块中检索数据。
当我执行以下选择查询需要很长时间(大约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
请注意
答案 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”。Meal
,MailDay
和PriceArtifact
上的联接都在同一列上。这看起来很奇怪。