【问题标题】:How to properly index attributes in wordpress database如何正确索引 wordpress 数据库中的属性
【发布时间】:2020-07-13 16:59:58
【问题描述】:

我正在扩展一个产品销售插件,并试图了解 wordpress 如何处理数据库关系。我正在使用dbDelta 构建激活表。表模式的一个示例是:

$table_schema = [
        "CREATE TABLE IF NOT EXISTS `{$wpdb->prefix}plugin_orders` (
          `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
          `people_id` bigint(20) DEFAULT NULL,
          `order_id` bigint(20) DEFAULT NULL,
          `order_status` varchar(11) DEFAULT NULL,
          `order_date` datetime DEFAULT NULL,
          `order_total` decimal(13,2) DEFAULT NULL,
          `accounting` tinyint(4) DEFAULT '0',
          PRIMARY KEY (`id`),
          KEY `people_id` (`people_id`),
          KEY `order_id` (`order_id`)
        ) $collate;",

        "CREATE TABLE IF NOT EXISTS `{$wpdb->prefix}plugin_order_product` (
          `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
          `order_id` bigint(20) DEFAULT NULL,
          `product_id` bigint(20) DEFAULT NULL,
          PRIMARY KEY (`id`),
          KEY `order_id` (`order_id`),
          KEY `product_id` (`product_id`)
        ) $collate;"
    ];

我看到每个表中的idPRIMARY KEY,但声明另一个KEYs 实际上有什么作用?我读过 wordpress 使用 MyISAM,它实际上并没有建立外键连接。虽然这些表可能指向其他已经存在的表,但在此示例中,声明 KEY order_id (order_id) 是否会创建一个名为 order_id 的任何其他表可以用来引用的变量?此代码是否专门将一个表属性连接到另一个表属性(它似乎不是)?构建这些表后,我可以在 phpMyAdmin 中检查它们,并查看分配了索引但没有外键约束。此代码如何创建将一个表指向另一个表以建立关系的表?

