Слишком длинный подзапрос на сервере PostgreSQL

#sql #postgresql

#sql #postgresql

Вопрос:

У меня есть запрос, выполнение которого занимает много времени. Я не уверен, как мне уменьшить это. Не только время, этот запрос также требует от PSQL высокой загрузки процессора.

Я должен выбрать один столбец sip_username в качестве разных имен в разных условиях. Из-за этого требования у меня есть подзапросы create,

Запрос является :

 SELECT   sip_username,
         product_code,
         display_name as dname,
         user_id as uid,
         location_id,
         tenant_id,
         (
           SELECT sip_username
           FROM   admin_users_product
           WHERE  (sip_username = A.sip_username)  AND    
                  (product_code = 'bizfms')
         ) AS bizfms_username,
         (
           SELECT sip_username
           FROM admin_users_product
           WHERE (sip_username = A.sip_username) AND
                 (product_code = 'mlc')
                 ) AS mlc_username,
         (
           SELECT sip_username
           FROM admin_users_product
           WHERE (sip_username = A.sip_username) AND
                 (product_code = 'bizrtm')
         ) AS bizrtm_username
FROM     admin_users_product AS A
WHERE    A.location_id = 18
  

Что я должен изменить, чтобы сделать это быстрее?

Комментарии:

1. Пожалуйста, удалите тег: sql-server .

2. Пожалуйста, выполните запрос с префиксом EXPLAIN (ANALYZE, BUFFERS) и добавьте выходные данные к вашему вопросу. Это поможет показать вам, как самостоятельно решать подобные проблемы в будущем.

3. Каков первичный ключ таблицы admin_users_product ? Будет ли условие a.location_id = 18 возвращать несколько строк с разными product_code и sip_username значениями?

4. Не могли бы вы опубликовать образцы данных и ожидаемый результат для них? Было бы гораздо легче помочь вам.

5. Ваши подзапросы не имеют смысла. Условие возврата строки заключается в том, sip_username = A.sip_username чтобы sip_username, возвращаемое для каждого подзапроса, было идентичным тому, в a.sip_username котором у вас уже есть. Итак, я не понимаю, чего вы пытаетесь достичь с помощью подзапросов. Похоже, вы можете легко просто удалить их

Ответ №1:

Вы можете попробовать этот код:

 SELECT sip_username,
   product_code,
   display_name as dname,
   user_id      as uid,
   location_id,
   tenant_id,
   (CASE product_code
        WHEN 'bizfms' THEN
            sip_username
        ELSE Null
       END)     AS bizfms_username,
   (CASE product_code
        WHEN 'mlc' THEN
            sip_username
        ELSE Null
       END)     AS mlc_username,
   (CASE product_code
        WHEN 'bizrtm' THEN
            sip_username
        ELSE Null
       END)     AS bizrtm_username
  FROM admin_users_product AS A
  WHERE A.location_id = 18
  

Ответ №2:

Вы должны создать индекс для некоторого столбца

  1. Создайте индекс в таблице admin_users_product по столбцам location_id и sip_username
  2. Создайте индекс в таблице admin_users_product по столбцам sip_username и product_code

и тогда ваш запрос выполняется быстрее…

Ответ №3:

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

 SELECT   sip_username,
         product_code,
         display_name as dname,
         user_id as uid,
         location_id,
         tenant_id,
         B.sip_username bizfms_username,
         C.sip_username mlc_username,
         D.sip_username bizrtm_username,
FROM      admin_users_product AS A
left join admin_users_product B
    on A.sip_username = B.sip_username and B.product_code = 'bizfms'
left join admin_users_product C
    on A.sip_username = C.sip_username and C.product_code = 'mlc'
left join admin_users_product D
    on A.sip_username = D.sip_username and D.product_code = 'bizrtm'
WHERE
    A.location_id = 18;