I have multiple databases on a single instance of SQL Server 2005. I've created a synonym on one database to access a table on another database and when writing my queries, I'd like to utilize a specific index, however, when evaluating the execution plan, it doesn't appear to use it. If I write the query to access the database explicitly, it works, but I can't seem to get it to work using a synonym. For example:
select *
from testdb..testtable with (index(testindex))
|--Nested Loops(Inner Join, OUTER REFERENCES:([testdb].[dbo].[testtable].[id]))
|--Index Scan(OBJECT:([testdb].[dbo].[testtable].[testindex]))
|--Clustered Index Seek(OBJECT:([testdb].[dbo].[testtable].[PK_testtable]), SEEK:([testdb].[dbo].[testtable].[id]=[testdb].[dbo].[testtable].[id]) LOOKUP ORDERED FORWARD)
does not yield the same execution plan as
select *
from testdb_synonym with (index(testindex))
|--Clustered Index Scan(OBJECT:([testdb].[dbo].[testtable].[PK_testtable]))
Is this a limitation with Synonyms or is there something specific I need to do to get this to work?
This is a bug that Microsoft have fixed: see MS KB 963684
In Microsoft SQL Server 2005, you
create a synonym for a table. You run
a query against the synonym. The query
uses the INDEX optimizer hint to force
an index. If you examine the execution
plan that is generated for the query,
you may find the execution plan does
not use the forced index.
I tested the same thing and it seems that the query optimizer ignores that hint when done via a synonym. The details are I did a select * against an arbitrary table with an index hint to use a non-clustered index. Without the synonym, it does a bookmark lookup/nested loop join. With it, it does a table scan. Since there are no options on the create synonym syntax, I can only assume that the index hint is ignored. No details in BOL as to why. I would chalk it up as a "feature".
WITH INDEX hints seems to be ignored for synonyms.
CREATE SYNONYM syn_master FOR master
SELECT *
FROM syn_master WITH (INDEX (wow_i_can_write_everything_here))
compiles and runs allright despite the fact I don't have an index named wow_i_can_write_everything_here in my schema.
Do you need the hint in your case? MS recommendations is to avoid index hints if it is possible due to the fact that may invalidate a more optimized plan. Even if it is optimized today it may be inefficiens tomorrow due to data load etc.
I tried to use a synonym without the hint in SQL server 2008 and got the same execution plan with the synonym as with the fully qualified name (database.schema.table).
I even tried to use the synonym with an index hint and successfully forced a non clustered index seek (and a key lookup to get the rest of the data), and i get the same execution plan with fully qualified name.
Are your statisitics updated? Do you have a selective index or does SQL server think it is more efficient to use a table scan.
Related
I ran into a very strange situation. I have a query and the optimizer advises to create an missing index for one of the tables. For example
create index on table1 (id) include (dt);
After the index is created, the optimizer doesn't use it, but advise to create the same index!
Never experienced this kind of behavior before. Can anyone suggest how to force SQL server to use the existing indexes?
I am trying to determine if there is a way in Oracle 11g to find out if an index is reversed. I looked through the documentation for ALL_INDEXES* however I didn't see anything in that table that would indicate that the index is reversed or not.
The reasoning behind this is that we reversed an index to fix an issue with IO Wait in our production environment. We use flyway for schema migrations to sync our environments and all scripts must be idempotent. However, I'm not able to find a way to determine if the index in question is reversed on not in order to conditionally rebuild it as reversed.
Is there a way to determine if an index in Oracle DB is reversed using built-in meta tables/views?
* Additional info:
I won't actually have access to the ALL_INDEXES table when this would be run, only USER_INDEXES since this will not be executed with DBA permissions.
The index in question is the primary key of a table if that makes a difference in querying the schema metadata
The column ALL_INDEXES.INDEX_TYPE will contain the type of the index. For a reverse index this will be NORMAL/REV or FUNCTION-BASED NORMAL/REV.
This will be the same for USER_INDEXES
ALL_INDEXES in the Oracle 11 manual
ALL_INDEXES in the Oracle 12 manual
I wonder why one should ever care on explicitly writing an index in query. I frequently see queries like this
select blabla from Table with(nolock index = index_name)
Index is already defined, and query optimizer chooses the best index by itself. Isn't it more logical and efficient to write query as this:
select blabla from Table with(nolock)
What are the advantages of explicitly writing an index in query?
EDIT
Thank you all for your opinions. The best choice is not to force seeking indexes explicitly.
In this case only database vendors could be advantageous and it is not related with performance. They indicate indexes explicitly and force execution plan to not to change in order to be able to predict execution times.
This is question is kind of rhetoric: one must measure efficiency, not reason about it.
In ssms you can do it with "Include Actual Execution Plan" (Ctrl-M).
Try execute following in ssms and look at "Execution plan":
SELECT * FROM msdb.dbo.sysjobs with (index = nc1)
SELECT * FROM msdb.dbo.sysjobs with (index = clust)
SELECT * FROM msdb.dbo.sysjobs
You will find that: a)first index hint is only slowing, b) hint on clustered index and no hint have equivalent plans
Specifying Index in the SQL SERVER causes Force Seeking of that Index.
When any query is ran SQL Server Engine determines which index has to
be used. SQL Server makes uses Index which has lowest cost based on
performance. Index which is the best for performance is automatically
used. There are some instances when Database Developer is best judge
of the index used. DBA can direct SQL Server which index to be used to
execute query.
If the index that you have created is not picked up by SQL Server,
then try telling the SQL Server by using the HINT.
you can refer below links
http://blog.sqlauthority.com/2009/02/07/sql-server-introduction-to-force-index-query-hints-index-hint/
https://www.simple-talk.com/sql/performance/index-selection-and-the-query-optimizer/
I think it can be useful in case when sql engine creates execution plan for queries in stored procedure. It maybe situation when SQL engine created execution plan for parameters that passed in stored procedure first (parameters sniffing). For that values SQL engine can take decision not to use index. So to avoid it you can explicit set index usage.
Additional information about parameter sniffing you can find in this article (http://sqlperformance.com/2013/08/t-sql-queries/parameter-sniffing-embedding-and-the-recompile-options) and here (http://www.sommarskog.se/query-plan-mysteries.html)
I have implemented SQL Server's Change Data Capture feature in my database. When you enable CDC in your database , sql server will create some system tables for you like : cdc.dbo_Person_CT for tracking the changes you have in main Person table . I am using cdc.dbo_Person_CT table and i have applied Non-Clustered index on a column and i am using that column in select statement.
But when i see execution plan for my table ,it doesn't show Non-Clustered index ?? why
We would have to see the query and the index details but I would guess that the query is returning so many rows or that the index is not exclusive enough so the query analyzer decided to use a scan instead.
How can I compare the performance of an Index on a table using the Query Analyzer?
I would like to run the same query through the Estimated Execution Plan twice, once using the index and once without, and have a good comparison of the table scans/index scans that are generated.
I have tried CREATE INDEX..., SELECT..., DROP INDEX..., SELECT. I expect the first query to use the index and the second to have no index, but both execution plans will use the index.
If there is no index, then it can't be used. However, the index still exists for the estimated execution plan for the 2nd select, so it is evaluated. The DROP INDEX plan is also just an estimate too
I'd use the actual execution plan anyway, because personally I don't like the estimated one.
You can use SET SHOWPLAN TEXT to capture what is actually used in the query window (or use the graphical one). I'd also use SET STATISTICS IO and often SET STATISTICS TIME too.
Use the Sql Server Profiler under configuration tools. Run your queries with and without indexing and record the data reads / writes timing etc of your function calls. This should give you a clear idea if your indexes have improved performance (less reads / latency etc.)
use this at the beginning of the query window. it'll clear any plan caches.
dbcc freeproccache
go
dbcc dropcleanbuffers
go
so have that at the top, and then put your dreat and drop index code in a comment, and then your query. run it initially without an index and see what it looks like, then create the index and rerun it.
and yes, use the actual execution plan and you can also use client statistics.
The technique that ended up working for me was to use the WITH keyword in the FROM clause.
When the index is created:
SELECT * FROM table WHERE ...
SELECT * FROM table WITH (INDEX(0)) WHERE ...
The first query will (probably) use the index, the second will not.
You could also use multiple indexes like:
SELECT * FROM table WITH (INDEX(IX_test1)) WHERE ...
SELECT * FROM table WITH (INDEX(IX_test2)) WHERE ...