I am setting up some SQL views to be used as Power BI data sources. However, one of the queries constantly takes a long time to run, and I want to figure out what the best way to resolve this is. I am in the finance department at my employer, so SQL query tuning is not really what I do day to day, but I am trying to learn.
The execution plan is here:
https://www.brentozar.com/pastetheplan/?id=BJGHe1W0H
I can see the execution plan is asking me to add some indexes, but I am not sure if I should do that or not. I have read that the SQL hints should not be followed blindly, as it could cause other issues
The query is:
select ansapbicalls.*
from ansapbicalls
inner join
ANSAPBIStatus
on ansapbicalls.[Call Status]=ansapbistatus.[Status ID]
inner join ansapbifault on ansapbicalls.Fault=ANSAPBIFault.[Fault ID]
where ANSAPBIStatus.[Status Type]='Operations' and ANSAPBIFault.[Job Type]='RR'
And the missing index warnings are:
Missing Index (Impact 39.0531):
CREATE NONCLUSTERED INDEX [<Name of Missing Index, sysname,>]
ON [dbo].[MXMSERVCALLAUDIT] ([TYPE],[DATAAREAID]) INCLUDE ([JOBID],[RECID])
Missing Index (Impact 51.6627):
CREATE NONCLUSTERED INDEX [<Name of Missing Index, sysname,>]
ON [dbo].[MXMSERVCALLAUDIT] ([DATAAREAID],[RECID]) INCLUDE ([JOBID],[USERID],[DATE])
In my experience it is best to just try to apply the index.
Create the index by copying the code and name the Index, usually something like IX_Tablename_columnames.
Creating the index will take some time but afterwards running the query should be a lot faster. If this isn't the case (which I doubt) you can always remove the index again.
So run this code
CREATE NONCLUSTERED INDEX [IX_MXMSERVCALLAUDIT_TYPE_DATAAREAID_JOBID_RECID]
ON [dbo].[MXMSERVCALLAUDIT] ([TYPE],[DATAAREAID]) INCLUDE ([JOBID],[RECID])
CREATE NONCLUSTERED INDEX [IX_MXMSERVCALLAUDIT_DATAAREAID_RECID_JOBID_USERID_DATE]
ON [dbo].[MXMSERVCALLAUDIT] ([DATAAREAID],[RECID]) INCLUDE ([JOBID],[USERID],[DATE])
And then run the original query again.
Related
I having a non-clustered indexes created in my SQL database server with Include keyword.
Please find my non-clustered index created for FACTORS table.
CREATE NONCLUSTERED INDEX [FACTORS_BKEY_PNO_IDX] ON [dbo].[FACTORS]
(
[BATCH_KEY] ASC,
[PART_NO] ASC
)
INCLUDE([FACTOR_NAME],[FACTOR_VALUE],[FACTOR_NAME_ETL],[INDUSTRY],[PROGRAM_ID],[PROGRAM_NAME]) WITH (STATISTICS_NORECOMPUTE = OFF, DROP_EXISTING = OFF, ONLINE = OFF) ON [PRIMARY]
GO
if am having a SELECT query like below will my indcxes FACTORS_BKEY_PNO_IDX cover my select query. ( i mean will this index will help my below select query to retrieve records faster or do i need to create another indexes with exact match of INCLUDE fields).
select
BATCH_KEY ,
FACTOR_NAME ,
FACTOR_VALUE ,
INDUSTRY
PART_NO ,
CREATED_TS ,
FACTOR_NAME_ETL ,
PROGRAM_ID ,
PROGRAM_NAME
from
FACTORS
where BATCH_KEY and PART_NO
order by
PART_NO, FACTOR_NAME, FACTOR_VALUE
As the non-clustered index does not include all the fields in your SELECT query (e.g., it doesn't have Industry) then it is not a covering index. Unfortunately, it will need to get that extra data from elsewhere e.g., by going back to the original table.
Indexes can help in two main ways
a covering index which has all the columns you need for a query - where it can reduce the amount of data to be read
pre-sorting the data allowing an index seek to occur
The fastest is when both of these occur e.g., it is sorted appropriately and it is a covering index. In your example, it looks like the index's main fields are appropriate, but it isn't a covering index.
The pre-sorts can still help even if it isn't a covering index e.g., it uses the index to determine which rows to go back to the table to get the rest of the data from. It uses the index much like you would an index in a book - e.g., you use the index to find the relevant pages in the book, then go and read each page to get the information you need. In these cases, a smaller index (e.g., on just batch_key and part_no, no other fields) will function in the same way as the broader index you have. Indeed, a smaller index would be marginally better as it has less data to read (2 columns vs 8): because it has to go back to the table anyway to get the data; it may as well get the other columns from there too.
However, if the index indicates there are just too many rows for this, often the SQL engine will just read the whole table at once as if there wasn't an index on there already.
Brent Ozar does a really good video on this called How to think like an SQL Server engine - given you're using dbo. I'm guessing you're using SQL Server. I strongly recommend watching it as I learned a lot about indexes etc from it, and you seem to have a good base level of knowledge to also gain a lot.
(PS - I'm guessing that the where BATCH_KEY and PART_NO is just a typo).
I have a table with 300 million rows. One of the columns is type of date and when I select rows within two dates, it takes forever. About 3 minutes. The date field is indexed and I'm using SQL Server 2012 on a very powerful machine with high specs.
Is there anything I can do to make it significantly faster?
This is the query:
Select flightID, FlightDirection, DestinationID, FlightDuration
from T_Flights (nolock)
where FlightDate between #fromDate And #toDate
Scan is not good in the execution plan.
It should be seek.
try to add the columns in the select statement to the index and run the query.
If it still doesn't work another thing you could do is use the Database Engine Tuning Advisor to see if it gives you any suggestions. Select the query in SSMS, right click and select Analyze Query in Database Engine Tuning Advisor.
From your discussion, I understand that you are not having proper index on the date column. You have mentioned that index is being scanned. As you have not given enough details about which index being scanned, I would suggest you to create included index for suiting your query.
Now, your query can be satisfied by the below Nonclustered index itself. But, adding index brings additional overhead of maintaining it. So, add the index, only when your workload demanding it.
-- Assuming FlightID is primary key. primary key is included by default and no need
--to add it separately. If FlightID is not primary key, add that to the list
-- of included columns
CREATE NONCLUSTERED INDEX NCI_FlightDate ON dbo.T_Flights(FlightDate)
INCLUDE (FlightDirection, DestinationID, FlightDuration)
If you have 300 million rows, then an index on (flightdate) might help -- but depending on how many flights per day and how many days. You can include the other columns in the index which should help a bit more.
However, for what you want to do, it sounds like a better solution is to partition the table. This would store each day's of data in a separate "file" and only the ones needed for the query would be read for a given query.
The downside is that this requires re-creating the table. However, you might find that this is a big win performance-wise so worth the effort.
You need to use the Database Engine Tuning Advisor to optimize the query execution
I have a table on which I have created Non-Clustered Index, but in a query I am not able to make Table Seek on ipReq. As you can see in first image I have created index and also tried with different combinations. But didn't get success to make this table in seek. Due to this query my overall performance has been degraded. Let me know if anyone wants more information which I haven't added.
Im running a query that is taking 2 seconds but it should perform better, so I run the Execute Plan details from SQL Managemenet Studio and I found a "step" in the process that the Cost is 70%.
Then, I right click on the item and I found an option that says "Missing Index Details", after I clicked that then a query with a recommendation is generated:
/*
Missing Index Details from SQLQuery15.sql - (local).application_prod (appprod (58))
The Query Processor estimates that implementing the following index could improve the query cost by 68.8518%.
*/
/*
USE [application_prod]
GO
CREATE NONCLUSTERED INDEX [<Name of Missing Index, sysname,>]
ON [dbo].[cloud_document] ([isactivedocument])
INCLUDE ([objectuid])
GO
*/
So my question is exactly what happens if I execute the query? Is it going to affect my database, is there any sideback or sideeffects after applying that?
Thanks a lot and appreciate in advance.
Running the query qill create an Index on the table specified (cloud_document).
This should improve the reading performance and improve performance/query time.
It does also affect the performance of INSERT/UPDATE/DELETE statements as the indexes needs to be maintained during these statements.
The decision to use indexing, how many indexes and what the index consists of is more an art than an exact science.
The actual maintinance of indexes, defragmenting, and statistics is something that can be automated, but should be left, until you have a better understanding of what indexes are and what they do.
I would recomend that you start reading some documentation regarding indexing.
May start with Stairway to SQL Server Indexes
The literal meaning is telling you to build an index on isactivedocument of table [dbo].[cloud_document], from which I assume you are using isactivedocument as a condition to filter the table, and select the column objectuid. Something like
select objectuid, ... from [dbo].[cloud_document] where isactivedocument = 0/1
Note that the "Clustered Index Scan (70%)" doesn't mean it's a problem of the clustered index. It means you don't have index on isactivedocument, then sql engine has to scan clustered index to find what you want. That's why it's taking so much pressure. Once you create index on isactivedocument, check out the plan again, and you'll see the node becomes "index seek", which is a much faster way to find out what you want.
Usually if your database stress mainly comes from query, new index doesn't do much harm to your system. Just go ahead and create the index. But of course you need to keep index quantities as less as possible.
I am tuning my SQL server and when I show my execution plan for one of my queries at the top it reads:
"Missing Index (Impact 99.7782): CREATE NONCLUSTERED INDEX..."
So I looked at the missing index details and it is showing this:
/*
Missing Index Details from ExecutionPlan1.sqlplan
The Query Processor estimates that implementing the following index could improve the query cost by 99.7782%.
*/
/*
USE [phsprod]
GO
CREATE NONCLUSTERED INDEX [<Name of Missing Index, sysname,>]
ON [dbo].[address] ([userid])
GO
*/
I have only been working with SQL for about a month now and I have never done anything with this as all my tables have been built for me already. Can anyone help explain/give me any ideas on what to do with this? Thanks.
That means SQL Server is suggesting that your query could run faster with an index. Indexes add overhead and disk storage, so you should ignore this hint unless the query is giving performance problems in production.
To create the index, uncomment the statement after use, replace [<Name of Missing Index, sysname,>] with a real name, and run it:
USE [phsprod]
GO
CREATE NONCLUSTERED INDEX IX_Address_UserId
ON [dbo].[address] ([userid])
That means SQL Server is suggesting that your query could run faster with this index.
It can mean that your current indexes are not the greatest for the query you are running. Maybe your query could be optimised. Or maybe you COULD add the index. But if you decide to do this, you have to analyse carefully.
Indeed, indexes add overhead and disk storage. But, it can also improve performance.
For instance, if you always search in your table based on a "userid", then maybe it can payoff to add an index on that column, since SQL will be able to search usign this index.
Think a little bit of this like if you search for a word in a dictionnary.
If your looking for the word "dog", your going to search for "d" and then words that begin with "do" to finally find the word "dog".
If the words were not in alphabetical order in the dictionnary, you would have to search the whole dictionnary to find the word "dog"!
A clustered index (or a primary key) is the order of your columns.
Right now, it seems that you don't have an index on the column "userid". So SQL Server has (probably) to scan the entire table until he finds the userid.
If you add a nonclustered index, it will not re-order your table, but it will tell SQL Server between what range he should search to find the userid you want to. (Like "in the dictionnary, between page 20 and 30") So it will not have to search the whole table to find it.
But it also means that when you add new data to the table, or remove, or modify, he needs to keep his index up-to-date. Generally, a few indexes don't hurt, but you need to be sure they are needed. You don't want to add too much indexes as they can hurt performances if you add too much.
And if your table contains only a few hundreds of rows, maybe it won't show you a big improvement of performances. But over time, when your table grows, it may make a difference.
Hope that helps!