Tôi có dịch vụ điểm số cao đơn giản cho trò chơi trực tuyến và nó đã trở nên phổ biến hơn mong đợi. Điểm số cao là một dịch vụ web sử dụng phần phụ trợ MYSQL với một bảng đơn giản như hình dưới đây. Mỗi bản ghi điểm cao được lưu trữ như một hàng trong bảng này. Vấn đề là, với> 140k hàng, tôi thấy một số truy vấn quan trọng nhất làm chậm quá nhiều đến mức nó sẽ sớm quá chậm đối với các yêu cầu dịch vụ.Mở rộng Cơ sở dữ liệu Điểm cao
Bảng chính trông như thế này:
- id là một chìa khóa duy nhất cho mỗi điểm số kỷ lục
- trò chơi là số ID của trò chơi mà nộp số điểm (hiện tại, luôn luôn tương đương với "1" , sẽ sớm có để hỗ trợ trò chơi nhiều hơn mặc dù)
- name là tên hiển thị cho trình của người chơi mà
- playerid là một ID duy nhất cho một người dùng nào đó
- điểm là điểm số đại diện cũ 42.035
- thời gian gửi bài là
- xếp hạng là một số nguyên lớn duy nhất sắp xếp số lần gửi điểm cho một trò chơi cụ thể. Nó là phổ biến cho mọi người để buộc ở một số điểm nhất định, do đó, trong trường hợp đó tie bị hỏng bởi những người được gửi đầu tiên. Do đó giá trị của lĩnh vực này là tương đương xấp xỉ để "điểm * 100000000 + (MAX_TIME - thời gian)"
+----------+---------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +----------+---------------+------+-----+---------+----------------+ | id | int(11) | NO | PRI | NULL | auto_increment | | game | int(11) | YES | MUL | NULL | | | name | varchar(100) | YES | | NULL | | | playerId | varchar(50) | YES | | NULL | | | score | int(11) | YES | | NULL | | | time | datetime | YES | | NULL | | | rank | decimal(50,0) | YES | MUL | NULL | | +----------+---------------+------+-----+---------+----------------+
Các chỉ số giống như thế này:
+-----------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+ | Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | +-----------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+ | pozscores | 0 | PRIMARY | 1 | id | A | 138296 | NULL | NULL | | BTREE | | | pozscores | 0 | game | 1 | game | A | NULL | NULL | NULL | YES | BTREE | | | pozscores | 0 | game | 2 | rank | A | NULL | NULL | NULL | YES | BTREE | | | pozscores | 1 | rank | 1 | rank | A | 138296 | NULL | NULL | YES | BTREE | | +-----------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
Khi người dùng yêu cầu điểm cao, họ thường yêu cầu khoảng 75 điểm cao từ một điểm tùy ý trong danh sách "sắp xếp theo xếp hạng giảm dần". Các yêu cầu này thường là "mọi giờ" hoặc chỉ cho điểm số trong 7 ngày qua.
Truy vấn điển hình trông giống như sau: "SELECT * FROM scoretable WHERE game=1 AND time>? ORDER BY rank DESC LIMIT 0, 75;"
và chạy trong 0,00 giây.
Tuy nhiên, nếu bạn yêu cầu đến cuối danh sách "SELECT * FROM scoretable WHERE game=1 AND time>? ORDER BY rank DESC LIMIT 10000, 75;"
và chạy trong 0,06 giây.
"SELECT * FROM scoretable WHERE game=1 AND time>? ORDER BY rank DESC LIMIT 100000, 75;"
và chạy trong 0,58 giây.
Có vẻ như điều này sẽ nhanh chóng bắt đầu nhận quá lâu vì hàng nghìn điểm mới được gửi mỗi ngày!
Ngoài ra, có hai loại truy vấn khác, được sử dụng để tìm một trình phát cụ thể theo id trong danh sách thứ tự được xếp hạng. Họ trông như thế này:
"SELECT * FROM scoretable WHERE game=1 AND time>? AND playerId=? ORDER BY rank DESC LIMIT 1"
theo sau là một
"SELECT count(id) as count FROM scoretable WHERE game=1 AND time>? AND rank>[rank returned from above]"
câu hỏi
của tôi là: Có thể làm gì để tạo ra một hệ thống mở rộng? Tôi có thể thấy số lượng hàng tăng lên đến vài triệu rất sớm. Tôi đã hy vọng rằng việc lựa chọn một số chỉ số thông minh sẽ giúp ích, nhưng cải tiến này chỉ ở mức thấp.Cập nhật: Dưới đây là một giải thích dòng:
mysql> explain SELECT * FROM scoretable WHERE game=1 AND time>0 ORDER BY rank DESC LIMIT 100000, 75; +----+-------------+-----------+-------+---------------+------+---------+------+--------+-------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+-----------+-------+---------------+------+---------+------+--------+-------------+ | 1 | SIMPLE | scoretable| range | game | game | 5 | NULL | 138478 | Using where | +----+-------------+-----------+-------+---------------+------+---------+------+--------+-------------+
Solution Tìm thấy!
Tôi đã giải quyết được sự cố nhờ một số gợi ý từ chuỗi này. Làm một chỉ số nhóm là chính xác những gì tôi cần, vì vậy tôi đã chuyển đổi bảng để sử dụng InnoDB trong mysql, hỗ trợ các chỉ số nhóm. Tiếp theo, tôi đã xóa trường id và chỉ đặt khóa chính là (trò chơi ASC, xếp hạng DESC). Bây giờ, tất cả các truy vấn đều chạy siêu nhanh, bất kể tôi sử dụng offset nào. Giải thích cho thấy rằng không có sắp xếp bổ sung nào đang được thực hiện và có vẻ như nó dễ dàng xử lý tất cả lưu lượng truy cập.
Sử dụng Mongo DB. Đó là quy mô web. – anon
Thật kỳ lạ là không thể đánh giá nhận xét ("Sử dụng Mongo DB. Đó là quy mô web.") – zerkms
@ user509841: đưa ra một số giải thích. – zerkms