MySQL:优化无主键的表(索引、外键)

发布于 2024-12-15 16:29:06 字数 1468 浏览 1 评论 0原文

每个会员有0个或多个订单。每个订单至少包含 1 件商品。 memberid - varchar,而不是整数 - 没关系(请不要提到这不是很好,我无法更改它)。 因此,共有 3 个表:members、orders 和 order_items。订单和 order_items 如下:

CREATE TABLE `orders` (
`orderid` INT(11)  UNSIGNED NOT NULL AUTO_INCREMENT,
`memberid` VARCHAR( 20 ),
`Time` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ,
`info` VARCHAR( 3200 ) NULL ,
PRIMARY KEY (orderid) ,
FOREIGN KEY (memberid) REFERENCES members(memberid)
) ENGINE = InnoDB;


CREATE TABLE `order_items` (
`orderid` INT(11)  UNSIGNED NOT NULL,
`item_number_in_cart` tinyint(1) NOT NULL , --- 5 items in cart= 5 rows
`price` DECIMAL (6,2) NOT NULL,
FOREIGN KEY (orderid) REFERENCES orders(orderid)
) ENGINE = InnoDB;

因此,order_items 表如下所示:

orderid - item_number_in_cart - 价格:

...

1000456 - 1 - 24.99

1000456 - 2 - 39.99

1000456 - 3 - 4.99

1000456 - 4 - 17.97

1000457 - 1 - 20.00

1000458 - 1 - 99.99

1000459 - 1 - 2.99

1000459 - 2 - 69.99

1000460 - 1 - 4.99

...

如您所见, order_items 表没有主键(我认为有创造没有意义该表的 auto_increment id,因为一旦我们想要提取数据,我们总是将其提取为 WHERE orderid='1000456' order by item_number_in_card asc - 整个块,id 对查询没有帮助)。 一旦数据被插入到 order_items 中,它就不会被更新,而只是被选择。

问题是:

  • 我认为将索引放在购物车中的 item_number_in_cart 上是个好主意。有人可以证实一下吗?
  • 我还需要对 order_items 做些什么来提高性能,或者看起来不错吗?我可能会错过一些东西,因为我是新手。

先感谢您。

Each member has 0 or more orders. Each order contains at least 1 item.
memberid - varchar, not integer - that's OK (please do not mention that's not very good, I can't change it).
So, thera 3 tables: members, orders and order_items. Orders and order_items are below:

CREATE TABLE `orders` (
`orderid` INT(11)  UNSIGNED NOT NULL AUTO_INCREMENT,
`memberid` VARCHAR( 20 ),
`Time` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ,
`info` VARCHAR( 3200 ) NULL ,
PRIMARY KEY (orderid) ,
FOREIGN KEY (memberid) REFERENCES members(memberid)
) ENGINE = InnoDB;


CREATE TABLE `order_items` (
`orderid` INT(11)  UNSIGNED NOT NULL,
`item_number_in_cart` tinyint(1) NOT NULL , --- 5 items in cart= 5 rows
`price` DECIMAL (6,2) NOT NULL,
FOREIGN KEY (orderid) REFERENCES orders(orderid)
) ENGINE = InnoDB;

So, order_items table looks like:

orderid - item_number_in_cart - price:

...

1000456 - 1 - 24.99

1000456 - 2 - 39.99

1000456 - 3 - 4.99

1000456 - 4 - 17.97

1000457 - 1 - 20.00

1000458 - 1 - 99.99

1000459 - 1 - 2.99

1000459 - 2 - 69.99

1000460 - 1 - 4.99

...

As you see, order_items table has no primary keys (and I think there is no sense to create an auto_increment id for this table, because once we want to extract data, we always extract it as WHERE orderid='1000456' order by item_number_in_card asc - the whole block, id woudn't be helpful in queries).
Once data is inserted into order_items, it's not UPDATEd, just SELECTed.

The questions are:

  • I think it's a good idea to put index on item_number_in_cart. Could anybody please confirm that?
  • Is there anything else I have to do with order_items to increase the performance, or that looks pretty good? I could miss something because I'm a newbie.

Thank you in advance.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

凉月流沐 2024-12-22 16:29:06

主键可以跨越多个列。您不能使用列的 PRIMARY 属性来执行此操作,但您可以定义具有多个列的单独主键:

CREATE TABLE `order_items` (
    `orderid` INT(11)  UNSIGNED NOT NULL,
    `item_number_in_cart` tinyint(1) NOT NULL , --- 5 items in cart= 5 rows
    `price` DECIMAL (6,2) NOT NULL,
    PRIMARY KEY (orderid, item_number_in_cart),
    FOREIGN KEY (orderid) REFERENCES orders(orderid)
) ENGINE = InnoDB;

此外,主键只是一个唯一键,其中每列都不为空某个名字;您可以在不可为空的列上创建自己的唯一键以获得相同的效果。

通过索引 item_number_in_cart 不太可能获得很大的性能提升;由于给定订单的订单项数量往往较小,因此按 item_number_in_cart 排序不会占用太多时间或内存。但是,将列包含在主键中将有助于数据一致性。

Primary keys can span multiple columns. You can't use the PRIMARY attribute of columns to do this, but you can define a separate primary key with multiple columns:

CREATE TABLE `order_items` (
    `orderid` INT(11)  UNSIGNED NOT NULL,
    `item_number_in_cart` tinyint(1) NOT NULL , --- 5 items in cart= 5 rows
    `price` DECIMAL (6,2) NOT NULL,
    PRIMARY KEY (orderid, item_number_in_cart),
    FOREIGN KEY (orderid) REFERENCES orders(orderid)
) ENGINE = InnoDB;

Moreover, a primary key is simply a unique key where every column is not null with a certain name; you can create your own unique keys on non-nullable columns to get the same effects.

You'll not likely get much of a performance improvement by indexing item_number_in_cart; as the number of line items for a given order will tend to be small, sorting by item_number_in_cart won't take much time or memory. However, including the column in a primary key will help with data consistency.

看透却不说透 2024-12-22 16:29:06

将不会使用 item_number_in_cart 上的索引。它是很小的整数,选择性不够,一旦你有 2 条记录,引擎甚至不会考虑它。您可以将其作为第二列添加到 orderid 上的现有索引中(由于您在 orderid 上创建了 FK 约束,mysql 会自动在此字段上添加索引)。
你说order_items中的数据从未更新过,但我认为可以删除;在没有主键的情况下这样做将会出现问题。

Index on item_number_in_cart won't be used. It's tiny int, not selective enough, and won't even considered by the engine once you have 2 records. You can add it as a second column to the existing index on orderid (since you created FK constraint on orderid, mysql automatically adds an index on this field).
You say that data in order_items never updated, but I think it can be deleted; doing so without primary key will be problematic.

千秋岁 2024-12-22 16:29:06

好吧,无论如何我都会有一个 autoinc,因为我非常相信代理键,但正如 alex07 所建议的,索引,甚至 orderid 的主键,item_number_in_cart 应该可以解决问题。请注意,按 item_number 排序将使用两遍排序(获取数据,然后按数字顺序对其进行排序),因此索引/键将直接将其切掉,因此即使使用代理键,您也需要该索引。

Well I'd be having an autoinc anyway, as I'm a big believer in surrogate keys, but as suggested by alex07 an index, or even primary key of orderid,item_number_in_cart should sort things out. Note the order by item_number will be using a two pass sort, (get the data and then sort it in the number order) so an index / key will chop that out straight off so you'd want that index even with a surrogate key.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文