Oracle DB: Почему переписывание этого запроса немного ускоряет его? - PullRequest
0 голосов
/ 31 августа 2018

У меня был запрос, выполнение которого занимало ~ 90 секунд. После повторного написания запроса слегка запрос выполняется через 1,5 секунды. Можете ли вы объяснить, почему он работает быстрее?

Контекст

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

В качестве иллюстрации предположим, что мы говорим о новом списке потенциальных клиентов, и мы хотим объединить эти предложения с услугами, которые мы продаем, а также с владельцами этих услуг и их менеджерами. ,

Таблица

Есть 3 объекта, из которых мы вытаскиваем:

1) Таблица sales_leads - простая локальная таблица с одним индексом:

  • Он имеет внешний ключ 'asset_id', 'is_live' и другие.

  • index_id проиндексирован

  • имеет ~ 5 тыс. Строк

2) таблица 'services' - простая локальная таблица других вещей:

  • имеет первичный ключ 'asset_id', который проиндексирован (и несколько других столбцов)
  • имеет такие столбцы, как «доступность» и «статус»
  • Имеет значение для 'asset_owner' - внешнего ключа для
  • В этой таблице ~ 50 000 строк, большинство из которых этот запрос не возвращает

3) Представление vw_people_Data - упаковка представления Удаленная таблица:

  • vw_people_Data по сути просто (создать представление vw_people_Data как select * from our_people_table @ our_database_link)

  • эта таблица содержит как владельцев, так и менеджеров (и всех остальных)

  • В этой таблице ~ 80 000 строк, большинство из которых этот запрос не возвращает

Медленный запрос

Этот запрос возвращает 557 строк за ~ 90 секунд:

    SELECT * 
    FROM sales_leads leads
    LEFT OUTER JOIN services srvc ON (leads.asset_id = srvc.asset_id)
    LEFT OUTER JOIN 
      (
        SELECT 
            c.emp_id,
            c.display_name,
            c.primary_email_address,
            c.functional_manager_emp_id,
        FROM vw_people_Data c
      )m1 ON (m1.emp_id = srvc.asset_owner)
    LEFT OUTER JOIN 
      (
        SELECT 
            c.emp_id, 
            c.primary_email_address 
        FROM vw_people_Data c
      )m2 ON m1.functional_manager_emp_id = m2.emp_id

    WHERE srvc.availability like 'A%'
    AND srvc.status = 'true'
    AND leads.is_live like 'Live'
    ;

Быстрый запрос:

Этот запрос возвращает 557 строк за 1,5 секунды:

    SELECT * 
    FROM sales_leads leads
    LEFT OUTER JOIN services srvc ON (leads.asset_id = srvc.asset_id)
    LEFT OUTER JOIN 
          (
            SELECT 
              m1.emp_id m1_emp_id,
              m1.display_name m1_display_name,
              m1.primary_email_address m1_email,
              m2.emp_id m2_emp_id,
              m2.primary_email_address m2_email
            FROM vw_people_Data m1
            LEFT OUTER JOIN 
              (
                    SELECT 
                      c.emp_id,
                      c.primary_email_address
                    FROM vw_people_Data c
              ) m2 ON (m1.functional_manager_emp_id = m2.emp_id)
          ) m1_m2 ON (srvc.asset_owner = m1_m2.m1_emp_id)

    WHERE srvc.availability like 'A%'
    AND srvc.status = 'true'
    AND leads.is_live like 'Live'
    ;

Вопрос:

Почему? Почему большое улучшение времени запроса от такого незначительного переписывания запроса? Что оптимизатор делает по-другому?

Я посмотрел планы выполнения, и они выглядят одинаково.

1 Ответ

0 голосов
/ 31 августа 2018

Советы по настройке без просмотра объяснительных планов для двух запросов - игра в кружку. Но давайте догадаемся.

Кажется, ключевой момент таков:

единственный вид - vw_people_Data, который определяется как
select *from tbl@our_db_link
................^

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

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

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