Выберите дольше, тем больше добавлений - PullRequest
0 голосов
/ 22 декабря 2010

У меня есть запрос, в котором каждое из 8 объединений по отдельности занимает 0,0007 секунд, но когда я их объединяю, время, затрачиваемое на запрос, растет экспоненциально, заканчиваясь 3-секундным запросом.

В основном у меня естьгибкий способ запроса мест с дополнительными полями.Это выглядело довольно хорошо с первыми тремя полями, но потом я заметил, когда мне выпало 7, что это занимает сумасшедшее много времени.Я рандомизировал порядок дополнительных полей, но оказалось, что не имеет значения, какое поле добавлено.

Нет дополнительных полей [0,52 мс]

SELECT 
  `v`.`venue_id`, `v`.`venue_nm`, GROUP_CONCAT(DISTINCT vtr.tag_id SEPARATOR ",") tags 
FROM 
   `listing_venue` AS `v` 
INNER JOIN 
   `listing_venue_tag_rel` AS `vtr` ON vtr.venue_id = v.venue_id WHERE  (v.venue_id = 79) AND (v.published = 1) 
GROUP BY 
   `venue_id`

1 дополнительное поле [0,72мс]

SELECT 
   `v`.`venue_id`, `v`.`venue_nm`, GROUP_CONCAT(DISTINCT vtr.tag_id SEPARATOR ",") tags, `addressvalue`.`value` AS `address`
FROM 
   `listing_venue` AS `v` 
INNER JOIN 
   `listing_venue_tag_rel` AS `vtr` ON vtr.venue_id = v.venue_id 
INNER JOIN 
   `listing_field` AS `addressfield` 
LEFT JOIN
   `listing_venue_field_rel` AS `addressvalue` ON addressvalue.venue_id = v.venue_id AND addressvalue.field_id = addressfield.field_id 
WHERE 
   (v.venue_id = 79) AND (v.published = 1) AND (addressfield.field_nm = 'address') 
GROUP BY 
   `venue_id`

2 дополнительных поля [1,42 мс]

SELECT `v`.`venue_id`, `v`.`venue_nm`, GROUP_CONCAT(DISTINCT vtr.tag_id SEPARATOR ",") tags, `addressvalue`.`value` AS `address`, `address_zhvalue`.`value` AS `address_zh` FROM `listing_venue` AS `v` INNER JOIN `listing_venue_tag_rel` AS `vtr` ON vtr.venue_id = v.venue_id INNER JOIN `listing_field` AS `addressfield` LEFT JOIN `listing_venue_field_rel` AS `addressvalue` ON addressvalue.venue_id = v.venue_id AND addressvalue.field_id = addressfield.field_id INNER JOIN `listing_field` AS `address_zhfield` LEFT JOIN `listing_venue_field_rel` AS `address_zhvalue` ON address_zhvalue.venue_id = v.venue_id AND address_zhvalue.field_id = address_zhfield.field_id WHERE (v.venue_id = 79) AND (v.published = 1) AND (addressfield.field_nm = 'address') AND (address_zhfield.field_nm = 'address_zh') GROUP BY `venue_id`

3 -> 1,13 мс

SELECT `v`.`venue_id`, `v`.`venue_nm`, GROUP_CONCAT(DISTINCT vtr.tag_id SEPARATOR ",") tags, `addressvalue`.`value` AS `address`, `address_zhvalue`.`value` AS `address_zh`, `address_nearvalue`.`value` AS `address_near` FROM `listing_venue` AS `v` INNER JOIN `listing_venue_tag_rel` AS `vtr` ON vtr.venue_id = v.venue_id INNER JOIN `listing_field` AS `addressfield` LEFT JOIN `listing_venue_field_rel` AS `addressvalue` ON addressvalue.venue_id = v.venue_id AND addressvalue.field_id = addressfield.field_id INNER JOIN `listing_field` AS `address_zhfield` LEFT JOIN `listing_venue_field_rel` AS `address_zhvalue` ON address_zhvalue.venue_id = v.venue_id AND address_zhvalue.field_id = address_zhfield.field_id INNER JOIN `listing_field` AS `address_nearfield` LEFT JOIN `listing_venue_field_rel` AS `address_nearvalue` ON address_nearvalue.venue_id = v.venue_id AND address_nearvalue.field_id = address_nearfield.field_id WHERE (v.venue_id = 79) AND (v.published = 1) AND (addressfield.field_nm = 'address') AND (address_zhfield.field_nm = 'address_zh') AND (address_nearfield.field_nm = 'address_near') GROUP BY `venue_id`

