NoSQL还是非NoSQL?

本文探讨了NoSQL数据库与传统SQL数据库之间的差异,强调了NoSQL在处理大数据、敏捷开发和可扩展性方面的优势,同时也指出了NoSQL在安全、数据一致性、事务处理和工具支持等方面的挑战。文章提供了一系列基准测试,展示了在不同场景下NoSQL和SQL的性能比较,并提出NoSQL不是SQL的替代品,而是根据特定需求选择的补充选项。
摘要由CSDN通过智能技术生成

目录

介绍

什么是NoSQL

NoSQL实现

面向文档

图数据库

键值存储

NOSQL的优势

合成中

NO-SQL的限制

安全

数据一致性

联接

棘手的事务

供应商技术缺少标准

架构灵活性可能是个麻烦

分析

更少的工具

性能比较

单一实体的大规模操作

搜索

事务

分析

兴趣点

什么时候应该使用NoSQL数据库?

上述情况下的表现好多少?

NoSQL系统是否已经成熟,可以在生产环境中使用?

SQL过时了吗?

市场准备好使用NoSQL了吗?

什么是最好的解决方案?


介绍

在过去的几年里,我们跟随NoSQL技术的兴起,它被用于更广泛的应用程序集。本文旨在从SQLNO-SQL技术进行客观比较,并试图澄清一些不清楚的方面,以帮助人们明智地选择其后端。

什么是NoSQL

简单来说,NoSQL是一种不遵循关系数据库模型的新型数据存储后端。这意味着我们谈论的是一个与传统的基于SQL的后端不同的容器
为满足一系列新需求而诞生的NoSQL技术问世,而传统数据库已经成熟。当然,在过去的几年里,应用程序需要改变并且变得更加挑剔(大数据、集群、文件存储库),所以这个新的存储系统的设计考虑到了这些新的要求。

但是,我所说的要求是什么意思?这是NoSQL旨在支持的一组案例。

  • 应用程序处理大量数据(大数据)
  • 应用程序处理快速改变关系和数据类型的数据(半结构化、非结构化和多态数据)
  • 开发人员使用敏捷方法在一个小团队中工作:大量小项目对抗长期瀑布迭代
  • 作为服务的应用程序,可以在网络上发布
  • 应用程序交付给成千上万的用户,而不是公司内部的少数人
  • 不确定应用程序的未来负载:需要可扩展和动态,需要轻松地将软件基于后端集群

市场提供了许多NoSQL解决方案,无论是否开源。它们每个的工作方式都略有不同,可能专门针对某些特定需求,但基本思想和共同特征是提供更好的可伸缩性和性能。为此,他们放弃了通用RDBMS的一些特性,引入了新特性,但保留了足够有用的功能。

NoSQL实现

SQL DB的一个重大变化是,与此同时,SQL后端是通用存储系统,而NoSQL发行版专注于特定类型的数据。这允许数据库在其范围内更有效,并允许拥有更高性能的系统。在本节中,报告了某种NoSQL数据库,以了解它们具有哪些应用程序。请注意,它们可以一起使用(也可以与传统的SQL系统一起使用)以充分利用所有系统。

面向文档

这种类型的数据库不需要具有一致的数据结构,因此当您必须处理多态数据或数据结构不断变化时,它们很有用。这种后端可以将规范化的实体(如键值数据集或EAV模型)转换为简单的文档集。

  • 目标:存储非类型化的记录集,称为文档
  • 示例MongoDBCouchDB
  • 目标:异构数据、工作面向对象、敏捷开发

图数据库

我们被告知NoSQL数据库去除了关系的概念以实现更好的性能。在这种数据库中,这是不正确的。相反,这些数据库强制执行关系的概念。

他们的目标是通过数据与其他数据的关系来定义数据。当大多数数据结构被设计为与实体保持关系时(即,如果您有很多表,而主要是外键列),这种数据库会很有用。

  • 目标:描述数据关系
  • 示例Neo4jGiraffeDB
  • 目标:数据挖掘

键值存储

这是一种旨在存储大量键值对数据的数据库。当数据库用于存储属性、翻译或缓存目的时,这可能很有用。

  • 目标:以键值形式存储数据
  • 示例RedisCassandraMemcacheDB
  • 目标:键值存储

