Creates an index on one or more columns in a table.
create [unique] [clustered | nonclustered] index index_name on [[database.]owner.]table_name (column_name [asc | desc] [, column_name [asc | desc]]...) [with { fillfactor = pct, max_rows_per_page = num_rows, reservepagegap = num_pages, consumers = x, ignore_dup_key, sorted_data, [ignore_dup_row | allow_dup_row], statistics using num_steps values } ] [on segment_name]
prohibits duplicate index values (also called “key values”). The system checks for duplicate key values when the index is created (if data already exists), and each time data is added with an insert or update. If there is a duplicate key value or if more than one row contains a null value, the command fails, and Adaptive Server prints an error message giving the duplicate entry.
WARNING! Adaptive Server does not detect duplicate rows if a table contains any non-null text or image columns.
update and insert commands that generate duplicate key values fail, unless the index was created with ignore_dup_row or ignore_dup_key.
Composite indexes (indexes in which the key value is composed of more than one column) can also be unique.
The default is nonunique. To create a nonunique clustered index on a table that contains duplicate rows, specify allow_dup_row or ignore_dup_row. See “Duplicate rows”.
means that the physical order of rows on the current database device is the same as the indexed order of the rows. The bottom, or leaf level, of the clustered index contains the actual data pages. A clustered index almost always retrieves data faster than a nonclustered index. Only one clustered index per table is permitted. See “Creating clustered indexes”.
If clustered is not specified, nonclustered is assumed.
means that the physical order of the rows is not the same as their indexed order. The leaf level of a nonclustered index contains pointers to rows on data pages. You can have as many as 249 nonclustered indexes per table.
is the name of the index. Index names must be unique within a table, but need not be unique within a database.
is the name of the table in which the indexed column or columns are located. Specify the database name if the table is in another database, and specify the owner’s name if more than one table of that name exists in the database. The default value for owner is the current user, and the default value for database is the current database.
is the column or columns to which the index applies. Composite indexes are based on the combined values of as many as 16 columns. The sum of the maximum lengths of all the columns used in a composite index cannot exceed 600 bytes. List the columns to be included in the composite index (in the order in which they should be sorted) inside the parentheses following table_name.
specifies whether the index is to be created in ascending or descending order for the column specified. The default is ascending order.
specifies how full Adaptive Server makes each page when it creates a new index on existing data. The fillfactor percentage is relevant only when the index is created. As the data changes, the pages are not maintained at any particular level of fullness.
The value you specify is not saved in sysindexes for display by sp_helpindex or for later use by the reorg command. Use sp_chgattribute to create stored fillfactor values.
The default for fillfactor is 0; this is used when you do not include with fillfactor in the create index statement (unless the value has been changed with sp_configure). When specifying a fillfactor, use a value between 1 and 100.
A fillfactor of 0 creates clustered indexes with completely full pages and nonclustered indexes with completely full leaf pages. It leaves a comfortable amount of space within the index B-tree in both the clustered and nonclustered indexes. There is seldom a reason to change the fillfactor.
If the fillfactor is set to 100, Adaptive Server creates both clustered and nonclustered indexes with each page 100 percent full. A fillfactor of 100 makes sense only for read-only tables—tables to which no additional data will ever be added.
fillfactor values smaller than 100 (except 0, which is a special case) cause Adaptive Server to create new indexes with pages that are not completely full. A fillfactor of 10 might be a reasonable choice if you are creating an index on a table that will eventually hold a great deal more data, but small fillfactor values cause each index (or index and data) to occupy more storage space.
WARNING! Creating a clustered index with a fillfactor affects the amount of storage space your data occupies, since Adaptive Server redistributes the data as it creates the clustered index.
limits the number of rows on data pages and the leaf level pages of indexes. max_rows_per_page and fillfactor are mutually exclusive. Unlike fillfactor, the max_rows_per_page value is maintained until it is changed with sp_chgattribute.
If you do not specify a value for max_rows_per_page, Adaptive Server uses a value of 0 when creating the table. Values for tables and clustered indexes are between 0 and 256. The maximum number of rows per page for nonclustered indexes depends on the size of the index key. Adaptive Server returns an error message if the specified value is too high.
A max_rows_per_page value of 0 creates clustered indexes with full pages and nonclustered indexes with full leaf pages. It leaves a comfortable amount of space within the index B-tree in both clustered and nonclustered indexes.
If max_rows_per_page is set to 1, Adaptive Server creates both clustered and nonclustered indexes with one row per page at the leaf level. Use low values to reduce lock contention on frequently accessed data. However, low max_rows_per_page values cause Adaptive Server to create new indexes with pages that are not completely full, uses more storage space, and may cause more page splits.
If Component Integration Services is enabled, you cannot use max_rows_per_page for remote servers.
WARNING! Creating a clustered index with max_rows_per_page can affect the amount of storage space your data occupies, since Adaptive Server redistributes the data as it creates the clustered index.
specifies a ratio of filled pages to empty pages to be left during extent I/O allocation operations. For each specified num_pages, an empty page is left for future expansion of the index. Valid values are 0 – 255. The default is 0.
cancels attempts of duplicate key entry into a table that has a unique index (clustered or nonclustered). Adaptive Server cancels the attempted insert or update of a duplicate key with an informational message. After the cancellation, the transaction containing the duplicate key proceeds to completion.
You cannot create a unique index on a column that includes duplicate values or more than one null value, whether or not ignore_dup_key is set. If you attempt to do so, Adaptive Server prints an error message that displays the first of the duplicate values. You must eliminate duplicates before Adaptive Server can create a unique index on the column.
allows you to create a new, nonunique clustered index on a table that includes duplicate rows. ignore_dup_row deletes the duplicate rows from the table, and cancels any insert or update that would create a duplicate row, but does not roll back the entire transaction. See “Duplicate rows” for more information.
allows you to create a nonunique clustered index on a table that includes duplicate rows, and allows you to duplicate rows with update and insert statements. See “Duplicate rows” for an explanation of how to use these options.
speeds creation of clustered indexes or unique nonclustered indexes when the data in the table is already in sorted order (for example, when you have used bcp to copy data that has already been sorted into an empty table). See “Using the sorted_data option to speed sorts” for more information.
specifies the number of steps to generate for the histogram used to optimize queries. If you omit this clause:
The default value is 20, if no histogram is currently stored for the leading index column.
The current number of steps is used, if a histogram for the leading column of the index column already exists.
If you specify 0 for num_steps, the index is re-created, but the statistics for the index are not overwritten in the system tables.
creates the index on the named segment. Before using the on segment_name option, initialize the device with disk init, and add the segment to the database using sp_addsegment. See your System Administrator, or use sp_helpsegment for a list of the segment names available in your database.
specifies the number of consumer processes that should perform the sort operation for creating the index. The actual number of consumer processes used to sort the index may be smaller than the specified number, if fewer worker processes are available when Adaptive Server executes the sort.
Creates an index named au_id_ind on the au_id column of the authors table:
create index au_id_ind on authors (au_id)
Creates a unique clustered index named au_id_ind on the au_id column of the authors table:
create unique clustered index au_id_ind on authors(au_id)
Creates an index named ind1 on the au_id and title_id columns of the titleauthor table:
create index ind1 on titleauthor (au_id, title_id)
Creates a nonclustered index named zip_ind on the zip column of the authors table, filling each index page one-quarter full and limiting the sort to 4 consumer processes:
create nonclustered index zip_ind on authors(postalcode) with fillfactor = 25, consumers = 4
Creates an index with ascending ordering on pub_id and descending order on pubdate:
create index pub_dates_ix on titles (pub_id asc, pubdate desc)
Creates an index on title_id, using 50 histogram steps for optimizer statistics and leaving 1 empty page out of every 40 pages in the index:
create index title_id_ix on titles (title_id) with reservepagegap = 40, statistics using 50 values
Run update statistics periodically if you add data to the table that changes the distribution of keys in the index. The query optimizer uses the information created by update statistics to select the best plan for running queries on the table.
If the table contains data when you create a nonclustered index, Adaptive Server runs update statistics on the new index. If the table contains data when you create a clustered index, Adaptive Server runs update statistics on all the table’s indexes.
Index all columns that are regularly used in joins.
When Component Integration Services is enabled, the create index command is reconstructed and passed directly to the Adaptive Server associated with the table.
You cannot create an index on a column with a datatype of bit, text, or image.
You can create non-indexable columns in a table by creating columns with lengths greater than the index row-size limit:
Logical page size |
Index column size limit |
---|---|
2K |
600 |
4K |
1250 |
8K |
2600 |
16K |
5300 |
A table can have a maximum of 249 nonclustered indexes.
A table can have a maximum of one clustered index.
You can specify up to 31 columns (formerly 16) for the index key. The maximum total number of bytes must be within the limits shown in the table above.
You can create an index on a temporary table. The index disappears when the table disappears.
You can create an index on a table in another database, as long as you are the owner of that table.
You cannot create an index on a view.
create index runs more slowly while a dump database is taking place.
You can create a clustered index on a partitioned table, or partition a table with a clustered index if all the following conditions are true:
The select into/bulkcopy/pllsort database option is turned on,
Adaptive Server is configured for parallel processing, and
There is one more worker process available than the number of partitions.
For more information about clustered indexes on partitioned tables, see Chapter 24, “Parallel Sorting,” in the Performance and Tuning Guide.
The maximum number of indexes allowed on a data-only-locked table with a clustered index is 249. A table can have one clustered index and 248 nonclustered indexes.
Indexes speed data retrieval, but can slow data updates. For better performance, create a table on one segment and create its nonclustered indexes on another segment, when the segments are on separate physical devices.
Adaptive Server can create indexes in parallel if a table is partitioned and the server is configured for parallelism. It can also use sort buffers to reduce the amount of I/O required during sorting. For more information, see Chapter 24, “Parallel Sorting,” in the Performance and Tuning Guide.
Create a clustered index before creating any nonclustered indexes, since nonclustered indexes are automatically rebuilt when a clustered index is created.
When using parallel sort for data-only-locked tables, the number of worker processes must be configured to equal or exceed the number of partitions, even for empty tables. The database option select into/bulkcopy/pllsort must also be enabled.
A table “follows” its clustered index. When you create a table, use the on segment_name extension to create clustered index, the table migrates to the segment where the index is created.
If you create a table on a specific segment, then create a clustered index without specifying a segment, Adaptive Server moves the table to the default segment when it creates the clustered index there.
Because text and image data is stored in a separate page chain, creating a clustered index with on segment_name does not move text and image columns.
To create a clustered index, Adaptive Server duplicates the existing data; the server deletes the original data when the index is complete. Before creating a clustered index, use sp_spaceused to make sure that the database has at least 120 percent of the size of the table available as free space.
The clustered index is often created on the table’s primary key (the column or columns that uniquely identify the row). The primary key can be recorded in the database (for use by front-end programs and sp_depends) using sp_primarykey.
To allow duplicate rows in a clustered index, specify allow_dup_row.
Use the asc and desc keywords after index column names to specify the sorting order for the index keys. Creating indexes so that columns are in the same order specified in the order by clause of queries eliminates the sorting step during query processing. For more information, see Chapter 8, “Indexing for Performance,” in the Performance and Tuning Guide.
Space is allocated to tables and indexes in increments of one extent, or eight pages, at a time. Each time an extent is filled, another extent is allocated. Use sp_spaceused to display the amount of space allocated and used by an index..
In some cases, using the sorted_data option allows Adaptive Server to skip copying the data rows as described in Table 7-8. In these cases, you need only enough additional space for the index structure itself. Depending on key size, this is usually about 20 percent of the size of the table.
The ignore_dup_row and allow_dup_row options are not relevant when you are creating a nonunique, nonclustered index. Adaptive Server attaches a unique row identification number internally in each nonclustered index; duplicate rows are not a problem even for identical data values.
ignore_dup_row and allow_dup_row are mutually exclusive.
A nonunique clustered index allows duplicate keys, but does not allow duplicate rows unless you specify allow_dup_row.
allow_dup_row allows you to create a nonunique, clustered index on a table that includes duplicate rows. If a table has a nonunique, clustered index that was created without the allow_dup_row option, you cannot create new duplicate rows using the insert or update command.
If any index in the table is unique, the requirement for uniqueness takes precedence over the allow_dup_row option. You cannot create an index with allow_dup_row if a unique index exists on any column in the table.
The ignore_dup_row option is also used with a nonunique, clustered index. The ignore_dup_row option eliminates duplicates from a batch of data. ignore_dup_row cancels any insert or update that would create a duplicate row, but does not roll back the entire transaction.
Table 7-6 illustrates how allow_dup_row and ignore_dup_row affect attempts to create a nonunique, clustered index on a table that includes duplicate rows and attempts to enter duplicate rows into a table.
Option setting |
Create an index on a table that has duplicate rows |
Insert duplicate rows into a table with an index |
---|---|---|
Neither option set |
create index fails. |
insert fails. |
allow_dup_row set |
create index completes. |
insert completes. |
ignore_dup_row set |
Index is created but duplicate rows are deleted; error message. |
All rows are inserted except duplicates; error message. |
Table 7-7 shows which index options can be used with the different types of indexes:
Index type |
Options |
---|---|
Clustered |
ignore_dup_row | allow_dup_row |
Unique, clustered |
ignore_dup_key |
Nonclustered |
None |
Unique, nonclustered |
ignore_dup_key, ignore_dup_row |
As an alternative to create index, you can implicitly create unique indexes by specifying a unique constraint with the create table or alter table statement. The unique constraint creates a clustered or nonclustered unique index on the columns of a table. These implicit indexes are named after the constraint, and they follow the same rules for indexes created with create index.
You cannot drop indexes supporting unique constraints using the drop index statement. They are dropped when the constraints are dropped through an alter table statement or when the table is dropped. See create table for more information about unique constraints.
The sorted_data option can reduce the time needed to create an index by skipping the sort step and by eliminating the need to copy the data rows to new pages in certain cases. The speed increase becomes significant on large tables and increases to several times faster in tables larger than 1GB.
If sorted_data is specified, but data is not in sorted order, Adaptive Server displays an error message, and the command fails.
Creating a nonunique, nonclustered index succeeds, unless there are rows with duplicate keys. If there are rows with duplicate keys, Adaptive Server displays an error message, and the command fails.
The effects of sorted_data for creating a clustered index depend on whether the table is partitioned and whether certain other options are used in the create index command. Some options require data copying, if used at all, for nonpartitioned tables and sorts plus data copying for partitioned tables, while others require data copying only if you:
Use the ignore_dup_row option
Use the fillfactor option
Use the on segmentname clause to specify a segment that is different from the segment where the table data is located
Use the max_rows_per_page clause to specify a value that is different from the value associated with the table
Table 7-8 shows when the sort is required and when the table is copied for partitioned and nonpartitioned tables.
Options |
Partitioned table |
Unpartitioned table |
---|---|---|
No options specified |
Parallel sort; copies data, distributing evenly on partitions; creates index tree. |
Either parallel or nonparallel sort; copies data, creates index tree. |
with sorted_data only or with sorted_data on same_segment |
Creates index tree only. Does not perform the sort or copy data. Does not run in parallel. |
Creates index tree only. Does not perform the sort or copy data. Does not run in parallel. |
with sorted_data and ignore_dup_row or fillfactor or on other_segment or max_rows_per_page |
Parallel sort; copies data, distributing evenly on partitions; creates index tree. |
Copies data and creates the index tree. Does not perform the sort. Does not run in parallel. |
Use the with statistics clause to specify the number of steps for a histogram for the leading column of an index. Histograms are used during query optimization to determine the number of rows that match search arguments for a column.
To re-create an index without updating the values in sysstatistics for a column, use 0 for the number of steps. This avoids overwriting statistics that have been changed with optdiag.
fillfactor, max_rows_per_page, and reservepagegap help manage space on index pages in different ways:
fillfactor applies to indexes for all locking schemes. For clustered indexes on allpages-locked tables, it affects the data pages of the table. On all other indexes, it affects the leaf level of the index.
max_rows_per_page applies only to index pages of allpages-locked tables.
reservepagegap applies to tables and indexes for all locking schemes.
reservepagegap affects space usage in indexes when
The index is created
reorg commands on indexes are executed
Nonclustered indexes are rebuilt after creating a clustered index
When a reservepagegap value is specified in a create clustered index command, it applies to:
The data and index pages of allpages-locked tables
Only the index pages of data-only-locked tables
The num_pages value specifies a ratio of filled pages to empty pages on the leaf level of the index so that indexes can allocate space close to existing pages, as new space is required. For example, a reservepagegap of 10 leaves 1 empty page for each 9 used pages.
reservepagegap specified along with create clustered index on an allpages-locked table overwrites any value previously specified with create table or alter table.
You can change the space management properties for an index with sp_chgattribute. Changing properties with sp_chgattribute does not immediately affect storage for indexes on the table. Future large scale allocations, such as reorg rebuild, use the sp_chgattribute value.
The fillfactor value set by sp_chgattribute is stored in the fill_factor column in sysindexes. The fillfactor is applied when an index is recreated as a result of an alter table...lock command or a reorg rebuild command.
Table 7-9 shows the index options supported for allpages-locked and data-only-locked tables. On data-only-locked tables, the ignore_dup_row and allow_dup_row options are enforced during create index, but are not enforced during insert and update operations. Data-only-locked tables always allow the insertion of duplicate rows.
Index type |
Allpages-locked table |
Data-only-locked table |
|
---|---|---|---|
During index creation |
During inserts |
||
Clustered |
allow_dup_row, ignore_dup_row |
allow_dup_row, ignore_dup_row |
allow_dup_row |
Unique clustered |
ignore_dup_key |
ignore_dup_key |
ignore_dup_key |
Nonclustered |
None |
None |
None |
Unique nonclustered |
ignore_dup_key |
ignore_dup_key |
ignore_dup_key |
Table 7-10 shows the behavior of commands that attempt to insert duplicate rows into tables with clustered indexes, and when the clustered indexes are dropped and re-created.
Options |
Allpages-locked table |
Data-only-locked table |
---|---|---|
No options specified |
Insert fails with error message 2615. Re-creating the index succeeds. |
Insert succeeds. Re-creating the index fails with error message 1508. |
allow_dup_row |
Insert and re-creating the index succeed. |
Insert and re-creating the index succeed. |
ignore_dup_row |
Insert fails with “Duplicate row was ignored” message. Re-creating the index succeeds. |
Insert succeeds. Re-creating the index deletes duplicate rows. |
The sorted_data option to create index can be used only immediately following a bulk copy operation into an empty table. Once data modifications to that table cause additional page allocations, the sorted_data option cannot be used.
Specifying different values for space management properties may override the sort suppression functionality of the sorted_data.
Each index—including composite indexes—is represented by one row in sysindexes.
For information about the order of the data retrieved through indexes and the effects of an Adaptive Server’s installed sort order, see the order by clause.
For information about a table’s indexes, execute sp_helpindex.
SQL92 – Compliance level: Transact-SQL extension.
create index permission defaults to the table owner and is not transferable.
Commands alter table, create table, drop index, insert, order by clause, set, update
System procedures sp_addsegment, sp_chgattribute, sp_helpindex, sp_helpsegment, sp_spaceused