Na verdade, o design que você descreveu (tabela comum mais tabelas específicas de subtipo) é chamado de Class Table Inheritance .
Herança de tabela de concreto teria todos os atributos comuns duplicados nas tabelas de subtipos e você não teria nenhuma tabela de supertipos como tem agora.
Sou fortemente contra o EAV. Eu considero um antipadrão SQL. Pode parecer uma solução elegante porque requer menos mesas, mas você está se preparando para muita dor de cabeça mais tarde. Você identificou algumas desvantagens, mas existem muitas outras. IMHO, EAV é usado apropriadamente somente se você absolutamente não deve crie uma nova tabela ao introduzir um novo subtipo ou se tiver um número ilimitado de subtipos (por exemplo, os usuários podem definir novos atributos ad hoc).
Você tem muitos subtipos, mas ainda um número finito deles, então se eu estivesse fazendo este projeto eu ficaria com Class Table Inheritance . Você pode ter poucas linhas de cada subtipo, mas pelo menos você tem alguma garantia de que todas as linhas em cada subtipo têm as mesmas colunas, você pode usar
NOT NULL
se precisar, você pode usar tipos de dados SQL, você pode usar restrições de integridade referencial, etc. De uma perspectiva relacional, é um design melhor que EAV. Mais uma opção que você não mencionou é chamada LOB serializado . Ou seja, adicione uma coluna BLOB para uma coleção semiestruturada de atributos personalizados. Armazene XML, YAML, JSON ou seu próprio DSL nessa coluna. Você não poderá analisar atributos individuais desse BLOB facilmente com SQL, você terá que buscar todo o BLOB de volta em seu aplicativo e extrair atributos individuais no código. Então, de certa forma, é menos conveniente. Mas se isso satisfaz seu uso dos dados, não há nada de errado com isso.