對於排名系統(在擁有數萬用戶的數據庫中),我想按用戶總數排列三列: Points_A
,Points_B
和Points_C
。我想知道這將是一個更好的選擇:總列或新列
- 每個被訪問排名網頁時,通過總和所有列和順序相加計算用戶的排名
- 創建一個新列
Points_total
與三列的總和(我每次更新其他列之一時更新總數),並按此Points_total
排序查詢。
排名頁面可能每秒要求多次,所以表現非常重要。第二種選擇更快還是不推薦?
對於排名系統(在擁有數萬用戶的數據庫中),我想按用戶總數排列三列: Points_A
,Points_B
和Points_C
。我想知道這將是一個更好的選擇:總列或新列
Points_total
與三列的總和(我每次更新其他列之一時更新總數),並按此Points_total
排序查詢。排名頁面可能每秒要求多次,所以表現非常重要。第二種選擇更快還是不推薦?
從MySQL 5.7.6開始,您可以創建生成的列,使您能夠根據表中其他列中的其他值存儲虛擬值。
CREATE TABLE tbl (
Points_A INT,
Points_B INT,
Points_C INT,
Points_total INT AS (Points_A + Points_B + Points_C)
);
生成列定義具有以下語法:
COL_NAME DATA_TYPE [總是GENERATED] AS(表達式)
[VIRTUAL | STORED] [UNIQUE [KEY] [註釋評論]
[NOT] NULL] [PRIMARY] KEY]
您可以決定使用VIRTUAL
或STORED
(取決於你的需要)。
從MySQL 5.7.8開始,你也可以添加INDEXes on virtual columns,所以在你的情況下 - 這正是你正在尋找的(這種方式列中的值被索引)。
如果您使用的是比5.7.8更早的MySQL,並且多次訪問排名頁面 - 我建議您將特定列中的計算值相同並在該列上添加索引。
如果OP有成千上萬的用戶,那麼需求可能需要一個索引。 –
注意:某些時候(數百萬用戶?)重複更新索引的成本將會過高。成本本質上是「從BTree(索引)中刪除一行並將其重新插入到其他地方」。 –
這是一個想法。而不是在排名的每一個變化上採取昂貴的行動,看看這個複雜的方法可能會更好:
但首先,這取決於Points
只增加,從不減少。它還假定你只需要排在前10名。並且不關心發現「我在10000中排名7654」)
設置一個觸發器(或應用程序代碼),每當排名增加時都會作出反應。它將點加在一起並根據閾值進行檢查。如果低於第10位的值,則不要做任何事情。
如果更高,則執行SELECT ... ORDER BY ... LIMIT 10
以獲得新的「前10位」並將結果存儲在單獨的表中。另外,更新閾值。
的可能好處:
query_cache_size = 20M
(不要太大),query_cache_type = DEMAND
SQL_CACHE
到基層SELECT
;將SQL_NO_CACHE
添加到其他大多數SELECTs
。如果你需要的不僅僅是一個的「前10名」頁多,考慮到節約「前50名」。對於前5頁,新表就足夠了。對於第6頁及更高版本,請以硬方式進行(掃描10K行表格)。希望這將會是非常罕見的,仍然是一個優勢。
最好的辦法就是試試更簡單的方法(不存儲總和),看看性能是否可以接受*。不是哪一個更好,因爲不管多困難多少,比方說,它的速度要快1000倍,比如它需要從120毫秒到少於一飛秒的延遲,120毫秒對於一個頁面來說足夠快加載。即只有在顯着影響用戶體驗的情況下,性能才非常重要。 –