我有下面的mysql select语句,它在一个小数据集上正常工作,但在卷增加时停止工作:
SELECT DISTINCT Bookings.BookingId, Bookings.ResortId, Bookings.WeekBeginning, Bookings.DepartDate, Bookings.CancelledDate,Clients.FirstName, Clients.LastName, Clients.Email, Clients.Address1, Clients.City, Clients.State, Clients.CountryId, Clients.ClientType, Countries.Country, BookingAccommodation.AccomId, BookingAccommodation.ShareType, BookingProgram.ProgramId, Programs.ProgramDesc
FROM Bookings, Clients, BookingProgram, BookingAccommodation, Countries, ClientType, Programs
WHERE Bookings.BookingId = BookingProgram.BookingId
AND Bookings.BookingId = BookingAccommodation.BookingId
AND Bookings.WeekBeginning >= '2016-10-01'
AND BookingAccommodation.Nights > 0
AND Clients.ClientId = Bookings.ClientId
AND Clients.Email <> ''
AND Clients.CountryId = Countries.CountryId
AND Programs.ProgramId = BookingProgram.ProgramId
bookings中大约有10k条记录,bookingaccommodation和bookingprograms中的每一条记录都有25k条记录,虽然量不大,但查询只需950秒。我正在本地mamp服务器上的phpadmin的sql窗口中运行查询。
将其拆分为3个查询,每个查询的结果在几秒钟内返回:
SELECT DISTINCT Bookings.BookingId, Bookings.ResortId, Bookings.WeekBeginning, Bookings.DepartDate, Bookings.CancelledDate, Clients.FirstName, Clients.LastName, Clients.Email, Clients.Address1, Clients.City, Clients.State, Clients.CountryId, Clients.ClientType, Countries.Country
FROM Bookings, Clients, Countries, ClientType
WHERE Bookings.WeekBeginning >= '2016-10-01'
AND Clients.ClientId = Bookings.ClientId
AND Clients.Email <> ''
AND Clients.CountryId = Countries.CountryId
SELECT DISTINCT Bookings.BookingId, BookingAccommodation.AccomId, BookingAccommodation.ShareType
FROM Bookings, BookingAccommodation
WHERE Bookings.BookingId = BookingAccommodation.BookingId
AND Bookings.WeekBeginning >= '2016-10-01'
AND BookingAccommodation.Nights > 0
SELECT DISTINCT Bookings.BookingId, BookingProgram.ProgramId, Programs.ProgramDesc
FROM Bookings, BookingProgram, Programs
WHERE Bookings.BookingId = BookingProgram.BookingId
AND Bookings.WeekBeginning >= '2016-10-01'
AND Programs.ProgramId = BookingProgram.ProgramId
bookingaccommodation和bookingprogram中有多个记录,但我只需要每个记录中的一个记录,因此选择distinct。
预订的主键是bookingid。
bookingaccommodation的主键是bookingid、accomdate、accomid
bookingprogram的主键是bookingid、programid、accomtype
我试图用连接和子查询重写查询,但显然做得不对。如何将这3个查询连接回一个性能良好的查询中?
3条答案
按热度按时间xoshrz7s1#
我没有花更多的时间来改进select语句,因为它访问了太多的表,我选择将它拆分为单独的查询,正如我在最初的问题中概述的那样。
最后,这是最快的实际解决办法。
omqzjyyz2#
试着把它改成
如果这不能得到您想要的结果,请尝试解释并查看查询计划。
请注意:我没有看到任何地方正在使用表clienttype,所以我没有将其包含在联接中
utugiqy63#
这些是使用子查询而不是连接(mysql假设为fwiw)的基础。为伪代码道歉,我认为尽快回答是很重要的,因为这是我刚才面对的这个问题的热门之一。
客户预订了一艘游轮。客户还应说明他们的饮食(如素食、纯素、不含大豆等)。因此,我们有三张table:
预订
预订id、预订日期、预订时间、客户id
客户
客户id,客户名称,客户电话,客户id
饮食
饮食id,饮食名称
我们现在要向礼宾部提供一个完整的预订视图。
使用“连接”:
SELECT Bookings.Booking_Id, Bookings.Booking_Date, Bookings.Booking_Time, Clients.Client_Name, Diets.Diet_Name FROM Bookings INNER JOIN Clients ON Bookings.Client_Id = Clients.Client_Id INNER JOIN Diets ON Clients.Client_DietId = Diets.Diet_Id
使用“子查询”:我认为它是如何在这些单独的连接中创建“临时表”的——当然“临时表”可能是准确的低级实现,也可能不是,等等。但有趣的是,子查询可能比大型连接(其他线程)更快。
我想从上面的示例中进行单独的连接:
首先,我需要加入客户的饮食,然后我加入“表”与预订。
因此,我的结论是(请注意,在引用子查询时表(重新)命名):
SELECT [RELEVANT FIELDS HERE ETC] FROM (SELECT Clients.Client_Id, Clients.Client_Name, Diets.Diet_Name FROM Clients INNER JOIN Diets ON Clients.Client_DietId = Diets.Diet_Id) AS ClientDetailsWithDiets INNER JOIN Bookings ON Bookings.Booking_Id = ClientDetailsWithDiets.Client_Id
现在,如果要连接另一个表(例如分配给特定预订的工作人员),则上面的整个内容都将嵌套,以此类推:SELECT [RELEVANT FIELDS HERE ETC] FROM (SELECT [RELEVANT FIELDS HERE ETC] FROM (SELECT Clients.Client_Id, Clients.Client_Name, Diets.Diet_Name FROM Clients INNER JOIN Diets ON Clients.Client_DietId = Diets.Diet_Id) AS ClientDetailsWithDiets INNER JOIN Bookings ON Bookings.Booking_Id = ClientDetailsWithDiets.Client_Id) AS BookingDetailsFull INNER JOIN Staff ON BookingDetailsFull.Booking_Id = Staff.Booking_Id_Assigned