12

Tôi muốn trích xuất kết quả từ bảng EAV (thuộc tính-giá trị-thuộc tính), hoặc cụ thể hơn bảng siêu dữ liệu thực thể (nghĩ như wordpress wp_postswp_postmeta) bảng quan hệ đã định dạng ", để thực hiện một số sắp xếp và/hoặc lọc.Hiệu suất tốt nhất cho việc lấy kết quả EAV của MySQL là Bảng quan hệ

Tôi đã tìm thấy một số ví dụ về cách định dạng kết quả trong truy vấn (trái ngược với viết 2 truy vấn và tham gia kết quả trong mã), nhưng tôi muốn biết phương pháp "hiệu quả nhất" để làm như vậy, đặc biệt là cho các tập kết quả lớn hơn.

Và khi tôi nói "hiệu quả nhất", tôi muốn nói một cái gì đó giống như các tình huống sau:

Nhận tất cả các thực thể với tên cuối cùng như XYZ

Return một danh sách các thực thể được sắp xếp theo ngày sinh nhật


ví dụ: tắt chức năng này:

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

vào đây:

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

vì vậy tôi có thể sắp xếp hoặc lọc theo bất kỳ trường nào meta.


Tôi đã tìm thấy một số đề xuất here, nhưng tôi không thể tìm thấy bất kỳ cuộc thảo luận nào hoạt động tốt hơn.

Tùy chọn:

  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-Tham:
     
    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. :
     
    SELECT e.* FROM `ENTITY` e WHERE e.ID = {whatever}; 
    
    trong PHP, tạo ra một đối tượng giữ chỗ từ kết quả
     
    SELECT m.* FROM `META` m WHERE m.EntityID = {whatever}; 
    
    trong PHP, vòng lặp thông qua kết quả và gắn với đối tượng thực thể như: $e->{$result->key} = $result->VALUE

Cái nào tốt hơn nói chung và để lọc/sắp xếp?

câu hỏi liên quan:

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

Nếu có đặt cược về hiệu suất và chỉ có một cơ hội để quay, tôi 'd đi cho đa tham gia. –

+0

Bạn cần một 'GROUP BY e.ID' trong các tùy chọn 1 và 3. –

+0

Hãy xem [câu hỏi này] (http://dba.stackexchange.com/questions/9466/most-performant-sql-query-needed) trên dba.se – ConcernedOfTunbridgeWells

Trả lời

0

Bất cứ điều gì bằng trục hoặc uẩn lẽ sẽ nhanh hơn, vì họ không yêu cầu bảng để thể tự tham gia. Các cách tiếp cận dựa trên kết nối sẽ yêu cầu trình tối ưu hóa thực hiện một số hoạt động truy vấn phụ và sau đó kết hợp các kết quả lại với nhau. Đối với một tập dữ liệu nhỏ, điều này có thể không quan trọng lắm, nhưng điều này có thể làm giảm đáng kể hiệu suất nếu bạn đang thực hiện truy vấn phân tích trên tập dữ liệu lớn hơn,

+0

dựa trên liên kết của bạn trong phần bình luận câu hỏi, tôi đang đánh dấu câu trả lời này, mặc dù tôi đã hy vọng điều gì đó rõ ràng hơn :) – drzaus

+0

tôi có hệ thống eav và phát triển như thế nào tôi có thể chuyển nó sang mô-đun tiết kiệm khác hệ thống? và câu hỏi là cách bạn muốn tiết kiệm (json?)? –

1

Cách tốt nhất để tìm hiểu sẽ được kiểm tra, tắt khóa học. Câu trả lời có thể khác nhau tùy thuộc vào kích thước của tập dữ liệu, số lượng các khóa meta khác nhau, phân phối của chúng (tất cả các thực thể có giá trị cho tất cả các khóa meta hay chỉ cho một số ít?), Cài đặt cơ sở dữ liệu của bạn máy chủ và có thể nhiều yếu tố khác.

Nếu tôi được đoán, tôi muốn nói rằng chi phí của JOIN hoạt động trong phương án 2 sẽ nhỏ hơn so với chi phí của GROUP BY và chức năng tổng hợp cần thiết trong lựa chọn 1 và 3.

Vì vậy, tôi sẽ mong muốn tìm tùy chọn 2 nhanh hơn 1 và 3.

Để đo tùy chọn 4, bạn sẽ phải xem xét nhiều yếu tố hơn vì ứng dụng có thể nằm trong máy chủ khác để tải trọng của hai máy chủ (db và ứng dụng) và số lượng khách hàng sẽ yêu cầu các kết quả này phải được tính đến.


Sidenote: bạn cần GROUP BY e.ID trong tùy chọn 1 và 3.