Does MySQL create an extra index for primary key or uses the data itself as an “index”

微笑、不失礼 提交于 2021-02-07 22:47:43

问题


Cant find a explicit answer of that. I know that when you create a primary key, MySQL orders the data according to that primary key, question is, does it actually create another index, or uses the actual data as an index since it should be ordered by the primary key?

EDIT:

if I have a table with has index A and index B and no primary key, I have the data + index A + index B. If I change the table to have columns of index A as the primary key, I will only have data (which is also used as an index) + index B right? The above is in terms of memory usage


回答1:


Clustered and Secondary Indexes

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. To get the best performance from queries, inserts, and other database operations, you must understand how InnoDB uses the clustered index to optimize the most common lookup and DML operations for each table.

  • When you define a PRIMARY KEY on your table, InnoDB uses it as the clustered index

  • 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 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.

How the Clustered Index Speeds Up Queries

Accessing a row through the clustered index is fast because the index search leads directly to the page with all the row data. If a table is large, the clustered index architecture often saves a disk I/O operation when compared to storage organizations that store row data using a different page from the index record.




回答2:


if I have a table with has index A and index B and no primary key, I have the data + index A + index B. If I change the table to have columns of index A as the primary key, I will only have data (which is also used as an index) + index B right? The above is in terms of memory usage

Yes, the index for the clustered index is the table itself. That's the only place other non-indexed columns are stored. When you SHOW TABLE STATUS you see this reported as Data_length. Secondary indexes are reported as Index_length.

mysql> show table status like 'redacted'\G
*************************** 1. row ***************************
           Name: redacted
         Engine: InnoDB
        Version: 10
     Row_format: Dynamic
           Rows: 100217
 Avg_row_length: 1168
    Data_length: 117063680    <-- clustered index
Max_data_length: 0
   Index_length: 3653632      <-- secondary index(es)

InnoDB always stores a clustered index. If you have no PRIMARY KEY defined on any columns of your table, InnoDB creates an artificial column as the key for the clustered index, and this column cannot be queried.




回答3:


if I have a table with has index A and index B and no primary key, I have the data + index A + index B. If I change the table to have columns of index A as the primary key, I will only have data (which is also used as an index) + index B right? The above is in terms of memory usage

While that is true - There is more to consider in terms of storage size.

Assuming, what you try to do is logically fine and your index, which you want to promote to primary key is actually a candidate key. If you can save on storage size depends on the number of indices and the size of the primary key columns. The reason is that InnoDB appends the primary key columns to every secondary index (if they are not already explicitely part of it). It can also affect other (bigger) tables, if they need to reference it as foreign key.

Here are some simple tests, which can show the differences. I am using MariaDB since it's sequence plugin makes it easy to create dummy data. But you should see the same effects on MySQL server.

So first I will just create a simple table with two INT columns and an index on each filling it with 100K rows.

drop table if exists test;
create table test(
    a int,
    b int,
    index(a),
    index(b)
);

insert into test(a, b)
    select seq as a, seq as b
    from seq_1_to_100000
;

To keep it simple, I will just look at the file size of the table (I'm using innodb_file_per_table=1).

16777216 test.ibd

Now let's do what you wanted, and make column a primary key, changing the CREATE statement:

create table test(
    a int,
    b int,
    primary key(a),
    index(b)
);

The file size now is:

13631488 test.ibd

So it's true - You can save on storage size by promoting an index to primary key. In this case almost 20%.

But what happens if I change the column type from INT (4 bytes) to BINARY(32) (32 byte)?

create table test(
    a binary(32),
    b binary(32),
    index(a),
    index(b)
);

File size:

37748736 test.ibd

Now make column a primary key

create table test(
    a binary(32),
    b binary(32),
    primary key(a),
    index(b)
);

File size:

41943040 test.ibd

As you can see, you can as well increase the size. In this case like 11%.

It is though advised to always define a primary key. If in doubt, just create an AUTO_INCREMENT PRIMARY KEY. In my example it could be:

create table test(
    id mediumint auto_increment primary key,
    a binary(32),
    b binary(32),
    index(a),
    index(b)
);

File size:

37748736 test.ibd

The size is the same as if we didn't have an explicit primary key. (Though I would expect to save a bit on size, since I use 3 byte PK instead of a hidden 6 byte PK.) But now you can use it in your queries, for foreign keys and joins.



来源:https://stackoverflow.com/questions/57134422/does-mysql-create-an-extra-index-for-primary-key-or-uses-the-data-itself-as-an

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!