12

Chcę wyodrębnić wyniki z tabel EAV (entity-attribute-value), a dokładniej tabele-encji (myślę, że wordpress wp_posts i wp_postmeta) jako "ładnie sformatowana tabela relacyjna ", w celu sortowania i/lub filtrowania.Jaka jest najlepsza wydajność do pobierania wyników EAV MySQL jako tabeli relacyjnej

Znalazłem kilka przykładów formatowania wyników w zapytaniu (w przeciwieństwie do pisania 2 zapytań i dołączania wyników do kodu), ale chciałbym poznać metodę "najbardziej wydajną", aby to zrobić, szczególnie w przypadku większych zestawów wyników.

A kiedy mówię „najbardziej skuteczny”, mam na myśli coś podobnego następujących scenariuszy:

uzyskać wszystkie podmioty, z nazwiska jak XYZ

Zwraca listę podmiotów Weaver urodzin


np. włączyć to:

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

do tego:

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

więc można sortować lub filtrować według któregokolwiek z pól meta.


Znalazłem kilka propozycji here, ale nie mogę znaleźć żadnej dyskusji, z których wykonuje się lepiej.

Opcje:

  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. Wielu Dołącz:
     
    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. koalescencyjny:
     
    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. Kod:
     
    SELECT e.* FROM `ENTITY` e WHERE e.ID = {whatever}; 
    
    w PHP, utworzenie obiektu zastępczego od wyniku
     
    SELECT m.* FROM `META` m WHERE m.EntityID = {whatever}; 
    
    w PHP, pętla poprzez wyników i dołączyć do obiektu jednostki jak: $e->{$result->key} = $result->VALUE

Co jest lepsze w ogóle i do filtrowania/sortowania?

Powiązane pytania:

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

Jeśli był zakład na wykonanie i tylko jedna szansa na zrobienie zdjęcia, idź do multi-join. –

+0

Potrzebujesz "GROUP BY e.ID" w opcjach 1 i 3. –

+0

Spójrz na [to pytanie] (http://dba.stackexchange.com/questions/9466/most-performant-sql-query-ededed) na dba.se – ConcernedOfTunbridgeWells

Odpowiedz

0

Anything za pomocą przegubu lub agregatów prawdopodobnie będzie szybsze, gdyż nie wymagają tabeli na własny połączone. Metody oparte na sprzęcie będą wymagać od optymalizatora wykonywania kilku operacji pod-kwerendy, a następnie łączenia wyników razem. W przypadku małego zestawu danych może to nie mieć większego znaczenia, ale może to znacznie obniżyć wydajność, jeśli wykonujesz zapytanie analityczne na większym zestawie danych,

+0

na podstawie twojego linku w pytaniu komentarze, zaznaczam to jako odpowiedź, chociaż miałem nadzieję na coś bardziej konkretnego :) – drzaus

+0

Mam system eav i jego rosnący w jaki sposób mogę przenieść go do innego modułu zapisu, aby zapisać system? a pytanie brzmi w którą sposób wolisz oszczędzać (json?)? –

1

Najlepszym sposobem, aby dowiedzieć się, będzie test, z kursu. Odpowiedź może być różna w zależności od rozmiaru zbioru danych, liczby różnych meta-kluczy, ich dystrybucji (czy wszystkie encje mają wartości dla wszystkich meta-kluczy lub tylko dla kilku z nich?), Ustawienia twojej bazy danych serwer i prawdopodobnie wiele innych czynników.

Gdybym miał zgadywać, powiedziałbym, że koszt operacji w wariancie 2 JOIN byłby mniejszy niż koszt GROUP BY i zagregowanych funkcji potrzebnych w opcji 1 i 3.

So, chciałbym spodziewaj się znaleźć opcję 2 szybszą niż 1 i 3.

Aby zmierzyć opcję 4, należy wziąć pod uwagę więcej czynników, ponieważ aplikacja może znajdować się na innym serwerze, więc obciążenia dwóch serwerów (db i aplikacji) oraz liczba klientów, którzy będą żądać tych wyników, musi być wzięta pod uwagę.


Sidenote musisz GROUP BY e.ID w opcji 1 i 3.