- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
从这个 SQL 语句中,我试图了解 pkey 的使用,我们已经将复合键作为主键,有人可以解释一下吗?
CREATE TABLE categories_products (
category_id int unsigned not null,
product_id int unsigned not null,
PRIMARY KEY (category_id, product_id),
KEY pkey (product_id),
FOREIGN KEY (category_id) REFERENCES categories (id)
ON DELETE CASCADE
ON UPDATE CASCADE,
FOREIGN KEY (product_id) REFERENCES products (id)
ON DELETE CASCADE
ON UPDATE CASCADE
);
最佳答案
通过扩展解释,并从你的例子出发:
首先,让我们设置环境:
mysql>
mysql> create table categories_products (
-> category_id int unsigned not null,
-> product_id int unsigned not null,
-> somefield varchar(25),
-> primary key (category_id, product_id)
-> );
Query OK, 0 rows affected (0.10 sec)
mysql>
mysql> insert into categories_products(category_id, product_id) values (1, 1), (1, 2), (2, 2);
Query OK, 3 rows affected (0.05 sec)
Records: 3 Duplicates: 0 Warnings: 0
我删除了外键,因为它们对此没有任何影响,而且我添加了一个额外的字段,因为它使结果更容易解释。之后我会对此进行扩展。
首先我们尝试查询特定类别:
mysql> explain select * from categories_products where category_id = 1;
+----+-------------+---------------------+------+---------------+---------+---------+-------+------+-------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+---------------------+------+---------------+---------+---------+-------+------+-------+
| 1 | SIMPLE | categories_products | ref | PRIMARY | PRIMARY | 4 | const | 2 | |
+----+-------------+---------------------+------+---------------+---------+---------+-------+------+-------+
1 row in set (0.00 sec)
我们可以从结果中看到它确实使用了 PRIMARY
键,并且只检查了 2
行,因为索引知道这就是匹配 的所有行>where
约束。
我们的下一个测试查询产品和类别:
mysql> explain select * from categories_products where category_id = 1 and product_id = 1;
+----+-------------+---------------------+-------+---------------+---------+---------+-------------+------+-------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+---------------------+-------+---------------+---------+---------+-------------+------+-------+
| 1 | SIMPLE | categories_products | const | PRIMARY | PRIMARY | 8 | const,const | 1 | |
+----+-------------+---------------------+-------+---------------+---------+---------+-------------+------+-------+
1 row in set (0.00 sec)
我们可以再次看到正在使用 PRIMARY 键,但这次更好,它只返回一行。
接下来,让我们试着只看一个产品:
mysql> explain select * from categories_products where product_id = 1;
+----+-------------+---------------------+------+---------------+------+---------+------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+---------------------+------+---------------+------+---------+------+------+-------------+
| 1 | SIMPLE | categories_products | ALL | NULL | NULL | NULL | NULL | 3 | Using where |
+----+-------------+---------------------+------+---------------+------+---------+------+------+-------------+
1 row in set (0.00 sec)
这一次,查询无法找到合适的索引来使用,因此不得不使用 where
来缩小结果范围。这比它能够执行索引查找的效率要低。
为什么会这样?为什么优化器可以使用 category_id
而不是 product_id
即使它们都在复合索引中?因为 MySQL 从左到右读取该索引。考虑一个大型复合索引 (f1, f2, f3, f4)
。这隐含地允许您访问这些附加索引,(f1)
、(f1, f2)
、(f1, f2, f3)
。
现在让我们在其中添加您的 pkey 索引,看看会发生什么。
mysql> create index pkey on categories_products(product_id);
explain select * from categories_products where product_id = 1;
Query OK, 0 rows affected (0.17 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql>
mysql> explain select * from categories_products where product_id = 1;
+----+-------------+---------------------+------+---------------+------+---------+-------+------+-------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+---------------------+------+---------------+------+---------+-------+------+-------+
| 1 | SIMPLE | categories_products | ref | pkey | pkey | 4 | const | 1 | |
+----+-------------+---------------------+------+---------------+------+---------+-------+------+-------+
好了,现在也可以使用索引执行与以前相同的查询。
现在来谈谈我添加额外字段的原因。当主键覆盖整个表时,就像在这种情况下所做的那样,任何查询都将从索引而不是表中读取整个结果,这可能会在解释结果中产生一些误导性的条目。例如,如果我删除该附加字段和 pkey 索引,然后重新运行查询,结果如下:
mysql> explain select * from categories_products where product_id = 1;
+----+-------------+---------------------+-------+---------------+---------+---------+------+------+--------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+---------------------+-------+---------------+---------+---------+------+------+--------------------------+
| 1 | SIMPLE | categories_products | index | NULL | PRIMARY | 8 | NULL | 3 | Using where; Using index |
+----+-------------+---------------------+-------+---------------+---------+---------+------+------+--------------------------+
1 row in set (0.00 sec)
现在乍一看似乎正在使用 PRIMARY 索引,但仔细检查我们发现它仍在检查整个表(3 行),并使用 where
限制结果,如以及索引。
无论如何,这就是为什么您需要 product_id
上的索引的原因
关于mysql - mysql数据库表中的pkey,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30364846/
我的 Django/PostgreSQL 系统有一个奇怪的行为。 保存模型对象后主键为无,尽管它是一个 AutoField 并且 id 已正确保存在数据库中。 以下脚本段落为 id 返回 None:
我正在尝试在低级别使用 SSH 协议(protocol)(即我不想启动 shell 或任何东西,我只想传递数据)。因此,我正在使用 Paramiko 的 Transport直接上课。 我已经完成了服务
如何创建使用以下公钥字符串初始化的 OpenSSL::PKey 对象?最终目标是使用对象通过 ruby-jwt 解码 JWT token 。 我试过以下方法: public_key = ""-----
我需要能够识别我在使用 pg_insert 后刚刚插入的行,但文档只是说它返回 true/false。我如何从 pg_insert() 中确定记录的 pkey?我知道我可以在末尾使用带有“RETURN
尝试插入新房间时出现以下错误 ** (Ecto.ConstraintError) constraint error when attempting to insert struct: * un
我随后在两个表中插入一条记录。在第一次插入时,我将记录放在主表中,主表中生成了主键值。现在我需要将这条记录的一些字段放在另一个表中,包括主表的键值。我该怎么做? 最佳答案 “SELECT LAST_I
谁能告诉我 Hibernate 是否支持关联作为实体的 pkey?我认为这会得到支持,但我很难让代表它的任何类型的映射正常工作。特别是,使用下面的直接映射: @Entity public class
我正在尝试使用公钥解密。 bob = TCPSocket.open(host, port) cs_public_key = OpenSSL::PKey::RSA.new File.read 'c_pu
我正在尝试使用公钥解密。 bob = TCPSocket.open(host, port) cs_public_key = OpenSSL::PKey::RSA.new File.read 'c_pu
我有一些实体: @Entity public class Event{ @Id @GeneratedValue(strategy = GenerationType.IDENTIT
我们有一个使用 openssl 的应用程序 1,并且有一个客户端能够连接(握手完成)的公钥和证书文件 (RSA)。 我们有另一个应用程序2,它不使用 openssl,而是使用 Java keytool
这个问题在这里已经有了答案: Retrieving the last record in each group - MySQL (33 个答案) Fetch the rows which have
我正在尝试使用库 gittle 来克隆一个 git 存储库,我遵循了自述文件中的示例,这是我的代码。 repo_path = '/path/to/dir/' repo_url = 'git@gitl
我正在尝试编写 Ruby 代码来检查我发现的特定消息上的椭圆曲线数字签名算法 (ECDSA) 签名 here . 问题是我不知道如何将公钥的八位字节字符串转换为 OpenSSL::PKey::EC::
我有一个 Django-Postgres 设置这个表 - class User(models.Model): id = models.CharField(max_length=255, pri
我正在建立一个电子商务商店,每件商品都有不同的颜色和尺寸。那么使用包含 3 个复合键的 ProductType 表来定义连接到 Product 表的唯一行是否合适? Product Table: Pr
我正在尝试使用 net/sftp gem 从 Heroku 的 SFTP To Go 下载文件,但我总是得到未定义的方法 `e=' for #。 一直在网上搜索,但找不到任何相关的解决方案。这是我的代
我目前正在使用 Vagrant 和 Chef-solo,效果非常好。我想将 Vagrant 魔法扩展到 Chef 服务器。我已将 Vagrantfile 中的配置程序从 Chef-solo 切换为 C
多年来,我一直在使用 Capistrano 成功部署我的 Rails 3.2.13 应用程序。但就在今天,我遇到了可怕的ArgumentError: Could not parse PKey: no
我从 paramiko 得到了非常奇怪的行为: bla=paramiko.pkey.PKey(msg=None,data=None).from_private_key_file() TypeError
我是一名优秀的程序员,十分优秀!