4 -> 1,94 мс

SELECT `v`.`venue_id`, `v`.`venue_nm`, GROUP_CONCAT(DISTINCT vtr.tag_id SEPARATOR ",") tags, `addressvalue`.`value` AS `address`, `address_zhvalue`.`value` AS `address_zh`, `address_nearvalue`.`value` AS `address_near`, `phone_numbervalue`.`value` AS `phone_number` FROM `listing_venue` AS `v` INNER JOIN `listing_venue_tag_rel` AS `vtr` ON vtr.venue_id = v.venue_id INNER JOIN `listing_field` AS `addressfield` LEFT JOIN `listing_venue_field_rel` AS `addressvalue` ON addressvalue.venue_id = v.venue_id AND addressvalue.field_id = addressfield.field_id INNER JOIN `listing_field` AS `address_zhfield` LEFT JOIN `listing_venue_field_rel` AS `address_zhvalue` ON address_zhvalue.venue_id = v.venue_id AND address_zhvalue.field_id = address_zhfield.field_id INNER JOIN `listing_field` AS `address_nearfield` LEFT JOIN `listing_venue_field_rel` AS `address_nearvalue` ON address_nearvalue.venue_id = v.venue_id AND address_nearvalue.field_id = address_nearfield.field_id INNER JOIN `listing_field` AS `phone_numberfield` LEFT JOIN `listing_venue_field_rel` AS `phone_numbervalue` ON phone_numbervalue.venue_id = v.venue_id AND phone_numbervalue.field_id = phone_numberfield.field_id WHERE (v.venue_id = 79) AND (v.published = 1) AND (addressfield.field_nm = 'address') AND (address_zhfield.field_nm = 'address_zh') AND (address_nearfield.field_nm = 'address_near') AND (phone_numberfield.field_nm = 'phone_number') GROUP BY `venue_id`

5-> 9,7 мс

SELECT `v`.`venue_id`, `v`.`venue_nm`, GROUP_CONCAT(DISTINCT vtr.tag_id SEPARATOR ",") tags, `addressvalue`.`value` AS `address`, `address_zhvalue`.`value` AS `address_zh`, `address_nearvalue`.`value` AS `address_near`, `phone_numbervalue`.`value` AS `phone_number`, `websitevalue`.`value` AS `website` FROM `listing_venue` AS `v` INNER JOIN `listing_venue_tag_rel` AS `vtr` ON vtr.venue_id = v.venue_id INNER JOIN `listing_field` AS `addressfield` LEFT JOIN `listing_venue_field_rel` AS `addressvalue` ON addressvalue.venue_id = v.venue_id AND addressvalue.field_id = addressfield.field_id INNER JOIN `listing_field` AS `address_zhfield` LEFT JOIN `listing_venue_field_rel` AS `address_zhvalue` ON address_zhvalue.venue_id = v.venue_id AND address_zhvalue.field_id = address_zhfield.field_id INNER JOIN `listing_field` AS `address_nearfield` LEFT JOIN `listing_venue_field_rel` AS `address_nearvalue` ON address_nearvalue.venue_id = v.venue_id AND address_nearvalue.field_id = address_nearfield.field_id INNER JOIN `listing_field` AS `phone_numberfield` LEFT JOIN `listing_venue_field_rel` AS `phone_numbervalue` ON phone_numbervalue.venue_id = v.venue_id AND phone_numbervalue.field_id = phone_numberfield.field_id INNER JOIN `listing_field` AS `websitefield` LEFT JOIN `listing_venue_field_rel` AS `websitevalue` ON websitevalue.venue_id = v.venue_id AND websitevalue.field_id = websitefield.field_id WHERE (v.venue_id = 79) AND (v.published = 1) AND (addressfield.field_nm = 'address') AND (address_zhfield.field_nm = 'address_zh') AND (address_nearfield.field_nm = 'address_near') AND (phone_numberfield.field_nm = 'phone_number') AND (websitefield.field_nm = 'website') GROUP BY `venue_id`

