12

我想從EAV(實體屬性值)表或更具體的實體元數據表(像wordpress wp_postswp_postmeta那樣)提取結果爲「很好格式化關係表「,以便進行一些排序和/或篩選什麼是用於檢索MySQL EAV結果爲關係表的最佳性能

我發現了一些如何在查詢中格式化結果的例子(與編寫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 

這樣我就可以通過任何元字段進行排序或篩選。


我發現了一些建議here,但我找不到它的性能更好的討論。

選項

  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 ,創建結果
     
    SELECT m.* FROM `META` m WHERE m.EntityID = {whatever}; 
    
    在PHP ,遍歷結果的佔位符對象,重視實體對象,如: $e->{$result->key} = $result->VALUE

哪個更好一般,並且過濾/排序?

相關問題:

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

如果有對性能的賭注,只有一次機會投籃,我'去參加多連接。 – 2012-01-06 21:23:12

+0

您在選項1需要一個'GROUP BY e.ID'和3 – 2012-01-06 21:25:16

+0

看看[這個問題](http://dba.stackexchange.com/questions/9466/most-performant-sql-query-needed )上dba.se – ConcernedOfTunbridgeWells 2012-01-06 23:16:41

回答

0

什麼。基於連接的方法將要求優化器執行多個子查詢操作,然後將結果結合在一起。對於小型數據集,這可能不是那麼重要,但如果你正在做一個更大的數據集的分析查詢,這可能顯著降低性能,

+0

根據您在問題評論中的鏈接,我將此標記爲答案,儘管我希望有更確切的內容:) – drzaus 2012-01-12 18:14:50

+0

我有eav系統及其不斷增長的如何將其移植到另一個保存模塊以保存我的系統?問題是你更喜歡保存的方式(json?)? – 2015-09-04 16:33:00

1

找出將是檢驗,關當然最好的辦法。答案可能取決於數據集的大小,不同的元密鑰的數量(?或只爲少數人做的所有實體對所有的元鍵的值?)是不同的,它們的分佈,數據庫的設置服務器和可能的許多其他因素。

如果我猜的話,我會說,在方案2中JOIN運營成本會比的GROUP BY成本,並在選項1需要聚合函數和3

那麼小,我會希望找到比1和3

選項2快測量方法4,你必須要考慮更多的因素,如應用程序可能在另一個服務器,這樣兩(db和應用程序)的負載服務器和必須考慮將要請求這些結果的客戶數量。


旁註:您使用透視或聚集可能會更快,因爲它們不需要表是自加盟需要在選項1 GROUP BY e.ID和3

相關問題