Какова лучшая производительность для получения результатов MySQL EAV в виде реляционной таблицы - PullRequest
14 голосов
/ 07 января 2012

Я хочу извлечь результаты из таблиц EAV (сущность-атрибут-значение) или, в частности, таблиц метаданных сущности (например, wordpress wp_posts и wp_postmeta), как "красиво отформатированную реляционную таблицу", чтобы сделать некоторую сортировку и / или фильтрацию .

Я нашел несколько примеров того, как отформатировать результаты в запросе (в отличие от написания двух запросов и объединения результатов в коде), но я хотел бы знать «наиболее эффективный» метод для этого, особенно для больших наборов результатов.

И когда я говорю «самый эффективный», я имею в виду что-то вроде следующих сценариев:

Получить все сущности с фамилией, такие как 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. Multi-Join :
    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, создайте объект-заполнитель из результата
    SELECT m.* FROM `META` m WHERE m.EntityID = {whatever};
    
    в PHP, просматривайте результаты и присоединяйте к объекту сущности как: $e->{$result->key} = $result->VALUE

Что лучше вообще и для фильтрации / сортировки?

Похожие вопросы:

  1. Результаты связывания EAV
  2. Как развернуть сущность MySQL

Ответы [ 2 ]

1 голос
/ 07 января 2012

Лучший способ узнать это, конечно, проверить. Ответ может быть разным в зависимости от размера набора данных, количества различных мета-ключей, их распределения (у всех сущностей есть значения для всех мета-ключей? Или только для нескольких из них?), Настроек вашей базы данных сервер и, возможно, многие другие факторы.

Если бы я догадался, я бы сказал, что стоимость операций JOIN в варианте 2 будет меньше, чем стоимость GROUP BY и агрегатных функций, необходимых в вариантах 1 и 3.

Итак, я ожидал бы найти вариант 2 быстрее, чем 1 и 3.

Чтобы измерить вариант 4, вам нужно учитывать больше факторов, поскольку приложение может находиться на другом сервере, поэтому нагрузки на два сервера (базы данных и приложения) и количество клиентов, которые будут запрашивать эти результаты, должны быть Учтено.


Sidenote: вам нужно GROUP BY e.ID в вариантах 1 и 3.

0 голосов
/ 07 января 2012

Все, что использует сводку или агрегаты, вероятно, будет быстрее, поскольку они не требуют самостоятельного объединения таблицы.Подходы, основанные на объединении, потребуют, чтобы оптимизатор выполнил несколько операций подзапроса, а затем объединил результаты.Для небольшого набора данных это может не иметь большого значения, но это может значительно снизить производительность, если вы выполняете аналитический запрос для большего набора данных,

...