2010-06-08 6 views
0

О системе:Mysql - помочь мне оптимизировать этот запрос

-Система имеет в общей сложности 8 таблиц - Пользователи - Tutor_Details (тьюторы тип пользователя, Tutor_Details таблица связана с пользователями) - learning_packs, (магазины пакеты, созданные наставники) - learning_packs_tag_relations (имеет тег отношение предназначены для поиска) - tutors_tag_relations и теги и заказов (содержащей информацию о покупке пачек воспитателя), order_details, связанный с заказами и tutor_details.

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

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

Ниже приводится простое представление (не фактическая) более сложного запроса, который я пытаюсь оптимизировать: - я использовал такие заявления explanation of parts в запросе

======== ================================================== ==================

select 

SUM(DISTINCT(t.tag LIKE "%Dictatorship%")) as key_1_total_matches, 
SUM(DISTINCT(t.tag LIKE "%democracy%")) as key_2_total_matches, 
td.*, u.*, count(distinct(od.id_od)), `if (lp.id_lp > 0) then some conditional logic on lp fields else 0 as tutor_popularity` 

from Tutor_Details AS td JOIN Users as u on u.id_user = td.id_user 

LEFT JOIN Learning_Packs_Tag_Relations AS lptagrels ON td.id_tutor = lptagrels.id_tutor 
LEFT JOIN Learning_Packs AS lp ON lptagrels.id_lp = lp.id_lp 
LEFT JOIN `some other tables on lp.id_lp - let's call learning pack tables set (including 

Learning_Packs table)` 

LEFT JOIN Order_Details as od on td.id_tutor = od.id_author LEFT JOIN Orders as o on 

od.id_order = o.id_order 

LEFT JOIN Tutors_Tag_Relations as ttagrels ON td.id_tutor = ttagrels.id_tutor 

JOIN Tags as t on (t.id_tag = ttagrels.id_tag) OR (t.id_tag = lptagrels.id_tag) 

where `some condition on Users table's fields` 

AND CASE WHEN ((t.id_tag = lptagrels.id_tag) AND (lp.id_lp > 0)) THEN `some 

conditions on learning pack tables set` ELSE 1 END 

AND CASE WHEN ((t.id_tag = wtagrels.id_tag) AND (wc.id_wc > 0)) THEN `some 

conditions on webclasses tables set` ELSE 1 END 

AND CASE WHEN (od.id_od>0) THEN od.id_author = td.id_tutor and `some conditions on Orders table's fields` ELSE 1 END 

AND (t.tag LIKE "%Dictatorship%" OR t.tag LIKE "%democracy%") 

group by td.id_tutor HAVING key_1_total_matches = 1 AND key_2_total_matches = 1 
order by tutor_popularity desc, u.surname asc, u.name asc limit 
0,20 

========================= ===================================================

Что делает вышеуказанный запрос?

  • И ИА логический поиск по ключевым словам для поиска (2 в этом примере - «Демократия» и «Диктатура»).
  • Возвращает только тех преподавателей, для которых оба ключевых слова присутствуют в объединении двух наборов - репетиторы деталей и деталей всех пакетов, созданных репетитором.

Чтобы сделать вещи ясно - Пусть имя Tutor "Sandeepan Нат" создал пакет "Мой первый пакет", затем: -

  • Поиск "Sandeepan Нат" возвращает Sandeepan Натхо.
  • Поиск «Сандипан первым» возвращает Сандипан Нат.
  • Поиск «Sandeepan second» не возвращает Sandeepan Nath.

====================================================================================================================================================================================== ===================================================

Проблема

Результаты, полученные вышеуказанным запросом, верны (и логика работает в соответствии с ожиданием), но время, затрачиваемое на запрос на сильно загружаемые базы данных, равно 25 секундам в сравнении с обычными таймингами запросов порядка 0,005-0,0002 секунды , что делает его совершенно непригодным для использования.

Вполне возможно, что некоторые задержки были вызваны, потому что все возможные поля еще не были проиндексированы, но я был бы признателен за лучший запрос в качестве решения, оптимизированные в максимально возможной степени, показывая те же результаты

==================================================================================================== =================================================

