2010-06-05 34 views
6

Đây là một dự án sắp tới. Tôi có hai bảng - lần đầu tiên một giữ dấu vết của hình ảnh, và một trong những thứ hai theo dõi thứ hạng của ảnhLàm cách nào để tối ưu hóa bảng MySQL này?

Photos: 
+-------+-----------+------------------+ 
| id | photo  | current_rank  | 
+-------+-----------+------------------+ 
| 1  | apple  | 5    | 
| 2  | orange | 9    | 
+-------+-----------+------------------+ 

Xếp hạng ảnh tiếp tục thay đổi một cách thường xuyên, và đây là bảng theo dõi nó:

Ranks: 
+-------+-----------+----------+-------------+ 
| id | photo_id | ranks | timestamp | 
+-------+-----------+----------+-------------+ 
| 1  | 1   | 8  | *   | 
| 2  | 2   | 2  | *   | 
| 3  | 1   | 3  | *   | 
| 4  | 1   | 7  | *   | 
| 5  | 1   | 5  | *   | 
| 6  | 2   | 9  | *   | 
+-------+-----------+----------+-------------+ * = current timestamp 

Mọi thứ hạng đều được theo dõi cho mục đích báo cáo/phân tích. [Chỉnh sửa] Người dùng sẽ có quyền truy cập vào số liệu thống kê theo yêu cầu.

Tôi đã nói chuyện với một người có kinh nghiệm trong lĩnh vực này, và anh ấy nói với tôi rằng lưu trữ các cấp bậc như trên là con đường để đi. Nhưng tôi chưa chắc lắm.

Sự cố ở đây là dự phòng dữ liệu. Sẽ có hàng chục ngàn bức ảnh. Xếp hạng ảnh thay đổi theo giờ (nhiều lần trong vòng vài phút) đối với các ảnh gần đây nhưng ít thường xuyên hơn đối với ảnh cũ hơn. Với tốc độ này, bảng sẽ có hàng triệu hồ sơ trong vòng vài tháng. Và vì tôi không có kinh nghiệm làm việc với các cơ sở dữ liệu lớn, điều này khiến tôi hơi lo lắng.

Tôi nghĩ về điều này:

Ranks: 
+-------+-----------+--------------------+ 
| id | photo_id | ranks    | 
+-------+-----------+--------------------+ 
| 1  | 1   | 8:*,3:*,7:*,5:* | 
| 2  | 2   | 2:*,9:*   | 
+-------+-----------+--------------------+ * = current timestamp 

Điều đó có nghĩa một số mã thêm trong PHP để chia cấp bậc/thời gian (và sắp xếp), nhưng điều đó có vẻ OK với tôi.

Đây có phải là cách chính xác để tối ưu hóa bảng cho hiệu suất không? Bạn muốn giới thiệu gì?

+0

là xếp hạng được kết nối với bất kỳ điều gì khác? như người dùng đã cho nó? và nếu quan trọng như vậy thì quan hệ đó có quan trọng không? I E? bạn có cần phải lưu trữ thứ hạng trò chơi của người dùng không? –

+0

Xếp hạng không được liên kết với bất kỳ thứ gì khác ngoài ảnh. Nó được tính toán và thay đổi bởi một thuật toán máy tính! :) – Yeti

+1

@Col: bình luận của bạn luôn làm tôi mỉm cười! :) Trên thực tế các id trông giống như thế này: ** 4606886418 **, Ngay bây giờ có khoảng 2 triệu bức ảnh. Mỗi thứ hạng của một người thay đổi 50 lần. Vì vậy, mặc dù điều đó có thể không quá lớn, nó cũng không thể được gọi là nhỏ. – Yeti

Trả lời

7

Thứ nhất. Giai đoạn.

Thực ra bạn sẽ mất nhiều hơn nữa. Dấu thời gian được lưu trữ trong cột int sẽ chỉ chiếm 4 byte không gian.

Trong khi cùng một dấu thời gian được lưu trữ ở định dạng chuỗi sẽ mất 10 byte.

+0

Tôi quên đề cập đến dấu thời gian không phải là dấu thời gian unix, đó là datetime. Điều đó có giống nhau không? – Yeti

