2016-12-05 61 views
0

我正在開發一個項目,現在我正在實施排行榜。在開始研究之前,我需要一些建議來更好地練習我的排行榜結構。MySQL - 擁有數百萬條目的排名

首先,排行榜將顯示在兩個頁面上,一個在每個玩家的主頁上,其中包含前10個球隊(所有球員相同的10個球隊),另一個排行榜將在排行榜的頁面,其中,將具有所有具有排序功能的團隊。

每行排行榜的結構如下:
•排名位置
•隊名
•團隊價值
•總場的球隊贏得了
•總遊戲團隊擊敗
•隊伍總共抽出的球隊
•球隊已經完成的總進球數球隊已經承認
•過去的4個比賽球隊

下面的結果目標 •總和是我的數據庫的表

挑戰表

CREATE TABLE `challenges` (
    id` int(10) unsigned NOT NULL AUTO_INCREMENT, 
    'challenge_date` datetime NOT NULL, 
    `status` varchar(20) COLLATE utf8_unicode_ci NOT NULL, 
    `created_at` timestamp NULL DEFAULT NULL, 
    `updated_at` timestamp NULL DEFAULT NULL, 
    PRIMARY KEY (`id`), 
    KEY `challanges_id_index` (`id`), 
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; 

挑戰導致

CREATE TABLE `challenges_results` (
    `id` int(11) unsigned NOT NULL AUTO_INCREMENT, 
    `challenge_id` int(11) NOT NULL, 
    `team_id` int(11) NOT NULL, 
    `goals` int(11) NOT NULL, 
    `result` char(1) DEFAULT NULL, 
    `challenge_date` datetime NOT NULL, 
    PRIMARY KEY (`id`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8; 

在挑戰結果導致列可以是W的勝利,d爲吸引和L爲負

團隊價值觀

CREATE TABLE `team_values` (
    `id` int(11) unsigned NOT NULL AUTO_INCREMENT, 
    `team_id` int(11) DEFAULT NULL, 
    `value` double(15,8) DEFAULT '1500.00000000', 
    `created_at` datetime DEFAULT NULL, 
    PRIMARY KEY (`id`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8; 

CREATE TABLE `teams` (
    `id` int(10) unsigned NOT NULL AUTO_INCREMENT, 
    `name` varchar(255) COLLATE utf8_unicode_ci NOT NULL, 
    `avatar` varchar(255) COLLATE utf8_unicode_ci NOT NULL, 
    `founded` date NOT NULL, 
    `residense_city_id` int(10) unsigned NOT NULL, 
    `slug` varchar(255) COLLATE utf8_unicode_ci NOT NULL, 
    `primary_color` char(10) COLLATE utf8_unicode_ci NOT NULL, 
    `secondary_color` char(10) COLLATE utf8_unicode_ci NOT NULL, 
    `status` varchar(20) COLLATE utf8_unicode_ci NOT NULL, 
    `created_at` timestamp NULL DEFAULT NULL, 
    `updated_at` timestamp NULL DEFAULT NULL, 
    PRIMARY KEY (`id`), 
    UNIQUE KEY `teams_slug_unique` (`slug`), 
    KEY `teams_id_index` (`id`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; 

一隊可以有多個值(teams_values),但只有最近纔會顯示。一個團隊可能面臨很多挑戰。 一個團隊可以從不同的挑戰獲得許多結果。

該排行榜將如下工作。這些球隊將以來自teams_values表的最高值排序。每當團隊遇到挑戰時,就會計算並存儲該值。

如果兩個或更多團隊具有相同的值,我們需要應用以下三條規則。規則還需要逐一執行,例如,如果我運行第一條規則,並且仍然存在同等價值和進球的球隊,那麼我將應用第二條規則等等。 •(高進球數得分)
•防守最佳(目標數較少失球)最好的進攻
•的最多的球隊勝在他們之間的比賽

於是我想出了三種解決方案仍然我不知道哪一個更好,哪一個更好。

第一個選項,我雖然是像內連接來使用的選項,工會等,以收集從表中的信息和應用在同一個SQL查詢的規則。所以每次我想查看排行榜時,我都會執行這個SQL。這個解決方案的問題在於,我不知道如果我們希望排行榜始終保持最新的結果,那麼效果會如何。因爲每天有10k個訪問者進行映像並且每個人都在執行此查詢。

第二個選項是收集信息,並在重複值的情況下,我會用PHP來獲得重複的隊伍,運用規則,然後根據規則的結果刷卡數組中的球隊。從表演網站我不知道這個選項有多有效。

第三種解決方案是創建另一個名爲排行榜的表格,我將在團隊不存在的情況下存儲所有這些信息,或者如果基於最新挑戰的結果存在,我將更新記錄,例如,如果球隊得分。然後,我將只使用排行榜表格來過濾數據並打印隊伍的排名。我相信這個選擇更好,因爲我只需要處理一張桌子,而且只有當一個團隊完成挑戰時我纔會更新記錄。

我們將使用高速緩存,但現在我們正在考慮的是,排行榜應該永遠是最新的,每天不是一次更新它。

哪一個更好的解決方案,爲什麼和更好的解決方案,我願意提供建議。謝謝

+1

您的問題太寬泛。如果您有硬件容量來即時重新生成排行榜,那就做吧。如果硬件容量有限,則緩存方法是有意義的。 –

+1

此外,使用PHP進一步過濾您的數據集是一個額外的計算層。如果您完全可以提供幫助,請嘗試將所有數據查詢特定的功能保留爲SQL代碼。否則,您會針對該資源運行資源來處理並返回數據集,但只能以不同的方式使用基於PHP的規則重新評估該數據集。 –

+0

開頭將在vps上的共享帳戶上。@KarlBuys –

回答

0

由於您在虛擬專用服務器上的共享帳戶上運行,因此很有可能理論上您會遇到爭用服務器資源,磁盤使用情況,內存使用情況等問題的情況。 cpu處理能力。

首先,嘗試做所有的MySQL數據庫的計算,一旦你已經完成了對所有這些操作只將數據返回到PHP。 MySQL針對這項工作進行了優化,而PHP在一般計算問題上更勝一籌。

您的一個選擇是從服務器獲取一些負載,將使用PHP創建一個可在瀏覽器中查看的網頁,每更換一次排行榜。這樣,每次需要更新排行榜時,您只需執行一次計算。

如果我正在構建系統並且系統永遠不會達到企業級的水平,而是保持小巧和功能性,我會盡早編寫一個PHP腳本,因爲您可以通過這種方式節省大量處理能力單獨。

對於它的價值,如果服務器被配置好,你不應該擔心得到10K用戶請求的一天,除非你的代碼是真正可怕的寫入。

編輯:作爲一種事後,你可以安裝像https://memcached.org/一個程序,它在RAM中緩存你的SQL數據。像LiveJournal和Wordpress等網站使用它,但你需要配置它的方式適用於其他的VPS用戶,除非該框是真正的高規格。

+0

該產品基於laravel,我們將使用redis。那麼你是說沒有必要用聚合值創建一個新表? –

+0

Redis會很不適合,除非在特定情況下,例如在查詢遠程服務器時。這就像在MySQL數據庫之上使用第二個數據庫來存儲第一個數據庫的結果。我建議你嘗試在沒有聚合表的情況下構建它,並看看你是否滿意它的響應速度。如果它沒有足夠的響應,那麼請優化它 –

+0

感謝您的建議。我將開始使用SQL查詢,如果需要時間,我會優化它。 –