I am learning from a tutorial that uses INDEX() within a CREATE TABLE statement, but does not explain whether it is clustered or non-clustered. My question is: does INDEX() when used in a CREATE TABLE statement result in a clustered or non-clustered index?
For example:
CREATE TABLE test (a varchar(30), b varchar(30), index(a));
/* Is column A a clustered or non-clustered index? */
Also wondering how to do the opposite as well: if the example results in a non-clustered index, how do you write a clustered index, and vice versa?
TL;DR The primary key - and only the primary key - is a clustered index. If you don't explicitly define a primary key, the first suitable UNIQUE key is used. If you don't have either a primary key or a suitable UNIQUE key, MySQL generates a hidden clustered index. You cannot create a clustered index using INDEX().
As explained in the docs (emphasis added):
Every InnoDB table has a special index called the clustered index where the data for the rows is stored. Typically, the clustered index is synonymous with the primary key.
...
When you define a PRIMARY KEY on your table, InnoDB uses it as the clustered index. Define a primary key for each table that you create. If there is no logical unique and non-null column or set of columns, add a new auto-increment column, whose values are filled in automatically.
If you do not define a PRIMARY KEY for your table, MySQL locates the first UNIQUE index where all the key columns are NOT NULL and InnoDB uses it as the clustered index.
If the table has no PRIMARY KEY or suitable UNIQUE index, InnoDB internally generates a hidden clustered index on a synthetic column containing row ID values. The rows are ordered by the ID that InnoDB assigns to the rows in such a table. The row ID is a 6-byte field that increases monotonically as new rows are inserted. Thus, the rows ordered by the row ID are physically in insertion order.
...
All indexes other than the clustered index are known as secondary indexes. In InnoDB, each record in a secondary index contains the primary key columns for the row, as well as the columns specified for the secondary index. InnoDB uses this primary key value to search for the row in the clustered index.
See also the definition of clustered index in the glossary, which defines it as "The InnoDB term for a primary key index," along with some additional details.
So, to answer your question, there's no way to create a clustered index, other than to create a primary key or, on a table without a primary key, a suitable UNIQUE key (all key columns NOT NULL). INDEX() just creates a secondary (i.e., non-clustered) key, no matter what you do with it.
* Note: as pointed out in the comments, some other databases don't have clustered indexes, at all, and some allow more than one clustered index on a table. I'm only addressing MySQL in my answer.
Is column A a clustered or non-clustered index?
It's a non-clustered index and only primary key field has clustered index. Remember, there can be only one clustered index in a table and thus it definitely can't create one.
Related
In MySQL, how can we tell if an index of a table is clustered or not?
We can use show index from table-name to get information about the table's indexes. But I don't find it shows whether each index is clustered or nonclustered.
This is for the purpose of If a table in MySQL has any index, must the table have a clustered index?
In the default storage engine, InnoDB, the PRIMARY KEY index is always the clustered index.
If you don't have a PRIMARY KEY, it's the first UNIQUE KEY index on non-null columns.
If you don't have either a PRIMARY KEY or UNIQUE KEY on non-null columns, then InnoDB has a hidden clustered index. You can't make a query use this clustered index in this case.
See https://dev.mysql.com/doc/refman/8.0/en/innodb-index-types.html
If the table has no PRIMARY KEY or suitable UNIQUE index, InnoDB internally generates a hidden clustered index named GEN_CLUST_INDEX on a synthetic column containing row ID values. The rows are ordered by the ID that InnoDB assigns to the rows in such a table. The row ID is a 6-byte field that increases monotonically as new rows are inserted. Thus, the rows ordered by the row ID are physically in insertion order.
MyISAM is the other common storage engine. MyISAM does not support a clustered index.
2 common answers are to use show_table_status and INFORMATION_SCHEMA.TABLES
But it seems, both of them don't count primary key's size.
I have tables with millions of records with primary key and no other indexes, and both of methods mentioned above show Index_length: 0 for that tables. Tables are INNODB.
Your primary key is your table. In an InnoDB the primary key contains the actual data thus if the primary key contains the data it is the table.
Think about it for a moment. You get two different types of indexes on an InnoDB table clustered and secondary indexes. The difference is that a clustered index contains the data and a secondary index contains the indexed columns and a pointer to the data. Thus a secondary index does not contain the data but rather the location of where the data is located in the CLUSTERED index.
Normally a primary key is a clustered index. It would be highly inefficient to store both the table with all its values and then a clustered index with all its values. This would effectively double the size of the table.
So when you have a primary key that is on an InnoDB the table size is the size of the primary key. In some database systems you can have a secondary index as a primary key and a separate index as a clustered key, however InnoDB does not allow this.
Go read the following links for more details:
http://dev.mysql.com/doc/refman/5.0/en/innodb-table-and-index.html
http://dev.mysql.com/doc/refman/5.0/en/innodb-index-types.html
In these links they explain all I have said above in more detail. Simply put you already have the size of the primary key index as it is the size of your table.
Hope that helps.
Folks, I would like to understand the answer for the following questions:
Can I have a primary key without clustered index ? ( I am aware that when we create primary key constraint on a column, it by default creates a clustered index. So in that case, how should I deactivate clustered index ?)
Can I have a clustered index with multiple columns together ? (Like in non-clustered where I can join different columns for a single non-clustered index).
(This answer is for SQL Server 2005+ only. I know nothing about MySQL.)
Can I have a primary key without clustered index?
Yes. As you mentioned, a primary key constraint is backed by a clustered index by default. You can tell SQL Server to back the constraint with a nonclustered index by declaring the constraint as follows:
ALTER TABLE MyTable
ADD CONSTRAINT PK_MyTable
PRIMARY KEY NONCLUSTERED(Col1);
Can I have a clustered index with multiple columns together ? (Like in non-clustered where I can join different columns for a single non-clustered index).
Yes, you can define an index with more than one column in the index key. It's really no different than a nonclustered index.
CREATE UNIQUE CLUSTERED INDEX IX_MyTable_Clus
ON MyTable(Col1, Col2, Col3);
References: ALTER TABLE, CREATE INDEX
MySQL and SQL-SERVER are different RDBMS. They have different capabilities and different syntax.
When using InnoDB, MySQL always makes the PK the clustered index.
SQL-SERVER, however, will let you create a PK without the CLUSTERED keyword, and let you use it within another index instead.
In both cases, PrimaryKeys and Indexes (clustered or not) can cover multiple fields.
If I have a table that has a primary key and a foreign key, and searches are frequently done with queries that include both (...WHERE primary=n AND foreign=x), is there any performance benefit to making a multiple index in MySQL using the two keys?
I understand that they are both indexes already, but I am uncertain if the foreign key is still seen as an index when included in another table. For example, would MySQL go to the primary key, and then compare all values of the foreign key until the right one is found, or does it already know where it is because the foreign key is also an index?
Update: I am using InnoDB tables.
For equality comparisons, you cannot get an improvement over the primary key index (because at that point, there is at most just one row that can match).
The access path would be:
look at the primary key index for primary = n
get the single matching row from the table
check any other conditions using the row in the table
A composite index might make some sense if you have a range scan on the primary key and want to narrow that down by the other column.
Is it possible to create an InnoDB table without a Primary Key?
Since InnoDB tables are structured as clustered index around the PK, what would be the structure of a table without PK? Would that table still be a clustered index, but around a secondary key?
Thanks.
http://www.sqlinfo.net/mysqldocs/v50/storage-engines.html#innodb-table-and-index
14.2.13. InnoDB Table and Index Structures
If you do not define a PRIMARY KEY for your table, MySQL picks the first UNIQUE index that has only NOT NULL columns as the primary key and InnoDB uses it as the clustered index. If there is no such index in the table, InnoDB internally generates a clustered index where the rows are ordered by the row ID that InnoDB assigns to the rows in such a table. The row ID is a 6-byte field that increases monotonically as new rows are inserted. Thus, the rows ordered by the row ID are physically in insertion order.