我们目前正在进行数据库性能调优。 Oracle数据库有DMV Select查询来直接查找丢失的索引吗?
Microsoft SqlServer 有以下内容:https://blog.sqlauthority.com/2011/01/03/sql-server-2008-missing-index-script-download/
-- Missing Index Script
-- Original Author: Pinal Dave
SELECT TOP 25
dm_mid.database_id AS DatabaseID,
dm_migs.avg_user_impact*(dm_migs.user_seeks+dm_migs.user_scans) Avg_Estimated_Impact,
dm_migs.last_user_seek AS Last_User_Seek,
OBJECT_NAME(dm_mid.OBJECT_ID,dm_mid.database_id) AS [TableName],
'CREATE INDEX [IX_' + OBJECT_NAME(dm_mid.OBJECT_ID,dm_mid.database_id) + '_'
+ REPLACE(REPLACE(REPLACE(ISNULL(dm_mid.equality_columns,''),', ','_'),'[',''),']','')
+ CASE
WHEN dm_mid.equality_columns IS NOT NULL
AND dm_mid.inequality_columns IS NOT NULL THEN '_'
ELSE ''
END
+ REPLACE(REPLACE(REPLACE(ISNULL(dm_mid.inequality_columns,''),', ','_'),'[',''),']','')
+ ']'
+ ' ON ' + dm_mid.statement
+ ' (' + ISNULL (dm_mid.equality_columns,'')
+ CASE WHEN dm_mid.equality_columns IS NOT NULL AND dm_mid.inequality_columns
IS NOT NULL THEN ',' ELSE
'' END
+ ISNULL (dm_mid.inequality_columns, '')
+ ')'
+ ISNULL (' INCLUDE (' + dm_mid.included_columns + ')', '') AS Create_Statement
FROM sys.dm_db_missing_index_groups dm_mig
INNER JOIN sys.dm_db_missing_index_group_stats dm_migs
ON dm_migs.group_handle = dm_mig.index_group_handle
INNER JOIN sys.dm_db_missing_index_details dm_mid
ON dm_mig.index_handle = dm_mid.index_handle
WHERE dm_mid.database_ID = DB_ID()
ORDER BY Avg_Estimated_Impact DESC
GO
这是一个很好的资源:https://www.dba-scripts.com/scripts/diagnostic-and-tuning/troubleshooting/find-missing-index/
如果大家有更多答案,欢迎留言
ACCEPT SCHEMA_NAME PROMPT 'Choose the schema to analyze:'
select * from (
select 'the column ' || c.name || ' of the table ' || us.name || '.' || o.name || ' was used ' || u.equality_preds || ' times in an equality predicate and ' || u.equijoin_preds || ' times in an equijoin predicate and is not indexed' as colum_to_index
from sys.col_usage$ u,
sys.obj$ o,
sys.col$ c,
sys.user$ us
where u.obj# = o.obj#
and u.obj# = c.obj#
and us.user# = o.owner#
and u.intcol# = c.col#
and us.name='&SCHEMA_NAME'
and c.name not in (select column_name from dba_ind_columns where index_owner ='&SCHEMA_NAME')
and (u.equality_preds > 100 OR u.equijoin_preds > 100)
order by u.equality_preds+u.equijoin_preds desc)
WHERE rownum <11;
SET PAGESIZE 5000
SET LINESIZE 350
COLUMN INDEX_STATUS FORMAT A10
COLUMN TABLE_NAME FORMAT A30
COLUMN FOREIGNKEY_NAME FORMAT A30
COLUMN FOREIGNKEY_COLUMNS FORMAT A30
COLUMN INDEX_NAME FORMAT A30
COLUMN INDEX_COLUMNS FORMAT A30
SELECT
CASE
WHEN B.TABLE_NAME IS NULL THEN
'UNINDEXED'
ELSE
'INDEXED'
END AS INDEX_STATUS,
A.TABLE_NAME AS TABLE_NAME,
A.CONSTRAINT_NAME AS FOREIGNKEY_NAME,
A.FK_COLUMNS AS FOREIGNKey_COLUMNS,
B.INDEX_NAME AS INDEX_NAME,
B.INDEX_COLUMNS AS INDEX_COLUMNS
FROM
(
SELECT
A.TABLE_NAME,
A.CONSTRAINT_NAME,
LISTAGG(A.COLUMN_NAME, ',') WITHIN GROUP (ORDER BY A.POSITION) FK_COLUMNS
FROM ALL_CONS_COLUMNS A, ALL_CONSTRAINTS B
WHERE A.CONSTRAINT_NAME = B.CONSTRAINT_NAME
AND B.CONSTRAINT_TYPE = 'R'
AND A.OWNER = '&&SCHEMA_NAME'
AND A.OWNER = B.OWNER
GROUP BY
A.TABLE_NAME, A.CONSTRAINT_NAME
) A
,(
SELECT
TABLE_NAME,
INDEX_NAME,
LISTAGG(C.COLUMN_NAME, ',') WITHIN GROUP (ORDER BY C.COLUMN_POSITION) INDEX_COLUMNS
FROM ALL_IND_COLUMNS C
WHERE C.INDEX_OWNER = '&&SCHEMA_NAME'
GROUP BY TABLE_NAME, INDEX_NAME
) B
WHERE A.TABLE_NAME = B.TABLE_NAME(+)
AND B.INDEX_COLUMNS(+) LIKE A.FK_COLUMNS || '%'
ORDER BY 1 DESC, 2;