SQL missing indexes from select Databases - sql

I am trying to use the SQL missing index feature; however.... I am not the DBO or admin. I have access to one database. is there a way to run this for only a single database without elevated permission
SELECT
migs.avg_total_user_cost * (migs.avg_user_impact / 100.0) * (migs.user_seeks + migs.user_scans) AS improvement_measure,
'CREATE INDEX [missing_index_' + CONVERT (varchar, mig.index_group_handle) + '_' + CONVERT (varchar, mid.index_handle)
+ '_' + LEFT (PARSENAME(mid.statement, 1), 32) + ']'
+ ' ON ' + mid.statement
+ ' (' + ISNULL (mid.equality_columns,'')
+ CASE WHEN mid.equality_columns IS NOT NULL AND mid.inequality_columns IS NOT NULL THEN ',' ELSE '' END
+ ISNULL (mid.inequality_columns, '')
+ ')'
+ ISNULL (' INCLUDE (' + mid.included_columns + ')', '') AS create_index_statement,
migs.*, mid.database_id, mid.[object_id]
FROM sys.dm_db_missing_index_groups mig
INNER JOIN sys.dm_db_missing_index_group_stats migs ON migs.group_handle = mig.index_group_handle
INNER JOIN sys.dm_db_missing_index_details mid ON mig.index_handle = mid.index_handle
WHERE migs.avg_total_user_cost * (migs.avg_user_impact / 100.0) * (migs.user_seeks + migs.user_scans) > 10
ORDER BY migs.avg_total_user_cost * migs.avg_user_impact * (migs.user_seeks + migs.user_scans) DESC

dm_db_missing_index_details dynamic view has Database Id in it.
WHERE migs.avg_total_user_cost * ( migs.avg_user_impact / 100.0 ) * ( migs.user_seeks + migs.user_scans ) > 10
AND mid.database_ID = Db_id('Database name') --Here
Note : Users must be granted the VIEW SERVER STATE permission or any permission that implies the VIEW SERVER STATE permission to access all the three dynamic view used in your query

Add following in the where clause:
AND mid.database_ID = Db_id('Your Database name')

Related

SQL Server : generate a different value for each output row

I am running a query in which I need the SCORE to have a different output for each row. I am able to do it per execution but I have had no luck with RAND as I get a convert from varchar to int error. I need variable number per execution within a range with no decimals. Is there anyway to do this? Any help is appreciated.
SELECT
'Row_Number^FEED_date^database_id^station_id^Form_Type^FBCS_CLAIM_ID^FBCS_LINE_ID^Pay^SCORE^score_date^reason_code^reason_description'
UNION ALL
SELECT
CAST(ROW_NUMBER() OVER ( ORDER BY ( SELECT 1 ) ) AS VARCHAR(20)) + '^' +
CONVERT(VARCHAR, getdate(), 112)+ '^' +
'FBCSTrans'+ '^' + ---took off the 1 so if problems put it back
stationnumber+ '^' +
case when claimtype = 0 then 'HCFA 1500' else 'UB 1450' end+ '^' +
CAST(Claims.claimid AS VARCHAR(50)) + '^' +
CAST(LineID AS VARCHAR(50)) + '^' +
'Y'+ '^' +
**RAND() * 100000 AS random_number** + '^' +
CONVERT(VARCHAR, getdate(), 112)+ '^' +
'' + '^' + ''
FROM
Claims
JOIN
ClaimLines ON Claims.Claimid = Claimlines.Claimid
JOIN
Facilities ON Claims.FacilityID = Facilities.FacilityID
WHERE
Claims.ClaimId IN (SELECT TOP(100000) ClaimId
FROM CLAIMS
WHERE Claims.RecordStatus = 55 AND facilityid = 40)
USE [DATABASE NAME]
SELECT 'Row_Number^FEED_date^database_id^station_id^Form_Type^FBCS_CLAIM_ID^FBCS_LINE_ID^Pay^SCORE^score_date^reason_code^reason_description'
UNION ALL
SELECT
CAST(ROW_NUMBER() OVER ( ORDER BY ( SELECT 1 ) ) AS VARCHAR(20)) + '^' +
CONVERT(VARCHAR, getdate(), 112)+ '^' +
'DATABASE NAME'+ '^' + ---took off the 1 so if problems put it back
stationnumber+ '^' +
case when claimtype = 0 then 'HCFA 1500' else 'UB 1450' end+ '^' +
CAST(Claims.claimid AS VARCHAR(50)) + '^' +
CAST(LineID AS VARCHAR(50)) + '^' +
'Y'+ '^' +
CAST (FLOOR(RAND(CHECKSUM(NEWID()))*(1000-0+1)+100) As NVARCHAR) + '^' +
CONVERT(VARCHAR, getdate(), 112)+ '^' +
'' + '^' + ''
FROM Claims
JOIN ClaimLines on Claims.Claimid = Claimlines.Claimid
JOIN Facilities ON Claims.FacilityID = Facilities.FacilityID
WHERE Claims.ClaimId IN (SELECT TOP(100000)ClaimId FROM CLAIMS WHERE Claims.RecordStatus = 55 and facilityid=40)

