2011-12-29 1 views
0

У меня возникла странная проблема и вам нужна помощь в определении причины. До сих пор я мог наблюдать симптомы. Что это значит, так это то, что MySQL выполняет запрос по-разному в зависимости от того, есть ли у меня символ новой строки перед моей первой «LEFT JOIN».Почему пробелы влияют на MySQL Left Join и возвращают значения NULL?

Вот мои настройки:

Я бегу запросов на экземпляре базы данных MySQL, предоставленной www.xeround.com. Я использую структуру Kohana версии 3.0. Я запускаю PHP 5.3.3 FastCGI на Lighttpd. Я составил PHP с MySQL Native Driver:

--with-MySQL = mysqlnd --with-MySQLi = mysqlnd --with-PDO-MySQL = mysqlnd

Я использую по умолчанию Kohana 3 базы данных MySQL драйвер на и QueryBuilder.

Я собираюсь пропустить PHP-код и разделить SQL с тех пор, как это кажется проблемой. QueryBuilder заканчивает строительство этого запроса:

SELECT `fieldreps`.`user_id` AS `fieldreps.user_id`, `fieldreps`.`availability_id` AS `fieldreps.availability_id`, `fieldreps`.`applicant_type` AS `fieldreps.applicant_type`, `fieldreps`.`license_number` AS `fieldreps.license_number`, `fieldreps`.`license_exp` AS `fieldreps.license_exp`, `fieldreps`.`license_state` AS `fieldreps.license_state`, `fieldreps`.`car` AS `fieldreps.car`, `fieldreps`.`authorized_worker` AS `fieldreps.authorized_worker`, `fieldreps`.`restrictions` AS `fieldreps.restrictions`, `fieldreps`.`night` AS `fieldreps.night`, `fieldreps`.`day` AS `fieldreps.day`, `fieldreps`.`longer` AS `fieldreps.longer`, `fieldreps`.`commitment` AS `fieldreps.commitment`, `fieldreps`.`travel_metro` AS `fieldreps.travel_metro`, `fieldreps`.`travel_states` AS `fieldreps.travel_states`, `fieldreps`.`big_employee` AS `fieldreps.big_employee`, `fieldreps`.`employed` AS `fieldreps.employed`, `fieldreps`.`retail` AS `fieldreps.retail`, `fieldreps`.`status` AS `fieldreps.status`, `fieldreps`.`start` AS `fieldreps.start`, `fieldreps`.`sales` AS `fieldreps.sales`, `fieldreps`.`study` AS `fieldreps.study`, `fieldreps`.`relevant` AS `fieldreps.relevant`, `fieldreps`.`experience` AS `fieldreps.experience`, `fieldreps`.`claims` AS `fieldreps.claims`, `fieldreps`.`education` AS `fieldreps.education`, `fieldreps`.`degree_details` AS `fieldreps.degree_details`, `fieldreps`.`degree_institution` AS `fieldreps.degree_institution`, `fieldreps`.`other_training` AS `fieldreps.other_training`, `fieldreps`.`jobs` AS `fieldreps.jobs`, `fieldreps`.`current_training` AS `fieldreps.current_training`, `fieldreps`.`interested` AS `fieldreps.interested`, `fieldreps`.`achievements` AS `fieldreps.achievements`, `fieldreps`.`passions` AS `fieldreps.passions`, `fieldreps`.`ambitions` AS `fieldreps.ambitions`, `fieldreps`.`max_travel_time` AS `fieldreps.max_travel_time`, `fieldreps`.`creation_time` AS `fieldreps.creation_time`, `fieldreps`.`resume` AS `fieldreps.resume`, `users`.`user_id` AS `users.user_id`, `users`.`email` AS `users.email`, `users`.`name` AS `users.name`, `users`.`password` AS `users.password`, `users`.`given_name` AS `users.given_name`, `users`.`title` AS `users.title`, `users`.`nationality` AS `users.nationality`, `availabilities`.`availability_id` AS `availabilities.availability_id`, `availabilities`.`fieldrep_id` AS `availabilities.fieldrep_id`, `availabilities`.`mon_start` AS `availabilities.mon_start`, `availabilities`.`mon_end` AS `availabilities.mon_end`, `availabilities`.`tue_start` AS `availabilities.tue_start`, `availabilities`.`tue_end` AS `availabilities.tue_end`, `availabilities`.`wed_start` AS `availabilities.wed_start`, `availabilities`.`wed_end` AS `availabilities.wed_end`, `availabilities`.`thur_start` AS `availabilities.thur_start`, `availabilities`.`thur_end` AS `availabilities.thur_end`, `availabilities`.`fri_start` AS `availabilities.fri_start`, `availabilities`.`fri_end` AS `availabilities.fri_end`, `availabilities`.`sat_start` AS `availabilities.sat_start`, `availabilities`.`sat_end` AS `availabilities.sat_end`, `availabilities`.`sun_start` AS `availabilities.sun_start`, `availabilities`.`sun_end` AS `availabilities.sun_end` FROM `fieldreps` AS `fieldreps` LEFT JOIN `users` ON (`fieldreps`.`user_id` = `users`.`user_id`) LEFT JOIN `availabilities` ON (`fieldreps`.`availability_id` = `availabilities`.`availability_id`) 