6 -> 230,52 мс

SELECT `v`.`venue_id`, `v`.`venue_nm`, GROUP_CONCAT(DISTINCT vtr.tag_id SEPARATOR ",") tags, `addressvalue`.`value` AS `address`, `address_zhvalue`.`value` AS `address_zh`, `address_nearvalue`.`value` AS `address_near`, `phone_numbervalue`.`value` AS `phone_number`, `websitevalue`.`value` AS `website`, `price_maxvalue`.`value` AS `price_max` FROM `listing_venue` AS `v` INNER JOIN `listing_venue_tag_rel` AS `vtr` ON vtr.venue_id = v.venue_id INNER JOIN `listing_field` AS `addressfield` LEFT JOIN `listing_venue_field_rel` AS `addressvalue` ON addressvalue.venue_id = v.venue_id AND addressvalue.field_id = addressfield.field_id INNER JOIN `listing_field` AS `address_zhfield` LEFT JOIN `listing_venue_field_rel` AS `address_zhvalue` ON address_zhvalue.venue_id = v.venue_id AND address_zhvalue.field_id = address_zhfield.field_id INNER JOIN `listing_field` AS `address_nearfield` LEFT JOIN `listing_venue_field_rel` AS `address_nearvalue` ON address_nearvalue.venue_id = v.venue_id AND address_nearvalue.field_id = address_nearfield.field_id INNER JOIN `listing_field` AS `phone_numberfield` LEFT JOIN `listing_venue_field_rel` AS `phone_numbervalue` ON phone_numbervalue.venue_id = v.venue_id AND phone_numbervalue.field_id = phone_numberfield.field_id INNER JOIN `listing_field` AS `websitefield` LEFT JOIN `listing_venue_field_rel` AS `websitevalue` ON websitevalue.venue_id = v.venue_id AND websitevalue.field_id = websitefield.field_id INNER JOIN `listing_field` AS `price_maxfield` LEFT JOIN `listing_venue_field_rel` AS `price_maxvalue` ON price_maxvalue.venue_id = v.venue_id AND price_maxvalue.field_id = price_maxfield.field_id WHERE (v.venue_id = 79) AND (v.published = 1) AND (addressfield.field_nm = 'address') AND (address_zhfield.field_nm = 'address_zh') AND (address_nearfield.field_nm = 'address_near') AND (phone_numberfield.field_nm = 'phone_number') AND (websitefield.field_nm = 'website') AND (price_maxfield.field_nm = 'price_max') GROUP BY `venue_id`

7-> 3375,29 мс

SELECT 
    `v`.`venue_id`, `v`.`venue_nm`, GROUP_CONCAT(DISTINCT vtr.tag_id SEPARATOR ",") tags, `addressvalue`.`value` AS `address`, `address_zhvalue`.`value` AS `address_zh`, `address_nearvalue`.`value` AS `address_near`, `phone_numbervalue`.`value` AS `phone_number`, `websitevalue`.`value` AS `website`, `price_maxvalue`.`value` AS `price_max`, `price_minvalue`.`value` AS `price_min` 
FROM 
    `listing_venue` AS `v` 
INNER JOIN 
    `listing_venue_tag_rel` AS `vtr` 
    ON 
        vtr.venue_id = v.venue_id 