Create dynamic column in SQL as VARCHAR MAX

I am using a standard SQL query to determine where indexes are needed however one of the columns which gives you the TSQL to build the index is getting cutoff because there are so many fields in the index. The columns themselves also appear cutoff. How do I modify it so CreateIndexStatement is a VARCHAR MAX which doesn't get cutoff:
SELECT sys.objects.name
, (avg_total_user_cost * avg_user_impact) * (user_seeks + user_scans) AS Impact
, 'CREATE NONCLUSTERED INDEX ix_IndexName ON ' + sys.objects.name COLLATE DATABASE_DEFAULT + ' ( ' + IsNull(mid.equality_columns, '') + CASE WHEN mid.inequality_columns IS NULL
THEN ''
ELSE CASE WHEN mid.equality_columns IS NULL
THEN ''
ELSE ',' END + mid.inequality_columns END + ' ) ' + CASE WHEN mid.included_columns IS NULL
THEN ''
ELSE 'INCLUDE (' + mid.included_columns + ')' END + ';' AS CreateIndexStatement
, mid.equality_columns
, mid.inequality_columns
, mid.included_columns
FROM sys.dm_db_missing_index_group_stats AS migs
INNER JOIN sys.dm_db_missing_index_groups AS mig ON migs.group_handle = mig.index_group_handle
INNER JOIN sys.dm_db_missing_index_details AS mid ON mig.index_handle = mid.index_handle AND mid.database_id = DB_ID()
INNER JOIN sys.objects WITH (nolock) ON mid.OBJECT_ID = sys.objects.OBJECT_ID
WHERE (migs.group_handle IN
(
SELECT TOP (500) group_handle
FROM sys.dm_db_missing_index_group_stats WITH (nolock)
ORDER BY (avg_total_user_cost * avg_user_impact) * (user_seeks + user_scans) DESC))
AND OBJECTPROPERTY(sys.objects.OBJECT_ID, 'isusertable')=1
ORDER BY 2 DESC , 3 DESC
Just cast the first column in the list as a varchar(max)
SELECT cast(ColumnA as varchar(max))
+ ColumnB + ColumnC + .... + ColumnZ AS SomeColumn
FROM SomeTable

Added a few lines of code and now query is taking 5x as long to run. Executions plans are almost identical

