主键和外键索引

2024-03-12

我有一个使用 GUI 工具创建的数据库,我注意到使用不一致KEY (aka INDEX) 定义:

CREATE TABLE `foo_bar` (
  `foo_id` int(10) unsigned NOT NULL,
  `bar_id` int(10) unsigned NOT NULL,
  PRIMARY KEY (`foo_id`, `bar_id`),
  KEY `foo_bar_fk2` (`bar_id`), -- <== ???
  CONSTRAINT `foo_bar_fk1` FOREIGN KEY (`foo_id`) REFERENCES `foo` (`foo_id`) ON DELETE CASCADE ON UPDATE CASCADE,
  CONSTRAINT `foo_bar_fk2` FOREIGN KEY (`bar_id`) REFERENCES `bar` (`bar_id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_spanish_ci COMMENT='Links between Foo and Bar';

我有以下问题indexes:

  1. 是否需要显式定义主键和外键的索引?
  2. 如果不是,你真的得到了吗two索引(以及较低的性能)?
  3. InnoDB和MyISAM有什么不同(外键除外)?

我一直在根据你告诉我的内容做一些实验,我想我会把它作为答案分享。

首先我创建一些测试表:

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)

我们的外键之一是使用主键索引。这意味着我们无法删除这样的索引!

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 会自动创建索引(但前提是它们是绝对必要的)。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

主键和外键索引 的相关文章

随机推荐

  • 如何查看 nginx 尝试访问文件的实际文件路径?

    现在我已经设置了 Nginx 来提供我确信是有效的文件路径的服务 但是 它给了我一个 404 未找到 我看过 var log nginx access log它向我展示了 05 Oct 2016 19 15 50 0500 GET menu
  • PagedListAdapter 不使用 DiffUtil 使数据无效

    每次我调用无效数据时 我的 DIFF UTIL 都不会被使用 日志未显示 整个列表已更新为新数据 导致屏幕移动位置等 不确定这里的问题是什么 I have PagedListAdapter with a LiveData
  • 平方根元函数?

    是否可以使用具有以下签名的元函数计算整数的平方根 template
  • Pandas DataFrame 删除 groupby 中的行

    我有一个包含三列的 DataFrameDate Advertiser和身份证 我首先对数据进行分组 看看某些广告商的列是否太小 例如当count 少于 500 然后我想将这些行删除到组表中 df groupby Date Advertise
  • android 如何动态改变进度条背景颜色

    我想动态改变android中进度条的背景颜色 我遵循本教程页面末尾附近的 奖励 部分 http colintmiller com 2010 10 how to add text over a progress bar on android
  • java Swing 背景图像

    我正在使用 JFrame 并且在框架上保留了背景图像 现在的问题是图像的大小小于框架的大小 所以我必须在窗口的空白部分再次保留相同的图像 如果用户单击最大化按钮 我可能必须在运行时将图像放在框架的空白区域 谁能告诉我如何实现这个目标 听起来
  • 多个服务的WCF之间的共享类型

    我有一个 Java Web 服务器 它有 2 个端点 系统管理和用户管理 两个端点使用相同的库 因此 这两个端点中的几乎所有类都是相同的 我有一个使用这两个服务的 C 客户端 我知道WCF可以共享类 所以我创建了一个新项目 并让我的客户项目
  • [Excel][VBA] 如何在图表中画一条线?

    Please view this image to get my clearly question Sub Tester Dim s d d 4 18 2011 1 a bit of a hack since I could figure
  • 如何使 Flask/保持 Ajax HTTP 连接处于活动状态?

    我有一个 jQuery Ajax 调用 如下所示 tags keyup function event ajax url terms type POST contentType application json data JSON strin
  • JavaScript 中嵌套函数的需求和用途是什么

    我理解什么是嵌套函数 但我不明白为什么我们首先需要嵌套函数 JavaScript 中是否存在只能使用嵌套函数才能解决的问题 我看到的所有创建嵌套函数的示例都可以在无需在函数内部创建函数的情况下进行编码 并且结果相同 那么哪些问题需要创建嵌套
  • 尝试使用转义字符时 OCaml 正则表达式有问题

    我正在尝试使用 OCaml 为 C 的变体编写一个词法分析器 对于词法分析器 我需要匹配字符串 和 分别作为幂和或符号 这两个都是正则表达式中的特殊字符 当我尝试使用反斜杠转义它们时 没有任何变化 代码运行时就好像 仍然是行首而 仍然是 或
  • 如何在Eclipse中添加GitLab存储库?

    如何在Eclipse中添加Gitlab 这样我就可以从 GitLab 推送或获取 我是这方面的新手 请给予更多解释 一 准备工作 确保 Eclipse 中有 eGit 帮助 gt 安装详细信息 看到 Eclipse Git Team 提供者
  • 将路径数组转换为 UL 列表

    我的数据库中有一个表 其中包含我网站页面的各种路径 每条路径仅列出一次 我目前有一系列非常长且复杂的查询和 PHP 来提取所有这些并将数据重写到无序列表中 为我的网站创建菜单 似乎有一种相对简单的循环方法可以更有效地工作 但我似乎无法让任何
  • 什么是语义标记,为什么我要使用它?

    就像它说的那样 使用语义标记意味着您在页面中使用的 X HTML 代码包含描述其用途的元数据 例如 h2 包含员工姓名的内容可能会被标记class employee name 最初有人希望搜索引擎能够使用这些信息 但随着网络的发展 语义标记
  • Java RMI 与 Scala,这可能吗?

    Java RMI 远程方法调用 仅适用于 Java 到 Java On the Scala http www scala lang org 网站上我读到与 Java 的集成是无缝的 并且 Scala 程序在 Java VM 上运行 字节码与
  • Spring Cloud Kubernetes 支持 Spring Cloud LoadBalancer 吗?

    Spring Cloud Kubernetes 支持 Spring Cloud 负载均衡器吗 我要在 Kubernetes 上部署 Spring boot 应用程序 并通过以下链接使用功能区客户端执行客户端负载平衡https cloud s
  • 将java方法转换为C#:使用位移运算符将字节转换为整数

    我正在尝试将以下 2 个方法转换为 C 而 net 编译器不会向我抱怨 坦率地说 我只是不明白这两种方法是如何在幕后真正发挥作用的 所以这里的答案和解释会很好 public static int bytesToInt byte b0 byt
  • “npm install --global”和“--save”一起吗?

    我想知道在中使用是否有意义npm 安装一起命令 global 和 save 参数 例如 npm install gulp g s 据我所知 npm 系统文件夹中没有 package json 所以我想答案是 否 但我想消除所有疑问 The
  • 使用InstallUtil工具时出现BadImageFormatException错误

    我已经使用 NET 4 0 创建并编译了我的 Windows 服务 所以我转到 NET 4 0 文件夹并说这样的话 我将 bin 文件夹复制到 C 盘以缩短路径 InstallUtil exe C bin Debug MyTestServi
  • 主键和外键索引

    我有一个使用 GUI 工具创建的数据库 我注意到使用不一致KEY aka INDEX 定义 CREATE TABLE foo bar foo id int 10 unsigned NOT NULL bar id int 10 unsigne