2010-06-28 33 views
5

Truy vấn sau hoạt động, nhưng nó rất chậm cho 10 bản ghi (2 giây). Các profiling nói rằng nó tạo ra một bảng tmp, nhưng tôi không chắc chắn lý do tại sao. Về cơ bản, tôi đang tham gia người dùng hiện tại, vào các nhóm ACL, để có được tất cả các nhóm họ đang ở, sau đó tham gia các nhóm với các công ty, để có được tất cả các công ty họ đang có, sau đó tham gia các công ty để các đơn đặt hàng , để có được tất cả các đơn đặt hàng ..MySQL - Cách truy vấn này có thể được tối ưu hóa?

Nếu tôi loại bỏ dòng này

ORDER BY orders.created_on DESC 

sau đó truy vấn thực hiện trong 0,06 giây (hơn sau đó chấp nhận được) ..

trợ giúp, bất kỳ ý tưởng về làm thế nào để tối ưu hóa ? Cảm ơn nhiều :)

SELECT 
    orders.uuid, 
    companies.name as company_name 
FROM 
    users u 
JOIN  
    users_acl_groups g on u.uuid = g.user_uuid 
JOIN 
    users_acl acl on (acl.user_uuid = u.uuid or acl.group_uuid = g.group_uuid) 
JOIN 
    companies on acl.item_uuid = companies.uuid 
JOIN 
    orders on companies.uuid = orders.company_uuid 
WHERE 
    u.uuid = 'DDEC8073-5056-C000-01ED583A51CBCA32' and orders.status <> '' 
ORDER BY orders.created_on DESC 

limit 0, 10; 

UPDATE, những giải thích của truy vấn ..

lệnh

1 ĐƠN GIẢN TẤT CẢ 9403 Sử dụng tạm thời; Sử dụng filesort

1 SIMPLE acl TẤT CẢ 1859 Sử dụng vị trí; Sử dụng bộ đệm nối

1 SIMPLE g ALL 2005 Sử dụng vị trí; Sử dụng tham gia đệm

1 công ty SIMPLE eq_ref TIỂU TIỂU 52 table.orders.company_uuid 1

1 SIMPLE u ALL 33.595 Sử dụng ở đâu; Đặc biệt; Sử dụng bộ đệm nối

+0

Đã sửa đổi tiêu đề của bạn, khi đoán rằng bạn phải trả một khoản tiền thấp do âm điệu bắt buộc và đòi hỏi khi câu hỏi của bạn được diễn đạt độc đáo. –

+0

Thử sử dụng cùng một truy vấn với tham gia được áp dụng trên bất kỳ cột nào khác ngoài UID. Hãy thử làm điều đó với int, float, string, UID và thông báo thời gian. Hãy cho chúng tôi biết nếu bạn tìm thấy bất kỳ biến thể nào. –

+0

Bạn có chỉ mục trên orders.created_on không? Hiển thị đầu ra trên 'EXPLAIN' trên truy vấn của bạn. Có lẽ bạn có thể hưởng lợi từ các chỉ mục khác. 'GIẢI THÍCH' nào sẽ cho chúng ta biết. – nos

Trả lời

2

Bạn đã xem xét thiết kế kiểu dáng bảng thực tế, làm bước chuẩn hóa không?

Về cơ bản nó là một loại nhiều-nhiều bảng giao, ví dụ:

CREATE TABLE user_order_fact (
    user_uuid ... 
    order_uuid ... 
    order_created_on ... 
    order_status ... 
    company_name ..., 
    primary key (user_uuid, order_uuid), 
    key (user_uuid, order_status, order_created_on, order_uuid, company_name) 
); 

... fill with data ... 

SELECT 
    order_uuid, 
    company_name 
FROM 
    user_order_fact 
WHERE 
    user_uuid = 'DDEC8073-5056-C000-01ED583A51CBCA32' and order_status <> '' 
ORDER BY order_created_on DESC 

limit 0, 10; 

Tôi đoán về chỉ số hợp chất. Bạn sẽ phải thử nghiệm cho đến khi bạn làm đúng. Về cơ bản, bạn đang cố gắng để kế hoạch trình tối ưu hóa báo cáo rằng đó là Sử dụng chỉ mục.

Tất nhiên điều này đang lưu trữ dữ liệu dư thừa và ở dạng không chuẩn hóa, vì vậy bạn cần phải thiết lập một số trình kích hoạt để giữ điều này đồng bộ với các bảng được chuẩn hóa.

