SQL Server missing index in execution plan - sql

We have created a view which contain 50 joins and some correlated subqueries.
When I am trying to look at the execution plan, it is not recommended missing index.
Could you please let me know why SQL Server is not showing any missing index statements for the running statement?

Here is my understanding. SQL is declarative language.
It means you only need to specify what data you want and from where you want it.
The rest is the task of server to do.
SQL server is using CBO (cost based optimizer) engine to determine which access method should be used. If you use select * from tablename without where it will be not used any index.
Index while increasing performance on certain case, it will be hindrance.
SQL uses the statistics to determine which access method will be used. Index seek, index scan, cluster index seek, cluster index scan etc.
So to answer your question is probably because of :
1. the statistics is not updated
2. you use select without where
3. your database is fit in memory so no index will be used

Related

Why Oracle uses Range Scan and Fast Full Scan on same index?

I have a strange situation:
there is a query (names of the objects are diffrent of course)
there is also an index GRANTEE_INDEX_01 on grante[pm, st] (every table has similar index [pm,st]), and I have no idea why - but oracle does both index range scan and fast full scan on same index, and I can't knock it out of his... core.
Actually there is no performance problem,at least no one complains. I just want to know why is this happening?
The clue is this is [Oracle 12c]. What you're seeing here is a manifestation of the adaptive cursor capability. This is a (controversial) feature Oracle added in 12c which allows the optimizer to change to a different plan if it thinks a query is running too slowly using the existing plan.
Oracle has actually come up with two plans for your query, one using hash joins and the other using nested loops. It's executing one plan but is using the STATISTICS COLLECTOR operation to monitor the other plan; this is how the CBO decides whether to switch to the other plan. You're seeing two hits on GRANTEE_INDEX_01 because it's used in both plans.
Incidentally, the explain plan should have some additional information (try the Text or HTML views) which would tell you this.
Note
-----
- this is an adaptive plan (rows marked '-' are inactive)
The inactive lines are the alternate plan joins and the STATISTICS COLLECTOR operations.
If you want to find out more, Maria Colgan wrote about in on the official Oracle blog site. Inevitably, Tim Hall also a good article on his Oracle-Base site.
I described adaptive cursors as controversial. This is a feature many DBAs disliked when it first came out and switched it off. Their objections centre mainly around its unpredictability: DBAs like their SQL to have stable execution plans.
Also I'm going to include Chris Saxon's comment, because he's closer to the product than I am:
I'd argue it's adaptive statistics, not adaptive plans that caused most the controversy. Which is why this was split into two parameters in 12.2, with adaptive plans on and adaptive stats off by default.
The difference comes from the definition of the index. If you have a composite index, the order of the columns in the index definition matters. In your example, pm column is defined before the st column. This will affect how that index will be organized. Because of this factor, you are seeing two different usages of that index.
" INDEX FAST FULL SCAN is the equivalent of a FULL TABLE SCAN, but for an index"
Could you please paste you grantee table structure and explain plan using
select * from table(dbms_xplan.display)
Index range scan is used to here to filter the rows based on where clause and then index fast full scan is used to access the rows.

Why "IN " query tag is so costly in sql stored procedures?

