Deprecated: imwpcache\f884414bce24ee67f\f73723ec7b1919fa5::__construct(): Implicitly marking parameter $YECBGYFECGEAFWHA as nullable is deprecated, the explicit nullable type must be used instead in /www/wwwroot/www.chuangxiangniao.com/wp-content/plugins/imwpcache-dist/build/f884414bce24ee67ff73723ec7b1919fa5.php on line 2

Deprecated: imwpcache\f884414bce24ee67f\f73723ec7b1919fa5::__construct(): Implicitly marking parameter $BBWFDDBHHYHDXXAB as nullable is deprecated, the explicit nullable type must be used instead in /www/wwwroot/www.chuangxiangniao.com/wp-content/plugins/imwpcache-dist/build/f884414bce24ee67ff73723ec7b1919fa5.php on line 2
Redshift大数据量DataFrame高速插入策略_创想鸟

Redshift大数据量DataFrame高速插入策略

redshift大数据量dataframe高速插入策略

本文旨在解决从Python DataFrame向Amazon Redshift数据库插入大量数据时效率低下的问题。我们将探讨并对比两种主要的高速插入策略:优化的SQL批量插入(通过psycopg2.extras.execute_values)和Redshift官方推荐的COPY命令(结合S3作为中间存储),提供详细的实现代码和最佳实践,帮助用户显著提升数据加载性能,避免长时间等待和超时错误。

Redshift大数据插入的挑战与优化

在处理大规模数据时,将Python DataFrame中的数据高效地导入到Amazon Redshift等列式存储数据库是一个常见的挑战。传统的逐行插入或使用executemany的批量插入方法,对于Redshift这类针对批量加载优化的数据库而言,效率往往低下,容易导致长时间运行甚至超时错误。Redshift的设计哲学是利用并行处理能力,一次性处理大量数据,而非频繁的小事务。

用户尝试的两种方法,无论是将DataFrame转换为字典列表后使用executemany,还是转换为元组列表后循环execute,都未能达到理想的速度。这主要是因为这些方法在底层可能仍然导致数据库执行了大量独立的INSERT语句,或者未能充分利用Redshift的并行加载优势。对于数十万甚至数百万行的数据,我们需要更专业的策略。

Redshift官方文档明确指出:“如果COPY命令不是一个选项,并且您需要SQL插入,请尽可能使用多行插入。当您一次只添加一行或几行数据时,数据压缩效率低下。” 这强调了两种核心优化方向:多行SQL插入和更高效的COPY命令。

方法一:优化SQL插入(批量插入)

虽然Redshift推荐使用COPY命令进行大规模数据加载,但在某些场景下,如果数据量不是极端巨大(例如数十万到数百万行),或者不希望引入S3作为中间存储的复杂性,优化的SQL批量插入仍然是一个可行的选择。这里的“优化”指的是使用数据库驱动程序提供的、能够将多行数据打包成单个SQL语句的机制,而不是发送多个独立的INSERT语句。

psycopg2库提供了psycopg2.extras.execute_values函数,它能够高效地构建一个包含多组VALUES的多行INSERT语句,并一次性发送给数据库。这比循环执行单行插入或简单的executemany(在某些情况下可能仍然分解为多个语句)效率更高。

实现示例:使用 psycopg2.extras.execute_values

