Çevrimiçi bir oyun için basit bir yüksek puan servisim var ve beklenenden daha popüler hale geldi. Yüksek puan, aşağıda gösterildiği gibi basit bir tablo ile MYSQL arka ucunu kullanan bir web servisidir. Her yüksek skor kaydı bu tabloda bir satır olarak saklanır. Sorun şu ki,> 140k satırı ile, bazı anahtar sorguları o kadar yavaşladığını görüyorum ki yakında hizmet istekleri çok yavaş olacak.Yüksek Puan Veri Tabanı Ölçeklendiriliyor
ana tablo aşağıdaki gibidir:
- id zaman eşit her biri için benzersiz bir anahtar skor oyun şu anda skoru (gönderilen oyunun kimlik numarasıdır
- rekor olduğu "1" yakında
- adı o oyuncunun teslim
- playerid için görünen addır) gerçi daha fazla oyun desteklemek zorunda kalacak
- skor sayısal puanı gösterimi ex 42035 olan belirli bir kullanıcı için benzersiz bir kimliktir
- gönderme zamanı
- sırası, belirli bir oyun için puan gönderimlerini benzersiz şekilde ayıran büyük bir tamsayıdır. İnsanların belirli bir skorla bağlanması için ortak olan , bu nedenle ilk önce kimin gönderdiği ile bağlantı kesilir.
+-----------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+ | 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 | | +-----------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
Bir kullanıcı istekleri yüksek puanlar, bunlar genellikle: - "(zaman MAX_TIME) puanı * 100.000.000 +"
endeksler
+----------+---------------+------+-----+---------+----------------+ | 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 | | +----------+---------------+------+-----+---------+----------------+şuna benzer Dolayısıyla bu alanın değeri kabaca eşittir "Sıralı azalan listeye göre sıralı" bir noktadan yaklaşık 75 yüksek puan istemek. Bu talepler genellikle "alltime" veya sadece son 7 gün içindeki puanlar içindir.
Tipik bir sorgu şu şekildedir: "SELECT * FROM scoretable WHERE game=1 AND time>? ORDER BY rank DESC LIMIT 0, 75;"
ve 0.00 sn. Ancak, "SELECT * FROM scoretable WHERE game=1 AND time>? ORDER BY rank DESC LIMIT 10000, 75;"
listesinin sonuna doğru istekte bulunursanız ve 0,06 saniyede çalışırsa,
"SELECT * FROM scoretable WHERE game=1 AND time>? ORDER BY rank DESC LIMIT 100000, 75;"
ve 0,58 saniyede çalışır.
Her gün birkaç bin yeni puanın gönderildiği gibi bu işlem çok hızlı bir şekilde başlayacak gibi görünüyor! Ayrıca, sıralı sıralama listesinde belirli bir oyuncuyu bulmak için iki farklı sorgu türü vardır. Onlar şuna benzer:
"SELECT * FROM scoretable WHERE game=1 AND time>? AND playerId=? ORDER BY rank DESC LIMIT 1"
"SELECT count(id) as count FROM scoretable WHERE game=1 AND time>? AND rank>[rank returned from above]"
Benim soru takip eder: Bu ölçeklenebilir sistem yapmak ne yapılabilir? Çok yakında birkaç milyon olacak şekilde artan satır sayısını görebiliyorum. Bazı akıllı indeksleri seçmenin yardımcı olacağını umuyordum, ancak bu gelişme sadece marjinaldi.
Güncelleme:
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 | +----+-------------+-----------+-------+---------------+------+---------+------+--------+-------------+
Çözüm Bulundu: İşte bir çizgi açıklamak olduğunu!
Bu iş parçacığındaki bazı işaretçiler sayesinde sorunu çözdüm. Kümelenmiş bir dizin yapmak tam olarak ihtiyacım olan şeydi, bu yüzden tabloyu kümelenmiş dizinleri destekleyen mysql içinde InnoDB kullanacak şekilde dönüştürdüm. Ardından, id alanını kaldırdım ve sadece birincil anahtarı (oyun ASC, sıralı DESC) ayarlayın. Şimdi, hangi sorguları kullanırsam kullanırım, tüm sorgular çok hızlı çalışır. Açıklama, ek bir sıralama yapılmadığını ve tüm trafiği kolayca işleyebildiğini gösteriyor.
Kullanımı Mongo DB. Bu web ölçeğidir. – anon
Yorumlar reddetmek mümkün değildir ("Mongo DB kullanın. Bu web ölçeği.") – zerkms
@ user509841: bazı açıklar vermek. – zerkms