How can I improve my performance issue? I have an sql query with 'IN' I guess 'IN' making some costly performance issue. But I need index my sql query?
My sql query:
SELECT [p].[ReferencedxxxId]
FROM [Common].[xxxReference] AS [p]
WHERE ([p].[IsDeleted] = 0)
AND (([p].[ReferencedxyzType] = #__refxyzType_0)
AND [p].[ReferencedxxxId] IN ('42342','ffsdfd','5345345345'))
My solution: (BUT I NEED YOUR HELP FOR BETTER ADVISE) Whichone is correct clustered or nonclustred index?
USE [xxx]
GO
CREATE NONCLUSTERED INDEX IX_NonClusteredIndexDemo_xxxId
ON [Common].[xxxReference](xxxId)
INCLUDE ([ID],[ReferencedxxxId])
WITH (DROP_EXISTING=ON, ONLINE=ON, FILLFACTOR=90)
GO
Second:
CREATE INDEX xxxReference_ReferencedxxxId_index
ON [Common].[xxxReference] (ReferencedxxxId)[/code]
Whichone is correct or do you have better solution?
The performance problem of this query is not the result of using the IN operator.
This operator performs very well with small lists (say, less than 1000 members).
The performance bottle neck here is the fact that SQL Server performs an index scan instead of an index seek (which is very costly), and the key lookup, which is 20% of the query cost.
To avoid both problems, you can add an index on IsDeleted, ReferencedxyzType and ReferencedxxxId - probably in this exact order.
SQL Performance tuning is a science that tends to look a little like art or magic - either way you look at it it requires a good knowledge of both the theory and practice of index settings and the relevant systems requirements.
Therefor, my suggestion is this: Do not attempt to solve it yourself with the help of strangers on the internet. Get an expert for a consulting job for a couple of hours/days to analyze the system and help you fine-tune it.
Learn whatever you can during this process. Ask questions about everything that is not trivial. This will be money well spent.
Couple of things:
If you have a SELECT statement inside the IN, that should be avoided
and should be replaced with an EXISTS clause. But in your above
example, that is not relevant as you have direct values inside IN.
Using EXISTS and NOT EXISTS instead of IN and NOT IN helps SQL
Server to not needing to scan each value of the column for each
values inside the IN / NOT IN and rather can short circuit the
search once a match or non-match found.
Avoid the implicit conversion. They degrade the performance due to
many reasons including i> SQL Server not able to find proper
statistics on an index and hence not able to leverage an index and
would rather go make use of a clustered index available in the table
(which may not be covering your query), ii> Not assigning proper
required RAM during memory allocation phase of the query by storage
engine, iii> Cardinality estimation becomes wrong as SQL Server
would not have statistics on the computed value of that column, and
rather probably had statistics on that column.
If you look at your execution plan posted above, you will see a
yellow mark in your 'SELECT'. If you hover over it, you will see
one/more warning messages. If your warning is related to implicit
conversion, try to use proper datatypes during comparison.
Eg. What is the datatype of the column '[ReferencedxxxId]'? If it
is not an NVARCHAR and is rather a VARCHAR, then I would suggest:
Make the values inside the IN as VARCHAR (currently you are making them NVARCHAR). This way you will still be able to take full advantage of the rowstore index created on [ReferencedxxxId] column.
If you must have the values as NVARCHAR inside the IN clause, then you should:
CONVERT/CAST the column [ReferencedxxxId] in your IN clause. This is going to get rid of the Implicit conversion but you will no longer be able to take full advantage of the rowstore index on [ReferencedxxxId] column.
+
Rather create a clustered/nonclustered columnstore index on the table covering the columns used in the query. This should significantly enhance the performance of your SELECT query.
If you decided to go with the route of using rowstore index by correcting the values inside the IN, you need to make sure that you create a clustered/nonclustered index which covers the query. Meaning the index covers the columns on which you are doing search ([ReferencedxxxId], [ReferencedxxxType], [IsDeleted]) and then including the columns used in SELECT statement under INCLUDE clause (if it is a nonclustered index)
Also, when you are creating a composite rowstore index, try to keep the order of columns inside the index high cardinality to low cardinality from left to right to make the best use of that index.
On the basis of assuming an OLTP based system and not OLAP, my first pass would be an NC Index - given isDeleted is likely to have the least selectivity, I would place it last, first pass would be an NC index ReferencedxyzType, ReferencedxxxId, IsDeleted
I might even be tempted in a higher volume scenario to move the IsDeleted out of the index onto an include instead, since it provides so little selectivity to the index itself.
There is clearly already a clustered index in place on the table (from the query plan we can see it), we don't have the details of what is in it.
The question around clustered vs non-clustered is more complex and requires a lot more knowledge of the system and usage.

How to use index in SQL query

Well i am new to this stuff ..I have created an index in my SP at start like follows
Create Index index_fab
ON TblFab (Fab_name)
Now i have query under this
select fab_name from TblFab where artc = 'x' and atelr = 'y'.
now Is it necessary to use this index name in select clause or it will automatically used to speed up queries
Do i have to use something like
select fab_name from TblFab WITH(INDEX(index_fab)) where artc = 'x' and atelr = 'y'.
or any other method to use this index in query
and also how to use index if we are using join on this table?
Firstly, do you mean you're creating the index in a stored procedure? That's a bad idea - if you run the stored procedure twice, it will fail because the index already exists.
Secondly, your query doesn't use the column mentioned in the index, so it will have no impact.
Thirdly, as JodyT writes, the query analyzer (SQL Server itself) will decide which index to use; it's almost certainly better at it than you are.
Finally, to speed up the query you mention, create an index on columns artc and atelr.
The Query Optimizer of SQL Server will decide if it the index is suitable for the query. You can't force it to use a specific index. You can give hints on which you want it to use but it won't be a guarantee that it will use it.
As the other people answered your question to help you to understand better, my opinion is, you should first understand why you need to use indexes. As we know that indexes increase the performance , they could also cause performance issues as well. Its better to know when you need to use indexes, why you need to use indexes instead of how to use indexes.
You can read almost every little detail from here .
Regarding your example, your query's index has no impact. Because it doesn't have the mentioned column in your query's where clause.
You can also try:
CREATE INDEX yourIndexName
ON yourTableName (column_you_are_looking_for1,column_you_are_lookingfor2)
Also good to know: If no index exists on a table, a table scan must be performed for each table referenced in a database query. The larger the table, the longer a table scan takes because a table scan requires each table row to be accessed sequentially. Although a table scan might be more efficient for a complex query that requires most of the rows in a table, for a query that returns only some table rows an index scan can access table rows more efficiently. (source from here )
Hope this helps.
An index should be used by default if you run a query against the table using it.
But I think in the query you posted it will not be used, because you are not filtering your data by the column you created your index on.
I think you would have to create the index for the artc and atelr columns to profit from that.
To see wether your index is used take a look at the execution plan that was used in the SQL Management Studio.
more info on indices: use the index luke
You dont need to include index in your query. Its managed by sql server. Also you dont need to include index in select if you want to make join to this table. Hope its clear.
You're index use "Fab_name" column which you don't filter on in your select statement, so it's of no use.
Since you're new to this, you might benefit from an index like this :
Create Index index_fab
ON TblFab (artc, atelr)
or maybe like this
Create Index index_fab
ON TblFab (atelr, artc)
...yes there are a lot of subtleties to learn.
For better performance:
List out the columns /tables which are frequently used,
Create index on those tables/columns only.
If index is properly set up, optimizer will use it automatically. By properly set up, I mean that it's selective enough, can effectively help the query etc. Read about it. You can check by yourself if index is being used by using "include actual execution plan" option in ssms.
It's generally not advised to use with(index()) hints and let optimizer decided by itself, except from very special cases when you just know better ;).

Sql Excution Plan Shows Different result for same inputs

declare #name varchar(156)
set #name ='sara'
--Query 1:
SELECT [PNAME] FROM [tbltest] where [PNAME] like '%'+#name+'%'
--Query 2:
SELECT [PNAME] FROM [tbltest] where [PNAME] like '%sara%'
suppose that there is a NoneClustered Index on [PNAME] column of [tbltest].
when running Queries, Excution plan show index Seek For Query 1 and Index Scan for Query 2.
i expected that Excution Paln Show Index Scan For both queries,but because of using parameter in the first Query,it Show Index Seek.
So what i the mater?
in both query we used '%' at oth side,and know that in this state ,sql does not consider index
but why in first Query Excution Plan Show Index Seek?
thanks
Query one uses a parameter, query 2 a constant.
The plan for query 2 will not be reused if you change the constant value.
The query for plan 1 can be. In this case, SQL Server (simply) leaves it's options open for reusing the plan.
AKA: the queries are not the same.
If you force parameterisation, then you should make both queries run like query 1. But I haven't tried...
If you do DBCC SHOW_STATISTICS on your table and the index that is being used, look for "String Index = YES" in the first row of the output. SQL Server maintains some sort of additional stats for satisfying queries like '%x'
In the first query, you'll probably see computed scalar values - look in the query plan for LikeRangeStart('%'+#name+'%'). The Index Seek is against those values as opposed to the index scan against %sara%.
How this works I don't know. Why SQL Server would not be smart enough to convert 'sara' to a constant and do the query the same way I don't know either. But I think that's what's going on.
Against %sara% it does an index scan, reading the entire index. Against %+#name+% it creates RangeStart/RangeEnd/RangeInfo computed values and uses them to do an index seek somehow taking advantage of the addtional string statistics.
I think that Mike is on the right track about whether you are hitting the index or not. Your follow-up regarding cost might need more of an understanding about how your data is distributed within the table. I've seen instances when hitting an index is more costly due to do the need for two disk reads. To understand why, you'll have to know how your data is distributed across the index, how many records will fit into a page, and what your caching scheme is.
I will say that it may be difficult to tune a query with a leading %. The database will need to fully traverse your index (or table) and hit every node looking for a value that contains "sara". Depending on your needs, you might want to consider full-text search (i.e., is the parameter value in this query used because it's provided as input from a user of your application).

How does including a SQL index hint affect query performance?

Say I have a table in a SQL 2005 database with 2,000,000+ records and a few indexes. What advantage is there to using index hints in my queries? Are there ever disadvantages to using index hints in queries?
First, try using SQL Profiler to generate a .trc file of activity in your database for a normal workload over a few hours. And then use the "Database Engine Tuning Advisor" on the SQL Server Management Studio Tools menu to see if it suggests any additional indexes, composite indexes, or covering indexes that may be beneficial.
I never use query hints and mostly work with multi-million row databases. They sometimes can affect performance negatively.
The key point that I believe everyone here is pointing to is that with VERY careful consideration the usage of index hints can improve the performance of your queries, IF AND ONLY IF, multiple indexes exist that could be used to retreive the data, AND if SQL Server is not using the correct one.
In my experience I have found that it is NOT very common to need Index hints, I believe I maybe have 2-3 queries that are in use today that have used them.... Proper index creation and database optimization should get you most of the way there to the performing database.
The index hint will only come into play where your query involves joining tables, and where the columns being used to join to the other table matches more than one index. In that case the database engine may choose to use one index to make the join, and from investigation you may know that if it uses another index the query will perform better. In that case you provide the index hint telling the database engine which index to use.
My experience is that sometimes you know more about your dataset then SQL Server does. In that case you should use query hints. In other words: You help the optimizer decide.
I once build a datawarehouse where SQL Server did not use the optimal index on a complex query. By giving an index hint in my query I managed to make a query go about 100 times faster.
Use them only after you analysed the query plan. If you think your query can run faster when using another index or by using them in a different order, give the server a hint.