import pandas as pdimport psycopg2from psycopg2.extras import execute_valuesfrom datetime import date# 假设这是你的DataFrame数据data = [    (69370, 'subject', 'working', 1, date(2023, 12, 15)),    (69370, 'subject', 'scenes', 1, date(2023, 12, 15)),    (69370, 'subject', 'intended', 1, date(2023, 12, 15)),    (69371, 'subject', 'redirected', 1, date(2023, 12, 15)),    (69371, 'subject', 'ge', 2, date(2023, 12, 15)),    (69371, 'subject', 'sensor', 1, date(2023, 12, 15)),    (69371, 'subject', 'flush', 1, date(2023, 12, 15)),    (69371, 'subject', 'motion', 1, date(2023, 12, 15)),    (69371, 'subject', 'led', 1, date(2023, 12, 15)),    (69371, 'subject', 'fixture', 1, date(2023, 12, 15)),    (69371, 'subject', 'contact', 1, date(2023, 12, 15)),    # ... 更多数据,假设有60万条记录]# 为了演示,我们生成更多数据for i in range(100000): # 模拟大量数据    data.append((70000 + i, 'subject_new', f'text_{i}', i % 5 + 1, date(2023, 12, 15)))df = pd.DataFrame(data, columns=['case_id', 'column_name', 'split_text', 'split_text_cnt', 'load_ts'])# Redshift连接参数REDSHIFT_HOST = 'redshift-####-dev.00000.us-east-1.redshift.amazonaws.com'REDSHIFT_DB = '*****'REDSHIFT_USER = '****'REDSHIFT_PASSWORD = '*****'REDSHIFT_PORT = '5439'conn = Nonecur = Nonetry:    conn = psycopg2.connect(        host=REDSHIFT_HOST,        database=REDSHIFT_DB,        user=REDSHIFT_USER,        password=REDSHIFT_PASSWORD,        port=REDSHIFT_PORT    )    conn.autocommit = False # 确保在事务中操作    print("成功连接到 RedShift")    cur = conn.cursor()    table_name = "odey.sfc_ca_sit_di"    columns = "(case_id, column_name, split_text, split_text_cnt, load_ts)"    # 将DataFrame转换为元组列表    # 注意:日期对象需要被psycopg2正确处理,通常直接传递date对象即可    rows_to_insert = [tuple(row) for row in df.itertuples(index=False)]    # 定义批量大小,可以根据网络、数据库性能调整    batch_size = 10000     total_inserted_rows = 0    print(f"开始批量插入 {len(rows_to_insert)} 条记录...")    for i in range(0, len(rows_to_insert), batch_size):        batch = rows_to_insert[i:i + batch_size]        sql = f"INSERT INTO {table_name} {columns} VALUES %s"        execute_values(cur, sql, batch)        total_inserted_rows += len(batch)        print(f"已插入 {total_inserted_rows} / {len(rows_to_insert)} 条记录")    conn.commit()    print(f"所有 {total_inserted_rows} 条记录成功插入 (批量插入方式)")except psycopg2.Error as e:    if conn:        conn.rollback()    print(f"批量插入失败: {e}")except Exception as e:    print(f"发生未知错误: {e}")finally:    if cur:        cur.close()    if conn:        conn.close()    print("数据库连接已关闭。")

注意事项

批量大小(batch_size):选择合适的批量大小至关重要。过小会增加数据库交互次数,过大可能导致单个SQL命令超过Redshift的16MB限制,或消耗过多内存。通常,几千到几万行是一个合理的起点,需要根据实际环境进行测试和调整。事务管理:务必在事务中执行批量插入,即在所有批次完成后统一commit(),如果任何批次失败则rollback()。这能保证数据的一致性。数据类型匹配:确保DataFrame中的数据类型与Redshift目标表的列类型严格匹配,否则可能导致插入失败。

方法二:Redshift COPY 命令(推荐的超高速方案)

对于真正大规模的数据加载(数百万行甚至TB级别),Redshift官方强烈推荐使用COPY命令。COPY命令是Redshift专门为高速数据加载设计的,它能够直接从Amazon S3、Amazon DynamoDB或Amazon EMR等数据源并行加载数据,效率远超任何基于SQL的INSERT方法。

其核心思想是:将DataFrame数据导出为文件(如CSV、Parquet),上传到Amazon S3,然后指示Redshift从S3读取这些文件并加载到表中。

工作流程

DataFrame导出为文件:将Python DataFrame中的数据导出为CSV或Parquet格式的文件。对于大型数据集,建议将数据分割成多个小文件(例如,每个文件1GB左右),以充分利用Redshift的并行加载能力。上传至Amazon S3:使用boto3库将这些文件上传到预配置的S3存储桶。执行Redshift COPY命令:通过psycopg2连接Redshift,并执行COPY SQL命令,指定S3文件的位置、IAM角色、文件格式等参数。

实现示例:使用 Pandas, Boto3, Psycopg2

