【问题标题】:Does Django ManyToManyField create table with a redundant index?Django ManyToManyField 是否创建具有冗余索引的表?
【发布时间】:2015-06-28 03:45:25
【问题描述】:

如果我有一个模型 Foo,它有一个简单的 M2M 字段来模拟 Bar

class Foo(Model):
    bar = ManyToManyField(Bar)

Django 似乎创建了一个表 foo_bar,它具有以下索引:

index 1: primary, unique (id)
index 2: unique (foo_id, bar_id)
index 3: non_unique (foo_id)
index 4: non_unique (bar_id)

我回忆起我对 SQL 的基本了解,如果一个查询需要在 foo_id 上查找条件,索引 2 就足够了(因为最左边的列可用于查找)。索引 3 似乎是多余的。

我是否正确假设索引 3 确实占用了索引空间而没有提供任何好处?我最好使用直通表并在 (foo_id, bar_id) 上手动创建唯一索引,如果需要,还可以选择在 (bar_id) 上创建另一个索引?

【问题讨论】:

  • 我认为索引 2 是为了防止重复。如果没有它,您可能会在表中多次组合 foo_id 和 bar_id。
  • 需要吗?可能不是。有关系吗?不,在 99% 的情况下(或 99.9%)它不会产生可衡量的差异。你自己做更好吗? *咳*过早优化*咳*...抱歉,那是什么?
  • 我理解 index2 的必要性,这里绝对需要它作为复合的唯一索引。我也知道索引 3 没有任何害处,除了可能占用内存空间和可能的 RAM(因为索引最好保存在 RAM 中以便快速查找,对吧?)所以如果它没有任何好处,为什么还要将它创建为默认值适用于所有 M2M 关系?也许在其他一些 SQL 后端中,这是需要的?

标签: python mysql django


【解决方案1】:

理解多对多关联如何在数据库中表示的关键是要意识到联结表(在本例中为 foo_bar)的每一行将左表 (foo) 中的一行与一行连接起来从右表(栏)。 “foo”的每个pk可以多次复制到“foo_bar”; “bar”的每个pk也可以多次复制到“foo_bar”。但是 "foo_bar" 中的同一对 fk 只能出现一次。

因此,如果您在“foo_bar”中只有一个索引(“foo”或“bar”的pk),则它只能出现一次......而且它不是多对多关系。

例如,我们有两个模型(电子商务):产品、订单。

每个产品可以有多个订单,一个订单可以包含多个产品。

class Product(models.Model):
    ...

class Order(models.Model):
    products = ManyToManyField(Product, through='OrderedProduct')


class OrderedProduct(models.Model):
    # each pair can be only one time, so in one order you can calculate price for each product (considering ordered amount of it).
    # and at the same time you can get somewhere in your template|view all orders which contain same product 

    order = models.ForeignKey(Order)
    product = models.ForeignKey(Product)

    amount = models.PositiveSmallIntegerField()  # amount of ordered products
    price = models.IntegerField()  # just int in this simple example

    def save(self, *args, **kwargs):
        self.price = self.product__price * self.amount

        super(OrderedProduct, self).save(*args, **kwargs)

【讨论】:

    猜你喜欢
    • 2018-01-01
    • 2014-10-11
    • 1970-01-01
    • 2020-05-04
    • 2011-06-28
    • 2016-06-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多