【问题讨论】:

    标签: php mysql database wordpress database-design


    【解决方案1】:
    KEY `foo_bar` (`order_id`)
    

    “KEY”与“INDEX”相同。它指定维护一个单独的数据结构,以便通过列order_id 高效访问表。

    foo_bar 是索引的名称。它没有特别的意义,也很少用。比如DROP KEY foo_bar;就是摆脱索引的方式。

    在 MyISAM 中,允许使用“外键”,但会被忽略。在 InnoDB 中,它做了两件事:

    • 如果尚未提供索引,请创建索引
    • 提供约束。默认值有效地“在另一个表还没有引用的值时抱怨”。

    拥有索引对性能很重要。上面的索引使这个

    SELECT ... WHERE order_id = 1234 ...
    

    以毫秒为单位运行,即使表中有数十亿行。如果没有索引,查询将需要几分钟或几小时。

    PRIMARY KEYUNIQUE 键,它是 INDEX

    UNIQUE(widget) 表示表格中只有一行可以有特定的 `widget 值。

    PRIMARY KEY(id) 表示每一行都由列id 唯一标识。 InnoDB 真的希望每个表都有一个 PK。

    id”是 PK 名称的约定(不是要求)。按照惯例,它也是INT AUTO_INCREMENT。你可能会也可能不会真的碰过id

    表格可以通过 3 种主要方式相互关联:

    1:1 -- 它们共享相同的唯一密钥。这很少有用;你也可以有一张桌子。

    1:many -- 一个“订单”中有几个“项目”(一个订单:许多项目)。这通常由order_id 作为items 表中的一列来处理。

    many:many -- students_classes -- 每个学生在多个班级;每个班都有很多学生。这是通过(通常)只有两列的映射表实现的:student_idclass_id(不需要id)和PRIMARY KEY(student_id, class_id)INDEX(class_id, student_id)。这两个索引使从已知学生到他们的班级变得高效,反之亦然。

    表的 PK 的另一个约定是包含表名。 (对于其他列,例如order_status,这样做会很混乱。)我假设student_idclass_id 有这个约定。

    但现在我对你的plugin_orders 感到困惑——它同时具有idorder_id。如果该表描述了“订单”,那么我希望 order_id 成为 PK 而不是 id

    而且,如果order_product 是每个“订单”中所有“产品”的列表,那么我希望您拥有 1:many 模式。

    有什么索引?

    • PRIMARY KEY 唯一标识每一行 - id 或唯一的某些列(或列组合)。
    • 其他列,根据需要,用于您拥有的 SELECTsUPDATEsDELETEs在获得一些可能需要的查询线索之前,不要盲目添加索引。

    索引有时有助于排序:

    SELECT ... ORDER BY last_name, first_name;
    

    一起

    INDEX(last_name, first_name)
    

    索引提供性能; FK 提供完整性检查。两者都不是“必需的”;两者都是“可取的”。

    MyISAM 是古老的;你应该换成 InnoDB。

    然后做类似的事情

    SELECT ...
        FROM plugin_orders AS o
        JOIN plugin_order_product AS op
               ON o.order_id = op.order_id
        WHERE ...
    

    在本例中,优化器将执行如下查询:

    1. 查看WHERE 以了解哪个表最适合根据那里的条件进行过滤。声明这是第一个使用的表。
    2. 扫描第一个表,如果可行,使用索引。
    3. 对于第一个表中的每一行,请访问第二个表。
    4. 可能会通过第二张桌子上的INDEX(order_id) 进入第二张桌子。这将使JOIN 快速高效。

    两个表都有INDEX(order_id),但这不相关。

    下一个例子:

    SELECT ...
        FROM plugin_orders AS o
        JOIN plugin_order_product AS op
               ON o.order_id = op.order_id
        WHERE o.people_id = 123   -- note
    
    1. 由于对people_id 进行过滤,因此选择o 作为第一个表
    2. 使用opINDEX(people_id) 快速找到相关的o 行。
    3. 等(op是第二张表)

    下一个例子:

    SELECT ...
        FROM plugin_orders AS o
        JOIN plugin_order_product AS op
               ON o.order_id = op.order_id
        WHERE op.product_id = 9887    -- changed again
    
    1. 由于对product_id 进行过滤,因此选择op 作为第一个表
    2. 使用oINDEX(people_id) 快速找到相关的op 行。
    3. 等(o这次是第二张桌子)

    【讨论】:

    • 我通常了解索引/FK,但在此示例中,如果我声称一列是 KEY 或索引,如何在不定义其关系的情况下将其链接到另一个表?如果表 1 有 order_id 作为键,并且我在另一个表中有元数据,列出了订单中的所有项目,并且有一列 order_id,它知道它们是链接的吗?我是否需要在每个表中将所有 order_id 列定义为KEY?我希望了解这种结构,因为这就是所有 wordpress 的工作方式,但我能找到的互联网上的每个示例都定义了严格的外键和连接。
    • 原始示例来自扩展 woocommerce 的插件,因此它可能无法显示需要连接的所有列。我只是想展示 wordpress $wpdb 如何用于创建新表并分配主键和索引的语法,因此对于表连接引用的位置,该示例可能不完整。
    • 实际上这是使用dbDelta 而不是$wpdb 创建表。我会更改帖子以反映
    • @JasonH - 我添加了JOIN 的粗略示例。它可能有效也可能无效,具体取决于表的语义。 SELECT 不依赖于任何 INDEX 或 FK,尽管它希望这样。
    • @RickJames 和我刚刚推出了一个(免费的,GPL)WordPress 插件,为一些繁忙的 WordPress 表添加高性能索引。 wordpress.org/plugins/index-wp-mysql-for-speed
    猜你喜欢
    • 1970-01-01
    • 2011-06-30
    • 2016-11-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-20
    相关资源
    最近更新 更多