import pandas as pdimport boto3import ioimport psycopg2from datetime import dateimport os# 假设这是你的DataFrame数据data = [    (69370, 'subject', 'working', 1, date(2023, 12, 15)),    (69370, 'subject', 'scenes', 1, date(2023, 12, 15)),    (69370, 'subject', 'intended', 1, date(2023, 12, 15)),    (69371, 'subject', 'redirected', 1, date(2023, 12, 15)),    (69371, 'subject', 'ge', 2, date(2023, 12, 15)),    (69371, 'subject', 'sensor', 1, date(2023, 12, 15)),    (69371, 'subject', 'flush', 1, date(2023, 12, 15)),    (69371, 'subject', 'motion', 1, date(2023, 12, 15)),    (69371, 'subject', 'led', 1, date(2023, 12, 15)),    (69371, 'subject', 'fixture', 1, date(2023, 12, 15)),    (69371, 'subject', 'contact', 1, date(2023, 12, 15)),    # ... 更多数据]# 为了演示,我们生成更多数据 (约60万条)for i in range(600000):     data.append((70000 + i, 'subject_new', f'text_{i}', i % 5 + 1, date(2023, 12, 15)))df = pd.DataFrame(data, columns=['case_id', 'column_name', 'split_text', 'split_text_cnt', 'load_ts'])# 将日期列转换为字符串,以匹配CSV格式df['load_ts'] = df['load_ts'].astype(str)# S3配置S3_BUCKET_NAME = 'your-s3-bucket-for-redshift-data' # 替换为你的S3桶名S3_KEY_PREFIX = 'redshift_temp_data/' # S3上的路径前缀IAM_ROLE_ARN = 'arn:aws:iam::YOUR_ACCOUNT_ID:role/YourRedshiftIAMRole' # 替换为具有S3读权限的IAM角色ARNAWS_REGION = 'us-east-1' # S3桶和Redshift集群所在的AWS区域# Redshift连接参数REDSHIFT_HOST = 'redshift-####-dev.00000.us-east-1.redshift.amazonaws.com'REDSHIFT_DB = '*****'REDSHIFT_USER = '****'REDSHIFT_PASSWORD = '*****'REDSHIFT_PORT = '5439'conn = Nonecur = Nones3_client = boto3.client('s3', region_name=AWS_REGION)try:    # 1. DataFrame导出为CSV并上传到S3    print("开始将DataFrame导出为CSV并上传到S3...")    file_name = f"data_{pd.Timestamp.now().strftime('%Y%m%d%H%M%S')}.csv"    s3_full_key = S3_KEY_PREFIX + file_name    csv_buffer = io.StringIO()    # 注意:header=False, index=False 是COPY命令的常见要求    df.to_csv(csv_buffer, index=False, header=False, sep=',', encoding='utf-8')     s3_client.put_object

以上就是Redshift大数据量DataFrame高速插入策略的详细内容,更多请关注创想鸟其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/1382660.html

