在创建表之后向SQLAlchemy模型添加索引

use*_*375 25 python indexing sqlalchemy

我有一个flask-sqlalchemy模型:

class MyModel(db.Model):
__tablename__ = 'targets'
id = db.Column(db.Integer, primary_key=True)
url = db.Column(db.String(2048))
Run Code Online (Sandbox Code Playgroud)

该表已经创建并正在使用中.我想在url属性上创建一个索引,所以我将index = True传递给它:

url = db.Column(db.String(2048), index=True)
Run Code Online (Sandbox Code Playgroud)

如何在不删除和重新创建表的情况下使此索引生效?

brt*_*ury 29

当我降落在这里时,目前的最佳答案并没有帮助我.阅读文档(和源代码)后,我发现这个工作,希望它有所帮助.

给出原始问题的模型类.

class MyModel(db.Model):
    __tablename__ = 'targets'
    id = db.Column(db.Integer, primary_key=True)
    url = db.Column(db.String(2048))
Run Code Online (Sandbox Code Playgroud)

您不能只是添加,index=True因为即使您调用db.Model.metadata.create_all()索引也不会在已创建的表上创建.

相反,您需要创建一个独立的Index对象,然后创建它.它看起来像这样:

class MyModel(db.Model):
    __tablename__ = 'targets'
    id = db.Column(db.Integer, primary_key=True)
    url = db.Column(db.String(2048))

mymodel_url_index = Index('mymodel_url_idx', MyModel.url)

if __name__ == '__main__':
    mymodel_url_index.create(bind=engine)
Run Code Online (Sandbox Code Playgroud)

现在engine来自你的sqlalchemy配置,但这段代码应该传达需要发生的事情的要点.

  • `mymodel_url_index.create(bind=engine)` 应该什么时候执行?如果我使用 Alembic,这会改变吗? (2认同)

flo*_*ter 25

自从提出问题以来,已为此添加了支持。

现在您只需添加index=True到现有列,并自动生成迁移。

检查以下软件包版本:

alembic==1.0.10
SQLAlchemy==1.3.4
SQLAlchemy-Utils==0.34.0
Flask-SQLAlchemy==2.4.0
Flask-Migrate==2.5.2
Run Code Online (Sandbox Code Playgroud)

  • 我真的很高兴看到这一点。我刚才尝试在相关库中搜索对此功能的引用,但无法找到任何对它的引用。我认为如果我/你/某人可以找到引用此功能的文档或更改日志的链接并将其包含在此处,那将会非常有帮助。 (2认同)

Rob*_*ant 8

如果您使用的是Alembic,则可以创建一个迁移来做到这一点,并且完全避免将其添加到模型中:

def upgrade():
    # ### commands auto generated by Alembic - please adjust! ###
    op.create_index('table1_id', 'table1', ['id'], unique=True)
    op.create_index('table2_id', 'table2', ['id'], unique=True)
    # ### end Alembic commands ###

def downgrade():
    # ### commands auto generated by Alembic - please adjust! ###
    op.drop_index('table1_id', table_name='table1')
    op.drop_index('table2_id', table_name='table2')
    # ### end Alembic commands ###
Run Code Online (Sandbox Code Playgroud)

  • 那么每次您要使用`autogenerate`时,它都希望将其删除 (2认同)

zzz*_*eek 5

致电create()指数:

index.create()
Run Code Online (Sandbox Code Playgroud)

http://docs.sqlalchemy.org/en/latest/core/constraints.html#sqlalchemy.schema.Index.create

  • 这个答案不知道从原始问题的代码中从哪里获取这个索引对象.通过文档进行搜索以发现这是艰苦的,并且实际上几乎没有帮助,因为他们没有涉及使用声明性api(在原始问题中使用).对于像我一样困惑的其他人,并且不想抓取文档和源代码,请参阅我的下面的答案. (21认同)

vvl*_*rov 3

请注意,这是不正确且过于复杂的答案

正确的方法是按照这里index.create所说的那样使用。


首先,确保您拥有数据库的最新快照,并且能够从该快照恢复数据库。

对于中型和大型项目(您可能需要同时支持多个版本并安装在多个环境中的项目),有一个特殊的过程,它是数据库管理生命周期的一部分,称为“数据库迁移”。数据库迁移包括对现有架构的更改。SQLAlchemy 不支持开箱即用的迁移。

有两种 SQLAlchemy 兼容的数据库迁移工具可用:

在 SQLAlchemy 文档页面中查看更多信息和这些工具的链接:通过迁移改变架构

但如果您正在开发小型项目,我建议您从数据库命令行实用程序或通过 python 脚本中的 connection.execute() 手动运行 ALTER TABLE DDL 查询。

在我现在正在使用的生产应用程序中,我们仅支持一个最新版本的应用程序。对于每个数据库架构更改,我们都会执行以下步骤:

  • 制作生产数据库的快照
  • 在开发环境中加载此快照
  • 更新 sqlalchemy 数据模型模块
  • 准备并运行更改表查询并保存此查询以供以后使用
  • 对代码进行其他相关更改
  • 在开发环境上运行测试
  • 将最新版本的代码部署到生产环境
  • 在生产中更改表

另外,我使用以下技巧来生成创建表/索引查询:我将我的应用程序指向全新的数据库,启用 sqlalchemy 查询的日志记录并运行metadata.create_all()- 因此在日志(或 STDOUT)中我看到由 sqlalchemy 生成的创建查询

根据您使用的数据库系统的不同,索引创建查询会略有不同。通用查询如下所示:

create index targets_i on targets(url);
Run Code Online (Sandbox Code Playgroud)