1

私はmysql DBから1つの非常に長い選択をしています。このINNER JOINを追加するまで、非常に高速に動作しています。この INNER JOIN 選択時間を追加する前は 2 秒でしたが、現在は約 20 秒です...

INNER JOIN 
   (SELECT 
      accomodation_id,
      SUM(accomodation_rooms.rooms) AS total_rooms,
      SUM(accomodation_rooms.beds * accomodation_rooms.rooms) AS total_persons 

   FROM accomodation_rooms 

   GROUP BY accomodation_id) accomodation_rooms

ON 
   accomodation_rooms.accomodation_id = accomodation.id
   AND 
   accomodation_rooms.total_persons >= '".$persons."'

誰かがより速い代替手段で私を助けることができますか??

4

2 に答える 2

0

余分な結合を削除して結合することでクエリを変更しました。これを試してください。

SELECT
  accomodation.id,
  accomodation.aid,
  accomodation.title_en,
  accomodation.title_url_en,
  accomodation.address,
  accomodation.zip,
  accomodation.stars,
  accomodation.picture,
  accomodation.valid_from,
  accomodation.valid_to,
  accomodation.latitude,
  accomodation.longitude,
  MAX(info_date_add)                    AS max_info_date_add,
  accomodation.city_id                  AS accomodation_city_id,
  db_cities.id                          AS city_id,
  db_cities.title_en                    AS city,
  db_cities.title_url                   AS city_url,
  db_countries.title_en                 AS country_title,
  db_countries.title_url_en             AS country_url,
  accomodation_type.class               AS accomodation_type_class,
  accomodation_review_value_total.value AS review_total,
  MIN(accomodation_price.price)         AS price_from,
  accomodation_rooms.total_persons,
  (((acos(sin((db_cities.latitude * pi()/180)) * sin((accomodation.latitude * pi()/180)) + cos((db_cities.latitude * pi()/180)) * cos((accomodation.latitude * pi()/180)) * cos(((db_cities.longitude - accomodation.longitude) * pi()/180)))) * 180/pi()) * 60 * 1.1515 * 1.609344) as Calculation
FROM accomodation
LEFT JOIN db_cities ON db_cities.id = accomodation.city_id
LEFT JOIN db_countries ON db_countries.id = accomodation.country_id
LEFT JOIN accomodation_review_value_total ON accomodation_review_value_total.accomodation_aid = accomodation.aid
LEFT JOIN accomodation_price ON (accomodation_price.accomodation_aid = accomodation.aid AND accomodation_price.accomodation_price_type_id = '1' AND accomodation_price.accomodation_price_cat_id = '1')
INNER JOIN (SELECT
                accomodation_id,
                SUM(accomodation_rooms.rooms)          AS total_rooms,
                SUM(accomodation_rooms.beds * accomodation_rooms.rooms) AS total_persons
              FROM accomodation_rooms
              GROUP BY accomodation_id) accomodation_rooms
    ON accomodation_rooms.accomodation_id = accomodation.id
      AND accomodation_rooms.total_persons >= '4'
WHERE db_countries.title_url_en LIKE '%country%'
    AND db_cities.title_url LIKE '%city%'
    AND total_rooms >= '2'
    AND db_cities.id = '2416'
GROUP BY accomodation.aid
HAVING Calculation < 20
ORDER BY CASE WHEN accomodation.valid_to >= NOW()
    AND accomodation.valid_from <= NOW()THEN 0 WHEN NOW() > accomodation.valid_to
    AND accomodation.valid_to != '0000-00-00'THEN 1 ELSE 2 END, review_total DESC, accomodation.title_en
LIMIT 10 OFFSET 0

編集:

独自の参加方法を引き続き使用できます

SELECT
  accomodation.id,
  accomodation.aid,
  accomodation.title_en,
  accomodation.title_url_en,
  accomodation.address,
  accomodation.zip,
  accomodation.stars,
  accomodation.picture,
  accomodation.valid_from,
  accomodation.valid_to,
  accomodation.latitude,
  accomodation.longitude,
  MAX(info_date_add)                    AS max_info_date_add,
  accomodation.city_id                  AS accomodation_city_id,
  db_cities.id                          AS city_id,
  db_cities.title_en                    AS city,
  db_cities.title_url                   AS city_url,
  db_countries.title_en                 AS country_title,
  db_countries.title_url_en             AS country_url,
  accomodation_type.class               AS accomodation_type_class,
  accomodation_review_value_total.value AS review_total,
  MIN(accomodation_price.price)         AS price_from,
  accomodation_rooms.total_persons,
  SUM(IFNULL(accomodation_rooms.rooms,0,1)) AS total_rooms,
  SUM(IFNULL(accomodation_rooms.beds * accomodation_rooms.rooms,0,1)) AS total_persons
FROM accomodation
  LEFT JOIN db_cities
    ON db_cities.id = accomodation.city_id
  LEFT JOIN db_countries
    ON (db_cities.id = accomodation.city_id
         OR (((acos(sin((db_cities.latitude * pi()/180)) * sin((accomodation.latitude * pi()/180)) + cos((db_cities.latitude * pi()/180)) * cos((accomodation.latitude * pi()/180)) * cos(((db_cities.longitude - accomodation.longitude) * pi()/180)))) * 180/pi()) * 60 * 1.1515 * 1.609344) < '20')
  LEFT JOIN accomodation_review_value_total
    ON accomodation_review_value_total.accomodation_aid = accomodation.aid
  LEFT JOIN accomodation_price
    ON (accomodation_price.accomodation_aid = accomodation.aid
        AND accomodation_price.accomodation_price_type_id = '1'
        AND accomodation_price.accomodation_price_cat_id = '1')
  LEFT JOIN accomodation_rooms
    ON accomodation_rooms.accomodation_id = accomodation.id
WHERE db_countries.title_url_en LIKE '%country%'
    AND db_cities.title_url LIKE '%city%'
    AND total_rooms >= '2'
    AND db_cities.id = '2416'
GROUP BY accomodation.aid
HAVING accomodation_rooms.total_persons >= '4'
ORDER BY CASE WHEN accomodation.valid_to >= NOW()
    AND accomodation.valid_from <= NOW()THEN 0 WHEN NOW() > accomodation.valid_to
    AND accomodation.valid_to != '0000-00-00'THEN 1 ELSE 2 END, review_total DESC, accomodation.title_en
LIMIT 10 OFFSET 0

ここで重要なことは、内部結合の代わりに左結合を使用できるということです。これはより高速になると思います。HAVAING 句に where 条件を入れます。また、選択中に IF 条件を適用していることに注意してください。null が来ると合計 0 でなければ 1 になります。

于 2013-09-24T09:45:14.467 に答える