Rails基于行的数据库,大量请求

时间:2015-04-06 13:14:17

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

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

我有以下架构:

  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%确定学生有一个给定的字段,所以当我现在查询时,如果数据库没有返回任何结果,我可以创建一个。

1 个答案:

答案 0 :(得分:0)

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

我假设您在问题中使用基于 Rails DSL ActiveRecord 。我建议您在添加FK后使用joinsActiveRecord Querying doc

如果您担心某些JOIN列不存在,可以在LEFT OUTER JOIN的调用中使用joins(在上面的链接中提及),这样您仍然可以使用即使连接条件没有匹配,左侧表中的行也只是获得右侧的NULL列值。那些NULL会告诉你哪些不存在,可能需要随后创建。

根据OP的评论进行编辑:

我自己没有使用 SchemaPlus gem,但我觉得如果你愿意的话可以使用外键,因为它支持的是其中一个(根据its doc )。

关于这个问题:

  

就像是因为认为它是外键而引起的问题   某些原因数据不再存在于一端?

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

例如,如果field_id表中有texts作为外键,则无法从field表中删除相应的记录(不使用cascade还要删除下游记录),因为它指的是field中的记录。

另一方面,如果texts中不存在field_id,您将无法插入field_id行,其中fields无效serial Postgres 会抛出外键约束违规

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

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

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