который возвращает результат как это: (. Я удалил большую часть возвращаемых полей из таблицы Fieldreps, чтобы держать его коротким и менее личный)

[0] => Array 
    (
     [fieldreps.user_id] => 1f01f4c2-43fd-550d-a53d-1f191786ebad 
     [fieldreps.availability_id] => e31b0773-ecba-41d1-8ebb-7ac718496456 
     [fieldreps.car] => Yes 
     [fieldreps.authorized_worker] => Yes 
     [fieldreps.restrictions] => Has Restrictions: No 
     [fieldreps.night] => Yes 
     [fieldreps.day] => Yes 
     [fieldreps.longer] => Yes 
     [users.user_id] => 1f01f4c2-43fd-550d-a53d-1f191786ebad 
     [users.email] => [email protected] 
     [users.name] => Jones 
     [users.password] => 
     [users.given_name] => Fred 
     [users.title] => Miss 
     [users.nationality] => 
     [availabilities.availability_id] => 
     [availabilities.fieldrep_id] => 
     [availabilities.mon_start] => 
     [availabilities.mon_end] => 
     [availabilities.tue_start] => 
     [availabilities.tue_end] => 
     [availabilities.wed_start] => 
     [availabilities.wed_end] => 
     [availabilities.thur_start] => 
     [availabilities.thur_end] => 
     [availabilities.fri_start] => 
     [availabilities.fri_end] => 
     [availabilities.sat_start] => 
     [availabilities.sat_end] => 
     [availabilities.sun_start] => 
     [availabilities.sun_end] => 
    ) 