NOSQL的优势

我们知道NoSQL db有一些有趣的优势,它们可以轻松解决传统RDMS无法解决的简单问题。如今,它们在关键系统中的大量使用,如大型云系统和一些大型SaaS产品,证实它们是成熟和有用的。但问题是,我为什么要搬到他们那里?在这种情况下,此举何时能盈利?我们不能仅仅根据我们的印象做出这样的决定,并且阅读一些供应商手册,其中认为NoSQL非常酷是不够的。此外,我们不能仅仅因为害怕变化而停留在不合适的平台上。

在本章中,我将尝试解释为什么这个解决方案足够好,可以继续使用它,以及什么用例使它更有利可图。

正如我们所说,NoSQL数据库是针对传统关系数据库技术的局限性而创建的。这意味着我们会发现一些改进,或者更好的是,一些传统rdbms中不存在且无法添加的特性,即使生产者会实现它们。

NoSQL的优势包括易于处理的能力:

  • 大数据:用这个术语,我们描述包含大量数据的数据集。
  • 可变数据:数据可以是结构化的、半结构化的和非结构化的。NoSQL还可以管理数据的转换。
  • 动态开发:在我们需要敏捷冲刺、快速迭代、频繁代码推送以及总而言之以响应变化的环境中,拥有一个包含动态的数据库非常有帮助。
  • 面向对象:易于使用且灵活的编程
  • 可扩展性:我们可以轻松实现高效、可扩展的架构,而不是昂贵的单体架构。即使在传统的数据库中,我们也可以做到这一点,但它更加困难和有限。
  • 开源:大多数解决方案都是开源的,因此无需支付许可费用。

合成中

NoSQL数据库更具可扩展性并提供更好的性能,并且它们的数据模型更接近应用程序内部使用的领域模型。如今,基于NoSQL数据库启动项目的公司正在增长。NoSQL数据库也往往是开源的,这意味着开发、实施和共享软件的成本相对较低。

NO-SQL的限制

在评估NoSQL数据库的局限性时,重要的是要记住NoSQL世界是一个多样化的生态系统。并非所有NoSQL存储产品都会在相同程度上受到所有缺陷的影响。这是一件好事,因为这意味着组织在权衡不同NoSQL解决方案的优缺点时有很多选择,以确定哪一个最适合他们的特定需求。本章总结了一些使用NoSQL解决方案可能会遗漏的特性。

通过阅读这篇文章,你会发现本章的内容比优点更丰富。这不会是阻止使用NoSQL的方法。本章将公正地描述NoSQL技术的所有限制,只是想让您了解使用它们时可能遇到的每一个问题。许多点可能会因实施而异(即,当我说支持的工具很少时,它可能适用于大多数工具但并非适用于所有工具),因此将它们视为一个概述,提醒您可能存在的风险找。我期望的是,在您选择了要使用的NoSQL产品之后,您可以使用本章作为清单来了解这些问题是否存在于您的特定数据库中,以及它们是否与应用程序相关。

安全

安全是每个人都想要的东西,但很难达到。从理论上讲,每种技术都可能存在安全问题。在SQL系统上存在并且可能存在安全问题。那么为什么我在NoSQL上将此标记为可能的问题呢?与安全相关的NoSQL“概念没有真正的问题,但我们可能会遇到与我们使用的产品的成熟度相关的安全问题。随着产品的增长和修复,安全问题就会出现。直觉上,一个年轻的产品可能有许多未知的安全问题。而且,年轻的产品上市时间还很短,所以顾问们还没有时间去体验它们,很多安全限制都可以忽略不计。所以,问题在于大多数NoSQL平台的年轻化。对于商业用途,我建议只采用成熟的解决方案,背后有供应商。

数据一致性

当我们开始学习RDBMS时,他们告诉我们ACID事务是使操作在整个数据库中保持一致的最佳选择。好吧,大多数NoSQL技术都没有实现这种事务。NoSQL系统基于最终一致性原则。在实践中,承担一点一致性风险(一个节点可能与其他节点不同步),它们获得了一些性能提升。是的,这是一种妥协,但我们不能拥有一切。

