How to resolve Multiple lookup operation in execution plan for same index

  • In a Query Block, We are using a table (CustomerOpenOrder) multiple time to join with other tables. In Execution plan, Lookup operation for that table is showing multiple times , attaching the complete query code also. 
    1. Can someone please help me to remove this duplicate effort from my query and reduce the query timing.
    2. How can I convert lookup operation into seek with the help of object and predicates ?
    QUERY:

    EXECUTION PLAN:

    .[fn_GetLeaseChargeIDs]())),
                        PlannedShippedQuantity = (SELECT SUM(co.AmountFilled) FROM CustomerOpenOrder(NOLOCK) co
                                        WHERE CO.MaterialID = opn.MaterialID AND CO.SalesOrderHeaderID = S.SalesOrderHeaderID AND CO.ChargeID IN(SELECT ChargeID FROM [dbo].[fn_GetLeaseChargeIDs]())),
                        ShippedQuantity = (SELECT SUM(co.AmountFilled) FROM CustomerOpenOrder(NOLOCK) co
                                        WHERE CO.MaterialID = opn.MaterialID AND CO.SalesOrderHeaderID = S.SalesOrderHeaderID AND CO.ChargeID IN(SELECT ChargeID FROM [dbo].[fn_GetLeaseChargeIDs]())),
                        OrderDate = s.OrderDate,                    
                        FromOrganizationID =FL.OrganizationID,
                        ToOrganizationID =TL.OrganizationID,
                        ShipFromLocationID = FL.LocationID,
                        ShipFrom = FL.LocationDescription,
                        ShipToLocationID = TL.LocationID,
                        ShipTo = TL.LocationDescription,
                        SheduleShipDate =S.ScheduledShipDate,
                        ExpectedDelieryDate = S.RequestedDeliveryDate,
                        ShipmentNo = CAST(Shp.ShipmentNumber AS NVARCHAR(25))+'.'+CAST(SHP.ShipmentVersion AS NVARCHAR(25)),
                        MASInvoiceNumber = s.InvoiceNo,
                        EstDelDate =ISNULL(s.EstimatedDeliveryDate,DATEADD(DAY,flane.TravelTimeInDays,S.ScheduledShipDate)),
                        Shipmentid = s.ShipmentID ,
                        ShipmentStatusID = Shp.ShipmentStatusID ,
                        OrderTypeid = ST.SystemTypeID,
                        Carrier = BP.BusinessPartnerName,
                        PurchaseOrderNumber =s.PurchaseOrderNumber,
                        ActualDeliveryDate = MAX(Shp.ActualDeliveryDateTime), --+ CAST(ISNULL( Shp.FromCarrierInTime,0) AS TIME),
                        IsDiverted = s.IsDiverted,
                        ToBeDeleted = 0,
                        StatusSequence = 1,
                        OrderAmount= 0,
                        SourceSystem=ss.SourceSystemDescription
                        
                    FROM OM_SalesOrderHeader s (NOLOCK)
                 LEFT JOIN CustomerOpenOrder Opn (NOLOCK)                ON opn.SalesOrderHeaderID = s.SalesOrderHeaderID and opn.MaterialID IS NOT NULL AND (opn.ChargeID IS NULL OR opn.ChargeID in (1,40))
                         LEFT JOIN Material Mat    (NOLOCK)                        ON mat.MaterialID                    = opn.MaterialID
                         LEFT JOIN #ShipmentData Shp                            ON Shp.ShipmentID = s.ShipmentID AND shp.EntityID = 290
                         LEFT JOIN Location    FL    (NOLOCK)                        ON ISNULL(s.LocationID,0)          = ISNULL(FL.LocationID,0)                AND FL.IsDeleted = 0
                         LEFT JOIN Location    TL  (NOLOCK)                        ON s.ShipToLocationID                = TL.LocationID                            AND TL.IsDeleted = 0
                         LEFT JOIN SystemType         ST    (NOLOCK)            ON s.OrderTypeID                    = st.SystemTypeID                        AND st.IsDeleted = 0
                         LEFT JOIN SystemType             SC    (NOLOCK)        ON s.OrderConditionID                = SC.SystemTypeID                AND SC.IsDeleted = 0
                         LEFT JOIN freightlane    FLANE    (NOLOCK)   ON FLANE.FreightLaneID     = s.ActualFreightLaneID
                         LEFT JOIN BusinessPartner      BP        (NOLOCK)        ON BP.BusinessPartnerID                = IIF(S.ShipmentID is null,S.Carrier,FLANE.BusinessPartnerID)AND BP.IsDeleted = 0
                         LEFT JOIN om_salesorderstatus stu    (NOLOCK)       ON s.StatusCode                        = stu.StatusCode                AND stu.IsDeleted = 0
                         LEFT JOIN SourceSystem            ss    (NOLOCK)       ON s.SourceSystemID                        = ss.SourceSystemID                AND ss.IsDeleted = 0
                         LEFT JOIN UOM                  U    (NOLOCK)            ON opn.UOM                            = U.UOMID                        AND U.IsDeleted = 0    
                                            
                        
            WHERE         s.IsDeleted=0 AND        
                        --s.OrderNo LIKE '%'+@No+'%'
                        s.OrderNo = CASE WHEN @No = '' THEN s.OrderNo ELSE @No END
                        AND s.OrderVersionNumber                = CASE WHEN @OrderVersion IS NULL THEN s.OrderVersionNumber       ELSE @OrderVersion        END                                
                        --AND s.OrderTypeID                        = CASE WHEN @Type = '00000000-0000-0000-0000-000000000000' THEN s.OrderTypeID    ELSE @Type                END
                        AND (s.OrderTypeID in (select items from dbo.SplitString(@OrderType,',') ) or IsNull( @OrderType,'00000000-0000-0000-0000-000000000000') = '00000000-0000-0000-0000-000000000000')
                        AND (@SalesOrderHeaderID IS NULL OR (s.SalesOrderHeaderID IN(select items from dbo.SplitString(@SalesOrderHeaderID,','))))
                        --AND stu.StatusCode                        = CASE WHEN @status    = 0        THEN stu.StatusCode                ELSE @status            END
                        AND (stu.StatusCode in (select items from dbo.SplitString(@StatusID,',') ) or IsNull( @StatusID,'0') = '0')                                        
                        AND ((s.SalesOrderHeaderID in (select items from dbo.SplitString(@MASInvoiceNumberID,',') ) AND s.InvoiceNo IS NOT NULL) or IsNull( @MASInvoiceNumberID,'0') = '0')                    
                        --AND ISNULL(FL.LocationFunctionID,0)        = CASE WHEN @FromLocationType    = 0 THEN ISNULL(FL.LocationFunctionID,0)        ELSE @FromLocationType    END
                        AND (FL.LocationFunctionID in (select items from dbo.SplitString(@FromLocationTypeID,',') ) or IsNull( @FromLocationTypeID,'0') = '0')
                        --AND ISNULL(s.LocationID,0)              = CASE WHEN @FromLocationid        = 0 THEN ISNULL(s.LocationID,0)                    ELSE @FromLocationid    END
                        AND (s.LocationID in (select items from dbo.SplitString(@FromLocation,',') ) or IsNull( @FromLocation,'0') = '0')
                        --AND TL.LocationFunctionID           = CASE WHEN @ToLocationtype        = 0 THEN TL.LocationFunctionID                    ELSE @ToLocationtype    END
                        AND (TL.LocationFunctionID in (select items from dbo.SplitString(@ToLocationTypeID,',') ) or IsNull( @ToLocationTypeID,'0') = '0')
                        --AND s.ShipToLocationID                    = CASE WHEN @ToLocationid        = 0 THEN s.ShipToLocationID                        ELSE @ToLocationid        END
                        AND (s.ShipToLocationID in (select items from dbo.SplitString(@ToLocation,',') ) or IsNull( @ToLocation,'0') = '0')
                   --AND s.OrderConditionID         = CASE WHEN @ConditionID = '00000000-0000-0000-0000-000000000000' THEN s.OrderConditionID ELSE @ConditionID        END
                        AND (s.OrderConditionID in (select items from dbo.SplitString(@Condition,',') ) or IsNull( @Condition,'00000000-0000-0000-0000-000000000000') = '00000000-0000-0000-0000-000000000000')
                        AND CAST(s.OrderDate AS DATE) BETWEEN @OrderDatestart AND @OrderDateEnd
                        AND isnull(CAST(S.scheduledShipdate AS DATE) ,'01/01/1900') BETWEEN @ScheduleShipStartDate AND @ScheduleShipEndDate        
                        AND CAST(s.RequestedDeliveryDate AS DATE) BETWEEN @DeliveryDateStart AND @DeliveryDateEnd
                    
                        AND CASE WHEN @Version = 2 THEN
                           CASE WHEN s.OrderVersionNumber = (SELECT MAX(a.OrderVersionNumber) FROM OM_SalesOrderHeader a(NOLOCK) WHERE a.OrderNo = s.OrderNo ) THEN 1 ELSE 0 END
                          ELSE 1 END = 1
            GROUP by
                        s.SalesOrderHeaderID,
                        s.OrderNo,
                        s.OrderVersionNumber,
                        ST.SystemTypeDescription,
                        stu.Description,
                        ST.SystemTypeDescription,
                        FL.LocationID,
                        FL.LocationDescription,
                        s.OrderDate,                    
                        TL.LocationID,
                        TL.LocationDescription,
                        U.UOM,
                        Shp.ShipmentID ,
                        ST.SystemTypeID,
                        BP.BusinessPartnerName,
                        --Shp.ActualDeliveryDateTime,
                        opn.MaterialID,
                        mat.MaterialDesc,
                        S.ScheduledShipDate,
                        S.RequestedDeliveryDate,
                        shp.ShipmentNumber,
                        s.InvoiceNo,
                        FLANE.TravelTimeInDays,
                        Shp.FromCarrierInTime,
                        SHP.ShipmentVersion,
                        s.ShipmentID,
                        Shp.ShipmentStatusID ,
                        --opn.Amount,
                        S.StatusCode,
                        S.OrderConditionID,
                        SC.SystemTypeDescription,
                        s.IsDiverted,                    
                        FL.OrganizationID,
                        TL.OrganizationID,
                        s.PurchaseOrderNumber,
                        ss.SourceSystemDescription
                        ,s.EstimatedDeliveryDate
                        OPTION(RECOMPILE);"]

  • Can you post the actual execution plan please? 
    😎

    This is one horiffic query and my thought is that those lookups are the least of the problem. Few points:

    1. GROUP BY on 36 columns
    2. Functions on join columns
    3. 40+ statements in the WHERE claus with multiple OR conditions
    4. Several string splitting operations in the WHERE clause
    5. The code is lettered with NOLOCK

    The query code (formatted for readability)
    SELECT DISTINCT SalesOrderHeaderID = s.salesorderheaderid,
          StatusCode = S.statuscode,
          OrderVersionNumber = s.orderversionnumber,
          OrderConditionID = s.orderconditionid,
          OrderNo = s.orderno + '.'
             + Cast(s.orderversionnumber AS NVARCHAR(25)),
          Type = ST.systemtypedescription,
          Status = stu.description,
          OrderCondition = SC.systemtypedescription,
          opn.materialid,
          Material = mat.materialdesc,
          --Quantity = SUM(DISTINCT CASE WHEN opn.AmountFilled>0 or opn.AmountFilled<0 THEN opn.AmountFilled else opn.Amount END),
          --RemainingQuantity = SUM(DISTINCT CASE WHEN ISNULL(opn.Amount,0) = 0 THEN 0 ELSE (ISNULL(opn.Amount,0)-ISNULL(opn.AmountFilled,0)) END),
          OrderQuantity = (SELECT Sum(Isnull(co.amount, 0))
               FROM customeropenorder(nolock) co
               WHERE CO.materialid = opn.materialid
                  AND CO.salesorderheaderid =
                   S.salesorderheaderid
                  AND CO.chargeid IN
                   (SELECT chargeid
                   FROM
                  [dbo].[Fn_getleasechargeids]())),
          PlannedShippedQuantity =
          (SELECT Sum(co.amountfilled)
          FROM customeropenorder(nolock) co
          WHERE CO.materialid = opn.materialid
            AND CO.salesorderheaderid =
              S.salesorderheaderid
            AND CO.chargeid IN
          (SELECT chargeid
          FROM [dbo].[Fn_getleasechargeids]())),
          ShippedQuantity = (SELECT Sum(co.amountfilled)
                FROM customeropenorder(nolock) co
                WHERE CO.materialid = opn.materialid
                  AND CO.salesorderheaderid =
                    S.salesorderheaderid
                  AND CO.chargeid IN(SELECT chargeid
                         FROM
                    [dbo].[Fn_getleasechargeids]())),
          OrderDate = s.orderdate,
          FromOrganizationID =FL.organizationid,
          ToOrganizationID =TL.organizationid,
          ShipFromLocationID = FL.locationid,
          ShipFrom = FL.locationdescription,
          ShipToLocationID = TL.locationid,
          ShipTo = TL.locationdescription,
          SheduleShipDate =S.scheduledshipdate,
          ExpectedDelieryDate = S.requesteddeliverydate,
          ShipmentNo = Cast(Shp.shipmentnumber AS NVARCHAR(25))
              + '.'
              + Cast(SHP.shipmentversion AS NVARCHAR(25)),
          MASInvoiceNumber = s.invoiceno,
          EstDelDate =Isnull(s.estimateddeliverydate,
          Dateadd(day, flane.traveltimeindays, S.scheduledshipdate)),
          Shipmentid = s.shipmentid,
          ShipmentStatusID = Shp.shipmentstatusid,
          OrderTypeid = ST.systemtypeid,
          Carrier = BP.businesspartnername,
          PurchaseOrderNumber =s.purchaseordernumber,
          ActualDeliveryDate = Max(Shp.actualdeliverydatetime),
          --+ CAST(ISNULL( Shp.FromCarrierInTime,0) AS TIME),
          IsDiverted = s.isdiverted,
          ToBeDeleted = 0,
          StatusSequence = 1,
          OrderAmount= 0,
          SourceSystem=ss.sourcesystemdescription
    FROM om_salesorderheader s (nolock)
       LEFT JOIN customeropenorder Opn (nolock)
         ON opn.salesorderheaderid = s.salesorderheaderid
          AND opn.materialid IS NOT NULL
          AND ( opn.chargeid IS NULL
            OR opn.chargeid IN ( 1, 40 ) )
       LEFT JOIN material Mat (nolock)
         ON mat.materialid = opn.materialid
       LEFT JOIN #shipmentdata Shp
         ON Shp.shipmentid = s.shipmentid
          AND shp.entityid = 290
       LEFT JOIN location FL (nolock)
         ON Isnull(s.locationid, 0) = Isnull(FL.locationid, 0)
          AND FL.isdeleted = 0
       LEFT JOIN location TL (nolock)
         ON s.shiptolocationid = TL.locationid
          AND TL.isdeleted = 0
       LEFT JOIN systemtype ST (nolock)
         ON s.ordertypeid = st.systemtypeid
          AND st.isdeleted = 0
       LEFT JOIN systemtype SC (nolock)
         ON s.orderconditionid = SC.systemtypeid
          AND SC.isdeleted = 0
       LEFT JOIN freightlane FLANE (nolock)
         ON FLANE.freightlaneid = s.actualfreightlaneid
       LEFT JOIN businesspartner BP (nolock)
         ON BP.businesspartnerid =
             Iif(S.shipmentid IS
             NULL, S.carrier, FLANE.businesspartnerid)
          AND BP.isdeleted = 0
       LEFT JOIN om_salesorderstatus stu (nolock)
         ON s.statuscode = stu.statuscode
          AND stu.isdeleted = 0
       LEFT JOIN sourcesystem ss (nolock)
         ON s.sourcesystemid = ss.sourcesystemid
          AND ss.isdeleted = 0
       LEFT JOIN uom U (nolock)
         ON opn.uom = U.uomid
          AND U.isdeleted = 0
    WHERE s.isdeleted = 0
       AND
       --s.OrderNo LIKE '%'+@No+'%'
       s.orderno = CASE
           WHEN @No = '' THEN s.orderno
           ELSE @No
           END
       AND s.orderversionnumber = CASE
                WHEN @OrderVersion IS NULL THEN
                s.orderversionnumber
                ELSE @OrderVersion
                END
       --AND s.OrderTypeID = CASE WHEN @Type = '00000000-0000-0000-0000-000000000000' THEN s.OrderTypeID ELSE @Type END
       AND ( s.ordertypeid IN (SELECT items
               FROM dbo.Splitstring(@OrderType, ','))
         OR Isnull(@OrderType, '00000000-0000-0000-0000-000000000000') =
          '00000000-0000-0000-0000-000000000000' )
       AND ( @SalesOrderHeaderID IS NULL
         OR ( s.salesorderheaderid IN(SELECT items
                   FROM
          dbo.Splitstring(@SalesOrderHeaderID, ',')) ) )
       --AND stu.StatusCode = CASE WHEN @status = 0 THEN stu.StatusCode ELSE @status END
       AND ( stu.statuscode IN (SELECT items
               FROM dbo.Splitstring(@StatusID, ','))
         OR Isnull(@StatusID, '0') = '0' )
       AND ( ( s.salesorderheaderid IN (SELECT items
                  FROM
         dbo.Splitstring(@MASInvoiceNumberID, ','))
         AND s.invoiceno IS NOT NULL )
         OR Isnull(@MASInvoiceNumberID, '0') = '0' )
       --AND ISNULL(FL.LocationFunctionID,0) = CASE WHEN @FromLocationType = 0 THEN ISNULL(FL.LocationFunctionID,0) ELSE @FromLocationType END
       AND ( FL.locationfunctionid IN (SELECT items
                 FROM
         dbo.Splitstring(@FromLocationTypeID, ',')
                 )
         OR Isnull(@FromLocationTypeID, '0') = '0' )
       --AND ISNULL(s.LocationID,0) = CASE WHEN @FromLocationid = 0 THEN ISNULL(s.LocationID,0) ELSE @FromLocationid END
       AND ( s.locationid IN (SELECT items
              FROM dbo.Splitstring(@FromLocation, ','))
         OR Isnull(@FromLocation, '0') = '0' )
       --AND TL.LocationFunctionID = CASE WHEN @ToLocationtype = 0 THEN TL.LocationFunctionID ELSE @ToLocationtype END
       AND ( TL.locationfunctionid IN (SELECT items
                 FROM
         dbo.Splitstring(@ToLocationTypeID, ','))
         OR Isnull(@ToLocationTypeID, '0') = '0' )
       --AND s.ShipToLocationID = CASE WHEN @ToLocationid = 0 THEN s.ShipToLocationID ELSE @ToLocationid END
       AND ( s.shiptolocationid IN (SELECT items
                FROM dbo.Splitstring(@ToLocation, ','))
         OR Isnull(@ToLocation, '0') = '0' )
       --AND s.OrderConditionID = CASE WHEN @ConditionID = '00000000-0000-0000-0000-000000000000' THEN s.OrderConditionID ELSE @ConditionID END
       AND ( s.orderconditionid IN (SELECT items
                FROM dbo.Splitstring(@Condition, ','))
         OR Isnull(@Condition, '00000000-0000-0000-0000-000000000000') =
          '00000000-0000-0000-0000-000000000000' )
       AND Cast(s.orderdate AS DATE) BETWEEN @OrderDatestart AND @OrderDateEnd
       AND Isnull(Cast(S.scheduledshipdate AS DATE), '01/01/1900') BETWEEN
        @ScheduleShipStartDate AND @ScheduleShipEndDate
       AND Cast(s.requesteddeliverydate AS DATE) BETWEEN
        @DeliveryDateStart AND @DeliveryDateEnd
       AND CASE
         WHEN @Version = 2 THEN
         CASE
          WHEN s.orderversionnumber = (SELECT Max(a.orderversionnumber)
                    FROM
            om_salesorderheader a(nolock)
                    WHERE a.orderno = s.orderno) THEN
          1
          ELSE 0
         END
         ELSE 1
        END = 1
    GROUP BY s.salesorderheaderid,
        s.orderno,
        s.orderversionnumber,
        ST.systemtypedescription,
        stu.description,
        ST.systemtypedescription,
        FL.locationid,
        FL.locationdescription,
        s.orderdate,
        TL.locationid,
        TL.locationdescription,
        U.uom,
        Shp.shipmentid,
        ST.systemtypeid,
        BP.businesspartnername,
        --Shp.ActualDeliveryDateTime,
        opn.materialid,
        mat.materialdesc,
        S.scheduledshipdate,
        S.requesteddeliverydate,
        shp.shipmentnumber,
        s.invoiceno,
        FLANE.traveltimeindays,
        Shp.fromcarrierintime,
        SHP.shipmentversion,
        s.shipmentid,
        Shp.shipmentstatusid,
        --opn.Amount,
        S.statuscode,
        S.orderconditionid,
        SC.systemtypedescription,
        s.isdiverted,
        FL.organizationid,
        TL.organizationid,
        s.purchaseordernumber,
        ss.sourcesystemdescription,
        s.estimateddeliverydate
    OPTION(recompile)

  • When you post the execution plans, if you post the execution plans, please post the XML of the plans themselves, preferably the actual plans instead of estimated. Posting a picture of a plan is grossly inadequate to help out. There are no details available in a picture.

    Also, everything that Eirikur said at the top of his post. That's where most of your problems are.

    What is the intent of this query? Why is it doing so much work? If this is meant to satisfy more than one business requirement, break them apart. Have a different query for each requirement. Stuff like this is crazy, and, as you can see, very hard to make run fast.

    "The credit belongs to the man who is actually in the arena, whose face is marred by dust and sweat and blood"
    - Theodore Roosevelt

    Author of:
    SQL Server Execution Plans
    SQL Server Query Performance Tuning

  • @Eirikur/@Fritchey - Thanks a lot for suggesting week points of this query, indeed these all are nice suggestions. if I remove group by list, IsNull function from where clause. but it didn't help me to reduce timing in 1 execution. Definitely the impact can be measured wen multiple hit/execution shall come from application. 
    I am attaching the xml execution plan in zip file here, please suggest in this. You can find there is 4-5 time lookup operation (cost - 18*4 )of clustered index [PK__tmp_ms_x__803D86A98F5505F0] of table CustomerOpenOrder, Can we remove this redundant effort. or anything else which can be improved in this,

  • Sometimes you need to draw a line in the sand and accept that it may be better to start again.
    Ask yourself 2 things:
    1) if you came back to this in a years time, would you be able to work with this query as if you were working on it yesterday?
    2) if somebody else came to work on the query would they we able to understand what is going on?

    If either of these is a 'no' then you need to strongly consider redesigning the query.

    There are a catalogue of problems here, most of which have already been mentioned.
    Firstly, understand the order in which sql server will process your query (starting with the FROM clause), this will allow you to be more sympathetic towards sql server's needs.
    When you run subqueries in the select list, realise that these will be executed for every row that is returned from the outer query.
    Try to avoid nesting subqueries, and using table valued functions within those subqueries (this is as good as another nested level). When you nest queries, debugging performance becomes a lot harder.
    Understand that joins on strings don't perform as well as joins on "predictable" predicates, i.e. numbers. Quite often these can force index scans because of the "unpredictable" nature of strings.
    every cast/convert/min/max/isnull is an additional operation that sql server needs to complete to satisfy your request. whilst some of these may have minimal overhead, they will add up over the duration of the query.
    try to avoid using nolock, it's not as good as you think! and will likely cause problems elsewhere, especially if running this in a live environment.
    do you need group by and select distinct? Again, this comes back to understanding the order in which the query is processed, and what each 'section' of the query does.
    option recompile may not be working in your favour?
    tempdb looks like it may be taking a hammering.
    and without even realising it you are sorting a lot of data, which means performance will never be on your side.

    I would start again and look to spilt the query out in to segments... not what you wanted to hear I'm sure.
    Consider using temp tables to store the results of each segment of the query, and then pull it all together if you need a single result set? But ensure you have tempdb well provisioned for this, otherwise you will run in to other problems (you may be facing them now!?). It looks like you may be using a temp table in your query, so I'm not sure why you aren't using more?
    Or store the results of each segment in newly defined tables and run a query against those tables.

  • DimPerson - Friday, December 1, 2017 2:23 AM

    Understand that joins on strings don't perform as well as joins on "predictable" predicates, i.e. numbers. Quite often these can force index scans because of the "unpredictable" nature of strings.

    That's an excellent set of advice and very well constructed... except for this bit.

    Indexed strings can perform perfectly well as long as the strings aren't insanely long, the statistics are up to date (an issue with any index), and the code is properly constructed. Strings from an index are not "unpredictable" in any way. They're going to behave basically the same way as any other data type. I'm unsure by what you mean between predictable and unpredictable in the way you use them here.

    Everything else you suggested is dead on accurate and very useful. Hopefully, @anujkumar.mca takes advantage of it.

    "The credit belongs to the man who is actually in the arena, whose face is marred by dust and sweat and blood"
    - Theodore Roosevelt

    Author of:
    SQL Server Execution Plans
    SQL Server Query Performance Tuning

  • poor choice of words... what I perhaps should have said was sequential, although I realise strings are sequential in an index!
    I was trying to illustrate that, as an int 2 will always follow 1, so sql server can better predict the behaviour of numbers, whereas with strings b will not always follow a (e.g. aa).
    It is fair to say that strings can perform just as well if they are short, and indexed (fingers crossed!), but if not indexed they can be possible candidates for causing index scans.

    EDIT: I also realise that unindexed numbers can also cause index scans, so perhaps ignore what I was saying and go with what you said... make sure your strings are indexed!!!!! 🙂 For some reason I have it in my head that joining on number types is better than joining on strings? But it shouldn't matter.

  • DimPerson - Friday, December 1, 2017 8:04 AM

    poor choice of words... what I perhaps should have said was sequential, although I realise strings are sequential in an index!
    I was trying to illustrate that, as an int 2 will always follow 1, so sql server can better predict the behaviour of numbers, whereas with strings b will not always follow a (e.g. aa).
    It is fair to say that strings can perform just as well if they are short, and indexed (fingers crossed!), but if not indexed they can be possible candidates for causing index scans.

    EDIT: I also realise that unindexed numbers can also cause index scans, so perhaps ignore what I was saying and go with what you said... make sure your strings are indexed!!!!! 🙂 For some reason I have it in my head that joining on number types is better than joining on strings? But it shouldn't matter.

    Oh, don't beat yourself up. There actually is a small degree of efficiency in dealing with numbers over dealing with strings. It's just fairly subtle (usually, there are always exceptions) and not so much in line with what you had said.

     I sure wasn't trying to beat on you at all. I think your advice here is excellent.

    "The credit belongs to the man who is actually in the arena, whose face is marred by dust and sweat and blood"
    - Theodore Roosevelt

    Author of:
    SQL Server Execution Plans
    SQL Server Query Performance Tuning

  • DimPerson - Friday, December 1, 2017 8:04 AM

    For some reason I have it in my head that joining on number types is better than joining on strings? But it shouldn't matter.

    It's on my list of 502,924,103 things I want to test yet - this one with different amounts of data. You might be interested in this article on Gail Shaw's site in which testing shows the joins on integers being better:
    Are int joins faster than string joins?

    Sue

  • Thanks a lot to all of you for your great suggestions, I agree this is bad query which doesn't follow even the basic rules of optimal query writing. 
    But I would eager to know below 2 points. Pls
    1. How we can avoid the redundant operation of same index. 
    In my original question thread, I shown,  the lookup operation of same index is available multiple times.(marked in red box). Is there a way to resolve this redundant sql effort.
    2.
    Do this predicates\Seek values help us to improve the working of index or change lookup to seek or scan to seek

Viewing 10 posts - 1 through 9 (of 9 total)

You must be logged in to reply to this topic. Login to reply