以关系表的形式检索MySQL EAV结果的最佳性能是什么

drz*_*aus 14 mysql performance database-design pivot entity-attribute-value

我想提取从EAV(实体属性值)的表,或更具体实体的元数据表的结果(认为像WordPress wp_postswp_postmeta),为"很好的格式化的关系表",以做一些排序和/或过滤.

我已经找到了一些如何在查询中格式化结果的示例(而不是编写2个查询并在代码中加入结果),但我想知道"最有效"的方法,特别是对于更大的结果集.

当我说"效率最高"时,我的意思是出现以下情况:

获取姓氏为XYZ的所有实体

返回按生日排序的实体列表


转过来:

** 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

进入这个:

** 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

所以我可以按任何元字段排序或过滤.


我在这里找到了一些建议,但是我找不到任何关于哪个更好的讨论.

选项:

  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. 多连接:
    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. 合并:
    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. 代码:
    SELECT e.* FROM `ENTITY` e WHERE e.ID = {whatever};
    
    在PHP中,从result创建一个占位符对象
    SELECT m.* FROM `META` m WHERE m.EntityID = {whatever};
    
    在PHP中,循环结果并附加到实体对象,如: $e->{$result->key} = $result->VALUE

一般来说哪个更好,过滤/排序?

相关问题:

  1. 绑定EAV结果
  2. 如何转动MySQL实体

Con*_*lls 0

任何使用数据透视或聚合的方法都可能会更快,因为它们不需要表是自连接的。基于连接的方法将要求优化器执行多个子查询操作,然后将结果连接在一起。对于小型数据集,这可能并不重要,但如果您对较大的数据集进行分析查询,这可能会显着降低性能,