优化Postgres查询

时间:2016-07-02 05:17:39

标签: sql postgresql query-performance

我有以下查询

            SELECT
                ca.sfid,
                CASE WHEN p.Name IS NOT NULL THEN p.Name ELSE '' END AS Property,
                CASE WHEN uc.Name IS NOT NULL THEN uc.Name ELSE '' END AS UnitofInterest,
                CASE WHEN fp.Name IS NOT NULL THEN fp.Name ELSE '' END AS FloorplanofInterest,
                CASE WHEN ca.Status IS NOT NULL THEN ca.Status ELSE '' END AS Status,
                CASE WHEN ca.Origin IS NOT NULL THEN ca.Origin ELSE '' END AS Origin,
                CASE 
                    WHEN ca.IC_Call_Answered_by_AH__c = 'true' THEN 'Anyone Home'
                    ELSE 'Property'   
                END AS AnswerBy,
                CASE WHEN ca.CaseNumber IS NOT NULL THEN ca.CaseNumber ELSE '' END AS CaseNumber,
                CASE WHEN ca.Ad_Source_Type__c IS NOT NULL THEN ca.Ad_Source_Type__c ELSE '' END AS Source,
                CONCAT(c.FirstName,' ',c.LastName) AS contactname,
                CASE WHEN (c.Phone IS NOT NULL OR c.Phone != '' ) THEN c.Phone ELSE '' END AS Phone,
                CASE WHEN c.MobilePhone IS NOT NULL THEN c.MobilePhone ELSE '' END AS Mobile,
                CASE WHEN c.Email IS NOT NULL THEN c.Email ELSE '' END AS Email,
                CASE WHEN c.most_recent_military_pay_grade__c IS NOT NULL THEN c.most_recent_military_pay_grade__c ELSE '' END AS MilitaryPayGrade,

                CASE WHEN ca.Price_Quoted_1__c IS NOT NULL THEN ca.Price_Quoted_1__c ELSE '' END AS "price/termquoted",
                CASE WHEN ca.Move_in_Date__c IS NOT NULL THEN to_char(ca.Move_in_Date__c AT TIME ZONE 'US/Pacific', 'MM/DD/YYYY') ELSE '' END AS MoveinDate,
                CASE WHEN ca.Of_Occupants__c::varchar IS NOT NULL THEN ca.Of_Occupants__c::varchar ELSE '' END AS "#occupants",
                CASE WHEN ca.Bed_Count_Pref__c IS NOT NULL THEN ca.Bed_Count_Pref__c ELSE '' END AS BedCountPref,
                CASE WHEN ca.Bath_Count_Pref__c IS NOT NULL THEN ca.Bath_Count_Pref__c ELSE '' END AS BathCountPref,
                CASE WHEN ca.Pet_Count__c::varchar IS NOT NULL THEN ca.Pet_Count__c::varchar ELSE '' END AS "#pets",
                CASE WHEN ca.Pet_Type__c IS NOT NULL THEN ca.Pet_Type__c ELSE '' END AS PetTypes,
                CASE WHEN ca.Breed__c IS NOT NULL THEN ca.Breed__c ELSE '' END AS Breed,
                CASE WHEN ca.Pet_Name__c IS NOT NULL THEN ca.Pet_Name__c ELSE '' END AS PetName,
                CASE 
                    WHEN (ca.Desired_Rent_Start__c IS NOT NULL AND ca.Desired_Rent_Range_End__c IS NOT NULL) THEN CONCAT(ca.Desired_Rent_Start__c,' - ',ca.Desired_Rent_Range_End__c)
                    ELSE '' 
                END AS DesiredRentRange,
                CASE WHEN ca.Desired_Lease_length__c::varchar IS NOT NULL THEN ca.Desired_Lease_length__c::varchar ELSE '' END AS DesiredLeaseLength,
                CASE WHEN ca.Reason_for_Moving__c IS NOT NULL THEN ca.Reason_for_Moving__c ELSE '' END AS ReasonforMoving,
                CASE WHEN ca.Notes__c IS NOT NULL THEN ca.Notes__c ELSE '' END AS Notes,
                CASE WHEN ca.Reasons_For_Not_Setting_a_Showing__c IS NOT NULL THEN ca.Reasons_For_Not_Setting_a_Showing__c ELSE '' END AS ReasonforNotSettingShowing,
                CASE WHEN ca.CreatedDate IS NOT NULL THEN to_char(ca.CreatedDate AT TIME ZONE 'US/Pacific', 'MM/DD/YYYY HH:MI AM') ELSE '' END AS "date/timeopened",
                CASE 
                    WHEN app.appointment_date__c IS NOT NULL THEN  CONCAT(to_char(app.appointment_date__c AT TIME ZONE 'US/Pacific', 'MM/DD/YYYY'),' ',app.from__c,'-',app.to__c)  
                    ELSE '' 
                END AS "appointmentdate/time",
                CASE WHEN ca.Yardi_Guest_Card_ID__c IS NOT NULL THEN ca.Yardi_Guest_Card_ID__c ELSE '' END AS PMSGuestCardID,
                rank() OVER (PARTITION BY ca.contactid, ca.property_of_interest__c ORDER BY ca.createddate DESC)
            FROM
                salesforce.Case ca
                INNER JOIN salesforce.Contact c on ca.ContactId = c.sfid AND c.accountId = ca.accountId
                LEFT JOIN salesforce.Appointment__c app ON ca.sfid = app.case__c
                LEFT JOIN salesforce.Property__c p ON p.sfid = ca.Property_of_Interest__c AND p.account__c = ca.accountId
                LEFT JOIN salesforce.Floor_Plan__c fp ON ca.Floor_Plan_of_Interest__c = fp.sfid AND fp.account__c = ca.accountId
                LEFT JOIN salesforce.Unit__c uc ON ca.Unit_of_Interest__c = uc.sfid AND uc.account__c = ca.accountId

            WHERE
        ca.Guest_Card_Status__c = 'Sent via Workflow'
        AND ca.accountId = '001i000000ESO3CAAX' 
        AND to_char(to_char(ca.createddate AT TIME ZONE 'UTC' AT TIME ZONE 'US/Pacific','YYYY-MM-DD HH24:MI:SS')::date, 'YYYY-MM-DD') BETWEEN  '2016-06-02' AND '2016-07-02' 
        AND to_char(c.Last_Activity__c AT TIME ZONE 'US/Pacific', 'YYYY-MM-DD') BETWEEN  '2016-03-04' AND '2016-07-02' 
        AND ( ca.Status IN ( 'Inquiry', 'Showing Set', 'Showing Completed', 'Application Pending', 'Resident' )  )  
        AND ( ca.IC_Call_Answered_by_AH__c IN ( 'false', 'true' ) )  
        AND ( ca.origin IN ( 'Phone', 'Email', 'Voicemail', 'Chat', 'Walk-In', 'Web' )  OR ca.origin IS NULL OR ca.origin = ''  ) LIMIT 20 OFFSET 0