Как работают теги эта система?

  • Когда Репетитор регистры, метки вводятся и теги отношения создаются в отношении деталей тьютора, как имя, фамилия и т.д.
  • Когда репетиторы создать пакеты, снова теги вводятся и теги отношения создаются с в отношении сведений о пакете, таких как название упаковки, описание и т. д.
  • отношения тегов для преподавателей, хранящихся в tutors_tag_relations, и те, которые хранятся в файлах learning_packs_tag_relations. Все отдельные теги хранятся в таблице тегов.

====================================================================================================================================================================================== ========================

таблицы

Большинство из следующих таблиц содержат много других полей, которые я опущенные здесь ,

CREATE TABLE IF NOT EXISTS `users` (
    `id_user` int(10) unsigned NOT NULL AUTO_INCREMENT, 
    `name` varchar(100) NOT NULL DEFAULT '', 
    `surname` varchar(155) NOT NULL DEFAULT '', 
    PRIMARY KEY (`id_user`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=636 ; 

CREATE TABLE IF NOT EXISTS `tutor_details` (
    `id_tutor` int(10) NOT NULL AUTO_INCREMENT, 
    `id_user` int(10) NOT NULL DEFAULT '0', 
    PRIMARY KEY (`id_tutor`), 
    KEY `Users_FKIndex1` (`id_user`) 
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=51 ; 



CREATE TABLE IF NOT EXISTS `orders` (
    `id_order` int(10) unsigned NOT NULL AUTO_INCREMENT, 
    PRIMARY KEY (`id_order`), 
    KEY `Orders_FKIndex1` (`id_user`), 
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=275 ; 

ALTER TABLE `orders` 
    ADD CONSTRAINT `Orders_ibfk_1` FOREIGN KEY (`id_user`) REFERENCES `users` 

(`id_user`) ON DELETE NO ACTION ON UPDATE NO ACTION; 



CREATE TABLE IF NOT EXISTS `order_details` (
    `id_od` int(10) unsigned NOT NULL AUTO_INCREMENT, 
    `id_order` int(10) unsigned NOT NULL DEFAULT '0', 
    `id_author` int(10) NOT NULL DEFAULT '0', 
    PRIMARY KEY (`id_od`), 
    KEY `Order_Details_FKIndex1` (`id_order`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=284 ; 

ALTER TABLE `order_details` 
    ADD CONSTRAINT `Order_Details_ibfk_1` FOREIGN KEY (`id_order`) REFERENCES `orders` 

(`id_order`) ON DELETE NO ACTION ON UPDATE NO ACTION; 



CREATE TABLE IF NOT EXISTS `learning_packs` (
    `id_lp` int(10) unsigned NOT NULL AUTO_INCREMENT, 
    `id_author` int(10) unsigned NOT NULL DEFAULT '0', 
    PRIMARY KEY (`id_lp`), 
    KEY `Learning_Packs_FKIndex2` (`id_author`), 
    KEY `id_lp` (`id_lp`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=23 ; 


CREATE TABLE IF NOT EXISTS `tags` (
    `id_tag` int(10) unsigned NOT NULL AUTO_INCREMENT, 
    `tag` varchar(255) DEFAULT NULL, 
    PRIMARY KEY (`id_tag`), 
    UNIQUE KEY `tag` (`tag`), 
    KEY `id_tag` (`id_tag`), 
    KEY `tag_2` (`tag`), 
    KEY `tag_3` (`tag`) 
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=3419 ; 



CREATE TABLE IF NOT EXISTS `tutors_tag_relations` (
    `id_tag` int(10) unsigned NOT NULL DEFAULT '0', 
    `id_tutor` int(10) DEFAULT NULL, 
    KEY `Tutors_Tag_Relations` (`id_tag`), 
    KEY `id_tutor` (`id_tutor`), 
    KEY `id_tag` (`id_tag`) 
) ENGINE=InnoDB DEFAULT CHARSET=latin1; 

ALTER TABLE `tutors_tag_relations` 
    ADD CONSTRAINT `Tutors_Tag_Relations_ibfk_1` FOREIGN KEY (`id_tag`) REFERENCES 

`tags` (`id_tag`) ON DELETE NO ACTION ON UPDATE NO ACTION; 


CREATE TABLE IF NOT EXISTS `learning_packs_tag_relations` (
    `id_tag` int(10) unsigned NOT NULL DEFAULT '0', 
    `id_tutor` int(10) DEFAULT NULL, 
    `id_lp` int(10) unsigned DEFAULT NULL, 
    KEY `Learning_Packs_Tag_Relations_FKIndex1` (`id_tag`), 
    KEY `id_lp` (`id_lp`), 
    KEY `id_tag` (`id_tag`) 
) ENGINE=InnoDB DEFAULT CHARSET=latin1; 

ALTER TABLE `learning_packs_tag_relations` 
    ADD CONSTRAINT `Learning_Packs_Tag_Relations_ibfk_1` FOREIGN KEY (`id_tag`) 

REFERENCES `tags` (`id_tag`) ON DELETE NO ACTION ON UPDATE NO ACTION; 

=========================================== =================================================

Ниже приводится точный запрос (это включает в себя классы также - преподаватели могут создавать классы и условие поиска совпадает с классами, созданных преподавателями): -

SELECT SUM(DISTINCT(t.tag LIKE "%Dictatorship%")) AS key_1_total_matches, 
     SUM(DISTINCT(t.tag LIKE "%democracy%")) AS key_2_total_matches, 
     COUNT(DISTINCT(od.id_od))     AS tutor_popularity, 
     CASE 
     WHEN (IF((wc.id_wc > 0), (wc.wc_api_status = 1 
             AND wc.wc_type = 0 
             AND wc.class_date > '2010-06-01 22:00:56' 
             AND wccp.status = 1 
             AND (wccp.country_code = 'IE' 
               OR wccp.country_code IN ('INT') 
              )), 0) 
      ) THEN 1 
     ELSE 0 
     END           AS 'classes_published', 
     CASE 
     WHEN (IF((lp.id_lp > 0), (lp.id_status = 1 
             AND lp.published = 1 
             AND lpcp.status = 1 
             AND (lpcp.country_code = 'IE' 
               OR lpcp.country_code IN ('INT') 
              )), 0) 
      ) THEN 1 
     ELSE 0 
     END           AS 'packs_published', 
     td . *, 
     u . * 
FROM tutor_details AS td 
     JOIN users AS u 
     ON u.id_user = td.id_user 
     LEFT JOIN learning_packs_tag_relations AS lptagrels 
     ON td.id_tutor = lptagrels.id_tutor 
     LEFT JOIN learning_packs AS lp 
     ON lptagrels.id_lp = lp.id_lp 
     LEFT JOIN learning_packs_categories AS lpc 
     ON lpc.id_lp_cat = lp.id_lp_cat 
     LEFT JOIN learning_packs_categories AS lpcp 
     ON lpcp.id_lp_cat = lpc.id_parent 
     LEFT JOIN learning_pack_content AS lpct 
     ON (lp.id_lp = lpct.id_lp) 
     LEFT JOIN webclasses_tag_relations AS wtagrels 
     ON td.id_tutor = wtagrels.id_tutor 
     LEFT JOIN webclasses AS wc 
     ON wtagrels.id_wc = wc.id_wc 
     LEFT JOIN learning_packs_categories AS wcc 
     ON wcc.id_lp_cat = wc.id_wp_cat 
     LEFT JOIN learning_packs_categories AS wccp 
     ON wccp.id_lp_cat = wcc.id_parent 
     LEFT JOIN order_details AS od 
     ON td.id_tutor = od.id_author 
     LEFT JOIN orders AS o 
     ON od.id_order = o.id_order 
     LEFT JOIN tutors_tag_relations AS ttagrels 
     ON td.id_tutor = ttagrels.id_tutor 
     JOIN tags AS t 
     ON (t.id_tag = ttagrels.id_tag) 
      OR (t.id_tag = lptagrels.id_tag) 
      OR (t.id_tag = wtagrels.id_tag) 
WHERE (u.country = 'IE' 
      OR u.country IN ('INT')) 
     AND CASE 
      WHEN ((t.id_tag = lptagrels.id_tag) 
        AND (lp.id_lp > 0)) THEN lp.id_status = 1 
               AND lp.published = 1 
               AND lpcp.status = 1 
               AND (lpcp.country_code = 'IE' 
                 OR lpcp.country_code IN (
                  'INT' 
                 )) 
      ELSE 1 
      END 
     AND CASE 
      WHEN ((t.id_tag = wtagrels.id_tag) 
        AND (wc.id_wc > 0)) THEN wc.wc_api_status = 1 
               AND wc.wc_type = 0 
               AND 
      wc.class_date > '2010-06-01 22:00:56' 
               AND wccp.status = 1 
               AND (wccp.country_code = 'IE' 
                 OR wccp.country_code IN (
                  'INT' 
                 )) 
      ELSE 1 
      END 
     AND CASE 
      WHEN (od.id_od > 0) THEN od.id_author = td.id_tutor 
             AND o.order_status = 'paid' 
             AND CASE 
      WHEN (od.id_wc > 0) THEN od.can_attend_class = 1 
      ELSE 1 
              END 
      ELSE 1 
      END 
GROUP BY td.id_tutor 
HAVING key_1_total_matches = 1 
     AND key_2_total_matches = 1 
ORDER BY tutor_popularity DESC, 
      u.surname ASC, 
      u.name ASC 
LIMIT 0, 20 

Обратите внимание - Предоставленная структура базы данных не показывает все поля и таблицы, как в запросе

============================================================================================================ ========================================================

Выход запроса пояснения: - Пожалуйста, смотрите этот скриншот http://www.test.examvillage.com/Explain_query.jpg

ответ

0

Отвечая на мой вопрос.

Основная проблема с этим подходом заключалась в том, что слишком много таблиц были объединены в один запрос. Некоторые из этих таблиц, таких как Tags (с большим количеством записей, которые могут в будущем удерживать столько же, сколько все английские слова в словаре) при соединении с таким количеством таблиц, вызывают эффект умножения, который никоим образом не может быть противопоставлен.

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

Постараюсь более подробно объяснить это позже.

0

информацию по пунктам строки, распределение значений, индексы, размер базы данных, размер памяти, дисковый макет - рейд 0, 5, и т.д. - сколько пользователей поражающих баз данных, когда запросы slow - какие другие запросы выполняются. Все это влияет на производительность.

Также распечатка вывода плана объяснения может пролить свет на причину, если это просто проблема запроса/индекса. Точный запрос также потребуется.

+0

Hello Khorkrak Спасибо, что ответили на мой длинный вопрос. Пожалуйста, проверьте полный запрос в конце моего вопроса. –

0
  1. Вы действительно должны использовать некоторое лучшее форматирование для запроса. Просто добавьте по крайней мере 4 пробела в начало каждой строки, чтобы получить это красивое форматирование кода.

    SELECT * FROM sometable 
        INNER JOIN anothertable ON sometable.id = anothertable.sometable_id 
    

    Или посмотреть здесь: https://stackoverflow.com/editing-help

  2. могли бы вы предоставить план выполнения от MySQL? Вам нужно добавить «EXPLAIN» в запрос и скопировать результат.

    EXPLAIN SELECT * FROM ...complexquery... 
    

    даст вам несколько полезных советов (порядок выполнения, возвращаются строки, доступные/используемые индексы)

+0

Привет, SchlaWiener, Я не мог отступывать запросы, но теперь их можно разделить на отдельные блоки. Кроме того, я копировал и вставлял вывод запроса объяснения в конце моего ответа. Извините, у меня даже нет красок ms в моей системе, чтобы сделать снимок. Почему в stackoverflow не разрешено вложение файлов, я не знаю. Пожалуйста, посмотрите, можете ли вы дать некоторую идею. Спасибо Sandeepan –

+0

посмотрите, можете ли вы ответить на мой новый вопрос http://stackoverflow.com/questions/3030022/mysql-help-me-alter-this-search-query-to-get-desired-results –

0

Ваш вопрос, «как я могу найти репетиторов, которые соответствуют определенным теги?» Это не сложный вопрос, поэтому запрос на него тоже не должен быть трудным.

Что-то вроде:

SELECT * 
FROM tutors 
WHERE tags LIKE '%Dictator%' AND tags LIKE '%Democracy%' 

Это будет работать, если вы изменить дизайн, чтобы иметь поле «метки» в вашем «тьюторов» таблицы, в которой вы положили все теги, которые относятся к этому воспитателя. Он устранит слои соединений и таблиц.

Все ли эти слои объединений и таблиц обеспечивают реальную функциональность или просто больше головных болей программирования? Подумайте о функциональных возможностях, которые необходимы вашему приложению, а затем упростите дизайн своей базы данных!

Смежные вопросы