我不得不提到一些NoSQL实现,比如FoundationDB,允许类似ACID的事务来保持NoSQL的高性能。顺便说一句,虽然我们仍然使用NoSQL,但数据一致性仍然是一个关键部分:根据您正在开发的应用程序,这可能是一个问题,也可能不是。

联接

当您与试图将您转换为NoSQL技术的人交谈时,您可以从他们那里听到的第一个好处是由于删除关系而带来的性能优势。我们都同意关系可能会降低性能,但是删除它们会失去什么?这就像你背着一个又大又重的背包在下降。当然,放下它你会走得更快。这样做方便吗?取决于这个包包含什么,取决于背包内容对你有什么价值。如果它包含过夜的帐篷,也许,最好晚一小时到达目的地但睡得暖和,然后走得更快。如果你带了有用的一次性物品,也许你可以做相反的事情。

遵循这种并行性,我们是否可以接受失去一致性来获得性能?这很方便?

退后一步,我将从联接的起源开始。RDBMS使用关系将数据从一个表链接到另一个表,以便将数据保存在一个地方并且不复制它们。Join是允许在查询中重新连接它们的构造。当然,相对于直接在您正在查询的表中查找数据而言,在表之间进行连接是一项额外的计算成本。但是这个成本是保持关系所必需的(没有复制,一致性)。

很明显,虽然这样的构造具有可接受的开销,但这是可以的,并且可能是最佳选择。但是当它减慢一切或需要太多硬件时怎么办?这个问题允许NoSQL开发人员声称缺少JOIN某个功能,但NoSQL是解决方案吗?

不总是。有时,我们只需要重新设计数据库结构,可能会删除一些关系或重新构建数据。是的,我们会失去一些关系,或者我们会复制日期的某些部分,但这是可以接受的(在NoSQL中,我们将失去所有的关系)。

另一个问题是一致性。考虑类别和产品。我们可能有一个嵌套的类别树,其中有许多产品作为树的叶子。在传统的RDMS中,更改类别树只是对category表上的外键(自关系)进行更新。这些更改会自动反映在所有子类别和产品上。在NoSQL方式中,我们可以在所有类别\产品上拥有冗余数据,并且更改将需要对子元素进行大量更新。

棘手的事务

让我假设我们的应用程序可以放弃JOIN以提高速度,在我们的例子中,这是一个可以接受的权衡。我们还说过,在许多NoSQL实现中,很难使各种条目保持一致。当你在没有事务的情况下工作时,你可以按顺序进行许多操作,但在粉碎之后,你会得到不一致。对于NoSQL的首次实现来说确实如此,并且一些新技术试图提供开箱即用的东西来提供开箱即用的事务。您还可以考虑在应用程序级别管理事务,尝试回滚脏数据,但在许多情况下可能很难管理。

供应商技术缺少标准

SQL是一种标准语言。特定方言可能有许多变化,但这很复杂,并不禁止抽象数据访问。想想HibernateNHibernateDoctrineEntity Framework或您喜欢的其他ORM:它们证明了区分SQL方言并不那么相关。我们可以得出结论,SQL是一种标准语言,即使许多供应商实现了不同的数据库技术。此外,如果您不是基于ORM层,如果您为数据库生成查询,则大部分代码都可以在其他人中重用。这使得迁移更容易,开发人员可以快速适应不同的数据库解决方案。

另一方面,在NoSQL世界中,存在更多的混乱。每个供应商都在不涉及任何共享标准的情况下实现其特定语法。这意味着在不同的NoSQL实现之间迁移应用程序更加困难。这意味着很难找到熟悉许多NoSQL技术的程序员。

架构灵活性可能是个麻烦

NoSQL系统的特点之一是它们不需要模式。在实践中,程序员在保存数据结构的那一刻就决定了它。所以没有地方写数据是如何构造的,数据的含义是什么。即使您可以使用一些自动化工具从数据关系开始轻松地重新创建数据库模型,这可能是传统应用程序中缺少的东西。此外,如果出现错误怎么办?我们知道在某些情况下代码可能有问题。传统的RDMS是脚手架式的,因此如果您切换某些字段或字段格式错误,它们可以保护您免受不一致的影响。在NoSQL的情况下,数据库没有帮助,因为没有定义任何模式,就没有任何关于数据的信息应该被保存:没有人可以说数据是否错误。最糟糕的副作用是流程给开发人员带来了很多权力和很多责任,他们通常不知道所有的流程或结构。