赞 (0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
SQLAlchemy 2.0与Pydantic:实现类型安全的模型转换
上一篇 2025年12月15日 00:25:45
Python中字典赋值与列表操作的陷阱:理解引用与深浅拷贝
下一篇 2025年12月15日 00:25:48

相关推荐

  • Debian Tomcat日志中的慢查询如何优化

    Debian Tomcat日志中的慢查询如何优化Debian Tomcat日志中的慢查询如何优化Debian Tomcat日志中的慢查询如何优化Debian Tomcat日志中的慢查询如何优化

    本文探讨如何在Debian系统上优化Tomcat应用中的数据库慢查询。需要注意的是,Tomcat本身不记录慢查询,而是由数据库(如MySQL)负责。因此,优化过程主要针对数据库层面。 第一步:启用数据库慢查询日志 首先,确保你的数据库已启用慢查询日志记录功能。以MySQL为例,可以通过以下两种方式实…

    2026年9月25日 • 用户投稿
    000
  • Linux sudo日志查看与分析方法

    sudo日志默认存储在/var/log/auth.log(Debian系)或/var/log/secure(RHEL系),可通过grep、tail等命令筛选用户操作、成功命令及失败尝试,日志包含时间、用户、命令等信息;可通过visudo配置独立日志文件及输入输出记录,结合journalctl、awk…

    2026年9月25日
    000
  • Java布尔方法条件逻辑解析与预期行为校正

    Java布尔方法条件逻辑解析与预期行为校正Java布尔方法条件逻辑解析与预期行为校正Java布尔方法条件逻辑解析与预期行为校正Java布尔方法条件逻辑解析与预期行为校正

    本文旨在探讨Java中布尔方法条件表达式的常见误解,通过一个具体的kindaLiked()方法案例,详细分析代码逻辑与预期行为不符的原因。我们将演示如何精确定义条件,确保方法返回结果与业务逻辑一致,并提供示例代码、调试技巧及最佳实践,以帮助开发者编写更准确、可维护的布尔判断逻辑。 理解布尔方法与条件…

    2026年9月25日 • 用户投稿
    100
  • sublime怎么快速查看函数或类列表_sublime结构导航与符号浏览技巧

    sublime怎么快速查看函数或类列表_sublime结构导航与符号浏览技巧sublime怎么快速查看函数或类列表_sublime结构导航与符号浏览技巧sublime怎么快速查看函数或类列表_sublime结构导航与符号浏览技巧sublime怎么快速查看函数或类列表_sublime结构导航与符号浏览技巧

    使用Ctrl+R或Cmd+R打开“前往符号”面板,可快速定位函数和类;通过安装SideBarEnhancements等插件,在侧边栏查看文件符号树;配合LSP插件支持,使用F12实现“转到定义”跨文件跳转;自定义快捷键如Ctrl+Shift+R优化操作效率。 在使用 Sublime Text 编辑代…

    2026年9月25日 • 用户投稿
    300
  • 京东延迟发货赔付怎么操作?店铺如何避免延迟发货?小心!京东48小时未发货就赔30%?手把手教你申请赔偿+紧急报备技巧!

    京东延迟发货赔付怎么操作?店铺如何避免延迟发货?小心!京东48小时未发货就赔30%?手把手教你申请赔偿+紧急报备技巧!京东延迟发货赔付怎么操作?店铺如何避免延迟发货?小心!京东48小时未发货就赔30%?手把手教你申请赔偿+紧急报备技巧!京东延迟发货赔付怎么操作?店铺如何避免延迟发货?小心!京东48小时未发货就赔30%?手把手教你申请赔偿+紧急报备技巧!京东延迟发货赔付怎么操作?店铺如何避免延迟发货?小心!京东48小时未发货就赔30%?手把手教你申请赔偿+紧急报备技巧!

    最新数据显示,京东平台因延迟发货产生的纠纷投诉量同比激增35%,90%的商家因不了解规则面临高额赔付。本文将深度解析2025年最新赔付政策:买家可获订单金额30%的赔偿(最高500元),通过「联系商家→纠纷申请→提交证据」3步即可快速到账;商家则需掌握24小时报备黄金期、三级预警机制(12/6/2小…

    2026年9月25日 • 用户投稿
    100
  • mysql怎么创建新连接

    mysql怎么创建新连接mysql怎么创建新连接mysql怎么创建新连接mysql怎么创建新连接

    要创建新的 MySQL 连接,需要导入 MySQL Connector,然后依次创建连接对象、验证连接、创建游标对象、执行查询、检索结果,最后关闭连接。 如何创建新的 MySQL 连接 若要创建新的 MySQL 连接,可以使用以下步骤: 1. 导入 MySQL Connector 导入 MySQL …

    2026年9月25日 • 用户投稿
    000
  • 关闭Win10这三大新功能:系统重回Win7风

    关闭Win10这三大新功能:系统重回Win7风关闭Win10这三大新功能:系统重回Win7风关闭Win10这三大新功能:系统重回Win7风关闭Win10这三大新功能:系统重回Win7风

    发布超过3年,win10依然未能全面取代win7,反而因各类问题频繁遭到批评。 Softpedia发表文章,指出Win10目前的三项核心功能——Cortana(小娜)、Aciton Centre(操作中心)以及Timeline(时间线),其关闭方式过于繁琐且隐蔽,建议微软提供更加便捷的一键屏蔽选项。…

    2026年9月25日 • 用户投稿
    000
  • 夸克怎么更新到最新版本_夸克App版本检查与升级方法

    夸克怎么更新到最新版本_夸克App版本检查与升级方法夸克怎么更新到最新版本_夸克App版本检查与升级方法夸克怎么更新到最新版本_夸克App版本检查与升级方法夸克怎么更新到最新版本_夸克App版本检查与升级方法

    首先检查应用商店是否有更新,其次在夸克App内“我的-设置-关于夸克”中查看版本并更新,最后可通过官网下载最新安装包手动升级。 如果您尝试在设备上使用夸克App,但发现某些功能无法正常使用或界面显示异常,可能是由于当前版本过旧导致与服务器不兼容。以下是检查并升级夸克App至最新版本的操作步骤: 本文…

    2026年9月25日 • 用户投稿
    200
  • sublime怎么恢复上次打开的文件_sublime自动恢复文件会话设置方法

    sublime怎么恢复上次打开的文件_sublime自动恢复文件会话设置方法sublime怎么恢复上次打开的文件_sublime自动恢复文件会话设置方法sublime怎么恢复上次打开的文件_sublime自动恢复文件会话设置方法sublime怎么恢复上次打开的文件_sublime自动恢复文件会话设置方法

    Sublime Text 能自动恢复文件和布局,需确保设置中”remember_open_files”: true且”hot_exit”: false,正常关闭程序以保存会话,会话文件位于系统指定路径,若丢失可手动重命名备份文件恢复。 Sublime …

    2026年9月25日 • 用户投稿
    200
  • sublime的拼写检查怎么添加自定义词典_sublime拼写检查自定义词典设置

    sublime的拼写检查怎么添加自定义词典_sublime拼写检查自定义词典设置sublime的拼写检查怎么添加自定义词典_sublime拼写检查自定义词典设置sublime的拼写检查怎么添加自定义词典_sublime拼写检查自定义词典设置sublime的拼写检查怎么添加自定义词典_sublime拼写检查自定义词典设置

    Sublime Text拼写检查可通过用户词汇表自定义,首先启用spell_check并设置dictionary路径,然后右键误报词选“Add to Dictionary”或手动编辑User/Dictionary.sublime-settings添加词汇,也可复制.dic文件到User目录创建专用词…

    2026年9月25日 • 用户投稿
    100
  • VBA使用API_04:创建按钮

    VBA使用API_04:创建按钮VBA使用API_04:创建按钮VBA使用API_04:创建按钮VBA使用API_04:创建按钮

    在创建了窗体的基础上,接下来我们将进一步添加一个按钮来增强程序的交互性。按钮是windows系统中预定义的控件,因此无需额外注册,直接使用createwindowex函数即可。在创建窗体之后、显示窗体之前,我们可以插入代码来创建这个按钮。 按钮的父窗口句柄(hWndParent)应当设置为之前创建的…

    2026年9月24日 • 用户投稿
    200
  • 淘宝品牌库申请入口在哪里?需要注意什么?2025最新操作指南

    淘宝品牌库申请入口在哪里?需要注意什么?2025最新操作指南淘宝品牌库申请入口在哪里?需要注意什么?2025最新操作指南淘宝品牌库申请入口在哪里?需要注意什么?2025最新操作指南淘宝品牌库申请入口在哪里?需要注意什么?2025最新操作指南

    在淘宝平台成功入驻品牌库不仅能增强店铺的权威性,还能享受官方流量倾斜与营销资源支持。然而,大多数商家往往因找不到申请入口或材料反复被驳回而止步不前。本文将全面解析pc端与手机端的品牌库申请路径,并分享7条提高审核通过率的关键技巧。 一、淘宝品牌库申请入口详细指引 1. PC端操作路径 登录【淘宝商家…

    2026年9月24日 • 用户投稿
    100
  • 如何在Java中使用Collections.shuffle打乱列表

    使用Collections.shuffle()可随机打乱列表元素,但列表必须为可变类型。Arrays.asList()返回固定列表,直接使用会抛出UnsupportedOperationException;正确做法是将其复制到ArrayList等可修改列表中再调用shuffle。基本用法示例如Lis…

    2026年9月24日
    300
  • Java双向链表:实现高效的按索引删除节点操作

    Java双向链表:实现高效的按索引删除节点操作Java双向链表:实现高效的按索引删除节点操作Java双向链表:实现高效的按索引删除节点操作Java双向链表:实现高效的按索引删除节点操作

    本文详细讲解了如何在Java中为双向链表实现按索引删除节点的操作。教程涵盖了泛型设计、节点结构、参数校验、以及针对头节点、尾节点和中间节点的删除逻辑,并强调了维护链表head、tail和size等状态的准确性,确保了删除操作的健壮性和正确性。 1. 双向链表节点与泛型设计 在实现双向链表时,为了提高…

    2026年9月24日 • 用户投稿
    200
  • MAC怎么查看电脑配置信息_Mac硬件配置与系统信息查看方法

    MAC怎么查看电脑配置信息_Mac硬件配置与系统信息查看方法MAC怎么查看电脑配置信息_Mac硬件配置与系统信息查看方法MAC怎么查看电脑配置信息_Mac硬件配置与系统信息查看方法MAC怎么查看电脑配置信息_Mac硬件配置与系统信息查看方法

    首先通过“关于本机”查看Mac基础配置,包括系统版本、处理器和内存;再进入“系统信息”获取硬件、网络等详细数据;最后可用终端命令精准查询序列号、芯片架构及系统版本。 如果您想了解您的Mac电脑的具体硬件配置和系统信息,可以通过多种内置工具快速获取。这些信息包括处理器型号、内存大小、存储容量、显卡详情…

    2026年9月24日 • 用户投稿
    100
  • Word转PDF:简单几步完成转换

    Word转PDF:简单几步完成转换Word转PDF:简单几步完成转换Word转PDF:简单几步完成转换Word转PDF:简单几步完成转换

    本文介绍几种实用的word转pdf方法,操作简单高效,助你轻松完成文件格式转换。 1、 在线转换无需下载软件,方便快捷,具体操作请见图片链接。 2、 亲测好用的在线转换工具推荐 3、 该地址还支持PHP转Word、Excel转PDF、PPT转PDF功能,本人未实际测试,感兴趣者可自行尝试验证效果。 …

    2026年9月24日 • 用户投稿
    200
  • mysql怎么使用数据库命令

    mysql怎么使用数据库命令mysql怎么使用数据库命令mysql怎么使用数据库命令mysql怎么使用数据库命令

    MySQL 命令包括:1. 数据操作语言(DML):SELECT、INSERT、UPDATE、DELETE;2. 数据定义语言(DDL):CREATE、ALTER、DROP;3. 数据控制语言(DCL):GRANT、REVOKE;4. 事务控制:BEGIN、COMMIT、ROLLBACK;5. 实用…

    2026年9月24日 • 用户投稿
    100
  • 抖音不是好友会显示已读吗?抖音不是好友显示好友

    抖音不是好友会显示已读吗?抖音不是好友显示好友抖音不是好友会显示已读吗?抖音不是好友显示好友抖音不是好友会显示已读吗?抖音不是好友显示好友抖音不是好友会显示已读吗?抖音不是好友显示好友

    抖音,作为一款风靡全球的短视频社交平台,不仅让我们足不出户便能领略世界的精彩,也为日常生活增添了无数乐趣。在使用过程中,你是否也曾好奇过:如果和对方不是好友,抖音消息会显示“已读”吗?今天,我们就来深入探讨这个问题,揭开抖音私信功能背后的真相。 一、抖音非好友聊天会显示已读吗? 答案是:不会显示已读…

    2026年9月24日 • 用户投稿
    000
  • VS2010工具箱控件不显示

    1、 首先关闭所有正在运行的Visual Studio 2010项目。 2、 打开项目后,点击顶部“视图”菜单,选择“工具箱”,在工具箱面板中右键单击,然后选择“重置工具箱”。 3、 查看工具箱中的控件是否已正常显示,如果问题依旧存在,请继续执行下一步。 4、 启用系统文件夹选项以显示隐藏的项目。进…

    2026年9月24日
    000
  • Java中实现跨类和函数共享变量的策略

    Java中实现跨类和函数共享变量的策略Java中实现跨类和函数共享变量的策略Java中实现跨类和函数共享变量的策略Java中实现跨类和函数共享变量的策略

    本文深入探讨了在Java中实现跨类和函数共享变量的有效策略。通过利用public static关键字,可以在不创建对象实例的情况下,使变量在整个应用程序中具备全局可访问性。文章将通过示例代码演示其使用方法,并提供关于此模式的注意事项与最佳实践,以帮助开发者理解其优势和潜在风险。 核心概念:publi…

    2026年9月24日 • 用户投稿
    100

发表回复

登录后才能评论
关注微信