+0

Hmm có lẽ PK chỉ là order_uuid. Tôi không đảm bảo đây là thiết kế tốt nhất, chỉ cần cố gắng để cung cấp cho bạn một cảm giác về những gì tôi có ý nghĩa. –

0

đảm bảo "orders.created_on" có chỉ mục ... Nếu có, thì cách tiếp cận của Bill ở đầu sẽ là tốt nhất tuy nhiên sẽ yêu cầu một chút công việc.

+0

Tôi nghĩ là như vậy? KEY 'created_on' (' created_on') – Brett

0

Khó trả lời mà không biết nhiều về các chỉ mục hiện có hoặc khối lượng của mỗi bảng.

Bên cạnh đó, không có nhiều thông tin về mô hình ... truy vấn có trả về tất cả kết quả không?

Tất cả người dùng có thuộc về một nhóm không? Dường như không ... và truy vấn sẽ không trả lại người dùng bên ngoài một nhóm.

Nhóm có thể thuộc về một nhóm, gọi cho truy vấn đệ quy không?

+0

Tôi đã cố gắng để làm điều đó truy vấn đệ quy ra nhưng tôi đã không có nhiều may mắn: (bảng là yên tĩnh nhỏ, 10.000 hồ sơ tất cả lên. Không có chỉ số tại thời điểm này .. – Brett

+0

@Brett: Các chỉ mục nếu có trong trường hợp này sẽ không hoạt động, vì NOT operator và Like Operator không sử dụng các chỉ mục –

0

Tôi không chắc chắn lý do chính xác để mất 2 giây. Mà không phải là có thể cho truy vấn này lấy 10 hồ sơ nhưng là những gì nhìn thấy ở đây là

  1. acl.user_uuid = u.uuid or acl.group_uuid = g.group_uuid

    UID dựa tham gia, có thể bạn cũng sử dụng nó như một khóa chính như đã trả lời ở trên.

  2. ORDER BY orders.created_on. Sử dụng Order by trên date sẽ không tối ưu bằng cách sử dụng PK hoặc bất kỳ giá trị số nguyên nào phù hợp hơn.

  3. orders.status <> '' Nếu sử dụng bất kỳ chỉ số trên bảng sau đó không có chỉ mục thể được sử dụng trong truy vấn này vì KHÔNG điều hành và Giống như điều hành không sử dụng chỉ số khi được sử dụng trong bất kỳ truy vấn.

  4. Số lượng bản ghi có trong bảng có thể là một lý do khác nhưng chỉ do các yếu tố trên. Nếu không nó có thể đã xử lý khối lượng lớn là tốt.

Major Góp yếu tố mà tôi nghĩ là UID được sử dụng trong tham gia Vì vậy, tất cả ba điều kiện tránh có thể được nhìn thấy trong truy vấn của bạn có thể thực hiện truy vấn của bạn lười biếng

+0

Xin chào, cảm ơn bạn đã trả lời .. Điều gì làm giảm tối đa số 2 nghĩa là gì? – Brett

0

vài ý tưởng:

Bạn thực sự không chọn orders.created_on trong truy vấn của mình. Vì vậy, không có điểm phân loại trên cột đó. Có lẽ, chọn nó (SELECT orders.created_on ...) sẽ giúp hiệu suất (Chỉ cần đoán hoang dã - Tôi không có ý tưởng những gì tôi đang nói ở đây).

Bạn luôn có thể sắp xếp trong ứng dụng của mình - nếu không có số lượng lớn các bản ghi được trả về bởi truy vấn của bạn.

Thỉnh thoảng hiệu quả hơn là sử dụng N truy vấn nhỏ thay vì 1 truy vấn sql lớn. Mã giả:

user_id = get_one("SELECT uuid FROM users WHERE ..."); 
group_ids = get_many("SELECT uuid FROM groups WHERE user_uuid = " + user_id); 
comps_ids = get_many("SELECT DISTINCT item_uuid FROM acls WHERE user_uuid = " + user_id + " OR group_uuid IN " + groups_ids.to_q()); 
orders = get_many("SELECT * FROM orders WHERE company_uuid IN " + comps_ids.as_q() + " WHERE status <> '' ORDER BY created_on"); 
Các vấn đề liên quan