Schema and indexes are only one aspect of query plan and performance. Your statement "but with different data" is likely the source of the difference. The number of rows and the distribution of data is essential to the query optimizer. If you have significantly more rows in D2, or if the data is of entirely different characteristics (wider or narrower range of values), then you should expect to see different performance and execution plans.
For each set of statistics, SQL Server keeps a maximum of 200 samples. As the rows in the tables grow and the more irregular the distribution of values the more likely it is that SQL Server will not have enough information to generate optimal execution plans. That's where the use of filtered indexes and statistics comes into play.
If this is a parameterized query you may also be running into a parameter sniffing problem. Note that if you're using local variables the calculation changes also.
1. How to understand estimated operator cost? Tb1 which don't have index is scanned and cost is 2 %, whereas index is being used on tb2 and cost is 98%.
The heap table is only fully scanned once, but the index seek is executed 1,000,000 times. The optimizer estimates that a million seeks in this case will represent 98.4% of the total cost of executing the query, whereas a single parallel scan of the heap table will represent 0.9% of the cost.
These are just estimates used for internal plan choice reasons; they do not generally reflect real-world performance on modern hardware, and are never anything more than an estimate - even in a post-execution ("actual") execution plan.
In Management Studio:
In SQL Sentry Plan Explorer:
2. From the above snip of table scan (whose cost is 2%),number of executions are 24,will that means sql read rows in batches and stored in memory and for each row it did a seek operation from tbl2.
No, it means 24 parallel threads co-operated to perform a single scan of the heap table. Each thread still reads a row at a time from the scan, performs a seek into the indexed table, then gets the next row from the scan, and so on until the task is complete.
Rows are not read in batches and stored in memory in this plan. SQL Server reports 24 scans because 24 threads each performed a partial scan of the table, resulting in one full scan overall.
3. Also any pointers to know more about force scan,force index when I pressed F4 after clicking an operator
The ForceScan
, ForceSeek
, and ForcedIndex
properties are set to true if the query specifies a FORCESCAN
, FORCESEEK
, or INDEX
hint - or if the query optimizer decides that a particular access strategy is required for correctness (for example, when checking foreign key constraints).
Best Answer
The full cost derivation logic is complex, but for the relatively simple case in the question:
Inputs
The number of times the operator is executed
This is the Estimated Number of Executions: 504
The cardinality (total number of rows) in the index
The TableCardinality property of the Index Seek operator gives this: 113,443
The number of data pages in the index: 201
This number can be obtained multiple ways, for example from
sys.allocation_units
:The density (1 / distinct values) of the index: 0.002267574
This is available in the density vector of the index statistics:
Computation
db<>fiddle