Need some help with query taking forever

  • Here is my query

    *********************************************************************

    ;with qtysold(itemid,qtysold) as

    (select itemid,sum(sliretailquantity) from sale_line_item

    where txid in (select txid from transactions t where txstartdate >= '2/9/2011' and txstartDate < '2/16/2011')

    group by itemid),

    previousday (itemid,qtysoldprevious) as

    (select itemid, sum(sliretailquantity) from sale_line_item

    where txid in (select txid from transactions t where txstartDate >= '2/2/2011' and txstartDate < '2/8/2011')

    group by itemid)

    select 'itemid' = i.id, i.title

    'qtysold' = qtysold.qtysold,

    'change' = qtysold.qtysold - previousday.qtysoldprevious

    from imitem i

    inner join qtysold on i.id = qtysold.itemid

    left join previousday on i.id = previousday.itemid

    *********************************************************************

    Ok i am basically using one cte table to get the number of products sold from my product detail table (sale_line_item) for a certain date range

    using another cte table to get the number of products sold from my product detail table (sale_line_item) for a different date range

    is i run the the 2 cte queries alone they are fast, less then a second

    if i run the whole query and do not join that 2nd cte it is fast and the reads are like 35899

    when i join that 2nd cte the reads jump to like 16317830. and the query takes like 60 seconds.

    Any ideas on how i can redo or can someone explain why this is happening

  • We'd need to see the execution plans for the queries to really help you here. If you need some help doing that the link in my sig for index/tuning help will show you how.

    I'm not even sure I can hazard a guess at what's gone wrong there offhand without knowing DDL and expected rowcounts.


    - Craig Farrell

    Never stop learning, even if it hurts. Ego bruises are practically mandatory as you learn unless you've never risked enough to make a mistake.

    For better assistance in answering your questions[/url] | Forum Netiquette
    For index/tuning help, follow these directions.[/url] |Tally Tables[/url]

    Twitter: @AnyWayDBA

  • I agree with Craig, but also - why not try doing it all in one SELECT...?

    edit: sorry my bad code removed

    MM



    select geometry::STGeomFromWKB(0x0106000000020000000103000000010000000B0000001000000000000840000000000000003DD8CCCCCCCCCC0840000000000000003DD8CCCCCCCCCC08408014AE47E17AFC3F040000000000104000CDCCCCCCCCEC3F9C999999999913408014AE47E17AFC3F9C99999999991340000000000000003D0000000000001440000000000000003D000000000000144000000000000000400400000000001040000000000000F03F100000000000084000000000000000401000000000000840000000000000003D0103000000010000000B000000000000000000143D000000000000003D009E99999999B93F000000000000003D009E99999999B93F8014AE47E17AFC3F400000000000F03F00CDCCCCCCCCEC3FA06666666666FE3F8014AE47E17AFC3FA06666666666FE3F000000000000003D1800000000000040000000000000003D18000000000000400000000000000040400000000000F03F000000000000F03F000000000000143D0000000000000040000000000000143D000000000000003D, 0);

  • Forum Etiquette: How to post Reporting Services problems
  • [/url]
  • Forum Etiquette: How to post data/code on a forum to get the best help - by Jeff Moden
  • [/url]
  • How to Post Performance Problems - by Gail Shaw
  • [/url]

  • I think this is what I meant to write just now...

    SELECT

    sli.itemid ,

    sli.title,

    qtysold = SUM(qtys.qtysold),

    change = SUM(qtys.qtysold - qtys.qtysoldprevious)

    FROM

    sale_line_item AS sli

    JOIN

    transactions AS trn

    ON

    trn.txid=sli.txid

    CROSS APPLY

    (

    SELECT

    qtysold = CASE WHEN trn.txstartDate >= '2011-02-08' THEN sli.sliretailquantity ELSE 0 END,

    qtysoldprevious = CASE WHEN trn.txstartDate < '2011-02-08' THEN sli.sliretailquantity ELSE 0 END

    ) AS qtys

    WHERE

    trn.txstartdate >= '2011-02-02' AND trn.txstartDate < '2011-02-16'

    GROUP BY

    sli.itemid,sli.title

    MM



    select geometry::STGeomFromWKB(0x0106000000020000000103000000010000000B0000001000000000000840000000000000003DD8CCCCCCCCCC0840000000000000003DD8CCCCCCCCCC08408014AE47E17AFC3F040000000000104000CDCCCCCCCCEC3F9C999999999913408014AE47E17AFC3F9C99999999991340000000000000003D0000000000001440000000000000003D000000000000144000000000000000400400000000001040000000000000F03F100000000000084000000000000000401000000000000840000000000000003D0103000000010000000B000000000000000000143D000000000000003D009E99999999B93F000000000000003D009E99999999B93F8014AE47E17AFC3F400000000000F03F00CDCCCCCCCCEC3FA06666666666FE3F8014AE47E17AFC3FA06666666666FE3F000000000000003D1800000000000040000000000000003D18000000000000400000000000000040400000000000F03F000000000000F03F000000000000143D0000000000000040000000000000143D000000000000003D, 0);

  • Forum Etiquette: How to post Reporting Services problems
  • [/url]
  • Forum Etiquette: How to post data/code on a forum to get the best help - by Jeff Moden
  • [/url]
  • How to Post Performance Problems - by Gail Shaw
  • [/url]

  • wow never even heard of a cross apply, let me read up on that and try that out. thanks for the replies. I will attach execution plan if cross apply still slow

  • In this case, I am using CROSS APPLY just as a way of creating placeholders for the calculations.

    It just makes the SELECT cleaner - but should not have any other effect.

    MM



    select geometry::STGeomFromWKB(0x0106000000020000000103000000010000000B0000001000000000000840000000000000003DD8CCCCCCCCCC0840000000000000003DD8CCCCCCCCCC08408014AE47E17AFC3F040000000000104000CDCCCCCCCCEC3F9C999999999913408014AE47E17AFC3F9C99999999991340000000000000003D0000000000001440000000000000003D000000000000144000000000000000400400000000001040000000000000F03F100000000000084000000000000000401000000000000840000000000000003D0103000000010000000B000000000000000000143D000000000000003D009E99999999B93F000000000000003D009E99999999B93F8014AE47E17AFC3F400000000000F03F00CDCCCCCCCCEC3FA06666666666FE3F8014AE47E17AFC3FA06666666666FE3F000000000000003D1800000000000040000000000000003D18000000000000400000000000000040400000000000F03F000000000000F03F000000000000143D0000000000000040000000000000143D000000000000003D, 0);

  • Forum Etiquette: How to post Reporting Services problems
  • [/url]
  • Forum Etiquette: How to post data/code on a forum to get the best help - by Jeff Moden
  • [/url]
  • How to Post Performance Problems - by Gail Shaw
  • [/url]

  • The cross apply is a lot faster thanks. but i am actually using a lot more fields and my group by looks like

    GROUP BY

    i.id,i.title + ' ' + coalesce(i.subtitle,''),'http://images.xxxx.com/ProductImages/' + I.imagepath + '/' + i.itemphoto1 + '_' + convert(nvarchar(10),i.id) + '_d.jpg',

    m.title,imcategory2.description,i.condition,inventory.qtyonhand

    Is there a cleaner way of doing this without having to group by all those fields? Here is the full query

    ;with inventory(itemid,qtyonhand) as

    (select itemid,sum(qtyonhand) - sum(qtyproblem) from iminv

    group by itemid)

    SELECT 'itemid' = i.id ,'title' = (i.title + ' ' + coalesce(i.subtitle,'')),

    'itempic' = 'http://images.xxxx.com/ProductImages/' + I.imagepath + '/' + i.itemphoto1 + '_' + convert(nvarchar(10),i.id) + '_d.jpg',

    'kittype' = 'no','manufacturer' = m.title,

    'category' = imcategory2.description,

    'condition' = i.condition,

    'qtyonhand' = inventory.qtyonhand,

    qtysold = SUM(qtys.qtysold),

    change = SUM(qtys.qtysold - qtys.qtysoldprevious)

    FROM

    sale_line_item AS sli

    JOIN transactions AS t ON t.txid=sli.txid

    join imitem i on sli.itemid = i.id

    left join inventory on i.id = inventory.itemid

    left join xmanufacturer m on i.mfrid = m.id

    left join imcategory on i.catid = imcategory.id

    LEFT JOIN IMCategory IMCategory2 on IMCategory2.id = IMCategory.parentID

    CROSS APPLY

    (

    SELECT

    qtysold = CASE WHEN t.txstartDate >= '2/21/2011' and t.txstartdate < '2/28/2011' THEN sli.sliretailquantity ELSE 0 END,

    qtysoldprevious = CASE WHEN t.txstartDate > '2/14/2011' and t.txstartdate < '2/21/2011' THEN sli.sliretailquantity ELSE 0 END

    ) AS qtys

    WHERE

    t.txstartdate >= '2/14/2011' AND t.txstartDate < '2/28/2011'

    and t.txbackorder is null and t.txexchange is null and txsubtype is null and groupleadersliid is null

    and kittype is null and isgeneric = 0 and i.id <> 9999

    GROUP BY

    i.id,i.title + ' ' + coalesce(i.subtitle,''),'http://images.xxxx.com/ProductImages/' + I.imagepath + '/' + i.itemphoto1 + '_' + convert(nvarchar(10),i.id) + '_d.jpg',

    m.title,imcategory2.description,i.condition,inventory.qtyonhand

    order by qtysold desc

  • Michael,

    You actually don't have to use the constants from your select statement in the GROUP BY clause. I know it's easy to just copy/paste them into the GROUP BY, but they are not necessary. Only the actual columns used for the grouping are necessary. It can look cleaner if constants and functions are left out.

    For instance, here is your GROUP BY without the constants and functions (I hope I don't have a typo here since I didn't test it):

    GROUP BY

    i.id,i.title, i.subtitle, I.imagepath, i.itemphoto1

    , m.title, imcategory2.description, i.condition, inventory.qtyonhand

    Todd Fifield

  • Michael T2 (2/17/2011)


    is i run the the 2 cte queries alone they are fast, less then a second...

    I went to the doctor, held my arm over my head in a certain fashion and said, "It hurts like hell when I do this."

    Doctor said, "Well, stop doing that." 😛

    Having two aggregate queries in CTE's and then trying to join on them means the same thing as if they were views. Separately, they run very fast... together, they must resolve simultaneously and they are more prone to joining at the row level instead of the aggregate level.

    Divide'n'Conquer. Dump the results of each query into it's own Temp Table and then join the Temp Tables. I believe you'll find things run much faster that way.

    As a side bar, remember that "Set Based" doesn't mean "All in one query." 😉

    --Jeff Moden


    RBAR is pronounced "ree-bar" and is a "Modenism" for Row-By-Agonizing-Row.
    First step towards the paradigm shift of writing Set Based code:
    ________Stop thinking about what you want to do to a ROW... think, instead, of what you want to do to a COLUMN.

    Change is inevitable... Change for the better is not.


    Helpful Links:
    How to post code problems
    How to Post Performance Problems
    Create a Tally Function (fnTally)

  • Viewing 9 posts - 1 through 8 (of 8 total)

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