INNER JOIN
    `listing_field` AS `addressfield` 
LEFT JOIN 
    `listing_venue_field_rel` AS `addressvalue` 
    ON 
        addressvalue.venue_id = v.venue_id AND addressvalue.field_id = addressfield.field_id 
INNER JOIN 
    `listing_field` AS `address_zhfield` 
LEFT JOIN 
    `listing_venue_field_rel` AS `address_zhvalue` 
    ON 
        address_zhvalue.venue_id = v.venue_id AND address_zhvalue.field_id = address_zhfield.field_id 
INNER JOIN 
    `listing_field` AS `address_nearfield` 
LEFT JOIN 
    `listing_venue_field_rel` AS `address_nearvalue` 
    ON 
    address_nearvalue.venue_id = v.venue_id AND address_nearvalue.field_id = address_nearfield.field_id 
INNER JOIN 
    `listing_field` AS `phone_numberfield` 
LEFT JOIN 
    `listing_venue_field_rel` AS `phone_numbervalue` 
    ON 
        phone_numbervalue.venue_id = v.venue_id AND phone_numbervalue.field_id = phone_numberfield.field_id 
INNER JOIN 
    `listing_field` AS `websitefield` 
LEFT JOIN 
    `listing_venue_field_rel` AS `websitevalue` 
    ON 
        websitevalue.venue_id = v.venue_id AND websitevalue.field_id = websitefield.field_id 
INNER JOIN 
    `listing_field` AS `price_maxfield` 
LEFT JOIN 
    `listing_venue_field_rel` AS `price_maxvalue` 
    ON 
        price_maxvalue.venue_id = v.venue_id AND price_maxvalue.field_id = price_maxfield.field_id 
INNER JOIN 
    `listing_field` AS `price_minfield` 
LEFT JOIN 
    `listing_venue_field_rel` AS `price_minvalue`
    ON 
        price_minvalue.venue_id = v.venue_id AND price_minvalue.field_id = price_minfield.field_id 
WHERE 
    (v.venue_id = 79) 
AND (v.published = 1) 
AND (addressfield.field_nm = 'address') 
AND (address_zhfield.field_nm = 'address_zh') 
AND (address_nearfield.field_nm = 'address_near') 
AND (phone_numberfield.field_nm = 'phone_number') 
AND (websitefield.field_nm = 'website') 
AND (price_maxfield.field_nm = 'price_max') 
AND (price_minfield.field_nm = 'price_min') GROUP BY `venue_id`

Очевидно, я могупросто разбить запрос на 7, но я не понимаю, почему происходит это странное увеличение времени.

Также я не уверен, что использую правильное соединение.Поле может быть пустым, поэтому я и остаюсь присоединяющимся к venue_field_rel ...

вот структуры таблиц

listing_field:
field_id | field_nm

listing_venue_field_rel
venue_id | field_id| value

listing_venue
venue_id | venue_nm

EXPLAIN