此外,即使您现在知道保存在哪里,您认为下个月您会记住所有内容吗?明年呢?并非所有项目都需要持续开发,在我们需要进行一些更改之前,可能会有业务应用程序保持原样一年。无论如何,在IT领域,公司经常将项目委托给某个供应商,因此必须考虑这部分,以确保在项目结束时轻松移交,也许要求提供有关数据结构的准确文档以及每个字段\集合的含义。与模式灵活性相关的最后一个问题是团队中的每个成员都无法在项目中工作一辈子,因此对于并非所有成员都完全了解数据结构或没有足够文档的小团队来说,更替是至关重要的。

分析

将大量嵌套数据保存在单个文档中,可能会丢失SUMCOUNT等分析函数。不好的是,这在第一次应用程序开发过程中可能不是问题,但是以后有人可能会要求一些报告,那么这种情况下该怎么办?数据库填充后很难更改数据结构,并且由于定义良好的数据结构的泄漏,这样做可能会产生许多不可预知的影响。分析是NoSQL的难点。

此外,虽然有许多商业工具可以连接到传统数据库来管理分析部分,但对NoSQL系统的支持有限。

可以采取的另一种解决方案是在NoSQL数据库中复制某种与非结构化数据的关系,可能会创建许多集合并将对象与其他对象链接起来。如果您计划遵循此路径以允许分析报告,请记住,这可能会降低性能以与标准SQL系统相媲美。当此数据库中涉及的部分最少且记录数有限时,这是可以接受的。无论如何,即使根据我的经验,允许在NoSQL查询上连接数据的构造,因为背后没有明确定义的关系非常有限,并且性能不如我们预期的那么好(即,在撰写本文时,MongoDB不支持inner join,每次只能进化到table,不用创建临时表)。

更少的工具

我们谈到了NoSQL查询语言和语法缺乏标准化。这个问题可能也反映在工具上,以及大多数平台的年轻化。我说的是用于查询的工具,还有用于在数据库之间迁移数据、管理备份等的工具。当然,大多数NoSQL项目都在增长,我们希望工具会随之增长,所以这个问题会在不远的将来。

缺乏标准化使得第三方供应商很难构建可以支持多种NoSQL解决方案的工具。此外,年轻的平台意味着更少的用户、更少的客户和更少的时间来开发成熟的工具。

性能比较

指定如何进行比较很重要。首先,我需要将两种解决方案置于相同的条件下。这意味着,例如,使用相同的硬件并具有相同级别的调整。所以我在同一台机器上安装了MongoDB(最新版本)和SQLServer Express。因为我们对数据库本身的性能不感兴趣,所以我使用基于标准框架的C#代码构建了我的基准测试。在这两种保存数据的方式上,一切都是共享的(实体、逻辑、数据生成)以确保公平。

基准详情

特征

NoSQL

SQL

中央处理器

i7

i7

内存

16GB

16GB

磁盘

固态硬盘

固态硬盘

我们将比较所有操作的列表:

  • 批量插入
  • 查询
  • 分析
  • 事务(或者更好,在NoSQL情况下,事务模拟)

单一实体的大规模操作

该基准测试由一大组要插入的对象组成,可以在更短的时间内执行。该测试使用越来越多的项目进行复制以保存,以证明两个系统的性能如何扩展。该基准以毫秒为单位测量执行时间,并坚持使用单个表\集合。

性能比较

#

NoSQL(毫秒)

SQL(毫秒)

100

1

3

1000

12

163

10000

85

202

100000

842

2182

1000000

9179

19875

搜索

该基准测试专注于查询功能。我们将以下模式分开:

  • 案例 1 使用主键获取一个实体:此模式用于使用唯一标识符从db获取单个实体。
  • 案例 2 完全扫描失败:当您正在寻找已删除的元素并且数据库必须在回复之前扫描所有索引时。
  • 案例 3 分页查询:一个复杂的查询,您有一些过滤器、一个订单条件,并且您只想获取一页数据。

