Rails 采用视图减少 Rails 底层的复杂的表连接操作是否可取?

yangyuqian · 2015年07月02日 · 最后由 yangyuqian 回复于 2015年07月02日 · 2042 次阅读

有时候,复杂的业务需求中,为了获取一些额外信息,需要去 join 很多表,比如一个经典的 user role permission 的 5 表设计: user user_role role role_permission permission

如果想要获取某个 User 的所有权限,可以借助以下 SQL:

SELECT u.id, u.username, r.name, p.name FROM user u 
INNER JOIN user_role ur ON ur.user_id = u.id
INNER JOIN role r ON r.id = ur.role_id
INNER JOIN role_permission rp ON rp.role_id = r.id
INNER JOIN permission p ON rp.permission_id = p.id;

采用 ActiveRecord 定义时需要加入很多额外的 association,极大地提升了业务复杂度。

如果能创建一个 view,建立从 user -> permission 的关系:

CREATE VIEW user_permission AS SELECT u.id uid, r.id rid, p.id pid, u.username username, r.name rname, p.name pname FROM user u 
INNER JOIN user_role ur ON ur.user_id = u.id
INNER JOIN role r ON r.id = ur.role_id
INNER JOIN role_permission rp ON rp.role_id = r.id
INNER JOIN permission p ON rp.permission_id = p.id;

只需要定义一个 UserPermission 就能查询相应的 view 了:

class UserPermission < ActiveRecord::Base; end

目前看到这种方案是可以降低业务代码的复杂度的,但是否会对性能造成影响呢?

  1. 通过视图并没有避免 join,只是把 join 交给数据库视图处理而已,性能上和自己 join 应该没有多大区别。
  2. 有一种视图叫物化视图,pg, oracle 数据库有,mysql 没有。物化视图真正把数据生成了,所以避免了 join,性能上有提升,代价就是数据库要维护。
  3. 按正常的建模方法,rails 可以使用 eager load 和 cache,不一定非要 join,我认为更可控,性能也不会差。

视图在 sql 查询层面没任何优化。

但在 AR 对象生成的层面是有优化和简化的。

另,Rails 对视图支持不友好。

视图无法创建索引。

@vincent 大神言之有理!

需要 登录 后方可回复, 如果你还没有账号请 注册新账号