Search code examples
grailsinheritancegrails-orm

How much domain class inheritance is too much in Grails?


From reading the docs in Grails I found the following statement:

However, excessive use of inheritance and table-per-subclass can result in poor query performance due to the use of outer join queries. In general our advice is if you're going to use inheritance, don't abuse it and don't make your inheritance hierarchy too deep.

My question is: how deep is too deep?

Will 5 extensions in an inheritance chain make Grails cry?, 10?, 20?... what is the criteria to determine this?, or do we know if there is a clear way to extrapolate such performance degradation?


Solution

  • How deep is too deep? is a rather subjective question. But, it's possible to make an educated guess when you consider what happens at the database level with table-per-subclass inheritance. Lets assume you have these domain classes:

    class Employee {    
        String firstName
        String lastName
    
        static constraints = {
        }
    
        static mapping = {
            tablePerHierarchy false
        }
    
    }
    
    class Supervisor extends Employee {
        String office
    
        static constraints = {
        }
    }
    

    You'd end up with two tables: EMPLOYEE and SUPERVISOR. The EMPLOYEE table would contain the columns id, first_name, and last_name. But notice that the SUPERVISOR table would only contain the columns id and office.

    This means that to retrieve a Supervisor GORM has to join both tables in order to populate the inherited properties.

    SELECT EMPLOYEE.ID, FIRST_NAME, LAST_NAME, OFFICE
    FROM   SUPERVISOR INNER JOIN EMPLOYEE 
           ON SUPERVISOR.ID = EMPLOYEE.ID
    

    It's these joins which have the potential to result in reduced performance. As you can imagine, 10 or 20 levels of inheritance would be disastrous. Yet a few, especially if the tables are small, would likely be OK.

    Besides, a deep inheritance hierarchy is a sign that something is probably wrong with the domain model architecture (ie. consider using Traits).

    You can read more about both forms of inheritance in my article here.