[1] => Array 
    (
     [fieldreps.user_id] => 812c3a9f-d7d8-565a-a886-1b182753dd41 
     [fieldreps.availability_id] => 
     [fieldreps.car] => 1 
     [fieldreps.authorized_worker] => 1 
     [fieldreps.restrictions] => 
     [fieldreps.night] => 1 
     [fieldreps.day] => 1 
     [fieldreps.longer] => 1 
     [users.user_id] => 812c3a9f-d7d8-565a-a886-1b182753dd41 
     [users.email] => [email protected] 
     [users.name] => Smith 
     [users.password] => 
     [users.given_name] => Jill 
     [users.title] => 
     [users.nationality] => 
     [availabilities.availability_id] => 
     [availabilities.fieldrep_id] => 
     [availabilities.mon_start] => 
     [availabilities.mon_end] => 
     [availabilities.tue_start] => 
     [availabilities.tue_end] => 
     [availabilities.wed_start] => 
     [availabilities.wed_end] => 
     [availabilities.thur_start] => 
     [availabilities.thur_end] => 
     [availabilities.fri_start] => 
     [availabilities.fri_end] => 
     [availabilities.sat_start] => 
     [availabilities.sat_end] => 
     [availabilities.sun_start] => 
     [availabilities.sun_end] => 

Тем не менее, когда я вставить символ новой строки непосредственно перед первым LEFT JOIN, как это:

SELECT `fieldreps`.`user_id` AS `fieldreps.user_id`, `fieldreps`.`availability_id` AS `fieldreps.availability_id`, `fieldreps`.`applicant_type` AS `fieldreps.applicant_type`, `fieldreps`.`license_number` AS `fieldreps.license_number`, `fieldreps`.`license_exp` AS `fieldreps.license_exp`, `fieldreps`.`license_state` AS `fieldreps.license_state`, `fieldreps`.`car` AS `fieldreps.car`, `fieldreps`.`authorized_worker` AS `fieldreps.authorized_worker`, `fieldreps`.`restrictions` AS `fieldreps.restrictions`, `fieldreps`.`night` AS `fieldreps.night`, `fieldreps`.`day` AS `fieldreps.day`, `fieldreps`.`longer` AS `fieldreps.longer`, `fieldreps`.`commitment` AS `fieldreps.commitment`, `fieldreps`.`travel_metro` AS `fieldreps.travel_metro`, `fieldreps`.`travel_states` AS `fieldreps.travel_states`, `fieldreps`.`big_employee` AS `fieldreps.big_employee`, `fieldreps`.`employed` AS `fieldreps.employed`, `fieldreps`.`retail` AS `fieldreps.retail`, `fieldreps`.`status` AS `fieldreps.status`, `fieldreps`.`start` AS `fieldreps.start`, `fieldreps`.`sales` AS `fieldreps.sales`, `fieldreps`.`study` AS `fieldreps.study`, `fieldreps`.`relevant` AS `fieldreps.relevant`, `fieldreps`.`experience` AS `fieldreps.experience`, `fieldreps`.`claims` AS `fieldreps.claims`, `fieldreps`.`education` AS `fieldreps.education`, `fieldreps`.`degree_details` AS `fieldreps.degree_details`, `fieldreps`.`degree_institution` AS `fieldreps.degree_institution`, `fieldreps`.`other_training` AS `fieldreps.other_training`, `fieldreps`.`jobs` AS `fieldreps.jobs`, `fieldreps`.`current_training` AS `fieldreps.current_training`, `fieldreps`.`interested` AS `fieldreps.interested`, `fieldreps`.`achievements` AS `fieldreps.achievements`, `fieldreps`.`passions` AS `fieldreps.passions`, `fieldreps`.`ambitions` AS `fieldreps.ambitions`, `fieldreps`.`max_travel_time` AS `fieldreps.max_travel_time`, `fieldreps`.`creation_time` AS `fieldreps.creation_time`, `fieldreps`.`resume` AS `fieldreps.resume`, `users`.`user_id` AS `users.user_id`, `users`.`email` AS `users.email`, `users`.`name` AS `users.name`, `users`.`password` AS `users.password`, `users`.`given_name` AS `users.given_name`, `users`.`title` AS `users.title`, `users`.`nationality` AS `users.nationality`, `availabilities`.`availability_id` AS `availabilities.availability_id`, `availabilities`.`fieldrep_id` AS `availabilities.fieldrep_id`, `availabilities`.`mon_start` AS `availabilities.mon_start`, `availabilities`.`mon_end` AS `availabilities.mon_end`, `availabilities`.`tue_start` AS `availabilities.tue_start`, `availabilities`.`tue_end` AS `availabilities.tue_end`, `availabilities`.`wed_start` AS `availabilities.wed_start`, `availabilities`.`wed_end` AS `availabilities.wed_end`, `availabilities`.`thur_start` AS `availabilities.thur_start`, `availabilities`.`thur_end` AS `availabilities.thur_end`, `availabilities`.`fri_start` AS `availabilities.fri_start`, `availabilities`.`fri_end` AS `availabilities.fri_end`, `availabilities`.`sat_start` AS `availabilities.sat_start`, `availabilities`.`sat_end` AS `availabilities.sat_end`, `availabilities`.`sun_start` AS `availabilities.sun_start`, `availabilities`.`sun_end` AS `availabilities.sun_end` FROM `fieldreps` AS `fieldreps` 
LEFT JOIN `users` ON (`fieldreps`.`user_id` = `users`.`user_id`) LEFT JOIN `availabilities` ON (`fieldreps`.`availability_id` = `availabilities`.`availability_id`) 

теперь я получаю результат я хочу:

[0] => Array 
    (
     [fieldreps.user_id] => 1f01f4c2-43fd-550d-a53d-1f191786ebad 
     [fieldreps.availability_id] => e31b0773-ecba-41d1-8ebb-7ac718496456 
     [fieldreps.car] => Yes 
     [fieldreps.authorized_worker] => Yes 
     [fieldreps.restrictions] => Has Restrictions: No 
     [fieldreps.night] => Yes 
     [fieldreps.day] => Yes 
     [fieldreps.longer] => Yes 
     [users.user_id] => 1f01f4c2-43fd-550d-a53d-1f191786ebad 
     [users.email] => [email protected] 
     [users.name] => Jones 
     [users.password] => 
     [users.given_name] => Fred 
     [users.title] => Miss 
     [users.nationality] => 
     [availabilities.availability_id] => e31b0773-ecba-41d1-8ebb-7ac718496456 
     [availabilities.fieldrep_id] => 1f01f4c2-43fd-550d-a53d-1f191786ebad 
     [availabilities.mon_start] => 540 
     [availabilities.mon_end] => 1020 
     [availabilities.tue_start] => 540 
     [availabilities.tue_end] => 1020 
     [availabilities.wed_start] => 540 
     [availabilities.wed_end] => 1020 
     [availabilities.thur_start] => 540 
     [availabilities.thur_end] => 1020 
     [availabilities.fri_start] => 540 
     [availabilities.fri_end] => 1020 
     [availabilities.sat_start] => 
     [availabilities.sat_end] => 
     [availabilities.sun_start] => 
     [availabilities.sun_end] => 
    ) 
[1] => Array 
    (
     [fieldreps.user_id] => 812c3a9f-d7d8-565a-a886-1b182753dd41 
     [fieldreps.availability_id] => 
     [fieldreps.car] => 1 
     [fieldreps.authorized_worker] => 1 
     [fieldreps.restrictions] => 
     [fieldreps.night] => 1 
     [fieldreps.day] => 1 
     [fieldreps.longer] => 1 
     [users.user_id] => 812c3a9f-d7d8-565a-a886-1b182753dd41 
     [users.email] => [email protected] 
     [users.name] => Smith 
     [users.password] => 
     [users.given_name] => Jill 
     [users.title] => 
     [users.nationality] => 
     [availabilities.availability_id] => 
     [availabilities.fieldrep_id] => 
     [availabilities.mon_start] => 
     [availabilities.mon_end] => 
     [availabilities.tue_start] => 
     [availabilities.tue_end] => 
     [availabilities.wed_start] => 
     [availabilities.wed_end] => 
     [availabilities.thur_start] => 
     [availabilities.thur_end] => 
     [availabilities.fri_start] => 
     [availabilities.fri_end] => 
     [availabilities.sat_start] => 
     [availabilities.sat_end] => 
     [availabilities.sun_start] => 
     [availabilities.sun_end] => 

Обратите внимание, что LEFT JOIN в таблице Users отлично работает в обоих сценариях. Я также попытался добавить новую строку перед вторым LEFT JOIN, а не первым. Такой же нежелательный результат. Единственное, что я могу найти, чтобы исправить это, - это поставить новую строку перед первой LEFT JOIN. Запросы, которые построены QueryBuilder и отправленные в MySQL, всегда являются длинными, однострочными, минимальными пробелами ... нет новых строк! Это первый раз, когда я столкнулся с этой проблемой. Я просто не могу поверить, что было бы требование разместить новую строку перед первым LEFT JOIN.

Мой вопрос сводится к этим пунктам:

  1. это должно ли происходить таким образом? (Пробел, результатом которого является результат запроса)
  2. Каков наилучший способ получить результат, который я хочу.

Я не эксперт по SQL, иначе мне, вероятно, не нужно было задавать этот вопрос. Я уверен, что есть кое-что, что я пропускаю.

Спасибо,

Джонатану

ответ

0

Мой вопрос был прямо передо мной, как я думал:

Индексы

я нечаянно создал два индекса на availabilities.fieldrep_id и индексы на остальной части схемы были, дрянные - в лучшем случае.

Я использовал EXPLAIN, указав, что он не использует индекс для двух из трех объединений. Я очистил свои показатели, и теперь он отлично работает, каждый раз.

Кроме того, я думаю, я понял, почему новая строка изменит запрос. Если бы я снова и снова запускал запрос, я бы увидел, что он переключается между приведенными примерами, независимо от добавления новой строки или нет. Я предполагаю, что MySQL имеет некоторое кэширование для повторных запросов. Бьюсь об заклад, что новой строки было достаточно, чтобы заставить ее игнорировать кешированную версию, поэтому она иногда давала мне желаемый результат.

Независимо от того, проблема была с индексами. Все остальное было всего лишь симптомом.

Возможно, это поможет кому-то сэкономить немного времени.