I have a query that has been in production a long time and takes an average of 4 seconds to run. I added the code below which is a declaration of a table and then an insert into that table. then the select query joins to that and returns 1 field from it in the select statement. Now the query takes up to 25 seconds to run.
DECLARE #tmpStageLoc TABLE
(
LP VARCHAR(20) ,
stgloc VARCHAR(20)
)
INSERT INTO #tmpStageLoc
EXEC dbo.spGetStageLoc #ActLP = #LP;
--Try to get data from DW tables first.
INSERT INTO [COMMON_INFORMATION].[dbo].[ProcTmpData]
( SPID ,
DataSetName ,
IntValue1 , --JRB004
ChValue1 , --JRB001
String1 ,
InsDate
)
SELECT DISTINCT
##SPID ,
#datasetname ,
ls.ToDC ,
col.Cust_No --JRB001
,
REPLACE(#LOADNUM, ' ', '') + --JRB007
'~' + 'N/A'
+ --JRB005 Wave number no longer printed on label
'~' + CASE WHEN la.stage_loc IS NULL THEN ''
ELSE la.stage_loc + '-' + ISNULL(la.misc_info,
'')
END + '~' + fa.OrderControlNo + '~' + col.Cust_No
+ '~' + SUBSTRING(cst.name, 1, 20) + '~'
+ SUBSTRING(cst.name, 21, 5) + '~' + LEFT(cst.address1
+ ', '
+ CASE
WHEN cst.address2 IS NULL
THEN ''
ELSE ( cst.address2
+ ', ' )
END + cst.city
+ ', '
+ cst.state, 45)
+ '~' + ls.StopNO + '~' + ls.LoadNo + '~' + e.first_name
+ ' ' + e.last_name + --JRB009
'~' + --JRB009
CASE WHEN cst.plt_usage IS NULL --JRB009
THEN '' --JRB009
ELSE --JRB009
'# ' + LEFT(cst.plt_usage, 20) --JRB009
END + '~' + ISNULL(STG.STGLOC, '') + '~' --JRB009
,
#RUNDTE
FROM dbo.tblFactAction AS fa
LEFT OUTER JOIN COMMON_INFORMATION.dbo.LoadStop AS ls ON LEFT(fa.OrderControlNo,
8) = ls.ExtOrderNo
AND ls.LatestLoadFlg = 1 --JRB008
LEFT OUTER JOIN dbo.RP_LaneAssign AS la ON ls.LoadNo = la.carrier_move_id
OR ls.ExtOrderNo = la.order_num
LEFT OUTER JOIN dbo.Cust_Order_Lookup AS col ON fa.OrderControlNo = col.Order_Control_no
LEFT OUTER JOIN COMMON_INFORMATION.dbo.Partners AS cst ON col.Cust_No = cst.partner_shipto
LEFT OUTER JOIN COMMON_INFORMATION.dbo.Employee AS e ON fa.EmployeeID = CAST(e.emp_no AS VARCHAR(40))
LEFT OUTER JOIN #tmpStageLoc STG ON fa.actlp = STG.LP
WHERE fa.ActLP = #LOADNUM
AND fa.AssignTypeID IN ( 'PB01', 'PF01' )
I have looked at the execution plans in SQL Sentry Plan Explorer and they look almost identical. I am using the free version of the software. I am at a loss at why the query takes so long to run. just an FYI when I execute the stored procedure that is being called it runs instantly.
Any ideas on how I can figure out why the query now runs for so long?

SQL Server 2008 r2 high cpu usage

We running a photo sharing website in Windows Server 2008 r2 ent edition & SQL Server 2008 r2 ent edition. Server configuration is xeon 5620 with 48GB RAM & 4 x 450GB 15k Scsi Hdd's.
we have about minimum 50 and max 500 active connections on DB as per last month average. Now also the average is same. 1 Month back our sql server cpu usage is less then 1% but now it's using minimum 25% and upto 100% always. This problem we are facing from last 8 days. From this last 8 days anwards our CPU usage is increasing always when we start SQL Service & when we stop it's normal only. I request you can any one tell me how to solve this problem.
agreed with TomTom, you have to get to the bottom of it. Good guess is lack/inaccurate indexing, it very often results with high CPU w/o high number of sessions.
Check the information in your DMV's ( be careful though, they're just hints from SQL engine, should be analyzed by a trained professional ) :
SELECT
migs.avg_total_user_cost * (migs.avg_user_impact / 100.0) * (migs.user_seeks + migs.user_scans) AS improvement_measure,
'CREATE INDEX [missing_index_' + CONVERT (varchar, mig.index_group_handle) + '_' + CONVERT (varchar, mid.index_handle)
+ '_' + LEFT (PARSENAME(mid.statement, 1), 32) + ']'
+ ' ON ' + mid.statement
+ ' (' + ISNULL (mid.equality_columns,'')
+ CASE WHEN mid.equality_columns IS NOT NULL AND mid.inequality_columns IS NOT NULL THEN ',' ELSE '' END
+ ISNULL (mid.inequality_columns, '')
+ ')'
+ ISNULL (' INCLUDE (' + mid.included_columns + ')', '') AS create_index_statement,
migs.*, mid.database_id, mid.[object_id]
FROM sys.dm_db_missing_index_groups mig
INNER JOIN sys.dm_db_missing_index_group_stats migs ON migs.group_handle = mig.index_group_handle
INNER JOIN sys.dm_db_missing_index_details mid ON mig.index_handle = mid.index_handle
WHERE migs.avg_total_user_cost * (migs.avg_user_impact / 100.0) * (migs.user_seeks + migs.user_scans) > 10
ORDER BY migs.avg_total_user_cost * migs.avg_user_impact * (migs.user_seeks + migs.user_scans) DESC

