PostgreSQL
 sql >> база данни >  >> RDS >> PostgreSQL

Оптимизиране на множество присъединявания

Винаги има 2 неща, които трябва да имате предвид, когато оптимизирате заявките:

  • Какви индекси могат да се използват (може да се наложи да създадете индекси)
  • Как е написана заявката (може да се наложи да промените заявката, за да позволите на оптимизатора на заявки да може да намира подходящи индекси и да не препрочита данните излишно)

Няколко наблюдения:

  • Вие извършвате манипулации с дати, преди да се присъедините към вашите дати. Като общо правило това ще попречи на оптимизатора на заявки да използва индекс, дори ако той съществува. Трябва да опитате да напишете вашите изрази по такъв начин, че индексираните колони да съществуват непроменени от едната страна на израза.

  • Вашите подзаявки се филтрират към същия период от време като generate_series . Това е дублиране и ограничава способността на оптимизатора да избере най-ефективната оптимизация. Подозирам, че това може да е записано, за да се подобри производителността, защото оптимизаторът не успя да използва индекс в колоната с дата (body_time )?

  • ЗАБЕЛЕЖКА :Всъщност много бихме искали да използваме индекс на Body.body_time

  • ORDER BY в рамките на подзаявките е в най-добрия случай излишен. В най-лошия случай може да принуди оптимизатора на заявки да сортира набора от резултати, преди да се присъедини; и това не е непременно добро за плана на заявката. По-скоро прилагайте подреждане само в края за окончателно показване.

  • Използване на LEFT JOIN във вашите подзаявки е неподходящо. Ако приемем, че използвате ANSI конвенции за NULL поведение (и трябва да бъдете), всяко външно се присъединява към envelope ще върне envelope_command=NULL и те следователно биха били изключени от условието envelope_command=? .

  • Подзаявки o и i са почти идентични освен за envelope_command стойност. Това принуждава оптимизатора да сканира едни и същи базови таблици два пъти. Можете да използвате осева таблица техника за присъединяване към данните веднъж и разделяне на стойностите в 2 колони.

Опитайте следното, което използва техниката на завъртане:

SELECT  p.period,
        /*The pivot technique in action...*/
        SUM(
        CASE WHEN envelope_command = 1 THEN body_size
        ELSE 0
        END) AS Outbound,
        SUM(
        CASE WHEN envelope_command = 2 THEN body_size
        ELSE 0
        END) AS Inbound
FROM    (
        SELECT  date '2009-10-01' + s.day AS period
        FROM    generate_series(0, date '2009-10-31' - date '2009-10-01') AS s(day)
        ) AS p 
        /*The left JOIN is justified to ensure ALL generated dates are returned
          Also: it joins to a subquery, else the JOIN to envelope _could_ exclude some generated dates*/
        LEFT OUTER JOIN (
        SELECT  b.body_size,
                b.body_time,
                e.envelope_command
        FROM    body AS b 
                INNER JOIN envelope e 
                  ON e.message_id = b.message_id 
        WHERE   envelope_command IN (1, 2)
        ) d
          /*The expressions below allow the optimser to use an index on body_time if 
            the statistics indicate it would be beneficial*/
          ON d.body_time >= p.period
         AND d.body_time < p.period + INTERVAL '1 DAY'
GROUP BY p.Period
ORDER BY p.Period

РЕДАКТИРАНЕ :Добавен филтър, предложен от Том Х.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. psql грешка за възстановяване на pgsl архив на cmd

  2. Има ли инструмент за визуализация на данни за postgresql, който може да показва и връзки между схемите?

  3. Hibernate и Postgresql - клас генератор във файл за картографиране на хибернация

  4. Подреждане на резултатите от заявката по числови низове в django (backend на postgres)

  5. как да конвертирам текст в jsonB