Справка по производительности MySQL Query, многие из одной таблицы объединяются - PullRequest
3 голосов
/ 30 марта 2012

Я пишу скрипт PHP, который создает запрос SQL. Этот скрипт и база данных предназначены для CMS Joomla, и, в частности, он запрашивает таблицы компонента SOBIPro (чтобы использовать данные, введенные там в этом компоненте). Однако из-за способа обработки таблиц SOBI Pro, когда каждый экземпляр поля является отдельной строкой в ​​таблице, это означает включение отдельного экземпляра таблицы для каждого поля, которое я хочу отозвать. Это кажется не очень эффективным, и на самом деле в этом поиске время ожидания истекло.

Запрос SQL выглядит следующим образом (это после того, как он был сгенерирован моим PHP-кодом):

    SELECT DISTINCT o.id AS entryid, o.parent AS parentID, name.baseData AS title,business.baseData AS business_data,
    contact_fn.baseData AS contact_fn_data ,contact_ln.baseData AS contact_ln_data ,position.baseData AS position_data,
    civic1.baseData AS civic1_data ,civic2.baseData AS civic2_data ,mailing.baseData AS mailing_data,
    community.baseData AS community_data ,municip.baseData AS municip_data ,county.baseData AS county_data,
    province.baseData AS province_data ,country.baseData AS country_data ,postal.baseData AS descr_data,
    phone.baseData AS phone_data ,tollfree.baseData AS tollfree_data ,fax.baseData AS fax_data,
    email.baseData AS email_data ,web.baseData AS web_data ,empTotal.baseData AS empTotal_data
    FROM jos_sobipro_object AS o
    INNER JOIN jos_sobipro_field_data AS name ON name.sid = o.id
    INNER JOIN jos_sobipro_relations AS r ON o.id = r.id
    LEFT JOIN jos_sobipro_field_data AS business ON business.sid = o.id AND business.fid = 36
    LEFT JOIN jos_sobipro_field_data AS contact_fn ON contact_fn.sid = o.id AND contact_fn.fid = 74
    LEFT JOIN jos_sobipro_field_data AS contact_ln ON contact_ln.sid = o.id AND contact_ln.fid = 75
    LEFT JOIN jos_sobipro_field_data AS position ON position.sid = o.id AND position.fid = 76
    LEFT JOIN jos_sobipro_field_data AS civic1 ON civic1.sid = o.id AND civic1.fid = 77
    LEFT JOIN jos_sobipro_field_data AS civic2 ON civic2.sid = o.id AND civic2.fid = 78
    LEFT JOIN jos_sobipro_field_data AS mailing ON mailing.sid = o.id AND mailing.fid = 79
    LEFT JOIN jos_sobipro_field_data AS community ON community.sid = o.id AND community.fid = 80
    LEFT JOIN jos_sobipro_field_data AS municip ON municip.sid = o.id AND municip.fid = 81
    LEFT JOIN jos_sobipro_field_data AS county ON county.sid = o.id AND county.fid = 82
    LEFT JOIN jos_sobipro_field_data AS province ON province.sid = o.id AND province.fid = 83
    LEFT JOIN jos_sobipro_field_data AS country ON country.sid = o.id AND country.fid = 84
    LEFT JOIN jos_sobipro_field_data AS postal ON postal.sid = o.id AND postal.fid = 85
    LEFT JOIN jos_sobipro_field_data AS phone ON phone.sid = o.id AND phone.fid = 86
    LEFT JOIN jos_sobipro_field_data AS tollfree ON tollfree.sid = o.id AND tollfree.fid = 87
    LEFT JOIN jos_sobipro_field_data AS fax ON fax.sid = o.id AND fax.fid = 88
    LEFT JOIN jos_sobipro_field_data AS email ON email.sid = o.id AND email.fid = 89
    LEFT JOIN jos_sobipro_field_data AS web ON web.sid = o.id AND web.fid = 90
    LEFT JOIN jos_sobipro_field_data AS empTotal ON empTotal.sid = o.id AND empTotal.fid = 106
    WHERE o.approved = 1 AND o.oType = 'entry' AND name.fid = 36 AND name.baseData <> ''
    AND name.section = 54 AND r.pid IN (415,418,425,431,458) AND (municip.baseData = "Municipality Name")
    ORDER BY name.baseData ASC

