SQL Server doesn't use missing indexes after it creation - sql

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?

Related

Advantages of explicitly writing an index

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)

DDL changes not showing in Oracle sql developer

I have sql Upgrade script which has many sql statements(DDL,DML). When i ran this upgrade script in SQL developer, it runs successufully.I also provide in my script at the bottom commit. I can see all the changes in the database after running this upgrade script except the unique index constraints. When i insert few duplicate records it says unique constraint violated. It means the table has unique constraints. But i dont know why i cant view this constraints in oracle sql developer. The other DDL changes made i can view.I dont know is there any settings to view it in oracle sql developer.
CREATE UNIQUE INDEX "RATOR_MONITORING"."CAPTURING_UK1" ON "RATOR_MONITORING"."CAPTURING" ("DB_TABLE");
CREATE UNIQUE INDEX "RATOR_MONITORING_CONFIGURATION"."BRAND_UK1" ON "RATOR_MONITORING_CONFIGURATION"."BRAND" ("NAME");
CREATE UNIQUE INDEX "RATOR_MONITORING_CONFIGURATION"."BRAND_BUSINESS_PROCESS_UK1" ON "RATOR_MONITORING_CONFIGURATION"."BRAND_BUSINESS_PROCESS" ("BRAND_ID", "BP_ID");
CREATE UNIQUE INDEX "RATOR_MONITORING_CONFIGURATION"."BRAND_ENGINE_UK1" ON "RATOR_MONITORING_CONFIGURATION"."BRAND_ENGINE" ("BRAND_ID", "ENGINE_ID");
As A Hocevar noted, if you create an index
create unique index test_ux on test(id);
you see it in the Indexes tab of the table properties (not in the Constraints tab).
Please note that COMMIT is not required here, it is done implicitely in each DDL statement. More usual source of problems are stale metadata in SQL Developer, i.e. missing REFRESH (ctrl R on user or table node).
If you want to define the constraint, add following statement, that will reuse the index defined previously
alter table test add constraint test_unique unique(id) using index test_ux;
See further discussion about the option in Documentation
I am assuming you are trying to look for index on a table in the correct tab in sql developer. If you are not able to see the index there, one reason could be that your user (the one with which you are logged in) doesn't have proper rights to see the Index.
If you not obtain any error, the solution is very simple and tedious. SQL Developer doesn't refresh his fetched structures. Kindly push Refresh blue icon (or use Ctrl-R) in Connections view or disconnect and connect again (or restart SQL Developer) to see your changes in structures.

SQL Server Table Synonyms with Indexes

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.

Should I drop and create indexes on my tables that SQL Server created?

In an effort to get rid of some fragmentation left from rebuilding and defraging
we thought that we would drop and create indexes so I went to write a script.
It identifies a clustered index that needs work and drops indexes and primary keys
and rebuilds the indexes and primary keys for a table.
Here is the problem I ran into: SQL Server makes quite a bit of its own indexes
based on statistics with its own unique naming system.
Question: Do I want to only drop and create the indexes we made or do I want to drop all indexes and create only the ones that we made or do we want to drop all indexes including
the ones SQL Server made and create all indexes including the ones that SQL Server made?
You can always defrag your indexes, which is easier than drop and recreate. There's a decent explanation of how to do it in this article.

Dropping a group of tables in SQL Server

Is there a simple way to drop a group of interrelated tables in SQL Server? Ideally I'd like to avoid having to worry about what order they're being dropped in since I know the entire group will be gone by the end of the process.
At the risk of sounding stupid, I don't believe SQL Server supports the delete / cascade syntax. I think you can configure a delete rule to do cascading deletes (http://msdn.microsoft.com/en-us/library/ms152507.aspx), but as far as I know the trick with SQL Server is to just to run your drop query once for each table you're dropping, then check it worked.
I'm not sure, if Derek's approach works. You haven't mark it as best answer yet.
If not: with SQL Server 2005 it should be possible, I guess.
There they introduced exceptions (which I've not used yet). So drop the table, catch the exception, if one occurs and try the next table till they are all gone.
You can store the list of tables in a temp-table and use a cursor to traverse it, if you want to.
A diferent approach could be: first get rid of the constraints, then drop the tables in a single shot.
In other words, a DROP CONSTRAINT for every constraint, then a DROP TABLE for each table; at this point the order of execution shouldn't be an issue.
This requires the sp___drop___constraints script you can find at Database Journal:
sp_MSforeachtable #command1="print 'disabling constraints: ?'", #command2="sp_drop_constraints #tablename=?"
GO
sp_MSforeachtable #command1="print 'dropping: ?'", #command2="DROP TABLE ?"
GO
NOTE this - obviously - if you meant to drop ALL of the tables in your database, so be careful
I don't have access to SQL Server to test this, but how about:
DROP TABLE IF EXISTS table1, table2, table3 CASCADE;
I ended up using Apache's ddlutils to perform the dropping for me, which sorted it out in my case, though a solution which worked only within sql server would be quite a bit simpler.
#Derek Park, I didn't know you could comma separate tables there, so that's handy, but it doesn't seem to work quite as expected. Nether IF EXISTS nor CASCADE are recognised by sql server it seems, and running drop table X, Y, Z seems to work only if they should be dropped in the stated order.
See also http://msdn.microsoft.com/en-us/library/ms173790.aspx, which describes the drop table syntax.
The thing holding you back from dropping the tables in any order are foreign key dependencies between the tables. So get rid of the FK's before you start.
Using the INFORMATION_SCHEMA system views, retrieve a list of all foreign keys related to any of these tables
Drop each of these foreign keys
Now you should be able to drop all of the tables, using any order that you want.