Grouping by an alias

SELECT COALESCE (rsu.last_name + ', ' + rsu.first_name + ' ' + rsu.middle_name + '.', rsu.last_name + ', ' + rsu.first_name) as student_name, rsu.day_id
FROM roster_school_unattended rsu
GROUP BY student_name
ORDER BY rsu.day_id
does not work. What's the most elegant workaround?
EDIT: The result-set should have something like this
Muster, Hans | 2011-11-01
Muster, Hans | 2011-11-02
Williams, Clay | 2011-10-01
Williams, Clay | 2011-10-02
First the name is grouped by, then for each name there is a sorting of dates.
Doing a subselect would let you avoid having to type it twice:
select t.student_name, t.day_id
from (
select COALESCE (rsu.last_name + ', ' + rsu.first_name + ' ' + rsu.middle_name + '.', rsu.last_name + ', ' + rsu.first_name) as student_name,
rsu.day_id
from roster_school_unattended rsu ) t
group by t.student_name
order by t.day_id
But you've still got a problem with the day_id - it's not included in your grouping clause, so you won't be able to select it without using an aggregate (such as MAX).
You can use a subquery:
select student_name, day_id
from (SELECT COALESCE (rsu.last_name + ', ' + rsu.first_name + ' ' + rsu.middle_name + '.', rsu.last_name + ', ' + rsu.first_name) as student_name, rsu.day_id
FROM roster_school_unattended rsu
) as rows
GROUP BY student_name
ORDER BY day_id
EDIT: Whole thing replaced as the recent edit to the question shows that GROUP BY isn't needed...
Without any changes for 'elegance'...
SELECT
rsu.last_name + ', ' + rsu.first_name + COALESCE (' ' + rsu.middle_name + '.', '') as student_name,
rsu.day_id
FROM
roster_school_unattended AS [rsu]
ORDER BY
rsu.last_name + ', ' + rsu.first_name + COALESCE (' ' + rsu.middle_name + '.', ''),
rsu.day_id
Possible change for 'elegance'...
WITH formatted_rsu AS
(
SELECT rsu.last_name + ', ' + rsu.first_name + COALESCE (' ' + rsu.middle_name + '.', '') as student_name, rsu.day_id
FROM roster_school_unattended AS [rsu]
)
SELECT student_name, day_id
FROM formatted_rus
ORDER BY student_name, day_id
Another possible using APPLY...
SELECT formatted_rsu.student_name, rsu.day_id
FROM roster_school_unattended AS [rsu]
CROSS APPLY (SELECT rsu.last_name + ', ' + rsu.first_name + COALESCE (' ' + rsu.middle_name + '.', '') as student_name) AS [formatted_rsu]
ORDER BY formatted_rsu.student_name, rsu.day_id
I would go with:
SELECT
rsu.last_name
+ ', ' + rsu.first_name
+ COALESCE ( ' ' + rsu.middle_name + '.'
, ''
)
AS student_name
, rsu.day_id
FROM
roster_school_unattended AS rsu
ORDER BY
rsu.last_name
, rsu.first_name
, rsu.middle_name
, rsu.day_id
CROSS APPLY is your friend for aliasing non-windowed expressions:
SELECT this.student_name, MAX(rsu.day_id) AS day_id
FROM roster_school_unattended rsu
CROSS APPLY (
SELECT COALESCE (
rsu.last_name+', '+rsu.first_name+' '+rsu.middle_name+'.'
, rsu.last_name+', '+rsu.first_name
) AS student_name
) this
GROUP BY this.student_name
ORDER BY this.student_name, MAX(rsu.day_id)
(assumes SQL2005 and above).