php 数据图形,php-存储图形数据的最有效方法

我总共提出了三种不同的,同样可行的方法来保存图形数据.

所讨论的图表是“随时间推移在各个类别中的玩家得分”.类别包括“建筑物”,“项目”,“任务完成”,“成就”等.

方法1:

CREATE TABLE `graphdata` (

`userid` INT UNSIGNED NOT NULL,

`date` DATE NOT NULL,

`category` ENUM('buildings','items',...) NOT NULL,

`score` FLOAT UNSIGNED NOT NULL,

PRIMARY KEY (`userid`, `date`, `category`),

INDEX `userid` (`userid`),

INDEX `date` (`date`)

) ENGINE=InnoDB

该表针对每个用户/日期/类别组合包含一行.要显示用户数据,请按用户ID选择.旧条目通过以下方式清除:

DELETE FROM `graphdata` WHERE `date` < DATE_ADD(NOW(),INTERVAL -1 WEEK)

方法2:

CREATE TABLE `graphdata` (

`userid` INT UNSIGNED NOT NULL,

`buildings-1day` FLOAT UNSIGNED NOT NULL,

`buildings-2day` FLOAT UNSIGNED NOT NULL,

... (and so on for each category up to `-7day`

PRIMARY KEY (`userid`)

)

由于是主键,因此按用户ID选择的速度更快.每天得分都在字段中向下移动,如下所示:

... SET `buildings-3day`=`buildings-2day`, `buildings-2day`=`buildings-1day`...

条目不会被删除(除非用户删除其帐户).可以使用INSERT … ON DUPLICATE KEY UPDATE查询添加/更新行.

方法3:

为每个用户使用一个文件,其中包含其分数数据的JSON编码数组.由于无论如何都是通过AJAX JSON调用获取数据的,因此这意味着可以静态获取文件(甚至缓存到下一个午夜),而不会对服务器造成任何压力.服务器每天都要运行每个文件,shift()会将每个数组的最旧记录除掉,最后将push()的新数组推入.

我个人认为方法3到目前为止是最好的,但是我听说过使用文件而不是数据库的不好的事情-例如,如果我希望能够根据用户在不同类别中的得分来对其进行排名,那么该解决方案将非常糟糕.

在这两种数据库解决方案中,我已经在一个较旧的项目中实现了方法2,这似乎工作得很好.方法1似乎“更好”,因为它更好地利用了关系数据库和所有这些东西,但是我有点担心它会包含(用户数量)*(类别数量)* 7行,出来是一个很大的数字.

我缺少什么可以帮助我最终决定使用哪种方法的东西吗? 1、2、3还是以上都不是?

解决方法:

如果要使用关系数据库,则方法1比方法2更好.它经过规范化,因此易于维护和搜索.我将date字段更改为时间戳,并将其称为add_on(或诸如“ date”之类的非保留字).并且我要添加一个auto_increment主键score_id,以便user_id / date / category不必唯一.这样,如果用户设法在同一秒内将其建筑得分增加两次,则两者仍将被记录.

第二种方法要求您每天更新所有记录.第一种方法仅执行插入操作,不执行任何更新,因此每个记录仅写入一次.

… SET buildings-3day=buildings-2day, buildings-2day=buildings-1day…

您是否真的想每天更新表中的每个记录,直到时间结束?!

Selecting by user id is faster due to being a primary key

由于user_id是您的Method 1主键中的第一个字段,因此查找起来同样会很快.作为常规索引的第一个字段(这是我上面建议的),它仍然会非常快.

关系数据库的想法是,每一行代表一个实例/动作/事件.因此,当用户做某件事以影响其分数时,请执行INSERT记录其所作的事情.您始终可以根据这样的数据创建摘要.但是您不能从摘要中获得此类数据.

其次,您似乎毫无疑问地担心摆脱旧数据.为什么?您选择的查询的日期范围将自动排除旧数据.而且,如果您担心性能,可以根据行龄来设置表partition,或者设置cronjob定期删除旧记录.

预计到达时间:关于文件中存储的JSON

在我看来,这将方法2的缺点(难以搜索,每个文件必须每天更新)与文件访问的其他缺点结合在一起.文件访问很昂贵.文件写入更是如此.如果您确实要存储摘要数据,则仅在请求数据时才运行查询,并将结果按user_id存储在摘要表中.该表可以包含一个JSON字符串:

CREATE TABLE score_summaries(

user_id INT unsigned NOT NULL PRIMARY KEY,

gen_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,

json_data TEXT NOT NULL DEFAULT '{}'

);

例如:

鲍勃(user_id = 7)首次登录游戏.他在个人资料页面上,显示他的每周统计信息.这些查询已运行:

SELECT json_data FROM score_summaries

WHERE user_id=7

AND gen_date > DATE_SUB(CURDATE() INTERVAL 1 DAY);

//returns nothing so generate summary record

SELECT DATE(added_on), category, SUM(score)

FROM scores WHERE user_id=7 AND added_on < CURDATE() AND > DATE_SUB(CURDATE(), INTERVAL 1 WEEK)

GROUP BY DATE(added_on), category; //never include today's data, encode as json with php

INSERT INTO score_summaries(user_id, json_data)

VALUES(7, '$json') //from PHP, in this case $json == NULL

ON DUPLICATE KEY UPDATE json_data=VALUES(json_data)

//use $json for presentation too

今天的分数是根据需要生成的,不会存储在摘要中.如果Bob今天再次查看自己的分数,则历史分数可以来自摘要表,也可以存储在第一个请求后的会话中.如果Bob一周都不来,则无需生成摘要.

标签:data-storage,graph,mysql,php

来源: https://codeday.me/bug/20191101/1982403.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值