12

que desea extraer los resultados de EAV (entidad-atributo-valor) mesas, o más específicamente tablas entidad de metadatos (piensa como wordpress wp_posts y wp_postmeta) como un "muy bien tabla relacional formateada ", para hacer algo de clasificación y/o filtrado.¿Cuál es el mejor rendimiento de Recuperación de resultados MySQL EAV como tabla relacional

He encontrado algunos ejemplos de cómo formatear los resultados dentro de la consulta (en lugar de escribir 2 consultas y unir los resultados en el código), pero me gustaría conocer el método "más eficiente" para hacerlo, especialmente para conjuntos de resultados más grandes.

Y cuando digo "más eficiente", me refiero a algo como los siguientes escenarios:

Consigue todas las entidades con apellido como XYZ

devolver una lista de entidades ordenado por el cumpleaños


por ejemplo convertir esto:

 
** ENTITY ** 
----------------------- 
ID | NAME | whatever 
----------------------- 
1 | bob | etc 
2 | jane | etc 
3 | tom | etc 

** META ** 
------------------------------------ 
ID | EntityID | KEY   | VALUE 
------------------------------------ 
1 | 1  | first name | Bob 
2 | 1  | last name | Bobson 
3 | 1  | birthday | 1983-10-10 
. | 2  | first name | Jane 
. | 2  | last name | Janesdotter 
. | 2  | birthday | 1983-08-10 
. | 3  | first name | Tom 
. | 3  | last name | Tomson 
. | 3  | birthday | 1980-08-10 

en esto:

 
** RESULTS ** 
----------------------------------------------- 
EID | NAME | first name | last name | birthday 
----------------------------------------------- 
1 | bob | Bob  | Bobson  | 1983-10-10 
2 | jane | Jane  | Janesdotter | 1983-08-10 
3 | tom | Tom  | Tomson  | 1980-08-10 

por lo que se puede ordenar o filtrar por cualquiera de los campos de metadatos.


he encontrado algunas sugerencias here, pero no puedo encontrar ninguna discusión de los cuales tiene un mejor rendimiento.

Opciones:

  1. GROUP_CONCAT:
     
    SELECT e.*, GROUP_CONCAT(CONCAT_WS('||', m.KEY, m.VALUE) ORDER BY m.KEY SEPARATOR ';;') 
    FROM `ENTITY` e JOIN `META` m ON e.ID = m.EntityID 
    
  2. Multi-Ingreso:
     
    SELECT e.*, m1.VALUE as 'first name', m2.VALUE as 'last name', m3.VALUE as 'birthday' 
    FROM `ENTITY` e 
    LEFT JOIN `META` m1 
        ON e.ID = m1.EntityID AND m1.meta_key = 'first name' 
    LEFT JOIN `META` m2 
        ON e.ID = m2.EntityID AND m2.meta_key = 'last name' 
    LEFT JOIN `META` m3 
        ON e.ID = m3.EntityID AND m3.meta_key = 'birthday' 
    
  3. Coalescing:
     
    SELECT e.* 
        , MAX(IF(m.KEY= 'first name', m.VALUE, NULL)) as 'first name' 
        , MAX(IF(m.KEY= 'last name', m.VALUE, NULL)) as 'last name' 
        , MAX(IF(m.KEY= 'birthday', m.VALUE, NULL)) as 'birthday' 
    FROM `ENTITY` e 
    JOIN `META` m 
        ON e.ID = m.EntityID 
    
  4. Código:
     
    SELECT e.* FROM `ENTITY` e WHERE e.ID = {whatever}; 
    
    en PHP, crear un objeto marcador de posición a partir del resultado
     
    SELECT m.* FROM `META` m WHERE m.EntityID = {whatever}; 
    
    en PHP, bucle a través de resultados y adjuntar a objeto de entidad como: $e->{$result->key} = $result->VALUE

¿Qué es mejor en general, y para filtrar/clasificar?

preguntas relacionadas:

  1. Binding EAV results
  2. How to Pivot a MySQL entity
+0

Si hubo una apuesta por el rendimiento y solo una oportunidad de disparar, apostaría por la unión múltiple. –

+0

Necesita un 'GROUP BY e.ID' en las opciones 1 y 3. –

+0

Mire [esta pregunta] (http://dba.stackexchange.com/questions/9466/most-performant-sql-query-needed) en dba.se – ConcernedOfTunbridgeWells

Respuesta

0

Cualquier cosa usando pivote o agregados probablemente será más rápido, ya que no requieren la mesa para ser auto-unido. Los enfoques basados ​​en la combinación requerirán que el optimizador realice varias operaciones de subconsulta y luego combine los resultados. Para un pequeño conjunto de datos esto podría no importar tanto, pero esto podría degradar significativamente el rendimiento si está haciendo una consulta analítica en un conjunto de datos más grande,

+0

basado en su enlace en los comentarios de la pregunta, estoy marcando esto como la respuesta, aunque esperaba algo más definido :) – drzaus

+0

tengo un sistema eav y está creciendo ¿cómo puedo portarlo a otro módulo de guardado para poder guardar mi sistema? y la pregunta es de qué manera prefiere guardar (json?)? –

1

La mejor manera de averiguarlo sería poner a prueba, por supuesto. La respuesta puede ser diferente según el tamaño del conjunto de datos, el número de metacódigos diferentes, su distribución (¿todas las entidades tienen valores para todas las metacódigos? O solo para algunas de ellas?), La configuración de su base de datos servidor y posiblemente muchos otros factores.

Si tuviera que adivinar, diría que el coste de las operaciones JOIN en la opción 2 sería menor que el costo de GROUP BY y funciones de agregación necesarios en las opciones 1 y 3.

Por lo tanto, lo haría esperar encontrar la Opción 2 más rápido que 1 y 3.

Para medir la Opción 4, tendrá que considerar más factores ya que la aplicación puede estar en otro servidor, por lo que las cargas de los dos servidores (db y aplicación) y número de clientes que solicitarán estos resultados deben tenerse en cuenta.


Nota al margen: se necesita GROUP BY e.ID en las opciones 1 y 3.

Cuestiones relacionadas