+0

@Lưu cho bài tập về nhà của bạn: http://dev.mysql.com/doc/refman/5.0/en/storage-requirements.html –

2

Tôi sẽ gắn bó với cách tiếp cận đầu tiên của bạn. Trong lần thứ hai, bạn sẽ có rất nhiều dữ liệu được lưu trữ trong hàng, khi thời gian trôi qua nó sẽ được xếp hạng cao hơn! Đó là, nếu một bức ảnh được hàng ngàn và hàng ngàn bảng xếp hạng.

Cách tiếp cận đầu tiên cũng dễ bảo trì hơn, tức là, nếu bạn muốn xóa thứ hạng.

+1

Trên thực tế, dữ liệu trong bảng xếp hạng không bao giờ được cập nhật vì nó được sử dụng để hiển thị số liệu thống kê. – Yeti

+0

Cảm ơn Peter (Tak Peter) – Phliplip

1

Tôi nghĩ rằng cơ sở dữ liệu 'hit' trên mức bình thường (truy vấn bảng xếp hạng hơn và hơn) là độc đáo tránh được bằng cách "lưu trữ" thứ hạng cuối cùng trong current_rank. Nó không thực sự quan trọng hàng ngũ đang phát triển rất nhiều nếu nó hiếm khi được truy vấn (phân tích/báo cáo bạn nói), không bao giờ được cập nhật nhưng chỉ được ghi vào cuối: ngay cả một hộp rất nhẹ sẽ không có vấn đề gì với hàng triệu hàng trong bảng đó.

Bạn thay thế sẽ yêu cầu nhiều cập nhật trên các vị trí khác nhau trên đĩa, có thể dẫn đến hiệu suất bị suy giảm. Tất nhiên, nếu bạn cần tất cả dữ liệu cũ và luôn luôn bằng photo_id, bạn có thể lập kế hoạch chạy theo lịch biểu sang bảng xếp hạng khác, có thể với photo_id, năm, tháng, thứ hạng (bao gồm cả dấu thời gian) khi hết tháng, do đó, việc lấy dữ liệu cũ vẫn dễ dàng có thể, nhưng không có cập nhật nào cần thiết trong bảng xếp hạng hoặc xếp hạng, chỉ chèn vào cuối bảng.

Và lấy nó từ tôi: hàng triệu hồ sơ trong một bảng đăng nhập thuần túy nên hoàn toàn không có vấn đề gì.

+0

Điều xấu của tôi, không đề cập đến nhật ký có sẵn cho chủ sở hữu của chủ sở hữu ảnh (họ có thể xem thống kê xếp hạng). Vì vậy, có thể cũng có rất nhiều truy vấn. – Yeti

+0

Sau đó, nó ít rõ ràng hơn, nhưng tôi vẫn nghĩ rằng giải pháp đầu tiên sẽ tốt hơn (cập nhật hiệu suất là chìa khóa ở đó, và cập nhật không nên khóa các lựa chọn). Có thể tôi sẽ làm việc với một bảng xếp hạng hàng ngày thay vì sau đó một tháng. – Wrikken

2

Thiết kế đầu tiên của bạn là chính xác cho cơ sở dữ liệu quan hệ. Sự dư thừa trong các cột chính là thích hợp hơn bởi vì nó mang lại cho bạn sự linh hoạt hơn trong cách bạn xác nhận và truy vấn thứ hạng. Bạn có thể làm các loại, đếm, trung bình, vv trong SQL mà không cần phải viết bất kỳ mã PHP nào để tách chuỗi của bạn theo sáu cách từ Chủ nhật.

Có vẻ như bạn muốn sử dụng cơ sở dữ liệu không phải SQL như CouchDB hoặc MongoDB. Những này sẽ cho phép bạn lưu trữ danh sách xếp hạng bán cấu trúc ngay trong hồ sơ cho ảnh và sau đó truy vấn xếp hạng hiệu quả. Với báo trước rằng bạn không thực sự biết rằng các bảng xếp hạng có định dạng đúng, giống như bạn làm với SQL.

0

