使服务器挂起的SQL查询?

时间:2015-02-21 12:49:25

标签: mysql sql query-performance

我刚才写了这个查询,似乎工作正常。

但是最近当这个查询运行时,它通常不会返回任何结果。 Ajax调用永远不会收到响应。如果我在phpMyAdmin中运行它是一样的,通常它可以工作,但有时它只是挂起。

就像那几个小时,然后它又开始恢复正常了。

我不确定我的查询是否存在导致服务器阻塞的问题,或者服务器本身是否存在问题。

这是运行的查询。我没有sql pro,所以也许有人注意到它有一个大问题,我应该采取不同的处理方式?如果我运行它,并且我收到响应,通常需要1.5 / 2秒才能完成。

SELECT country.CountryID,
    accommodation.AccommodationID,
    accommodation.CityID,
    accommodation.lodgement,
    accommodation.SumID,
    accommodation.RegionID,
    accommodation.starrating,
    accommodation.reviewrating,
    images.image1 AS image,
    summary.name,
    summary.lowestprice,
    summary.lowestpricedate,
    summary.url
FROM country
    INNER JOIN accommodation ON accommodation.CountryID = country.CountryID
    INNER JOIN images ON images.AccommodationID = accommodation.AccommodationID
    INNER JOIN cities ON cities.CityID = accommodation.CityID
    INNER JOIN summary ON summary.SumID = accommodation.SumID
WHERE country.name = 'x'
ORDER BY accommodation.reviewrating DESC LIMIT 0,25

3 个答案:

答案 0 :(得分:0)

您是否在连接中使用的所有列上都有索引?

country.CountryIDaccommodation.AccommodationIDcities.CityIDsummary.SumID都需要是主键。

accommodation.CountryIDimages.AccommodationIDaccommodation.CityIDaccommodation.SumIDcountry.name都需要索引。

答案 1 :(得分:0)

您的问题可以在这一行

ORDER BY accommodation.reviewrating DESC LIMIT 0,25

虽然使用LIMIT MySQL必须在选择第一个之前通过审核对所有住宿行进行排序。尝试使用以下方法创建新索引:

CREATE INDEX ON accommodation (CountryID, reviewrating);

因为您可能会注意到查询需要在桌子上进行全面扫描。

答案 2 :(得分:0)

如果没有关于表格中的架构和行数的大量详细信息,很难确切知道查询性能的恶化原因。但我怀疑这是因为你的桌子越来越大了。祝贺一个成功的应用程序,并欢迎关注您的RDMS,以确保它继续正确扩展。

延迟加入技术可能会非常有用。这是这样的。

首先,找出您需要报告的AccommodationID值。在您正在使用的查询中,可以这样做:

        SELECT AccomodationID
          FROM accomodation
          JOIN country USING(CountryID)
         WHERE country.name = 'x'
         ORDER BY reviewrating DESC
         LIMIT 0,25

如果你在(CountryID, reviewrating)上制作一个复合索引,这将非常快。 (如果您正在使用MyISAM表,请在(CountryID, reviewrating, AccomodationID)上创建一个复合索引。)它将提取前25个评论的ID。

接下来,在主查询中使用子查询 - 25个项目的列表。

 SELECT country.CountryID,
    accommodation.AccommodationID,
    accommodation.CityID,
    accommodation.lodgement,
    accommodation.SumID,
    accommodation.RegionID,
    accommodation.starrating,
    accommodation.reviewrating,
    images.image1 AS image,
    summary.name,
    summary.lowestprice,
    summary.lowestpricedate,
    summary.url
FROM country
    INNER JOIN accommodation ON accommodation.CountryID = country.CountryID
    INNER JOIN images ON images.AccommodationID = accommodation.AccommodationID
    INNER JOIN cities ON cities.CityID = accommodation.CityID
    INNER JOIN summary ON summary.SumID = accommodation.SumID
    INNER JOIN (
            SELECT AccomodationID
              FROM accomodation
              JOIN country USING(CountryID)
             WHERE country.name = 'x'
             ORDER BY reviewrating DESC
             LIMIT 0,25
               ) ids ON accomodation.AccomodationId = ids.AccomodationId
ORDER BY accommodation.reviewrating DESC LIMIT 0,25

为什么这有效?它不会创建一个大的结果集,并且它只会丢弃除25行以外的所有结果集。相反,它使用已经排序的索引非常精确地收集它所需的ID,然后创建一个小得多的最终结果集。

这称为延迟连接,因为它会推迟大连接操作,直到选择了正确的行子集为止。