以下哪种SQLite数据库方法在存储使用和查找速度方面更有效?

时间:2019-12-17 14:13:47

标签: java android database sqlite

我正在创建一个Android应用来存储纸牌游戏的数据,并且我想保存每个比赛数据(玩家资料ID和玩家分数)。我为此使用SQLite数据库。 我想起诉这些数据以回顾较旧的比赛,或者只是加载未完成的比赛。

当前,我将每个匹配数据存储在单独的表中,表名称为当前日期。我将4个玩家ID存储为整数,将4个玩家分数存储为字节数组(每轮得分)。

我当时想我可以将这些数据存储在单个表中,如下所示: 比赛日期的一列,球员ID的第4列为整数,球员得分的第4列为字节数组。

或者像这样: 比赛日期栏,球员ID栏组合为字符串,球员比分栏组合为字符串。

或者像这样: 比赛日期栏,球员ID和分数栏以字符串组合

3 个答案:

答案 0 :(得分:2)

通常,您将有一个表存储“比赛”,而另一个相关表存储每个得分。它们不会“组合为字符串”。

但是,这实际上取决于您:如果您的应用程序始终总是一次只想要分数,并且您不打算针对它们查询,可以那样做。

但是,您已经正确地猜到了,您不想拥有“每场比赛一张桌子”。

答案 1 :(得分:1)

结论

它将变得像您想要的那样复杂。考虑一下您想问数据库什么样的问题。我开始回答一个非常棘手的问题,这将涉及对提议的架构进行另一个重大更改,或者涉及子查询的更复杂的查询,或者可能只是我不太熟悉的SQL函数。我需要做更多的研究。

如果可以的话,我通常也可以弄清楚这些东西,但是我不是数据库专家,所以对我来说这绝非易事。我以为我对数据库的了解还不错,直到我对这个笑话了如指掌。

希望我没让您感到困惑。我认真考虑过要删除答案,但是我一直都投入其中。我给你一个不好的答案。但是我仍然希望它会有所帮助。

因此,我着手帮助并回答您的问题,然后我开始对此感到很开心,然后我意识到自己已不知所措。因此,请轻易接受我冗长的答案,并且对于您当前的知识和技能水平,请不要过于复杂。

就数据库基础而言,您尝试做的事情很简单,但是在您掌握数据库之前,我了解数据库可能是压倒性和困难的。。继续阅读,您会明白我为什么要这么做。如果您坚持最终成绩,那就不会太复杂。如果您想从停下来的地方重新加载游戏,它可能会变得非常复杂。

在代码中,可以执行相同操作的方法有很多,很少有“正确”的答案。无论如何,我会评论您建议的方法。

问题

您有一个纸牌游戏,您在数据库中将其表示为match_dateplayer_profile_idplayer_score。每场比赛有四名球员。而且您想查看或加载旧的比赛以继续进行。

您提供的选项

  

我将每个匹配数据存储在单独的表中,并带有当前日期的表名。我将4个玩家ID存储为整数,将4个玩家分数存储为字节数组(每轮得分)。

至少可以说,每场比赛都有一个单独的桌子很笨拙。

  

我当时想我可以将这些数据存储在一个表格中,例如:比赛日期列,4个玩家ID列为int,4个玩家分数列为字节数组。

好。切换到单个表是一个巨大的进步,但是数据仍然以无法查询的格式进行压缩,并且每个播放器具有不同的列不一定是理想的,但是它将满足当前的任务。

  

一列比赛日期,一列球员ID组合为字符串,一列球员比分组合为字符串。

我喜欢您要浓缩桌子而没有那么宽的东西。但是以这种方式压缩数据几乎无法达到数据库的目的。您将无法查询特定信息,并且可能会失去性能,因为您的Android代码(Kotlin,对吗?)必须解压缩数据。但是我没有基准来证明这一点。

  

一列比赛日期,一列球员ID和分数以字符串形式组合

