Может ли несколько предложений JOIN в запросе MySQL увеличить число строк, которые он должен проверить? - PullRequest
1 голос
/ 18 августа 2011

Так что я получил техническую поддержку от нашего хост-провайдера по поводу медленного ответа базы данных, который я испытывал на ключевой странице поиска, и после некоторого расследования он сказал мне, что используемый мной запрос проверяет 67 998 176 строк. Теперь самая большая таблица, которая появляется в этом запросе, имеет самое большее 116 строк, а остальные имеют в среднем по 25 строк каждая.

Вот SQL моего запроса

 SELECT COUNT( DISTINCT `A`.`id`) AS `total_num_resource_rows`
 FROM `admin_site_resources` AS `A`
 LEFT JOIN `admin_site_organization_resource` AS `B` ON `B`.`res_id`=`A`.`id`
 LEFT JOIN `admin_site_organizations` AS `C` ON `B`.`org_id`=`C`.`id`
 LEFT JOIN `admin_site_resource_res_topic` AS `D` ON `D`.`resource_id`=`A`.`id` 
 LEFT JOIN `admin_site_resource_topics` AS `E` ON `E`.`id`=`D`.`res_topic_id`
 LEFT JOIN `admin_site_resource_audience` AS `F` ON `F`.`resource_id`=`A`.`id`
 LEFT JOIN `admin_site_audiences` AS `G` ON `G`.`id`=`F`.`audience_id`
 LEFT JOIN `admin_site_resource_curriculum_topic` AS `H` ON `H`.`resource_id`=`A`.`id`
 LEFT JOIN `admin_site_curriculum_topics` AS `I` ON `I`.`id`=`H`.`curriculum_topic_id`
 LEFT JOIN `admin_site_resource_curriculum_grade` AS `J` ON `J`.`resource_id`=`A`.`id`
 LEFT JOIN `admin_site_curriculum_grades` AS `K` ON `K`.`id`=`J`.`curriculum_grade_id`
 LEFT JOIN `admin_site_resource_curriculum_subject` AS `L` ON `L`.`resource_id`=`A`.`id`
 LEFT JOIN `admin_site_curriculum_subjects` AS `M` ON `M`.`id`=`L`.`curriculum_subject_id` 
 LEFT JOIN `admin_site_resource_res_type` AS `N` ON `N`.`resource_id`=`A`.`id`
 LEFT JOIN `admin_site_resource_types` AS `O` ON `O`.`id`=`N`.`res_type_id` 
 LEFT JOIN `admin_site_resource_res_area_location` AS `P` ON `P`.`resource_id`=`A`.`id`
 LEFT JOIN `admin_site_resource_area_locations` AS `Q` ON `Q`.`id`=`P`.`res_area_location_id` 

 WHERE `A`.`post_status`='approved' AND (
`A`.`resource_name` LIKE '%alpha%'
OR `A`.`aliases` LIKE '%alpha%' 
OR `A`.`short_desc` LIKE '%alpha%' 
OR `A`.`resource_url` LIKE '%alpha%' 
OR `A`.`other_resource_type` LIKE '%alpha%' 
OR `C`.`org_name` LIKE '%alpha%' 
OR `E`.`topic_label` LIKE '%alpha%' 
OR `G`.`audience_label` LIKE '%alpha%' 
OR `I`.`topic_label` LIKE '%alpha%' 
OR `K`.`grade_label` LIKE '%alpha%' 
OR `M`.`subject_label` LIKE '%alpha%' 
OR `O`.`type_label` LIKE '%alpha%' 
OR `Q`.`area_location_label` LIKE '%alpha%' );

Да, я понимаю, что этот запрос довольно длинный и некрасивый, но я думаю, что это результат всей нормализации, которая должна была быть сделана для него. Что я не могу понять, так это то, как несколько строк неожиданно превратились в почти 68 миллионов строк. Виноваты ли в этом ЛЕВЫЕ СОЕДИНЕНИЯ?

Ответы [ 2 ]

2 голосов
/ 18 августа 2011

В зависимости от того, сколько строк в каждой таблице соответствует каждому условию соединения, вы можете иметь до 116 строк из первой таблицы, каждая из которых имеет до 116 строк из второй таблицы (сейчас 13456 строк), каждая из которых имеет до 116 строк из третьей таблицы (сейчас 1560896 строк), каждая из которых имеет до 116 строк из четвертой таблицы (сейчас 181063936 строк) ... вы видите, куда это идет?

В этой самой большой таблице может быть только 116 строк, но когда вы берете каждую комбинацию из 16 ключей таблицы ... http://en.wikipedia.org/wiki/Combination

1 голос
/ 18 августа 2011

Перепишите его как:

 SELECT COUNT(*) AS `total_num_resource_rows`
 FROM `admin_site_resources` AS `A`
 WHERE `A`.`post_status`='approved' AND
   ( `A`.`resource_name` LIKE '%alpha%'
  OR `A`.`aliases` LIKE '%alpha%' 
  OR `A`.`short_desc` LIKE '%alpha%' 
  OR `A`.`resource_url` LIKE '%alpha%' 
  OR `A`.`other_resource_type` LIKE '%alpha%' 
  OR EXISTS ( SELECT * 
              FROM `admin_site_organization_resource` AS `B` 
                JOIN `admin_site_organizations` AS `C`
                  ON `B`.`org_id`=`C`.`id`
              WHERE `B`.`res_id`=`A`.`id`
                AND `C`.`org_name` LIKE '%alpha%' 
            )
  OR EXISTS ( 
             ...
            )
  OR EXISTS ( 
             ...
            )
  ...
    )
...