2009-01-08 7 views
18

Je me demande ce que le plus simple façon de lister tous les index pour toutes les tables dans une base de données est.Liste de tous les index

Dois-je appeler sp_helpindex pour chaque table et stocker les résultats dans une table temporaire, ou y a-t-il un moyen plus facile?

Quelqu'un peut-il expliquer pourquoi les contraintes sont stockées dans sysobjects mais pas les index?

Répondre

6

Vous pouvez référencer sysindexes

Une autre astuce consiste à regarder le texte de sp_helpindex pour voir comment il reconstitue les informations des tables sous-jacentes.

sp_helptext 'sp_helpindex' 

Je n'ai pas une référence pour cela, mais je crois que les contraintes ne sont pas stockées dans sysobjects parce qu'ils sont une sorte de chose différente; sysindexes contient des méta-données sur les objets dans sysobjects.

4

Si vous avez besoin de plus amples informations, voici un beau script SQL, que je l'utilise de temps en temps:

DECLARE @TabName varchar(100) 

CREATE TABLE #temp (
    TabName varchar(200), IndexName varchar(200), IndexDescr varchar(200), 
    IndexKeys varchar(200), IndexSize int 
) 

DECLARE cur CURSOR FAST_FORWARD LOCAL FOR 
    SELECT name FROM sysobjects WHERE xtype = 'U' 

OPEN cur 

FETCH NEXT FROM cur INTO @TabName 
WHILE @@FETCH_STATUS = 0 
    BEGIN 
     INSERT INTO #temp (IndexName, IndexDescr, IndexKeys) 
     EXEC sp_helpindex @TabName 

     UPDATE #temp SET TabName = @TabName WHERE TabName IS NULL 

     FETCH NEXT FROM cur INTO @TabName 
    END 

CLOSE cur 
DEALLOCATE cur 

DECLARE @ValueCoef int 
SELECT @ValueCoef = low FROM Master.dbo.spt_values WHERE number = 1 AND type = N'E' 

UPDATE #temp SET IndexSize = 
    ((CAST(sysindexes.used AS bigint) * @ValueCoef)/1024)/1024 
     FROM sysobjects INNER JOIN sysindexes ON sysobjects.id = sysindexes.id 
      INNER JOIN #temp T ON T.TabName = sysobjects.name AND T.IndexName = sysindexes.name 

SELECT * FROM #temp 
ORDER BY TabName, IndexName 

DROP TABLE #temp 
33

Voici un exemple du genre de requête dont vous avez besoin:

select 
    i.name as IndexName, 
    o.name as TableName, 
    ic.key_ordinal as ColumnOrder, 
    ic.is_included_column as IsIncluded, 
    co.[name] as ColumnName 
from sys.indexes i 
join sys.objects o on i.object_id = o.object_id 
join sys.index_columns ic on ic.object_id = i.object_id 
    and ic.index_id = i.index_id 
join sys.columns co on co.object_id = i.object_id 
    and co.column_id = ic.column_id 
where i.[type] = 2 
and i.is_unique = 0 
and i.is_primary_key = 0 
and o.[type] = 'U' 
--and ic.is_included_column = 0 
order by o.[name], i.[name], ic.is_included_column, ic.key_ordinal 
; 

Celui-ci est assez spécifique à un certain but (je l'utilise dans une petite application C# pour trouver des index dupliqués et formater la sortie pour qu'elle soit réellement lisible par un humain). Mais vous pouvez facilement l'adapter à vos besoins.

+0

le type 2 est non-cluster, quelle que soit la raison pour laquelle vous avez filtré tous les autres types d'index? la question ne l'exige pas. ref https://msdn.microsoft.com/en-us/library/ms173760%28v=sql.110%29.aspx –

-1

Les autres réponses sont spécifiques à SQL Server, en utilisant sysobjects ou sys. * Catalogues - vous pouvez également consulter les vues ISO_SCHEMA standard.

Elles sont prises en charge par plusieurs fournisseurs de bases de données, par ex. SQL Server, MySQL, PostgreSQL et plus encore. Celui que vous êtes le plus probable pour la recherche est:

SELECT * FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS 

qui listera unique, clé primaire et les clés étrangères - tout ce qui se transforme en un index sur SQL Server.

+0

+1 pour la compatibilité ANSI! –

+12

La vue standard ANSI, 'INFORMATION_SCHEMA.TABLE_CONSTRAINTS' ne montrera pas index réguliers: elle n'affiche que 'CONSTRAINT_TYPE's de' UNIQUE', 'PRIMARY KEY',' FOREIGN KEY' ou' CHECK'. Voir [la section appropriée "SQL-99 Complete, Really"] (https://mariadb.com/kb/fr/sql-99-complete-really/16-sql-catalogs/the-information-schema/information_schema -views/information_schematable_constraints /) –

3

Voici un script qui retournera des instructions SQL pour recréer tous les index d'une base de données.