与上一个一样,它再次将数据库与Android代码紧密耦合。数据库应执行数据库工作,而Android代码应执行Android工作。我的意思是您的数据库应该是可移植的,没有复杂的逻辑来提取所需的信息。查询应提取您需要的信息。

我的建议

您正在考虑以不同的方式来做事情是件好事,这听起来像您有一个正在解决此问题的解决方案。但是,您可能会遇到的麻烦越来越大。我现在要添加很多数据库内容,因为您现在不需要实现。有时候最好做些自己拥有的技能,以便可以完成当前的任务。有时最好做一些您不知道该怎么做的复杂事情,以便可以学习。这取决于您的情况。

所以。我们将有roundplayermatch

架构

round表:

id | match_id | player_id | round_number | hand /*at the start of the round*/ 
87 |   3      |   96      |      0       | ["ace of spades", "kind of hearts", "7 of clubs"]
99 |   3      |   85      |      3       | [...]

以此类推
然后,您的玩家表中将包含名称,ID等列。您的比赛表将包含比赛日期,比赛ID和其他任何比赛数据

对我的解决方案的批评

  • 如果您要查询“在第7轮中有多少张牌手牌中有一张王牌,而没有国王留在甲板上”的查询,那么您需要将hand打开包装它也是自己的桌子。
  • 我个人更喜欢camelCase列名,而不是under_score列名。但是我认为under_score更常用于数据库。我没有什么可以支持的。
  • UUIDs是一回事。我还没有亲自开始使用它们,并且对于您的用例来说似乎没有必要。

让我们感到困惑

我想回答一个问题:“在第7轮中有多少场比赛,而任何球员手中都有一张红桃A,没有球员拥有2家具乐部,并且没有国王留在甲板上?” < / p>

  • deck_start表具有以下列:matchIdcardNamecardFace'index'
  • match表具有以下列:idnamedatetype(如果匹配类型不同)
  • card_in_hand表具有以下列:idmatchIdplayerIdroundNumbercardNamecardFace

所以回答这个问题

  

在第7轮中有多少场比赛的任何玩家都拥有一张红桃A? 没有玩家拥有两家具乐部,甲板上没有国王?

SELECT COUNT(DISTINCT match.id) FROM match
JOIN card_in_hand ON match.id = card_in_hand.matchId
WHERE card_in_hand.roundNumber = 7
AND card_in_hand.cardName LIKE 'ace'
AND card_in_hand.cardFace LIKE 'heart'

或者类似的东西。我触及了问题的第二部分……我思考得越多,问题就越复杂。您要么必须跟踪每个回合中的整个牌组,要么要使用手头上不同纸牌的数量来计算牌组索引。或者,您可以跟踪起跑阶段,然后跟踪每场比赛。真的,那可能就是那个。如果您跟踪每一个游戏。

play表可能包含idmatchIdplayerIdroundNumbersequenceNumberaction

然后您可能会有一个action表,或者另外展开action

您可能还希望将id表中的match列保留为matchId,而不仅仅是id。如果您开始进行联接并希望获得正确的ID(匹配v来回v播放v进行任何匹配),那么最好将其作为table.tableId而不是table.id

答案 2 :(得分:1)

我会尽力用这个回答您的问题。

  

我当时想我可以将这些数据存储在一个表格中,例如:比赛日期列,4个玩家ID列为int,4个玩家分数列为字节数组。

我认为这是最接近的。但是我认为可以扩展一点。我实际上不知道您正在使用什么数据,所以我不知道应该如何表示player_scores,但是我将使用字节数组滚动。

  • match表:matchId(int),matchDate(时间戳或日期类型)(以及其他元数据列,例如匹配项的昵称,如果不同则为类型比赛类型等)
  • score表:matchIdscoreIdplayerIdplayerPositionscore

这里,score是字节数组。

然后查询:

SELECT score.* FROM score  
JOIN match ON score.matchId = match.matchId
WHERE match.matchDate > /* start_date_for search */
AND match.matchDate < /* end_date_for_search */

然后,如果一场比赛中有四名球员,那么每场比赛你将获得四行,并且可以循环查看这些行中的球员特定数据。