Search

Cardinality Estimation Error With Pushed Predicate on a Lookup by Paul White NZ

Closed
as Won't Fix Help for as Won't Fix

56
0
Sign in
to vote
Type: Bug
ID: 767395
Opened: 10/14/2012 11:20:31 PM
Access Restriction: Public
0
Workaround(s)
7
User(s) can reproduce this bug
In SQL Server 2005, a filtering condition on a column retrieved from a Key Lookup is applied in an explicit Filter operator after an apply join. In SQL Server 2008 onward, this filter can be pushed down to the lookup during copy out, but cardinality estimates are not updated correctly. The post-filter cardinality estimate is applied to the inner side of the lookup join, rather than the result of the join as a whole.

-- SQL Server 2005 AdventureWorks
SELECT
    th.ProductID,
    th.TransactionID,
    th.TransactionDate
FROM Production.TransactionHistory AS th
WHERE
    th.ProductID = 1
    AND th.TransactionDate BETWEEN '20030901' AND '20031231';

Estimate from index seek: 45 rows
Estimate from clustered index lookup: 1 row per 45 executions
Estimate from join: 45 rows
Estimate from filter: 16.9951 rows

On SQL Server 2008+ the filter is pushed to the key lookup after optimization:

Estimate from index seek: 45 rows
Estimate from lookup: 16.9951 rows per 45 executions (transferred from the filter)
Estimate from join: 45 rows (should be 16.9951)
Filter removed from query plan

Any predicate pushed to a lookup causes this apparent cardinality estimation problem. Filters pushed to regular scans and seeks appear to result in correct cardinality adjustments. (We used trace flag 9130 to explore the copy out rewrite behaviour.)

I realise small changes to the optimizer are generally risky, but the current behaviour results in very strange looking plans that are tricky to interpret. The behaviour also seems to be unintentional given the behaviour of pushed predicates with non-lookup seeks and scans. Finally, the issue does not affect plan selection, just the estimates we see when analysing plans, so this might be a low-risk fix?
Details (expand)

Product Language

English

Version

SQL Server 2012 - Enterprise Edition

Category

SQL Engine

Operating System

Not Applicable

Operating System Language

Not Applicable

Steps to Reproduce

-- Change dates to 2007 year in later versions of AdventureWorks
SELECT
    th.ProductID,
    th.TransactionID,
    th.TransactionDate
FROM Production.TransactionHistory AS th
WHERE
    th.ProductID = 1
    AND th.TransactionDate BETWEEN '20030901' AND '20031231';

Actual Results

Lookup estimates 1 row per execution in SQL Server 2005
Lookup estimates 16.9951 rows per execution on SQL Server 2008+

Expected Results

The join cardinality estimate should be 16.9951

The per-execution lookup estimate should either be 1 or scaled so that 45 executions produce the expected 16.9951 rows from the whole lookup operation.

Platform

X64

Virtualization

 
File Attachments
0 attachments
Sign in to post a comment.
Posted by Microsoft on 10/26/2012 at 11:30 AM
Thanks for the feedback, we are looking into this request
Sign in to post a workaround.