DB2进行压缩的最佳实践

内容提要
这篇文章的目的是交流使用 DB2 的深度压缩解决方案的最佳实践。这个最佳实践允许你使用更少的数据面页来存储数据。数据库压缩的好处是:
使用更少的存储
存储以更低的速度被消耗
根据你的环境,有可能提高性能。
本文也提到了行压缩是如何适应更大的压缩策略背景的,包括值压缩和备份压缩。这里会讨论包括什么时候,在使用或不使用自动创建字典(ADC)DB2 9.5 功能情况下对行压缩实施最佳实践。一些 IBM 客户正在使用深度压缩功能,并且这些最佳实践已经使数据库体积的减小幅度达到过 50 个百分点,响应时间也提高了 20 个百分点。
总结的最佳实践:
评估压缩率以判断应该压缩哪张表
使用离线表重组来创建一个压缩字典并压缩整张表
除非必要,否则不要在表重组的时候集群数据
通过自动创建字典来减少使用表重组
把大型表迁移到一个压缩格式
控制压缩表的增长
监控并测量行压缩的有效性
释放已分配的表空间
压缩简介
压缩一张表有两个步骤。第一步是让一张表符合压缩条件,这由创建或更改一张表时使用 COMPRESS YES 子句完成。第二步是对要压缩的表的值建立一个字典。根据你使用的 DB2 版本,压缩字典有不同的含义。
一旦这两个条件达到,存储在这张表中的数据就可以被压缩。
每个表对象都有它自己的压缩字典。这意味着压缩字典是为每个数据分区创建的(无论是表分区或数据库分区)。结果就是,DB2 产品可以适应变化的数据就像你转入一个新分区。压缩是依赖于特定分区数据的。
建立压缩字典
基于你使用的 DB2 产品版本的级别来建立压缩字典有不同的方法:
DB2 9.1:主要方法是通过重组表。第二种方法是通过使用 INSPECT 实用工具,你可以在线创建压缩字典。
DB2 9.5:主要方法是通过数据来填充表。一旦表拥有了足够的数据,在表增加到 1-2 兆字节,就会自动创建字典。另外一种创建压缩字典的方法是通过 LOAD REPLACE 命令。
考虑在什么时候使用压缩的条件
你需要检查你的数据库以判断在这个数据库中的哪张表可以作为压缩的候选者。数据压缩最初是节约存储(在现有未压缩表上)和优化未来存储增长。你可以在数据库里的表上,在你希望随着时间增长的表上找到存储的“痛点”,或者二者皆有。 自然,最大的表很容易作为进行压缩的候选,但是也不要忽视小表。如果你有成百上千个小表,你或可能会体会到对大量小表进行压缩得到的总的效果带来的好处。“大”和“小”表的条件是:你的数据库设计将决定上万张表或者几百万行是“大”或“小”。
你应该考虑这张表中数据的典型行为。只读的表很适合压缩。如果表只有少数更新也可以是很好的候选。那些经过大量更改和操作的表可能不适合压缩。请考虑使用一个测试环境来对如何对候选表进行压缩运行基准测试。
低于 100KB 的小表可能不适合压缩,因为有可能节省的空间或许不能抵消压缩字典的存储需求。
一旦你决定了数据库中的哪张表适合行压缩,你应该决定每张表将使用什么方式来进行数据压缩。
在数据库中,以下表不能被压缩:
编目表
声明的全局临时表
系统临时表
行压缩和表数据复制不兼容。也就是说你不能在使用 DATA CAPTURE CHANGES 子句的同时使用 COMPRESS YES 子句。
行压缩只适用于行数据存储。这个意思是数据不是直接存储在数据行中的将不能被压缩:
索引
PureXML 是存在单独的对象中的 - XML 数据不能被压缩(除非 INLINE LENGTH 子句被使用并且 XML 数据足够小在一行数据中能容纳)
LOBs 是存储在单独的对象中 – LOB 数据不能被压缩
LONGs 也是存储在一个单独的对象中 – LONG 数据不能被压缩
一张表上的平均未压缩行大小对数据库设计使用大行标识符(RIDs)来说非常重要。普通 RIDs 在一个页上有 256 行的限制。这个页面限制在启用了压缩后很容易达到。 使用大 RIDs 让一张表中允许更多被压缩的行。同样的大 RIDs 也允许表变得更大。
复杂的查询倾向于顺序的操作行。有了行压缩,每个页面可以容纳更多的行。因此在进行了数据压缩的数据库的查询的工负载在访问相同的数据量的时候只需要比以前更少的 I/Os 。对于以离散的形式查询的数据,由于结果集只有很少的行(就像一个 OLTP 系统),压缩的效果就可能并不很好。
行压缩在受到 I/O 限制的环境中运行最佳,这个环境有空闲 CPU 周期并且可以被用来对行执行压缩以及解压。此功能在有复杂 select 查询 DSS 工作负载(I/O 查询大多数是顺序并有规律)下工作得非常好。
执行压缩操作,用户数据在 INSERT 和 DELETE 操作后产生的结果写入日志的记录很少。但是在压缩后一些 UPDATE 日志记录却可能比压缩前要大很多。当一个压缩后的行被更新的时候,就算解压后的记录长度没有变化,压缩后也可能发生变化。一个不同数字符号可能用于表示行更新后的版本。你也可以最小化日志压缩。 那些经常更新的列应该集中并存放在一起(见 http://publib.boulder.ibm.com/infocenter/db2luw/v9r5/topic/com.ibm.db2.luw.admin.dbobj.doc/doc/c0024496.html)。
评估压缩率
在压缩表数据之前,你可以使用 INSPECT ROWCOMPESTIMATE 实用工具来对每个候选表评估节约存储的好处。当你运行这个实用工具并且只希望评估而并不真正创建压缩字典,这张表不该被允许压缩。也就是说,这张表应该已经在创建时设置或之后更改为 COMPRESS NO(这是创建表时的默认值)。在运行 INSPECT 实用工具之前,表中必须有数据。如果表已经启用了压缩功能,那么运行 INSPECT ROWCOMPESTIMATE 实用工具完成已评估的存储节约并建立一个放置在表中的压缩字典。关于这个创建压缩字典的方法将在后面讨论。
对于还没有启用压缩的表,运行 INSPECT 实用工具来评估的压缩率。
DB2 INSPECT ROWCOMPESTIMATE TABLE NAME table_name RESULTS KEEP file_name 


然后运行命令:
db2inspf file_name output_file_name 


这个命令转换检查结果的二进制输出文件到一个叫 output_file_name 的可读的文本文件。这个文件包含使用行压缩页面节约的百分比的评估结果。
如果你使用一个现有表,DB2 9.5 产品有一个方法使用管理函数来评估压缩节约。为了在一个没有压缩过的现有表上判断行压缩的好处,又可以使用这个 SQL 语句:
SELECT * FROM TABLE
(SYSPROC.ADMIN_GET_TAB_COMPRESS_INFO( ‘ schema ’ , ‘ table_name ’ , ‘ mode’ )) AS T 


在这个 SQL 语句中,模式可以是 REPORT 或 ESTIMATE 。
使用 REPORT,你可以查看在创建压缩字典时的信息。如果表没有压缩字典,这个模式将不可用。这些信息也包括压缩节约的页面数目、什么时候创建压缩字典、用什么方法来创建压缩字典、平均行压缩率以及其他的信息。
使用 ESTIMATE 同样可以提供 REPORT 模式提供的信息,不过如果你继续进行行压缩,这张表中的数据也被抽样以了解有多少数据将被压缩。由于数据会被添加和更改,使用 RUNSTATS 和 ESTIMATE 模式是评估压缩影响的好办法。
可以对当前模式中的特定表的 ESTMATE 模式使用 SQL 管理函数 ADMIN_GET_TAB_COMPRESS_INFO 。 通过指定,你可以缩短在表上收集信息所需要的时间并限制使用的系统资源。如果你在运行 SQL 语句的时候没有包含‘表名’,那么将对这个模式下面的所有的表都进行压缩评估。如果你同时省略了模式和‘表名’,你将得到对整个数据库中的所有表的压缩评估。
这个 SQL 语句是用来判断压缩哪张表的好方法。你可以在某个特定模式下的所有表中选择表名以及节约页面的百分比。然后对节约页面的百分比用 ORDER BY 子句来找出从压缩中受益最多的表。如果你把这各表函数和 SYSCAT.TABLES 编目表进行连接,然后用增加的‘ npages ’值乘这张表所在的表空间的 PAGESIZE,再乘节约的百分比,最后你就可以计算出使用压缩节约出来的 gigabytes 数。你应该也看到了表的存储将会从压缩中得到最大的节约。
压缩使用表重组
一旦你决定了要压缩某个现有表,一个方法是对表启用压缩然后使用表重组命令来建立压缩字典。 当一个压缩字典建立好以后,及那个从实用程序堆中分配一个 10MB 在临时缓存里的空间,用于保存这个运算法则用于创建压缩字典的样本数据。
在重组、创建压缩字典时数据压缩也同时完成,这个过程中表处于离线状态。
表中的所有数据行都可以成为创建压缩字典的样本。在压缩之前,表的现有数据应该可以代表将在之后整个生命周期中插入的所有数据。
REORG TABLE 命令中添加了两个新的关键字,以使创建压缩字典变得更加容易了。默认关键字 KEPPDICTIONARY 用于检查用于判断这张表中是否已经有一个字典存在。如果压缩字典已经存在,它将在重组数据的时候被使用。如果不存在一个字典,就创建一个。如果没有字典存在,RESETDICTIONARY 关键字是指示创建一个新的压缩字典,如果有一个就覆盖它。
一旦表启用了压缩并通过重组表创来建了压缩字典,这张表中所有的数据都会被压缩而且从现在开始所有插入的数据也都将被压缩。
除非万不得已不要在重组数据过程中进行数据集群
使用 scan-sort 类型的 REORG 比使用 index-scan 类型的 REORG 创建压缩字典要更有效。此外,根据测试。当有相似的数据时,在对数据表的 10% 数据建立压缩字典的压缩率和对所有数据建立压缩表的压缩率是差不多的。
要是你想重组你的数据库并通过特定的索引来 re-cluster 它,你可以在一张表上运行应用了 scan-sort 或 index-scan 方法的完整 REORG 。在 REORG 命令中指定了一个索引的情况下,数据库管理器就已经默认使用 scan-sort 方法。这会进行表扫描并在内存中对结果排序(尽管有可能通过一个临时表空间溢出到磁盘)。 Index-scan REORG 方法需要显式的指定 INDEXSCAN 关键字;它不会排序,因为他是按照索引的顺序。然而,index-scan 方法需要对这张表在临时表空间中创建一个影子复制,并为索引中的每个 RID 从原表中读取数据。
基于这张表上 index 的数目变化,在重组处理过程中可能会产生额外的开销。虽然稍微提高了建立字典的开销,index-scan REORG 处理需要一个额外的表用于建立压缩字典。不过 scan-sort 处理通常能更快的完成重组和创建字典(除非这张表很小)。 Index-scan REORG 在 index 高度集群并且在系统没有足够的排序资源(内存和临时空间)时会更好,因为这种情况下 scan-sort 可能会溢出。此外,如果表已经被压缩过了,一个 index-scan 可能会运行得更好,因为有更少的页面被处理,这增加了提高缓冲池命中率的可能。
减少使用表重组
当你用 COMPRESS YES 子句来创建表或者更改表时,在 DB2 9 和 DB2 9.5 中压缩都是启用的。在 DB2 9 中你可以创建一个数据压缩字典,表现为一个离线表重组或者通过 INSPECT 实用工具。在 DB2 9.5 及以后的版本,你只需要对表启用压缩,而且一旦这张表中达到足够的数据量(大约 1 到 2M)那么将自动创建压缩字典。一旦表中存在数据压缩字典,所有后来添加的数据都将被压缩。
在 DB2 9 中,你可能对表已经启用了压缩,不过一个压缩字典还没有建立起来。为了不先用数据填充表然后重组(离线)表中所有的数据这样的方式来创建压缩字典,要在这张表中添加字典的另外一个方法是使用 INSPECT 命令。一旦一张表装入数据后,使用 INSPECT ROWCOMPESTIMATE 来创建数据压缩字典。运行这个操作,表将保持在线。 压缩字典只会在表中没有字典的情况下才会被创建。表中要是有字典,所有后来添加的数据都将根据这个字典被压缩;现有的行会保持未压缩的状态。你可以决定什么时候使用 INSPECT 命令来在表中创建压缩字典。你必须明确有足够的数据而且现有数据可以代表所有的数据。一旦这张表中有压缩字典,你期望更多数据添加到这张表中,以获得更多的压缩空间节省。
在 DB2 9.5 中,你可以从自动创建压缩字典(ADC)得到好处。在 ALTER TABLE 启用压缩功能的时候,你可能有一张表已经有足够的数据并且没有数据压缩字典。在对表启用压缩功能后,表的压缩字典是在洗一次数据添加的时候创建,并成为表的一部分。在你创建一个新表并启用压缩后,在有足够数据让表自动创建压缩字典之前可能需要一些时间。数据压缩字典创建的具体时间花费完全取决于有多少数据添加进这张表中。 在装载或插入操作过程中你可能会注意到一个由于创建压缩字典造成的延迟。
对内,数据库管理器持续跟踪表中的数据,你并不需要显式的创建这个字典并压缩数据。在大多数情况下,表越快达到 1-2M 数据,自动创建压缩字典点就会越早发生,并且从那以后的数据都将被压缩。这不在需要离线重组表或者运行 INSPECT 实用工具来创建压缩字典并压缩数据。
当使用了自动创建压缩字典,表可能有一个压缩和未压缩的数据混合存在。如果你的表是 1G 或 nG 大小 , 那么就不必担心这张表中头 1-2M 的数据(在压缩字典创建之前)对压缩效果的影响,这甚至都不用去考虑。
对大型表进行压缩
你可能遇到这种情况,你有一个没有启用行压缩的表,而你打算对它启用。这有很多方法来压缩这张表中的数据。
使用 INSPECT
使用 ALTER TABLE … COMPRESS YES 来对表启用压缩
使用 INSPECT 来建立数据压缩字典。更多信息参见前面对使用 INSPECT 命令的讨论。
使用 DB2 High Performance Unload 来卸载数据。
装载数据。它们将在装载操作中使用压缩字典进行压缩。这张表上所有后来增加的数据都将被压缩。
使用 REORG
DB2 High Performance Unload 实用工具来卸载现有数据。
重新装载一部分数据,它们可以代表所有数据。
使用 ALER TABLE … COMPRESS YES 来对表启用压缩。
使用 REORG TABLE 来建立压缩字典和压缩现有表中的数据。更多使用 REORG 命令的信息擦看上面的讨论。
装载剩下的数据。它们将在装载过程中使用数据压缩字典进行压缩。这张表中所有后来的数据都将进行压缩。
你可能有一张表已经启用了行压缩,并且你已经判断出需要重新创建压缩字典,你基于使用 RUNSTATS 命令和使用之前讨论过的 ADMIN_GET_TAB_COMPRESS_INFO 表函数得出的判断。 根据你的环境和状态,你可能想使用 REORG RESETDICTIONARY 命令(使用前面讨论的复制和重命名方法)和卸载数据然后重新装载以压缩表中数据 。
控制压缩表的增长
你或许工作在这样一个环境中,你向表中添加数据时基于时间周期的,比如每天、每周、每月、每季等等。 你应该基于选中的时间周期对你的压缩表添加分区。例如,你想添加每月销售数据到一张表。
通过使用 COMPRESS YES 选项来更改表,对销售表启用压缩。
为一个特定范围创建一个新的销售表,并启用压缩。
这个月数据被装载到新的销售表中。
在这个月月底,通过使用 RESETDICTIONARY 选项的重组来压缩新的销售表。
把新的销售表作为一张表分区添加到销售表中。
监控压缩效率
如前面所提到的,你可以使用 SQL 管理函数 ADMIN_GET_TAB_COMPRESS_INFO 来查看创建压缩字典使用的信息(在使用 REPORT 模式时),或者查看使用压缩是否可能在表中节省空间的信息并和当前表中已有数据做比较(当使用 ESTIMATE 模式时)。 RUNSTATS 可以用于查看数据压缩字典的效果随着时间推移在增减新数据到表中后是否会发生改变。通过监控 RUNSTATS 结果,你可以判断什么时候使用 SQL 管理函数来对压缩节省的空间进行一次新的评估。
基于你的数据库环境,你可能需要检查每个分布的数据库分区或者表分区来确认是否数据压缩字典对那个分区在压缩数据的时候是否仍然有效。


 
释放表空间已分配的空间
使用本文讨论的压缩方法,我们可以减少数据库中单张表的大小。根据你的表怎样被存储在表空间中和你怎么压缩这张表,以及未压缩的表相比,你可以让你的表空间有更多空闲空间。虽然你可能已经在表空间中减少了表的大小,表空间的高水位标记(HWM)或许仍然反映的是表空间分配的最大空间。 HWM 需要调低以释放节约的空间给你系统中的其他应用程序。
HWM 是在 DMS 表空间中已分配的页面的高数目。 HWM 可以在你对 DMS 表空间中的一张表执行离线表重组来释放。重组的过程数据需要一个影子副本。如果影子副本是建立在这张表所在的表空间。如果在当前 HWM 下没有足够的页面提供给这些影子副本,它们的扩展数据块会抬高 HWM 。在 HWM 下空闲的扩展数据块可能是像删除表、表截断操作(IMPORT/LOAD REPLACE)和表重组操作(压缩或不压缩)的结果。
如果在 HWM 下没有空闲的扩展数据块,那么降低 HWM 的唯一办法就是删除持有它所在位置的对象。任何类型的扩展数据块都可以持有 HWM 。 db2dart /DHWM 生成的报告将显示什么类型的的扩展数据块持有 HWM 并且 HWM 是否可以降低。 Db2dart /LHWM 列出了可以降低 HWM 的步骤。包括可对数据库运行的命令 , 不管 db2dart 返回的数据库是不一致或活动状态警告。唯一影响系统的是从表空间读取元数据信息带来的 I/Os 。
如果有一个 DMS 表的数据对象持有 HWM 那么需要在 DMS 表空间中的一个离线的表重组在 HWM 下的空闲扩展数据块足以容纳影子副本的情况下可以降低 HWM 。如果一个 DMS 索引对象持有 HWM,重组这个索引就能降低 HWM 。
把大表分别存放在它们自己的表空间里
如果在你的环境中有可能的话,在试图压缩这些表之前,把你的大表分别存放在它们自己的表空间中。
重组表通过指定 USE 子句给影子副本一个临时表空间。使用复制和重命名表的方法在 DMS 表空间中压缩大表。这个方法是创建一个新的 DMS LARGE 表空间,一个新表和新的索引,从当前的表中复制数据到新的表里,并对新表实施压缩。然后重命名当前的表到一个其他的名字然后把新表重命名为当前这张表的名字。这个重命名的方法只会造成几秒钟的离线避免了对这张表进行压缩造成这张表的长时间下线。一旦完成,老的表和表空间就可以删除了。
多张表在一张表空间中
如果你有表空间有很多表,考虑下执行下面步骤:
更改数据库管理表空间(DMS)从 REGULAR 到 LARGE 以获得更大的 RIDs,大 RIDs 让更多的数据存放在一个页面。
更改 DMS 表空间为 AUTORESIZE YES
在 DMS 表空间把表改为 COMPRESS YES 和 VALUE COMPRESSION 。(见本文其他地方关于 VALUE COMPRESSION 的信息)
在这张表空间中的重组从最小的表开始并使用一个临时表空间和 RESETDICTIONARY 选项。 HWM 只会增长一点,而且仅 HWM 下面空闲的表空间就可以用于下一张表的重组。
使用 DB2 LIST TABLESPACES SHOW DETAIL 命令。这个命令重置了恢复空间需要的表空间内部点。
重启 DB2 实例以刷新缓冲池和表空间在内存中的信息。
执行第二批表重组使用 INSPLACE 选项以释放在表空间在 HWM 下的空间。同样,REORG 表也是从小到大。
运行 DB2 LIST TABLESPACES SHOW DETAIL 命令。
重启 DB2 实例
更改表空间通过减少容器大小来恢复磁盘空间。
在压缩 DMS 表空间中的大表时,使用复制和重命名表的方法。这个方法是创建一个新的 DMS LARGE 表空间、一个新表和新的索引、从当前的表复制数据到新表、然后对新表进行压缩,最后重命名当前表到另外一个名字并把新表命名为当前的表面。这个重命名方法只花费数秒并避免了对大表进行压缩时的长时间下线。一旦完成,旧表和表空间就可以被删除了。
创建一个新的 DMS LARGE 表空间来替换 SMS 表空间。
对 SMS 表空间中的表使用复制和重命名表的方法
其他类型的压缩
在多个版本中,DB2 产品有多种类型的压缩:
有对空间或值的压缩,nulls 值的存储空间以及系统定义的默认值都也可以被压缩。
备份压缩以减少备份镜像在存储介质上的大小。
如果你在考虑行压缩之前已经实现了一个或多个其他类型的压缩,那么在添一个行压缩应该也没有问题。然而,如果你还没有实施任何其他压缩,而且你打算使用行压缩,那么在实施了行压缩后在使用这几类压缩的效果就不明显了。
空间或值压缩
值压缩包含删除重复条目值和只存储一个重复值的副本。存储的备份保持了所有对存储值的引用。当创建一张表时,你可以使用 VALUE COMPRESSION 子句来指定表将要用来在表层面也可能在列层面存储行格式的空间。分配给变长数据类型(VARCHAR、VARGRAPHICS、LONG VARCHAR、BLOB、CLOB 和 DBCLOB)的 NULLs 和零长度数据将不会被存储在磁盘上。只有与这些数据类型相关的替代值才会存储在磁盘上。如果使用了 VALUE COMPRESSION,那么可选 COMPRESS SYSTEM DEFAULT 子句也可以被用来进一步减少磁盘空间使用。更多关于空间或值压缩的信息见 http://publib.boulder.ibm.com/infocenter/db2luw/v9r5/topic/com.ibm.db2.luw.admin.dbobj.doc/doc/c0007306.html
备份压缩
在备份一个数据库或表空间时,你也可以压缩备份镜像。对 BACKUP DATABASE 命令使用 COMPRESS 子句。在压缩备份镜像(以及在对多张表空间进行备份时)时你也应该考虑使用 PARALLELISM 子句。用来压缩的压缩字典可以包含在备份镜像中也可以是备份镜像之外。压缩字典也可以从备份镜像中单独恢复。在你有一个压缩过的备份镜像后要想恢复或修复数据库压缩字典是必须的。更多使用压缩优化备份的信息,参见 http://publib.boulder.ibm.com/infocenter/db2luw/v9r5/topic/com.ibm.db2.luw.admin.ha.doc/doc/c0006205.html
你也应该考虑使用 AUTO_DEL_RED_OBJ 数据库配置参数和自动恢复历史文件裁剪来配置在每次完整备份操作后自动删除不需要的恢复对象。这将帮助你控制备份镜像的增长和其他回复对象会消耗大量的存储空间。虽然你可以自动裁剪这类文件,你也可以防止关键的恢复对象被删除。数据库管理器只能在你测存储介质是磁盘或者你使用了想 Tivoli Storage Manager 这类存储管理器的时候才能删除想数据库日志、备份镜像和装载复制镜像恢复对象。更多关于管理备份对象的信息,参见 http://publib.boulder.ibm.com/infocenter/db2luw/v9r5/topic/com.ibm.db2.luw.admin.config.doc/doc/r0051456.html


 
总结
DB2 产品的行压缩功能可以明显的减少存储需求,而且可以提高性能,尤其在数据库有磁盘限制的情况下。结合其他压缩功能,你将会注意到非常明显的成本节约和性能好处。
这是的最佳实践
使用 INSPECT ROWCOMPESTIMATE 来估算压缩率
使用自动压缩来减少表重组
对涉及的数据搜集统计信息和精确计量压缩效果
除非必要(也就是,在重组期间没有重新集群)不要在重组操作上指定索引
减少 DMS 表空间高水位标记对空间释放的影响
把大型表分别存放到它们自己的表空间中(索引和大对象也一样)
重组表时使用一个临时表空间来存储 shadow copy(指定 USE 子句)
一张表空间中有多张表
从这张表空间中最小的表开始重组
HWM 增长有限而已在表空间中低于 HWM 的空间得到释放并可以在下一次表重组中使用
把大表迁移到一个压缩格式: 考虑使用 INSPECT ROWCOMPESTIMATE 和 High Performance Unload 工具,以及 DB2 装载工具卸载并重新装载来在线建立字典。
ALTER TABLE sales ATTACH PARTITION mar08 
STARTING '03/01/2008' ENDING '03/31/2008' FROM TABLE newsales 
每个与你都可以添加另外的分区到销售表。

本文转载于http://blog.itpub.net/15082138/viewspace-584381/

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值