Кажется, он работает прилично быстро, пока поиск municip.baseData не задействован, и в этом случае он проваливается даже при 15 записях в каталоге. Должен быть лучший способ создать этот код SQL, при этом возвращая все необходимые поля. Этот запрос вызывается через AJAX, и в итоге в каталоге будет более 2000 записей.

РЕДАКТИРОВАТЬ: Вот вывод EXPLAIN, как и требовалось:

    id  select_type     table   type    possible_keys   key     key_len     ref     rows    Extra
    1   SIMPLE  name    ref     PRIMARY     PRIMARY     8   const,const     15  Using where; Using temporary; Using filesort
    1   SIMPLE  municip     ref     PRIMARY     PRIMARY     4   const   9   Using where
    1   SIMPLE  o   eq_ref  PRIMARY,oType   PRIMARY     4   [[dbname]].municip.sid  1   Using where
    1   SIMPLE  county  ref     PRIMARY     PRIMARY     4   const   10  
    1   SIMPLE  province    ref     PRIMARY     PRIMARY     4   const   10  
    1   SIMPLE  country     ref     PRIMARY     PRIMARY     4   const   8   
    1   SIMPLE  postal  ref     PRIMARY     PRIMARY     4   const   9   
    1   SIMPLE  business    ref     PRIMARY     PRIMARY     4   const   15  
    1   SIMPLE  contact_fn  ref     PRIMARY     PRIMARY     4   const   9   
    1   SIMPLE  contact_ln  ref     PRIMARY     PRIMARY     4   const   9   
    1   SIMPLE  position    ref     PRIMARY     PRIMARY     4   const   9   
    1   SIMPLE  civic1  ref     PRIMARY     PRIMARY     4   const   10  
    1   SIMPLE  civic2  ref     PRIMARY     PRIMARY     4   const   9   
    1   SIMPLE  phone   ref     PRIMARY     PRIMARY     4   const   10  
    1   SIMPLE  tollfree    ref     PRIMARY     PRIMARY     4   const   9   
    1   SIMPLE  fax     ref     PRIMARY     PRIMARY     4   const   10  
    1   SIMPLE  email   ref     PRIMARY     PRIMARY     4   const   9   
    1   SIMPLE  mailing     ref     PRIMARY     PRIMARY     4   const   11  
    1   SIMPLE  community   ref     PRIMARY     PRIMARY     4   const   9   
    1   SIMPLE  web     ref     PRIMARY     PRIMARY     4   const   10  
    1   SIMPLE  empTotal    ref     PRIMARY     PRIMARY     4   const   10  
    1   SIMPLE  r   ref     PRIMARY     PRIMARY     4   [[dbname]].name.sid     3   Using where; Using index; Distinct

1 Ответ

1 голос
/ 31 марта 2012

Много раз, когда у вас слишком расширенный JOIN / JOIN / JOIN / и т. Д., Движок SQL зависнет сам, пытаясь найти небольшие наборы результатов и менее эффективно обработать обратную связь.Ваш запрос выглядит хорошо.

Ваша ПЕРВИЧНАЯ таблица (ОТ jos_sobipro_object AS o) действительно является ключевым элементом KEY для запроса.Попробуйте добавить специальное ключевое слово "STRAIGHT_JOIN" с MySQL ..

SELECT STRAIGHT_JOIN DISTINCT ... остаток запроса ...

STRAIGHT_JOIN говорит оптимизатору просто выполнить запрос в том порядке, в котором яПеречислим здесь.Тогда он будет работать быстрее, Зная, что первая таблица является основной для запроса данных.

Тем не менее, и не совсем просматривая информацию об индексе, я бы СПЕЦИАЛЬНО имел индекс для jos_sobipro_field_data, чтобы ПОЛУЧИТЬ данные "поиска" по (СИД, ФИД).

Мне пришлось сделать аналогичный подход с данными правительства о 14+ миллионах записей в основной таблице и соединении с 22+ таблицами поиска.MySQL зависнет через 30+ часов.При добавлении STRAIGHT_JOIN запрос завершился примерно через 3 часа (как и ожидалось в зависимости от того, что он делал).

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