id  select_type     table               type    possible_keys                                                                                       key                 key_len     ref     rows    Extra
1   SIMPLE          v                   const   PRIMARY,item_id_UNIQUE                                                                              PRIMARY             4           const   1    
1   SIMPLE          addressfield        ALL     NULL                                                                                                NULL                NULL        NULL    7       Using where
1   SIMPLE          addressvalue        ref     field_value_venue,fk_mnc_listing_venue_field_rel_venue_id,fk_mnc_listing_venue_field_rel_field_id   field_value_venue   4           const   6       Using index
1   SIMPLE          address_zhfield     ALL     NULL                                                                                                NULL                NULL        NULL    7       Using where; Using join buffer
1   SIMPLE          address_zhvalue     ref     field_value_venue,fk_mnc_listing_venue_field_rel_venue_id,fk_mnc_listing_venue_field_rel_field_id   field_value_venue   4           const   6       Using index
1   SIMPLE          address_nearfield   ALL     NULL                                                                                                NULL                NULL        NULL    7       Using where; Using join buffer
1   SIMPLE          address_nearvalue   ref     field_value_venue,fk_mnc_listing_venue_field_rel_venue_id,fk_mnc_listing_venue_field_rel_field_id   field_value_venue   4           const   6       Using index
1   SIMPLE          phone_numberfield   ALL     NULL                                                                                                NULL                NULL        NULL    7       Using where; Using join buffer
1   SIMPLE          phone_numbervalue   ref     field_value_venue,fk_mnc_listing_venue_field_rel_venue_id,fk_mnc_listing_venue_field_rel_field_id   field_value_venue   4           const   6       Using index
1   SIMPLE          websitefield        ALL                                                                                                         NULL                NULL        NULL    7       Using where; Using join buffer
1   SIMPLE          websitevalue        ref     field_value_venue,fk_mnc_listing_venue_field_rel_venue_id,fk_mnc_listing_venue_field_rel_field_id   field_value_venue   4           const   6       Using index
1   SIMPLE          price_maxfield      ALL                                                                                                         NULL                NULL        NULL    7       Using where; Using join buffer
1   SIMPLE          price_maxvalue      ref     field_value_venue,fk_mnc_listing_venue_field_rel_venue_id,fk_mnc_listing_venue_field_rel_field_id   field_value_venue   4           const   6       Using index
1   SIMPLE          price_minfield      ALL                                                                                                         NULL                NULL        NULL    7       Using where; Using join buffer
1   SIMPLE          price_minvalue      ref     field_value_venue,fk_mnc_listing_venue_field_rel_venue_id,fk_mnc_listing_venue_field_rel_field_id   field_value_venue   4           const   6       Using index
1   SIMPLE          vtr                 ref     item_tag,fk_venue_id                                                                                fk_venue_id         4           const   11      Using index

EDIT Я "index uniqued" field_nm, который уменьшил скорость до 7 мс

id  select_type table               type    possible_keys           key                 key_len     ref     rows    Extra
1   SIMPLE      v                   const   PRIMARY,item_id_UNIQUE  PRIMARY             4           const   1    
1   SIMPLE      addressfield        const   field_nm,field_nm_2     field_nm            137         const   1   Using index
1   SIMPLE      address_zhfield     const   field_nm,field_nm_2     field_nm            137         const   1   Using index
1   SIMPLE      address_nearfield   const   field_nm,field_nm_2     field_nm            137         const   1   Using index
1   SIMPLE      phone_numberfield   const   field_nm,field_nm_2     field_nm            137         const   1   Using index
1   SIMPLE      websitefield        const   field_nm,field_nm_2     field_nm            137         const   1   Using index
1   SIMPLE      price_maxfield      const   field_nm,field_nm_2     field_nm            137         const   1   Using index
1   SIMPLE      addressvalue        ref     field_value_venue,...   field_value_venue   4           const   7   Using index
1   SIMPLE      address_zhvalue     ref     field_value_venue,...   field_value_venue   4           const   7   Using index
1   SIMPLE      address_nearvalue   ref     field_value_venue,...   field_value_venue   4           const   7   Using index
1   SIMPLE      phone_numbervalue   ref     field_value_venue,...   field_value_venue   4           const   7   Using index
1   SIMPLE      websitevalue        ref     field_value_venue,...   field_value_venue   4           const   7   Using index
1   SIMPLE      price_maxvalue      ref     field_value_venue,...   field_value_venue   4           const   7   Using index
1   SIMPLE      vtr                 ref     item_tag,fk_venue_id    fk_venue_id         4           const   17  Using index

Я уверен, однако, что запрос можно оптимизировать еще немного

1 Ответ

2 голосов
/ 22 декабря 2010

Я думаю, что вы, возможно, делаете здесь CROSS JOIN

INNER JOIN listing_field AS address_zhfield LEFT JOIN

У вас нет предложения ON, поэтому вы получаете декартово произведение со всем остальным, что, вероятно, приведет к экспоненциальному замедлению.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...