質問

Have added the following code to my SQL query: (Note cut down version)

DECLARE @rowType AS TABLE (
    rowTypeLabel NVARCHAR (20));

INSERT  INTO @rowType
VALUES ('Cumulative');

INSERT  INTO @rowType
VALUES ('Non-Cumulative');

--select * from @rowType


SELECT ID,Name,StartDate,
       EndDate,
       rowTypeLabel AS Period
FROM   dbo.sicky CROSS JOIN @rowType
WHERE  (rowTypeLabel = 'Cumulative'
        OR (rowTypeLabel = 'Non-Cumulative'
            AND (EndDate IS NULL
                 OR EndDate BETWEEN CAST (DateAdd(Day, 1 - Day(getDate()), getdate()) AS DATE) AND CAST (DateAdd(month, 1, DateAdd(Day, -Day(getDate()), getdate())) AS DATE))));

Run time has gone from around 10 minutes to around 1 hour, does anyone have any suggestions as to why this may be, the results without this cross join were around 46,000 and after brings back an additional 231 rows (anything that is classed as 'non-cumulative' as per query.

役に立ちましたか?

解決

I'm guessing that this is a much simplified example? So I can't give you specifics, but the simple answer is that the cumulative part of the query is doing a lot more work than the non cumulative part.

Try these two for comparison...

SELECT ID,Name,StartDate,
       EndDate,
       rowTypeLabel AS Period
FROM   dbo.sicky

And...

SELECT ID,Name,StartDate,
       EndDate,
       rowTypeLabel AS Period
FROM   dbo.sicky
WHERE  EndDate IS NULL
       OR EndDate BETWEEN CAST (DateAdd(Day, 1 - Day(getDate()), getdate()) AS DATE) AND CAST (DateAdd(month, 1, DateAdd(Day, -Day(getDate()), getdate())) AS DATE))));

The latter, I would expect, will take a lot longer.


Also, OR conditions to merge multiple pieces of business logic can be quite hard for the optimiser. This means that the following structure may be more efficient...

SELECT * FROM <non cumulative query>
UNION ALL
SELECT * FROM <cumulative query>

他のヒント

I don't see why you need the CROSS JOIN construct here -- it's just confusing the issue. I'd rewrite the query as this:

SELECT ID, Name, StartDate, EndDate, 'Cumulative' AS Period
FROM   dbo.sicky
UNION ALL
SELECT ID, Name, StartDate, EndDate, 'Non-Cumulative' AS Period
FROM   dbo.sicky
WHERE EndDate IS NULL
    OR EndDate BETWEEN CAST (DateAdd(Day, 1 - Day(getDate()), getdate()) AS DATE) AND CAST (DateAdd(month, 1, DateAdd(Day, -Day(getDate()), getdate())) AS DATE))));

This should be equivalent, but illustrates what you are doing more clearly. Assuming the first part of this UNION is what you had before, and the second part is what is slow, it's likely that EndDate (or whatever the equivalent is in your real query) isn't indexed properly and is causing excessive scanning. Post your execution plans for more detailed analysis.

46000 rows in 10 minutes for a simple SELECT with no JOIN or subqueries ... it seems too much. Check if you have created and enabled indexes on StartDate and EndDate. If so, I go with mwigdahl o Dems answers.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top