SELECT ' CREATE ' + 
     CASE 
      WHEN I.is_unique = 1 THEN ' UNIQUE ' 
      ELSE '' 
     END + 
     I.type_desc COLLATE DATABASE_DEFAULT + ' INDEX ' + 
     I.name + ' ON ' + 
     SCHEMA_NAME(T.schema_id) + '.' + T.name + ' (' + 
     KeyColumns + ') ' + 
     ISNULL(' INCLUDE (' + IncludedColumns + ') ', '') + 
     ISNULL(' WHERE ' + I.filter_definition, '') + ' WITH (' + 
     CASE 
      WHEN I.is_padded = 1 THEN ' PAD_INDEX = ON ' 
      ELSE ' PAD_INDEX = OFF ' 
     END + ',' + 
     'FILLFACTOR = ' + CONVERT(
      CHAR(5), 
      CASE 
       WHEN I.fill_factor = 0 THEN 100 
       ELSE I.fill_factor 
      END 
     ) + ',' + 
     -- default value 
     'SORT_IN_TEMPDB = OFF ' + ',' + 
     CASE 
      WHEN I.ignore_dup_key = 1 THEN ' IGNORE_DUP_KEY = ON ' 
      ELSE ' IGNORE_DUP_KEY = OFF ' 
     END + ',' + 
     CASE 
      WHEN ST.no_recompute = 0 THEN ' STATISTICS_NORECOMPUTE = OFF ' 
      ELSE ' STATISTICS_NORECOMPUTE = ON ' 
     END + ',' + 
     ' ONLINE = OFF ' + ',' + 
     CASE 
      WHEN I.allow_row_locks = 1 THEN ' ALLOW_ROW_LOCKS = ON ' 
      ELSE ' ALLOW_ROW_LOCKS = OFF ' 
     END + ',' + 
     CASE 
      WHEN I.allow_page_locks = 1 THEN ' ALLOW_PAGE_LOCKS = ON ' 
      ELSE ' ALLOW_PAGE_LOCKS = OFF ' 
     END + ') ON [' + 
     DS.name + ' ] ' + CHAR(13) + CHAR(10) + ' GO' [CreateIndexScript] 
FROM sys.indexes I 
     JOIN sys.tables T 
      ON T.object_id = I.object_id 
     JOIN sys.sysindexes SI 
      ON I.object_id = SI.id 
      AND I.index_id = SI.indid 
     JOIN (
       SELECT * 
       FROM (
          SELECT IC2.object_id, 
            IC2.index_id, 
            STUFF(
             (
              SELECT ' , ' + C.name + CASE 
                     WHEN MAX(CONVERT(INT, IC1.is_descending_key)) 
                      = 1 THEN 
                      ' DESC ' 
                     ELSE 
                      ' ASC ' 
                    END 
              FROM sys.index_columns IC1 
               JOIN sys.columns C 
                 ON C.object_id = IC1.object_id 
                 AND C.column_id = IC1.column_id 
                 AND IC1.is_included_column = 
                  0 
              WHERE IC1.object_id = IC2.object_id 
               AND IC1.index_id = IC2.index_id 
              GROUP BY 
               IC1.object_id, 
               C.name, 
               index_id 
              ORDER BY 
               MAX(IC1.key_ordinal) 
               FOR XML PATH('') 
            ), 
             1, 
             2, 
             '' 
           ) KeyColumns 
          FROM sys.index_columns IC2 
            --WHERE IC2.Object_id = object_id('Person.Address') --Comment for all tables 
          GROUP BY 
            IC2.object_id, 
            IC2.index_id 
         ) tmp3 
      )tmp4 
      ON I.object_id = tmp4.object_id 
      AND I.Index_id = tmp4.index_id 
     JOIN sys.stats ST 
      ON ST.object_id = I.object_id 
      AND ST.stats_id = I.index_id 
     JOIN sys.data_spaces DS 
      ON I.data_space_id = DS.data_space_id 
     JOIN sys.filegroups FG 
      ON I.data_space_id = FG.data_space_id 
     LEFT JOIN (
       SELECT * 
       FROM (
          SELECT IC2.object_id, 
            IC2.index_id, 
            STUFF(
             (
              SELECT ' , ' + C.name 
              FROM sys.index_columns IC1 
               JOIN sys.columns C 
                 ON C.object_id = IC1.object_id 
                 AND C.column_id = IC1.column_id 
                 AND IC1.is_included_column = 
                  1 
              WHERE IC1.object_id = IC2.object_id 
               AND IC1.index_id = IC2.index_id 
              GROUP BY 
               IC1.object_id, 
               C.name, 
               index_id 
               FOR XML PATH('') 
            ), 
             1, 
             2, 
             '' 
           ) IncludedColumns 
          FROM sys.index_columns IC2 
            --WHERE IC2.Object_id = object_id('Person.Address') --Comment for all tables 
          GROUP BY 
            IC2.object_id, 
            IC2.index_id 
         ) tmp1 
       WHERE IncludedColumns IS NOT NULL 
      ) tmp2 
      ON tmp2.object_id = I.object_id 
      AND tmp2.index_id = I.index_id 
WHERE I.is_primary_key = 0 
     AND I.is_unique_constraint = 0 
     --AND T.name NOT LIKE 'mt_%' 
     --AND I.name NOT LIKE 'mt_%' 
      --AND I.Object_id = object_id('Person.Address') --Comment for all tables 
      --AND I.name = 'IX_Address_PostalCode' --comment for all indexes 
Questions connexes