Bạn đã cho biết thứ hạng chỉ được liên kết với hình ảnh, trong trường hợp đó tất cả những gì bạn cần là bảng 1 và tiếp tục cập nhật thứ hạng trong thời gian thực. Bảng 2 chỉ lưu trữ dữ liệu không cần thiết. Điểm bất lợi của phương pháp này là người dùng không thể thay đổi phiếu bầu của mình.

1

Dữ liệu được chuẩn hóa hoặc không phải dữ liệu được chuẩn hóa. Bạn sẽ tìm thấy hàng ngàn bài viết về điều đó. :)

Nó thực sự phụ thuộc vào nhu cầu của bạn.

Nếu bạn chỉ muốn xây dựng cơ sở dữ liệu của mình với hiệu suất (tốc độ hoặc mức tiêu thụ RAM hoặc ...), bạn chỉ nên tin tưởng các con số. Để làm điều đó bạn phải lập hồ sơ các truy vấn của bạn với dữ liệu dự kiến ​​"khối lượng" (Bạn có thể tạo ra dữ liệu với một số kịch bản bạn viết). Để hồ sơ truy vấn của bạn, học cách đọc kết quả của 2 truy vấn sau đây:

  • EXPLAIN extended...
  • SHOW STATUS

Sau đó tìm hiểu những gì phải làm để cải thiện số liệu (cài đặt mysql, cấu trúc dữ liệu, phần cứng, v.v.)

Là một starter, tôi thực sự khuyên những 2 điều tuyệt vời:

  1. http://www.xaprb.com/blog/2006/10/12/how-to-profile-a-query-in-mysql/
  2. http://ajohnstone.com/archives/mysql-php-performance-optimization-tips/

Nếu bạn muốn xây dựng cho vẻ đẹp học năm bình thường: chỉ cần làm theo những cuốn sách và các khuyến nghị chung. :)

0

Bạn cho biết bảng thứ hai là để phân tích/thống kê, do đó, nó thực sự không phải là thứ cần được lưu trữ trong db. Đề xuất của tôi là thoát khỏi bảng thứ hai và sử dụng cơ sở ghi nhật ký để ghi lại các thay đổi về xếp hạng.

+0

Tôi quên đề cập rằng người dùng có thể truy cập dữ liệu từ bảng thứ hai. Đã chỉnh sửa câu hỏi. – Yeti

1

Trong số hai lựa chọn - như tất cả mọi người trước khi tôi nói - nó phải được lựa chọn 1.

gì bạn thực sự cần được quan tâm đến là các vướng mắc trong việc áp dụng chính nó. Người dùng có thường xuyên tham khảo dữ liệu lịch sử hay không chỉ hiển thị cho một số người dùng được chọn không? Nếu câu trả lời là tất cả mọi người được xem dữ liệu lịch sử của các cấp bậc, thì tùy chọn 1 là đủ tốt. Nếu bạn không định tham khảo các cấp bậc lịch sử thường xuyên, thì bạn có thể tạo bảng "lưu trữ" thứ ba và trước khi cập nhật xếp hạng, bạn có thể sao chép các hàng của bảng xếp hạng ban đầu sang bảng lưu trữ. Điều này đảm bảo rằng số hàng vẫn ở mức tối thiểu trên bảng chính đang được gọi.Hãy nhớ rằng, nếu bạn đang cập nhật các hàng và có 10 trong số hàng, nó có thể hiệu quả hơn để lấy kết quả trong mã của bạn (PHP/Python/etc), cắt bảng và chèn kết quả vào chứ không phải là cập nhật nó từng hàng, vì đó sẽ là một nút cổ chai tiềm ẩn.

Bạn có thể muốn nhìn lên sharding cũng (phân vùng ngang) - http://en.wikipedia.org/wiki/Shard_%28database_architecture%29

Và không bao giờ quên chỉ số tốt.

Hy vọng điều đó sẽ hữu ích.

0

Thiết kế thứ hai của bạn rất nguy hiểm trong trường hợp bạn có 1 triệu phiếu bầu cho một bức ảnh. PHP có thể xử lý điều đó không?

Với thiết kế đầu tiên, bạn có thể thực hiện tất cả toán học ở cấp cơ sở dữ liệu sẽ trả lại cho bạn một số result set nhỏ.

Các vấn đề liên quan