sql >> データベース >  >> RDS >> Mysql

主キーと外部キーのインデックス

    私はあなたが私に言ったことについていくつかの実験をしてきました、そして私はそれを答えとして共有したいと思いました。

    まず、いくつかのテストテーブルを作成します:

    CREATE TABLE foo (
        foo_id int(10) unsigned NOT NULL,
        PRIMARY KEY (foo_id)
    )
    ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_spanish_ci;
    CREATE TABLE bar (
        bar_id int(10) unsigned NOT NULL,
        PRIMARY KEY (bar_id)
    )
    ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_spanish_ci;
    
    
    CREATE TABLE foo_bar (
        foo_id int(10) unsigned NOT NULL,
        bar_id int(10) unsigned NOT NULL
    )
    ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_spanish_ci;
    

    これまでのところ、インデックスは存在しません:

    mysql> SHOW INDEXES FROM foo_bar;
    Empty set (0.00 sec)
    

    主キーを追加すると、インデックスが生成されます:

    mysql> ALTER TABLE foo_bar
        -> ADD PRIMARY KEY (`foo_id`, `bar_id`);
    Query OK, 0 rows affected (0.70 sec)
    Records: 0  Duplicates: 0  Warnings: 0
    
    mysql> SHOW INDEXES FROM foo_bar;
    +---------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
    | Table   | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment |
    +---------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
    | foo_bar |          0 | PRIMARY  |            1 | foo_id      | A         |           0 |     NULL | NULL   |      | BTREE      |         |
    | foo_bar |          0 | PRIMARY  |            2 | bar_id      | A         |           0 |     NULL | NULL   |      | BTREE      |         |
    +---------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
    2 rows in set (0.02 sec)
    

    foo_idに外部キーを追加した場合 その列はインデックスの最初の列であるため、主キーインデックスを再利用します。

    mysql> ALTER TABLE foo_bar
        -> ADD CONSTRAINT `foo_bar_fk1` FOREIGN KEY (`foo_id`) REFERENCES `foo` (`foo_id`) ON DELETE CASCADE ON UPDATE CASCADE;
    Query OK, 0 rows affected (0.27 sec)
    Records: 0  Duplicates: 0  Warnings: 0
    
    mysql> SHOW INDEXES FROM foo_bar;
    +---------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
    | Table   | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment |
    +---------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
    | foo_bar |          0 | PRIMARY  |            1 | foo_id      | A         |           0 |     NULL | NULL   |      | BTREE      |         |
    | foo_bar |          0 | PRIMARY  |            2 | bar_id      | A         |           0 |     NULL | NULL   |      | BTREE      |         |
    +---------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
    2 rows in set (0.00 sec)
    

    bar_idに外部キーを追加した場合 、既存のインデックスを再利用できないため、インデックスが作成されます:

    mysql> ALTER TABLE foo_bar
        -> ADD CONSTRAINT `foo_bar_fk2` FOREIGN KEY (`bar_id`) REFERENCES `bar` (`bar_id`) ON DELETE CASCADE ON UPDATE CASCADE;
    Query OK, 0 rows affected (0.25 sec)
    Records: 0  Duplicates: 0  Warnings: 0
    
    mysql> SHOW INDEXES FROM foo_bar;
    +---------+------------+-------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
    | Table   | Non_unique | Key_name    | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment |
    +---------+------------+-------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
    | foo_bar |          0 | PRIMARY     |            1 | foo_id      | A         |           0 |     NULL | NULL   |      | BTREE      |         |
    | foo_bar |          0 | PRIMARY     |            2 | bar_id      | A         |           0 |     NULL | NULL   |      | BTREE      |         |
    | foo_bar |          1 | foo_bar_fk2 |            1 | bar_id      | A         |           0 |     NULL | NULL   |      | BTREE      |         |
    +---------+------------+-------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
    3 rows in set (0.02 sec)
    

    外部キーの1つは、主キーインデックスを使用しています。つまり、そのようなインデックスを削除することはできません!

    mysql> ALTER TABLE foo_bar
        -> DROP PRIMARY KEY;
    ERROR 1025 (HY000): Error on rename of '.\test\#sql-568_c7d' to '.\test\foo_bar' (errno: 150)
    

    外部キーのインデックスを作成するか、キー自体を削除しない限り:

    mysql> ALTER TABLE foo_bar
        -> DROP FOREIGN KEY `foo_bar_fk1`;
    Query OK, 0 rows affected (0.19 sec)
    Records: 0  Duplicates: 0  Warnings: 0
    
    mysql> ALTER TABLE foo_bar
        -> DROP PRIMARY KEY;
    Query OK, 0 rows affected (0.23 sec)
    Records: 0  Duplicates: 0  Warnings: 0
    

    結論として、MySQLは、機能に必要なときにインデックスを自動的に作成します(ただし、厳密に必要な場合のみ)。



    1. C#はoracleストアド関数を呼び出します

    2. IF/ELSEステートメントを使用してSQLで新しいxmlノードエントリを更新または作成する方法

    3. データベースとテーブルスペース、違いは何ですか?

    4. ツリー階層を取得するためのCTE再帰