为什么要"SHOW INDEX FROM `table`"问题续集?



如果您启用Sequelize记录,则会在"同步"阶段和创建表之后立即看到Sequelize执行SHOW INDEX FROM table查询。问题是 - 为什么?


要更具体,这是我正在执行的代码:

var Sequelize = require('sequelize');
var connection = new Sequelize('demo_schema', 'root', 'password');
var Article = connection.define('article', {
    slug: {
        type: Sequelize.STRING,
        primaryKey: true
    },
    title: {
        type: Sequelize.STRING,
        unique: true,
        allowNull: false
    },
    body:  {
        type: Sequelize.TEXT
    }
}, {
    timestamps: false
});
connection.sync({
    force: true,
    logging: console.log
}).then(function () {
   // TODO
});

这是控制台上的输出:

Executing (default): DROP TABLE IF EXISTS `articles`;
Executing (default): DROP TABLE IF EXISTS `articles`;
Executing (default): CREATE TABLE IF NOT EXISTS `articles` (`slug` VARCHAR(255) , `title` VARCHAR(255) NOT NULL UNIQUE, `body` TEXT, UNIQUE `articles_title_unique` (`title`), PRIMARY KEY (`slug`)) ENGINE=InnoDB;
Executing (default): SHOW INDEX FROM `articles`

续集使用SHOW INDEX FROM的原因是避免第二次将现有索引添加到模型的表中。第二次添加现有索引将导致错误。

续集当前不够"聪明",无法理解您尚未定义任何索引。无论如何,它都会检查表。

在您的情况下,由于您强制同步而不会有所作为。这意味着这些表总是被删除和新创建。添加新索引时,不会有任何现有索引。

想象您将指定具有这样的索引的模型:

sequelize.define('user', {}, {
  indexes: [
    // Create a unique index on email
    {
      unique: true,
      fields: ['email']
    }
  ]
})
该示例的广泛形式可以在http://docs.sequs.sequeslizejs.com/en/latest/docs/models-definition/#indexes中找到。

虚构故事

如果您昨天使用quelize.sync()创建了表没有现有索引),续集将仅添加新索引。

在此处如何续集工作?

续集通过发出SHOW INDEX FROM并将返回值与模型的索引进行比较,确定了哪些索引是新的。如果续集发现模型中的索引比现有表中有更多(或不同的)索引,则将这些索引添加到基础表中。

可以在GitHub上找到执行此操作的代码。在以下代码段中,我在相应的代码中添加了一些注释:

// this.QueryInterface.showIndex produces the statement `SHOW INDEX FROM [table of the model]`. It returns a promise containing the found indexes.
.then(() => this.QueryInterface.showIndex(this.getTableName(options), options))
// `indexes` will contain the indexes which are present on the existing table.
// If you force sync, this will always be empty since the table is new.
.then(indexes => {
  // Assign an auto-generated name to indexes which are not named by the user
  this.options.indexes = this.QueryInterface.nameIndexes(this.options.indexes, this.tableName);
  // Fill `indexes` with only the indexes from your model which are not present on the table.
  indexes = _.filter(this.options.indexes, item1 => !_.some(indexes, item2 => item1.name === item2.name));
  // .map iterates over `indexes` and adds an index for each entry.
  // Remeber, this is for indexes which are present in the model definition but not present on the table.
  return Promise.map(indexes, index => this.QueryInterface.addIndex(
    this.getTableName(options),
    _.assign({
      logging: options.logging,
      benchmark: options.benchmark,
      transaction: options.transaction
    }, index),
    this.tableName
  ));
})

最新更新