我创建了一些基准来模拟上述模式的不同比例。在示例中,第一个基准测试假设5%的类型170%的类型225%的类型3。该基准以毫秒为单位测量执行时间。这个基准坚持一个表\集合。

您可以在github上找到用于执行这些测试的所有代码。

基准描述

 

案例1

案例2

案例 3

基准 1

5%

70%

25%

基准 2

10%

45%

45%

基准 3

15%

8%

77%

第一个测试是在一组数据上进行的,大约2.500.000行。

性能比较

基准

NoSQL(毫秒)

SQL(毫秒)

基准 1

47

244

基准 2

1

13

基准 3

1

12

第二次测试更大的数据集,大约5M行。

性能比较

基准

NoSQL(毫秒)

SQL(毫秒)

基准 1

56

287

基准 2

2

17

基准 3

2

18

该基准测试突出了查询相对于索引的性能有很大的提高,但是当使用MongoDB读取数据集时,增益会降低,并且相对于数据的增加保持稳定。

事务

我们知道NoSQL世界上的事务大多不受支持。我们也明白放弃事务可以提高性能,一个问题是:我能从中获得多少收益?我建立了这个基准来比较与许多孩子相关的一个主行的事务中的插入。基准侧重于执行时间,以毫秒表示。

性能比较

#事务

SQL (毫秒)

NoSQL(毫秒)

10

99

89

100

1004

764

1000

11025

7309

分析

该基准侧重于分析。假设我们有一个分类的主从数据模型,您想要:

  • 导出:整个连接所有数据树
  • report : 对所有类别的类别中的所有项目求和,即为所有客户提供发票金额
  • 关键绩效指标:将所有主计和和明细小计相加

在内部连接后的4M行的基础上:

性能比较

测试

SQL (毫秒)

NoSQL(毫秒)

关键绩效指标

1176

1403

报告

805

1363

兴趣点

在技​​术背景下,革命是不可避免的。一项新技术出现并带来了一些革命性的功能,但通常必须打破开发人员的先入之见。有时,他们被误解了,所以他们的弱点在他们被雇用后就会暴露出来。

关于创新,我们有对立的人群:

  1. 热情的人 想要无条件地拥抱变化,并准备好将过去所做的一切都与最新技术一起工作;
  2. 保守的人 讨厌变化,宁愿保持自己的习惯,拒绝任何新技术。

在现实生活中,我们必须处于中间状态,因此了解和理解新技术可以为我们做什么并准备好在项目需要新技术之前使用它们非常重要。在工作中试是一个坏习惯,会导致不好的结果。

同样的原则也适用于NoSQL技术。因为我们前段时间研究过NoSQL,现在我们知道了利弊,所以我们可以利用这种工具。当我们分析该技术时,我们不能停止查看我们从传统习惯中遗漏的东西,例如事务、模式和标准。我们需要研究和熟悉这些技术,这些技术在几年前还很年轻,但现在是一个具体的选择。学习、学习、理解、使用:这是进步的本质。

什么时候应该使用NoSQL数据库?

为什么NoSQL会比使用SQL数据库更好?看完这篇文章,相信你会明白NoSQL并不是SQL数据库的替代品,它只是一个不同的存储系统,具有不同的特性,在某些特定领域很有用。因此,答案不能与取决于不同。因为它确实取决于项目的许多特性。

老实说,当以下所有陈述都为真时,NoSQL是最好的解决方案:

  • 当您的项目需要扩展时,或者将来可能。
  • 当您必须处理大数据时,或者您的数据在不久的将来会变得很大
  • 当应用程序中的分析组件很简单或不那么重要时
  • 当您的应用程序需要适合数据库用途时(即,您将数据保存在图形中,而数据库会这样做)

在某些情况下,NoSQL可能是一个不错的选择,但对于构​​建持久的基础架构并不是必需的。当然,如果在您的应用程序中,NoSQL系统可以满足所有需求的99%,则没有理由将它与RDBMS结合使用。但是如果你需要标准RDBMS的关系、事务和其他特性,也许最好将它们用作主存储系统,并使用NoSQL仅覆盖关键部分(可能来自数据大小)。

上述情况下的表现好多少?

