【问题标题】:Rails Row-Based Database, Huge Number of RequestsRails 基于行的数据库,大量的请求
【发布时间】:2015-04-06 13:14:16
【问题描述】:

我设计了一个以短链接行为中心的数据库。

我有以下架构:

  create_table "students", force: :cascade do |t|
    t.string   "first_name"
    t.string   "last_name"
    t.string   "email"
    t.boolean  "recruit",    default: true
    t.boolean  "archive",    default: false
    t.datetime "created_at"
    t.datetime "updated_at"
  end

  create_table "fields", force: :cascade do |t|
    t.string   "name"
    t.integer  "index"
    t.integer  "group_id"
    t.string   "description"
    t.string   "options"
    t.boolean  "hidden"
    t.boolean  "locked",      default: false
    t.datetime "created_at"
    t.datetime "updated_at"
  end

  create_table "groups", force: :cascade do |t|
    t.string   "name"
    t.datetime "created_at"
    t.datetime "updated_at"
  end

  create_table "texts", force: :cascade do |t|
    t.integer  "student_id"
    t.integer  "field_id"
    t.string   "content",    default: ""
    t.datetime "created_at"
    t.datetime "updated_at"
  end

  create_table "options", force: :cascade do |t|
    t.integer  "student_id"
    t.integer  "field_id"
    t.string   "choice",     default: ""
    t.datetime "created_at"
    t.datetime "updated_at"
  end

  create_table "addresses", force: :cascade do |t|
    t.integer  "student_id"
    t.integer  "field_id"
    t.string   "address_1",  default: ""
    t.string   "address_2",  default: ""
    t.string   "city",       default: ""
    t.integer  "state_id",   default: 1
    t.string   "zip",        default: ""
    t.datetime "created_at"
    t.datetime "updated_at"
  end

这个组织背后的基础是一种完全灵活的形式。您只需在字段表中添加一个新行,该条目就会在生成学生的表单上定义一个新问题。组是指选项字段、文本字段或地址。保存数据后,与给定字段关联的组会告诉我的应用程序将其放入哪个表中。该系统运行良好。它超级灵活,我可以很容易地查看哪些学生有特定选项的数据,并且我几乎可以根据任何内容进行查询。

问题是当我开始展示学生时。我首先查询要显示的学生,然后我必须搜索每个学生的每个字段。这意味着对于 500 名学生,我在一个基本表单上大约有 2500 个查询。这会扼杀性能。

我想知道将查询连接在一起并加速该系统的最佳方法是什么?

部分问题是我不能 100% 确定学生有给定的字段,所以当我现在查询时,如果数据库没有返回结果,我可以创建一个。

【问题讨论】:

    标签: sql ruby-on-rails ruby database postgresql


    【解决方案1】:

    您似乎没有在此处定义任何外键。使用 FK 并确保它们在每个表上命中 索引 的组合应该允许快速连接。

    我假设您在问题中使用的是基于 RailsDSLActiveRecord。添加 FK 后,我建议您考虑使用 joinsActiveRecord Querying doc.

    如果您担心某些JOIN 列不存在,您可以在对joins 的调用中使用LEFT OUTER JOIN(在上面的链接中提到)这样您仍然可以从左侧获取所有行-即使连接条件不匹配,也可以简单地获取右侧的NULL 列值。 NULL 会告诉您哪些不存在并且可能需要随后创建。

    根据 OP 的评论进行编辑:

    我自己没有使用过 SchemaPlus gem,但如果你愿意,我认为它可以用于外键,因为这是它支持的东西之一(根据its doc)。

    关于这个问题:

    如果认为它是外键,是否会出现问题 出于某种原因数据不再存在于一端?

    外键对于强制执行 referential integrity 至关重要。

    例如,如果您在texts 表中将field_id 作为外键,则无法从field 表中删除相应的记录(不使用cascade 也可以删除下游记录) ,因为它指的是field 中的一条记录。

    另一方面,您将无法在 texts 中插入包含无效 field_id 的行——如果 field_idfields 中不存在,Postgres 会抛出外键约束冲突

    外键是表格设计的关键部分,绝对应该使用。它使您不必将所有这些逻辑放在应用程序代码中的所有位置,例如在尝试插入任何内容之前,必须检查您要插入的密钥是否有效;相反,如果它们不是,Postgres 将违反约束,并且作为可以处理的异常返回到您的应用程序,例如回滚并返回错误)。

    基本上,只要您在一个表中有一个 id 引用另一个表中的记录,就应该在外键约束中定义它。

    此外,可能值得为每个表添加一个主键。我经常喜欢使用serial 变量来确保每一行都可以通过一个键来识别,即使存在构成隐含主键的元组。主键还基于这些键隐式创建索引。

    【讨论】:

    • 嗨。我一直在研究 SchemaPlus gem,它似乎是将外部约束作为一个简单的约定添加到我的迁移中。将我打算作为外键的所有列都设为正式这样有什么问题吗?如果由于某种原因数据在一端不再存在,是否会因为认为它是外键而引起问题?我有一些行将引用我的主用户表,并且可能是一个键,但它们也可以被删除。外键会在删除过程中引起任何连锁反应吗?
    猜你喜欢
    • 1970-01-01
    • 2023-04-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多