以下是它的查询计划

Query Plan

我们在以下列上有索引:

  • ACCOUNTID
  • createddate
  • 状态
  • 来源

使用PostgreSQL。

但查询需要很长时间才能运行。你能建议任何优化吗?

由于

1 个答案:

答案 0 :(得分:3)

在不了解您的数据集且无法阅读查询计划的屏幕截图的情况下,我发现您可以进行一些简单的改进。

首先,您对索引列package com.example.dell.viewpagerlifecycle; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentStatePagerAdapter; /** * Created by dell on 2/7/16. */ public class MyAdapter extends FragmentStatePagerAdapter { public MyAdapter(FragmentManager fm) { super(fm); } @Override public Fragment getItem(int position) { return new FragmentItem().newInstance(position+""); } @Override public int getCount() { return 200; } } accountIdstatus列的使用很好。但是,您对origin列的使用存在缺陷。通过将列转换为字符串,然后在将其转换为字符串后执行比较,您将不再使用索引 - Postgres必须执行完整扫描并运行两次代价高昂的createddate转换。

to_char列进行限定,并对该列的数据类型进行原始比较。

例如,如果createddate的数据类型为createdate,那么您可以像这样符合条件:

timestamp

这将使用索引,它会表现得更好。

第二次,请确保您已创建一个索引,该 使用您列出的所有四个列。如果您为每个列创建了四个单独的索引,那么您没有意识到索引可能带来的全部性能提升。使用所有四列的索引将允许Postgres逐步缩小每列的结果集。如果您有四个单独的索引,那么Postgres只能使用一列缩小结果集。