这取决于具体的用例。一方面,我们在大表或大量使用方面有很多好处,但另一方面,使用查找而不是在小数据集上连接会造成一些性能损失。一个现实的估计,如果有使用NoSQL数据库的基础,我们可以将性能从10提高到100倍。当然,这个估计考虑了应用程序的所有方面,它关系到最终的用户体验。这意味着您可以在db层测量更好的加速,但最终用户体验会受到许多缩小差距的因素(缓存、网络延迟、页面渲染)的影响。只是为了解释我在说什么,以当有一个页面进行查询并返回数据时的限制情况为例。假设这个页面使用传统数据库获取结果需要500毫秒,使用NoSQL需要50毫秒,200毫秒用于渲染页面,1秒用于通过互联网传输数据。db层的性能提升是-90%,但是对于最终用户来说,在1700上只有450ms的提升,所以只有26%。通过这个例子,我将解释很难衡量复杂系统的改进,并且在许多情况下,NoSQL不足以解决性能问题。更直接地说,如果您考虑在迁移到NoSQL的应用程序中解决由于设计不良而导致的性能问题,那么您就没有走上正确的道路。

但最大的问题是:为了获得这种表现,我会失去什么?因为在某些情况下,不可能放弃交易或关系等某些功能。在搬家之前了解这一点非常重要。

NoSQL系统是否已经成熟,可以在生产环境中使用?

主要取决于您的需求,或者更好的项目要求。我们可以说NoSQL已经足够成熟,可以使用了。因此,如果您需要,您可以毫无顾忌地使用它。但并非所有应用程序都需要处理大数据或大规模扩展。大多数SaaS产品都可以,企业上下文中的许多关键应用程序也可以,但是现在的大多数应用程序仍然非常简单。以我的经验,很难在数据库中找到超过100 000行的表。想想你的数据库,排除你上面的2-3个更大的表,然后查看行数。他们多大?db应用程序上的通常db结构计算了很多相关的表(少于100 000行)。对于这样的应用程序,传统的RDBMS就足够了,而且它将永远存在。重要的是,而不是开始使用它,而是了解收益和开发模式,以便在您的情况需要它们时做好准备。

SQL过时了吗?

当男人发明飞机时,汽车就过时了吗?不,当然。即使飞机比汽车快,它们也只是两种不同的移动人员系统,具有不同的特性。根据您开始的旅行类型、您在旅行上花费的时间和预算,您将决定最适合您的选择。同样,NoSQL的到来并没有让SQL过时。它们只是两种不同的数据存储方式,具有不同的特性。您将根据自己的需要决定什么是最适合您的。

SQL不适合的问题,所以你不必用它来启动大数据项目。这就像试图用汽车而不是飞机到达一个岛屿。但是SQL仍然有它的优势。许多数据模型最好简单地表示为相互引用的表的集合。这就像试图用飞机去买牛奶一样。NoSQL数据库不是SQL的替代品,但它们是一种替代品。

市场准备好使用NoSQL了吗?

回答这个问题的关键点是更接近开发者所获得的体验。大多数数据库程序员都接受了一年的培训,以便以关系的方式思考数据。他们怎么能在这么短的时间内改变思维方式?这并不容易,尤其是当开发人员必须在许多项目中一起工作时,其中一些是SQL,另一些是NoSQL。将SQL上的相同模式复制到NoSQL系统的诱惑很难克服,而且往往会导致糟糕的结果。

所以实际上,关于SQL的知识要多得多,熟悉RDBMS的开发人员比NoSQL多。同时,有些DBA将大部分时间都花在了关系数据库上,我们不能指望在不到十年前诞生的技术上也能找到同样的东西。SQL在学校和大学中普及,NoSQL开始普及。

在这第一点之后,第二点是因为这些系统较新,开发工具较少,或者不像其他系统那么先进,但我确信这不是一个真正的问题。有一些企业就绪的解决方案提供了管理所有基本需求的工具,我们都希望这些工具能够随着平台的发展而发展。

什么是最好的解决方案?

没有涵盖任何情况的最佳解决方案。答案很简单,但还是一样:这取决于通过本文,我希望为您提供此类系统的所有功能的概述,以及了解它们何时有用的一些基础知识。

https://www.codeproject.com/Articles/1158951/NoSQL-or-not-NoSQL

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值