diff --git a/TOC-tidb-cloud-lake.md b/TOC-tidb-cloud-lake.md new file mode 100644 index 0000000000000..741f1b124609d --- /dev/null +++ b/TOC-tidb-cloud-lake.md @@ -0,0 +1,1243 @@ + + + +# 目录 + +## 开始使用 + +- [概览](/tidb-cloud-lake/lake-overview.md) +- [快速入门](/tidb-cloud-lake/lake-quick-start.md) + +## 指南 + +- 连接 + - [概览](/tidb-cloud-lake/guides/connection-overview.md) + - SQL 客户端 + - [LakeSQL](/tidb-cloud-lake/guides/connect-using-lakesql.md) + - 驱动 + - [概览](/tidb-cloud-lake/guides/driver-overview.md) + - [Golang](/tidb-cloud-lake/guides/connect-using-golang.md) + - [Java](/tidb-cloud-lake/guides/connect-using-java.md) + - [Node.js](/tidb-cloud-lake/guides/connect-using-node-js.md) + - [Python](/tidb-cloud-lake/guides/connect-using-python.md) + - [Rust](/tidb-cloud-lake/guides/connect-using-rust.md) + - AI 工具 + - [外部 AI 函数](/tidb-cloud-lake/guides/external-ai-functions.md) + - [MCP 客户端集成](/tidb-cloud-lake/guides/mcp-client-integration.md) + - [MCP 服务器](/tidb-cloud-lake/guides/mcp-server.md) + - 可视化 + - [Tableau](/tidb-cloud-lake/guides/tableau.md) + - [Deepnote](/tidb-cloud-lake/guides/deepnote.md) + - [Jupyter Notebook](/tidb-cloud-lake/guides/jupyter-notebook.md) + - [Superset](/tidb-cloud-lake/guides/superset.md) + - 网络访问 + - [使用 AWS PrivateLink 连接](/tidb-cloud-lake/guides/connect-with-aws-privatelink.md) + - [使用 Alibaba Cloud PrivateLink 连接](/tidb-cloud-lake/guides/connect-with-alibaba-cloud-privatelink.md) +- 管理资源 + - [仪表板](/tidb-cloud-lake/guides/dashboards.md) + - [任务流 (Task Flow)](/tidb-cloud-lake/guides/task-flow.md) + - [计算集群](/tidb-cloud-lake/guides/warehouse.md) + - [工作区](/tidb-cloud-lake/guides/worksheet.md) +- 数据集成 + - [概览](/tidb-cloud-lake/guides/data-integration-overview.md) + - 数据源 + - [概览](/tidb-cloud-lake/guides/data-sources.md) + - [Amazon S3 - 凭证](/tidb-cloud-lake/guides/aws-credentials.md) + - [Amazon SQS (S3) - IAM 角色](/tidb-cloud-lake/guides/amazon-sqs-s3-iam-role.md) ![PREVIEW](/media/tidb-cloud/blank_transparent_placeholder.png) + - [MySQL - 凭证](/tidb-cloud-lake/guides/mysql-credentials.md) + - [PostgreSQL - 凭证](/tidb-cloud-lake/guides/postgresql-credentials.md) + - [FeiShuBot](/tidb-cloud-lake/guides/feishubot.md) + - [Kafka - 凭证](/tidb-cloud-lake/guides/kafka-credentials.md) ![PREVIEW](/media/tidb-cloud/blank_transparent_placeholder.png) + - 集成任务 + - [概览](/tidb-cloud-lake/guides/integration-tasks.md) + - [任务管理](/tidb-cloud-lake/guides/task-management.md) + - [Amazon S3 集成任务](/tidb-cloud-lake/guides/integrate-with-amazon-s3.md) + - [Amazon SQS (S3) 集成任务](/tidb-cloud-lake/guides/integrate-with-amazon-sqs-s3.md) ![PREVIEW](/media/tidb-cloud/blank_transparent_placeholder.png) + - [MySQL 集成任务](/tidb-cloud-lake/guides/integrate-with-mysql.md) + - [PostgreSQL 集成任务](/tidb-cloud-lake/guides/integrate-with-postgresql.md) + - [Kafka Consumer 集成任务](/tidb-cloud-lake/guides/integrate-with-kafka.md) ![PREVIEW](/media/tidb-cloud/blank_transparent_placeholder.png) +- 加载数据 + - 使用 Stage + - [Stage 概述](/tidb-cloud-lake/guides/stage-overview.md) + - [上传到 Stage](/tidb-cloud-lake/guides/upload-to-stage.md) + - 从文件加载 + - [概览](/tidb-cloud-lake/guides/load-from-files.md) + - [从 Stage 加载](/tidb-cloud-lake/guides/load-from-stage.md) + - [从存储桶加载](/tidb-cloud-lake/guides/load-from-bucket.md) + - [从本地文件加载](/tidb-cloud-lake/guides/load-from-local-file.md) + - [从远程文件加载](/tidb-cloud-lake/guides/load-from-remote-file.md) + - 使用平台加载 + - [使用 dbt 加载](/tidb-cloud-lake/guides/load-with-dbt.md) + - 加载半结构化数据 + - [概览](/tidb-cloud-lake/guides/load-semi-structured-data.md) + - [加载 Parquet](/tidb-cloud-lake/guides/load-parquet.md) + - [加载 CSV](/tidb-cloud-lake/guides/load-csv.md) + - [加载 TSV](/tidb-cloud-lake/guides/load-tsv.md) + - [加载 NDJSON](/tidb-cloud-lake/guides/load-ndjson.md) + - [加载 ORC](/tidb-cloud-lake/guides/load-orc.md) + - [加载 Avro](/tidb-cloud-lake/guides/load-avro.md) + - 查询与转换 + - [概览](/tidb-cloud-lake/guides/query-stage.md) + - [查询 Parquet 文件](/tidb-cloud-lake/guides/query-parquet-files-in-stage.md) + - [查询 CSV 文件](/tidb-cloud-lake/guides/query-csv-files-in-stage.md) + - [查询 TSV 文件](/tidb-cloud-lake/guides/query-tsv-files-in-stage.md) + - [查询 NDJSON 文件](/tidb-cloud-lake/guides/query-ndjson-files-in-stage.md) + - [查询 Avro 文件](/tidb-cloud-lake/guides/query-avro-files-in-stage.md) + - [查询暂存的 ORC 文件](/tidb-cloud-lake/guides/query-staged-orc-files-in-stage.md) + - [加载时转换数据](/tidb-cloud-lake/guides/transform-data-on-load.md) + - [Schema Evolution](/tidb-cloud-lake/guides/schema-evolution.md) + - 持续数据管道 + - [概览](/tidb-cloud-lake/guides/continuous-data-pipelines.md) + - [通过 Streams 跟踪和转换数据](/tidb-cloud-lake/guides/track-and-transform-data-via-streams.md) + - [使用任务自动化数据加载](/tidb-cloud-lake/guides/automate-data-loading-with-tasks.md) +- 卸载数据 + - [概览](/tidb-cloud-lake/guides/unload-data.md) + - [卸载 Parquet 文件](/tidb-cloud-lake/guides/unload-parquet-file.md) + - [卸载 CSV 文件](/tidb-cloud-lake/guides/unload-csv-file.md) + - [卸载 TSV 文件](/tidb-cloud-lake/guides/unload-tsv-file.md) + - [卸载 NDJSON 文件](/tidb-cloud-lake/guides/unload-ndjson-file.md) + - [卸载 Lance 数据集](/tidb-cloud-lake/guides/unload-lance-dataset.md) +- 多模态数据分析 + - [概览](/tidb-cloud-lake/guides/multimodal-data-analytics.md) + - [SQL 分析](/tidb-cloud-lake/guides/sql-analytics.md) + - [JSON 与搜索](/tidb-cloud-lake/guides/json-search.md) + - [向量搜索](/tidb-cloud-lake/guides/vector-search-guide.md) + - [地理空间分析](/tidb-cloud-lake/guides/geo-analytics.md) + - [Lakehouse ETL](/tidb-cloud-lake/guides/lakehouse-etl.md) +- 性能优化 + - [概览](/tidb-cloud-lake/guides/performance-optimization.md) + - [Cluster Key](/tidb-cloud-lake/guides/cluster-key-performance.md) + - [虚拟列](/tidb-cloud-lake/guides/virtual-column.md) + - [聚合索引](/tidb-cloud-lake/guides/aggregating-index.md) + - [全文索引](/tidb-cloud-lake/guides/full-text-index.md) + - [Ngram 索引](/tidb-cloud-lake/guides/ngram-index.md) + - [查询结果缓存](/tidb-cloud-lake/guides/query-result-cache.md) +- 安全性与可靠性 + - [概览](/tidb-cloud-lake/guides/security-reliability.md) + - 访问控制 + - [概览](/tidb-cloud-lake/guides/access-control.md) + - [权限](/tidb-cloud-lake/guides/privileges.md) + - [角色](/tidb-cloud-lake/guides/roles.md) + - [所有权](/tidb-cloud-lake/guides/ownership.md) + - 数据保护策略 + - [概览](/tidb-cloud-lake/guides/data-protection-policies.md) + - [脱敏策略](/tidb-cloud-lake/guides/masking-policy.md) + - [行访问策略](/tidb-cloud-lake/guides/row-access-policy.md) + - [审计追踪](/tidb-cloud-lake/guides/audit-trail.md) + - [网络策略](/tidb-cloud-lake/guides/network-policy.md) + - [密码策略](/tidb-cloud-lake/guides/password-policy.md) + - [使用 AWS IAM Role 进行认证](/tidb-cloud-lake/guides/authenticate-with-aws-iam-role.md) + - [合规与安全](/tidb-cloud-lake/guides/compliance-security.md) + - [Fail-Safe](/tidb-cloud-lake/guides/fail-safe.md) + - [从操作错误中恢复](/tidb-cloud-lake/guides/recovery-from-operational-errors.md) +- 管理 + - [AI 驱动功能](/tidb-cloud-lake/guides/ai-powered-features.md) + - [管理成本](/tidb-cloud-lake/guides/manage-costs.md) + - [监控使用情况](/tidb-cloud-lake/guides/monitor-usage.md) + - [数据生命周期](/tidb-cloud-lake/guides/data-lifecycle.md) + - [数据血缘](/tidb-cloud-lake/guides/data-lineage.md) + - [数据保护](/tidb-cloud-lake/guides/data-protection.md) + - [数据清理与回收](/tidb-cloud-lake/guides/data-purge-and-recycle.md) +- [价格与计费](/tidb-cloud-lake/guides/pricing-billing.md) +- [故障排查](/tidb-cloud-lake/guides/troubleshooting.md) + +## 教程 + +- 导入与流式处理数据 + - [使用 Vector 导入 JSON 日志(Cloud)](/tidb-cloud-lake/tutorials/ingest-json-logs-with-vector-cloud.md) +- 迁移数据 + - [从 Snowflake 迁移](/tidb-cloud-lake/tutorials/migrate-from-snowflake.md) + +## 参考 + +- SQL 参考 + - [概览](/tidb-cloud-lake/sql/sql-statements-overview.md) + - SQL 通用 + - 数据类型 + - [概览](/tidb-cloud-lake/sql/data-types.md) + - [数组](/tidb-cloud-lake/sql/array.md) + - [Binary](/tidb-cloud-lake/sql/binary.md) + - [Bitmap](/tidb-cloud-lake/sql/bitmap.md) + - [Boolean](/tidb-cloud-lake/sql/boolean.md) + - [日期与时间](/tidb-cloud-lake/sql/date-time.md) + - [Decimal](/tidb-cloud-lake/sql/decimal.md) + - [Geospatial](/tidb-cloud-lake/sql/geospatial.md) + - [Interval](/tidb-cloud-lake/sql/interval.md) + - [Map](/tidb-cloud-lake/sql/map.md) + - [Numeric](/tidb-cloud-lake/sql/numeric.md) + - [字符串](/tidb-cloud-lake/sql/string.md) + - [Tuple](/tidb-cloud-lake/sql/tuple.md) + - [Variant](/tidb-cloud-lake/sql/variant.md) + - [Vector](/tidb-cloud-lake/sql/vector.md) + - Information Schema + - [Information_Schema Tables](/tidb-cloud-lake/sql/information-schema-tables-overview.md) + - [information_schema.columns](/tidb-cloud-lake/sql/information-schema-columns-sql.md) + - [information_schema.keywords](/tidb-cloud-lake/sql/information-schema-keywords-sql.md) + - [information_schema.schemata](/tidb-cloud-lake/sql/information-schema-schemata-sql.md) + - [information_schema.tables](/tidb-cloud-lake/sql/information-schema-tables-sql.md) + - [information_schema.views](/tidb-cloud-lake/sql/information-schema-views-sql.md) + - 表引擎 + - [概览](/tidb-cloud-lake/sql/table-engines.md) + - [Fuse Engine 表](/tidb-cloud-lake/sql/fuse-engine-tables.md) + - [Apache Iceberg™ Tables](/tidb-cloud-lake/sql/apache-icebergtm-tables.md) + - [Apache Hive Tables](/tidb-cloud-lake/sql/apache-hive-tables.md) + - [Delta Lake Engine](/tidb-cloud-lake/sql/delta-lake-engine.md) + - 系统表 + - [概览](/tidb-cloud-lake/sql/system-tables.md) + - [system.build_options](/tidb-cloud-lake/sql/system-build-options.md) + - [system.caches](/tidb-cloud-lake/sql/system-caches.md) + - [system.clusters](/tidb-cloud-lake/sql/system-clusters.md) + - [system.columns](/tidb-cloud-lake/sql/system-columns.md) + - [system.contributors](/tidb-cloud-lake/sql/system-contributors.md) + - [system.copy_history](/tidb-cloud-lake/sql/system-copy-history.md) + - [system.credits](/tidb-cloud-lake/sql/system-credits.md) + - [system.databases](/tidb-cloud-lake/sql/system-databases.md) + - [system.databases_with_history](/tidb-cloud-lake/sql/system-databases-with-history.md) + - [system.functions](/tidb-cloud-lake/sql/system-functions.md) + - [system.indexes](/tidb-cloud-lake/sql/system-indexes.md) + - [system.locks](/tidb-cloud-lake/sql/system-locks.md) + - [system.metrics](/tidb-cloud-lake/sql/system-metrics.md) + - [system.numbers](/tidb-cloud-lake/sql/system-numbers.md) + - [system.query_cache](/tidb-cloud-lake/sql/system-query-cache.md) + - [system.query_log](/tidb-cloud-lake/sql/system-query-log.md) + - [system.settings](/tidb-cloud-lake/sql/system-settings.md) + - [system.streams](/tidb-cloud-lake/sql/system-streams.md) + - [system.table_functions](/tidb-cloud-lake/sql/system-table-functions.md) + - [system.tables](/tidb-cloud-lake/sql/system-tables-sql.md) + - [system.tables_with_history](/tidb-cloud-lake/sql/system-tables-with-history.md) + - [system.temp_files](/tidb-cloud-lake/sql/system-temp-files.md) + - [system.temporary_tables](/tidb-cloud-lake/sql/system-temporary-tables.md) + - [system.user_functions](/tidb-cloud-lake/sql/system-user-functions.md) + - [system.views](/tidb-cloud-lake/sql/system-views.md) + - [system.virtual_columns](/tidb-cloud-lake/sql/system-virtual-columns.md) + - 系统历史表 + - [system_history.access_history](/tidb-cloud-lake/sql/system-history-access-history.md) + - [system_history.log_history](/tidb-cloud-lake/sql/system-history-log-history.md) + - [system_history.login_history](/tidb-cloud-lake/sql/system-history-login-history.md) + - [system_history.profile_history](/tidb-cloud-lake/sql/system-history-profile-history.md) + - [system_history.query_history](/tidb-cloud-lake/sql/system-history-query-history.md) + - [SQL 标识符](/tidb-cloud-lake/sql/sql-identifiers.md) + - [输入与输出文件格式](/tidb-cloud-lake/sql/input-output-file-formats.md) + - [连接参数](/tidb-cloud-lake/sql/connection-parameters.md) + - [SQL 方言与一致性](/tidb-cloud-lake/sql/sql-dialects-conformance.md) + - SQL 语句 + - [概览](/tidb-cloud-lake/sql/sql-statements-reference.md) + - DDL 命令 + - [DDL 概览](/tidb-cloud-lake/sql/ddl.md) + - 数据库 + - [概览](/tidb-cloud-lake/sql/ddl-database-overview.md) + - [CREATE DATABASE](/tidb-cloud-lake/sql/create-database.md) + - [SHOW CREATE DATABASE](/tidb-cloud-lake/sql/show-create-database.md) + - [USE DATABASE](/tidb-cloud-lake/sql/use-database.md) + - [ALTER DATABASE](/tidb-cloud-lake/sql/alter-database.md) + - [SHOW DATABASES](/tidb-cloud-lake/sql/show-databases.md) + - [DROP DATABASE](/tidb-cloud-lake/sql/drop-database.md) + - [SHOW DROP DATABASES](/tidb-cloud-lake/sql/show-drop-databases.md) + - [UNDROP DATABASE](/tidb-cloud-lake/sql/undrop-database.md) + - 表 + - [概览](/tidb-cloud-lake/sql/ddl-table-overview.md) + - [CREATE TABLE](/tidb-cloud-lake/sql/create-table.md) + - [CREATE EXTERNAL TABLE](/tidb-cloud-lake/sql/create-external-table.md) + - [CREATE TEMP TABLE](/tidb-cloud-lake/sql/create-temp-table.md) + - [CREATE TRANSIENT TABLE](/tidb-cloud-lake/sql/create-transient-table.md) + - [DROP TABLE](/tidb-cloud-lake/sql/drop-table.md) + - [UNDROP TABLE](/tidb-cloud-lake/sql/undrop-table.md) + - [RENAME TABLE](/tidb-cloud-lake/sql/rename-table.md) + - [TRUNCATE TABLE](/tidb-cloud-lake/sql/truncate-table.md) + - [DESCRIBE TABLE](/tidb-cloud-lake/sql/describe-table.md) + - [OPTIMIZE TABLE](/tidb-cloud-lake/sql/optimize-table.md) + - [FLASHBACK TABLE](/tidb-cloud-lake/sql/flashback-table.md) + - [ALTER TABLE](/tidb-cloud-lake/sql/alter-table.md) + - [VACUUM DROP TABLE](/tidb-cloud-lake/sql/vacuum-drop-table.md) + - [VACUUM TABLE](/tidb-cloud-lake/sql/vacuum-table.md) + - [ATTACH TABLE](/tidb-cloud-lake/sql/attach-table.md) + - [SHOW CREATE TABLE](/tidb-cloud-lake/sql/show-create-table.md) + - [SHOW DROP TABLES](/tidb-cloud-lake/sql/show-drop-tables.md) + - [SHOW FIELDS](/tidb-cloud-lake/sql/show-fields.md) + - [SHOW COLUMNS](/tidb-cloud-lake/sql/show-columns.md) + - [SHOW STATISTICS](/tidb-cloud-lake/sql/show-statistics.md) + - [SHOW TABLE STATUS](/tidb-cloud-lake/sql/show-table-status.md) + - [SHOW TABLES](/tidb-cloud-lake/sql/show-tables.md) + - 视图 + - [概览](/tidb-cloud-lake/sql/ddl-view-overview.md) + - [CREATE VIEW](/tidb-cloud-lake/sql/create-view.md) + - [ALTER VIEW](/tidb-cloud-lake/sql/alter-view.md) + - [DESC VIEW](/tidb-cloud-lake/sql/desc-view.md) + - [SHOW VIEWS](/tidb-cloud-lake/sql/show-views.md) + - [DROP VIEW](/tidb-cloud-lake/sql/drop-view.md) + - [物化视图](/tidb-cloud-lake/sql/materialized-view.md) + - [REFRESH LINEAGE](/tidb-cloud-lake/sql/refresh-lineage.md) + - 用户和角色 + - [概览](/tidb-cloud-lake/sql/user-role.md) + - [CREATE USER](/tidb-cloud-lake/sql/create-user.md) + - [DESC USER](/tidb-cloud-lake/sql/desc-user.md) + - [DROP USER](/tidb-cloud-lake/sql/drop-user.md) + - [SHOW USERS](/tidb-cloud-lake/sql/show-users.md) + - [ALTER USER](/tidb-cloud-lake/sql/alter-user.md) + - [CREATE ROLE](/tidb-cloud-lake/sql/create-role.md) + - [SET SECONDARY ROLES](/tidb-cloud-lake/sql/set-secondary-roles.md) + - [SET ROLE](/tidb-cloud-lake/sql/set-role.md) + - [SHOW ROLES](/tidb-cloud-lake/sql/show-roles.md) + - [DROP ROLE](/tidb-cloud-lake/sql/drop-role.md) + - [GRANT](/tidb-cloud-lake/sql/grant.md) + - [REVOKE](/tidb-cloud-lake/sql/revoke.md) + - [SHOW GRANTS](/tidb-cloud-lake/sql/show-grants.md) + - Stage + - [概览](/tidb-cloud-lake/sql/stage.md) + - [CREATE STAGE](/tidb-cloud-lake/sql/create-stage.md) + - [DROP STAGE](/tidb-cloud-lake/sql/drop-stage.md) + - [DESC STAGE](/tidb-cloud-lake/sql/desc-stage.md) + - [LIST STAGE FILES](/tidb-cloud-lake/sql/list-stage-files.md) + - [REMOVE STAGE FILES](/tidb-cloud-lake/sql/remove-stage-files.md) + - [SHOW STAGES](/tidb-cloud-lake/sql/show-stages.md) + - [PRESIGN](/tidb-cloud-lake/sql/presign.md) + - 序列 + - [概览](/tidb-cloud-lake/sql/sequence.md) + - [CREATE SEQUENCE](/tidb-cloud-lake/sql/create-sequence.md) + - [DESC SEQUENCE](/tidb-cloud-lake/sql/desc-sequence.md) + - [DROP SEQUENCE](/tidb-cloud-lake/sql/drop-sequence.md) + - [SHOW SEQUENCES](/tidb-cloud-lake/sql/show-sequences.md) + - Stream + - [概览](/tidb-cloud-lake/sql/stream.md) + - [CREATE STREAM](/tidb-cloud-lake/sql/create-stream.md) + - [DESC STREAM](/tidb-cloud-lake/sql/desc-stream.md) + - [DROP STREAM](/tidb-cloud-lake/sql/drop-stream.md) + - [SHOW STREAMS](/tidb-cloud-lake/sql/show-streams.md) + - 任务 + - [概览](/tidb-cloud-lake/sql/task.md) + - [CREATE TASK](/tidb-cloud-lake/sql/create-task.md) + - [ALTER TASK](/tidb-cloud-lake/sql/alter-task.md) + - [DROP TASK](/tidb-cloud-lake/sql/drop-task.md) + - [EXECUTE TASK](/tidb-cloud-lake/sql/execute-task.md) + - [SHOW TASKS](/tidb-cloud-lake/sql/show-tasks.md) + - [TASK ERROR NOTIFICATION PAYLOAD](/tidb-cloud-lake/sql/task-error-notification-payload.md) + - 通知 + - [概览](/tidb-cloud-lake/sql/notification.md) + - [CREATE NOTIFICATION INTEGRATION](/tidb-cloud-lake/sql/create-notification-integration.md) + - [ALTER NOTIFICATION INTEGRATION](/tidb-cloud-lake/sql/alter-notification-integration.md) + - [DROP NOTIFICATION INTEGRATION](/tidb-cloud-lake/sql/drop-notification-integration.md) + - [DESCRIBE NOTIFICATION INTEGRATION](/tidb-cloud-lake/sql/describe-notification-integration.md) + - 标签 + - [概览](/tidb-cloud-lake/sql/tag-overview.md) + - [CREATE TAG](/tidb-cloud-lake/sql/create-tag.md) + - [DROP TAG](/tidb-cloud-lake/sql/drop-tag.md) + - [SHOW TAGS](/tidb-cloud-lake/sql/show-tags.md) + - [SET TAG](/tidb-cloud-lake/sql/set-tag.md) + - 连接 + - [概览](/tidb-cloud-lake/sql/connection.md) + - [CREATE CONNECTION](/tidb-cloud-lake/sql/create-connection.md) + - [DESC CONNECTION](/tidb-cloud-lake/sql/desc-connection.md) + - [DROP CONNECTION](/tidb-cloud-lake/sql/drop-connection.md) + - [SHOW CONNECTIONS](/tidb-cloud-lake/sql/show-connections.md) + - Catalog + - [概览](/tidb-cloud-lake/sql/catalog.md) + - [SHOW CATALOGS](/tidb-cloud-lake/sql/show-catalogs.md) + - [SHOW CREATE CATALOG](/tidb-cloud-lake/sql/show-create-catalog.md) + - 文件格式 + - [概览](/tidb-cloud-lake/sql/file-format.md) + - [CREATE FILE FORMAT](/tidb-cloud-lake/sql/create-file-format.md) + - [DROP FILE FORMAT](/tidb-cloud-lake/sql/drop-file-format.md) + - [SHOW FILE FORMATS](/tidb-cloud-lake/sql/show-file-formats.md) + - Cluster Key + - [ALTER CLUSTER KEY](/tidb-cloud-lake/sql/alter-cluster-key.md) + - [DROP CLUSTER KEY](/tidb-cloud-lake/sql/drop-cluster-key.md) + - [RECLUSTER TABLE](/tidb-cloud-lake/sql/recluster-table.md) + - [SET CLUSTER KEY](/tidb-cloud-lake/sql/set-cluster-key.md) + - [Cluster Key](/tidb-cloud-lake/sql/cluster-key.md) + - 聚合索引 + - [CREATE AGGREGATING INDEX](/tidb-cloud-lake/sql/create-aggregating-index.md) + - [DROP AGGREGATING INDEX](/tidb-cloud-lake/sql/drop-aggregating-index.md) + - [聚合索引](/tidb-cloud-lake/sql/aggregating-index-sql.md) + - [REFRESH AGGREGATING INDEX](/tidb-cloud-lake/sql/refresh-aggregating-index.md) + - 倒排索引 + - [CREATE INVERTED INDEX](/tidb-cloud-lake/sql/create-inverted-index.md) + - [DROP INVERTED INDEX](/tidb-cloud-lake/sql/drop-inverted-index.md) + - [倒排索引](/tidb-cloud-lake/sql/inverted-index.md) + - [REFRESH INVERTED INDEX](/tidb-cloud-lake/sql/refresh-inverted-index.md) + - Ngram Index + - [CREATE NGRAM INDEX](/tidb-cloud-lake/sql/create-ngram-index.md) + - [DROP NGRAM INDEX](/tidb-cloud-lake/sql/drop-ngram-index.md) + - [Ngram 索引](/tidb-cloud-lake/sql/ngram-index-sql.md) + - [REFRESH NGRAM INDEX](/tidb-cloud-lake/sql/refresh-ngram-index.md) + - 空间索引 + - [空间索引](/tidb-cloud-lake/sql/spatial-index-overview.md) + - [CREATE SPATIAL INDEX](/tidb-cloud-lake/sql/create-spatial-index.md) + - [REFRESH SPATIAL INDEX](/tidb-cloud-lake/sql/refresh-spatial-index.md) + - [DROP SPATIAL INDEX](/tidb-cloud-lake/sql/drop-spatial-index.md) + - Vector Index + - [CREATE VECTOR INDEX](/tidb-cloud-lake/sql/create-vector-index.md) + - [DROP VECTOR INDEX](/tidb-cloud-lake/sql/drop-vector-index.md) + - [向量索引](/tidb-cloud-lake/sql/vector-index.md) + - [REFRESH VECTOR INDEX](/tidb-cloud-lake/sql/refresh-vector-index.md) + - Virtual Column + - [虚拟列](/tidb-cloud-lake/sql/virtual-column-overview.md) + - [REFRESH VIRTUAL COLUMN](/tidb-cloud-lake/sql/refresh-virtual-column.md) + - [SHOW VIRTUAL COLUMNS](/tidb-cloud-lake/sql/show-virtual-columns.md) + - 用户定义函数 + - [用户定义函数](/tidb-cloud-lake/sql/user-defined-function.md) + - [选择用户定义函数类型](/tidb-cloud-lake/guides/choose-a-udf-type.md) + - [ALTER FUNCTION](/tidb-cloud-lake/sql/alter-function.md) + - [CREATE AGGREGATE FUNCTION](/tidb-cloud-lake/sql/create-aggregate-function.md) + - [CREATE SCALAR FUNCTION](/tidb-cloud-lake/sql/create-scalar-function.md) + - [CREATE TABLE FUNCTION](/tidb-cloud-lake/sql/create-table-function.md) + - [DROP FUNCTION](/tidb-cloud-lake/sql/drop-function.md) + - [SHOW USER FUNCTIONS](/tidb-cloud-lake/sql/show-user-functions.md) + - 外部函数 + - [外部函数](/tidb-cloud-lake/sql/external-function.md) + - [CREATE FUNCTION](/tidb-cloud-lake/sql/create-function.md) + - [ALTER FUNCTION](/tidb-cloud-lake/sql/alter-function-sql.md) + - [DROP FUNCTION](/tidb-cloud-lake/sql/drop-function-sql.md) + - 脱敏策略 + - [概览](/tidb-cloud-lake/sql/masking-policy-sql.md) + - [CREATE MASKING POLICY](/tidb-cloud-lake/sql/create-masking-policy.md) + - [DESC MASKING POLICY](/tidb-cloud-lake/sql/desc-masking-policy.md) + - [DROP MASKING POLICY](/tidb-cloud-lake/sql/drop-masking-policy.md) + - 网络策略 + - [ALTER NETWORK POLICY](/tidb-cloud-lake/sql/alter-network-policy.md) + - [CREATE NETWORK POLICY](/tidb-cloud-lake/sql/create-network-policy.md) + - [DESC NETWORK POLICY](/tidb-cloud-lake/sql/desc-network-policy.md) + - [DROP NETWORK POLICY](/tidb-cloud-lake/sql/drop-network-policy.md) + - [SHOW NETWORK POLICIES](/tidb-cloud-lake/sql/show-network-policies.md) + - [网络策略](/tidb-cloud-lake/sql/network-policy-sql.md) + - 密码策略 + - [ALTER PASSWORD POLICY](/tidb-cloud-lake/sql/alter-password-policy.md) + - [CREATE PASSWORD POLICY](/tidb-cloud-lake/sql/create-password-policy.md) + - [DESC PASSWORD POLICY](/tidb-cloud-lake/sql/desc-password-policy.md) + - [DROP PASSWORD POLICY](/tidb-cloud-lake/sql/drop-password-policy.md) + - [密码策略](/tidb-cloud-lake/sql/password-policy-sql.md) + - [SHOW PASSWORD POLICIES](/tidb-cloud-lake/sql/show-password-policies.md) + - 行访问策略 + - [概览](/tidb-cloud-lake/sql/row-access-policy-overview.md) + - [CREATE ROW ACCESS POLICY](/tidb-cloud-lake/sql/create-row-access-policy.md) + - [DESC ROW ACCESS POLICY](/tidb-cloud-lake/sql/desc-row-access-policy.md) + - [DROP ROW ACCESS POLICY](/tidb-cloud-lake/sql/drop-row-access-policy.md) + - 字典 + - [概览](/tidb-cloud-lake/sql/dictionary.md) + - [CREATE DICTIONARY](/tidb-cloud-lake/sql/create-dictionary.md) + - [DROP DICTIONARY](/tidb-cloud-lake/sql/drop-dictionary.md) + - [RENAME DICTIONARY](/tidb-cloud-lake/sql/rename-dictionary.md) + - [SHOW CREATE DICTIONARY](/tidb-cloud-lake/sql/show-create-dictionary.md) + - [SHOW DICTIONARIES](/tidb-cloud-lake/sql/show-dictionaries.md) + - Pipe + - [概览](/tidb-cloud-lake/sql/pipe.md) + - [CREATE PIPE](/tidb-cloud-lake/sql/create-pipe.md) + - [DESCRIBE PIPE](/tidb-cloud-lake/sql/describe-pipe.md) + - [DROP PIPE](/tidb-cloud-lake/sql/drop-pipe.md) + - 事务 + - [BEGIN](/tidb-cloud-lake/sql/begin.md) + - [COMMIT](/tidb-cloud-lake/sql/commit.md) + - [事务](/tidb-cloud-lake/sql/transaction.md) + - [ROLLBACK](/tidb-cloud-lake/sql/rollback.md) + - [SHOW LOCKS](/tidb-cloud-lake/sql/show-locks.md) + - Variable + - [SQL 变量](/tidb-cloud-lake/sql/sql-variables.md) + - [SET VARIABLE](/tidb-cloud-lake/sql/set-variable.md) + - [SHOW VARIABLES](/tidb-cloud-lake/sql/show-variables.md) + - [UNSET VARIABLE](/tidb-cloud-lake/sql/unset-variable.md) + - 存储过程 + - [CALL PROCEDURE](/tidb-cloud-lake/sql/call-procedure.md) + - [CREATE PROCEDURE](/tidb-cloud-lake/sql/create-procedure.md) + - [DESC PROCEDURE](/tidb-cloud-lake/sql/desc-procedure.md) + - [DROP PROCEDURE](/tidb-cloud-lake/sql/drop-procedure.md) + - [存储过程](/tidb-cloud-lake/sql/stored-procedure.md) + - [SHOW PROCEDURES](/tidb-cloud-lake/sql/show-procedures.md) + - Warehouse + - [概览](/tidb-cloud-lake/sql/warehouse-overview.md) + - [CREATE WAREHOUSE](/tidb-cloud-lake/sql/create-warehouse.md) + - [USE WAREHOUSE](/tidb-cloud-lake/sql/use-warehouse.md) + - [SHOW WAREHOUSES](/tidb-cloud-lake/sql/show-warehouses.md) + - [ALTER WAREHOUSE](/tidb-cloud-lake/sql/alter-warehouse.md) + - [ALTER WAREHOUSE ASSIGN NODES](/tidb-cloud-lake/sql/alter-warehouse-assign-nodes.md) + - [ALTER WAREHOUSE UNASSIGN NODES](/tidb-cloud-lake/sql/alter-warehouse-unassign-nodes.md) + - [DROP WAREHOUSE](/tidb-cloud-lake/sql/drop-warehouse.md) + - [QUERY_HISTORY](/tidb-cloud-lake/sql/query-history.md) + - Worker + - [概览](/tidb-cloud-lake/sql/worker-overview.md) + - [CREATE WORKER](/tidb-cloud-lake/sql/create-worker.md) + - [ALTER WORKER](/tidb-cloud-lake/sql/alter-worker.md) + - [DROP WORKER](/tidb-cloud-lake/sql/drop-worker.md) + - [SHOW WORKERS](/tidb-cloud-lake/sql/show-workers.md) + - [Worker 示例](/tidb-cloud-lake/sql/worker-examples.md) + - Workload Group + - [Workload Group](/tidb-cloud-lake/sql/workload-group.md) + - [ALTER WORKLOAD GROUP](/tidb-cloud-lake/sql/alter-workload-group.md) + - [CREATE WORKLOAD GROUP](/tidb-cloud-lake/sql/create-workload-group.md) + - [DROP WORKLOAD GROUP](/tidb-cloud-lake/sql/drop-workload-group.md) + - [RENAME WORKLOAD GROUP](/tidb-cloud-lake/sql/rename-workload-group.md) + - [SHOW WORKLOAD GROUPS](/tidb-cloud-lake/sql/show-workload-groups.md) + - 表版本控制 + - [概览](/tidb-cloud-lake/sql/table-versioning.md) + - [CREATE SNAPSHOT TAG](/tidb-cloud-lake/sql/create-snapshot-tag.md) + - [DROP SNAPSHOT TAG](/tidb-cloud-lake/sql/drop-snapshot-tag.md) + - DML 命令 + - [DML 概览](/tidb-cloud-lake/sql/dml.md) + - [`COPY INTO `](/tidb-cloud-lake/sql/copy-into-location.md) + - [`COPY INTO `](/tidb-cloud-lake/sql/copy-into-table.md) + - [DELETE](/tidb-cloud-lake/sql/delete.md) + - [INSERT](/tidb-cloud-lake/sql/insert.md) + - [INSERT(多表)](/tidb-cloud-lake/sql/insert-multi-table.md) + - [MERGE](/tidb-cloud-lake/sql/merge.md) + - [REPLACE](/tidb-cloud-lake/sql/replace.md) + - [UPDATE](/tidb-cloud-lake/sql/update.md) + - 查询语法 + - [概览](/tidb-cloud-lake/sql/query-syntax.md) + - [SELECT](/tidb-cloud-lake/sql/select.md) + - [AT](/tidb-cloud-lake/sql/at.md) + - [JOIN](/tidb-cloud-lake/sql/join.md) + - [PIVOT](/tidb-cloud-lake/sql/pivot.md) + - [UNPIVOT](/tidb-cloud-lake/sql/unpivot.md) + - [GROUP BY](/tidb-cloud-lake/sql/group-by.md) + - [CHANGES](/tidb-cloud-lake/sql/changes.md) + - [QUALIFY](/tidb-cloud-lake/sql/qualify.md) + - [SETTINGS 子句](/tidb-cloud-lake/sql/settings-clause.md) + - [TOP](/tidb-cloud-lake/sql/top.md) + - [VALUES](/tidb-cloud-lake/sql/values.md) + - [WITH 子句](/tidb-cloud-lake/sql/clause.md) + - [WITH CONSUME](/tidb-cloud-lake/sql/with-consume.md) + - [WITH Stream Hints](/tidb-cloud-lake/sql/stream-hints.md) + - 查询运算符 + - [算术运算符](/tidb-cloud-lake/sql/arithmetic-operators.md) + - [比较运算符](/tidb-cloud-lake/sql/comparison-operators.md) + - [查询运算符](/tidb-cloud-lake/sql/query-operators.md) + - [JSON 运算符](/tidb-cloud-lake/sql/json-operators.md) + - [逻辑运算符](/tidb-cloud-lake/sql/logical-operators.md) + - [集合运算符](/tidb-cloud-lake/sql/set-operators-sql.md) + - [子查询运算符](/tidb-cloud-lake/sql/subquery-operators.md) + - EXPLAIN 命令 + - [概览](/tidb-cloud-lake/sql/explain-commands.md) + - [EXPLAIN](/tidb-cloud-lake/sql/explain.md) + - [EXPLAIN ANALYZE](/tidb-cloud-lake/sql/explain-analyze.md) + - [EXPLAIN ANALYZE GRAPHICAL](/tidb-cloud-lake/sql/explain-analyze-graphical.md) + - [EXPLAIN AST](/tidb-cloud-lake/sql/explain-ast.md) + - [EXPLAIN PERF](/tidb-cloud-lake/sql/explain-perf.md) + - [EXPLAIN RAW](/tidb-cloud-lake/sql/explain-raw.md) + - [EXPLAIN SYNTAX](/tidb-cloud-lake/sql/explain-syntax.md) + - 管理命令 + - [概览](/tidb-cloud-lake/sql/administration-commands.md) + - [KILL](/tidb-cloud-lake/sql/kill.md) + - [SET](/tidb-cloud-lake/sql/set.md) + - [UNSET](/tidb-cloud-lake/sql/unset.md) + - [SET_VAR](/tidb-cloud-lake/sql/set-var.md) + - [SHOW SETTINGS](/tidb-cloud-lake/sql/show-settings.md) + - [SHOW INDEXES](/tidb-cloud-lake/sql/show-indexes.md) + - [SHOW FUNCTIONS](/tidb-cloud-lake/sql/show-functions.md) + - [SHOW USER FUNCTIONS](/tidb-cloud-lake/sql/show-user-functions-sql.md) + - [SHOW TABLE FUNCTIONS](/tidb-cloud-lake/sql/show-table-functions.md) + - [SHOW PROCESSLIST](/tidb-cloud-lake/sql/show-processlist.md) + - [SHOW METRICS](/tidb-cloud-lake/sql/show-metrics.md) + - [VACUUM DROP TABLE](/tidb-cloud-lake/sql/vacuum-drop-table-sql.md) + - [VACUUM TABLE](/tidb-cloud-lake/sql/vacuum-table-sql.md) + - [VACUUM TEMPORARY FILES](/tidb-cloud-lake/sql/vacuum-temporary-files.md) + - [VACUUM VIRTUAL COLUMN](/tidb-cloud-lake/sql/vacuum-virtual-column.md) + - [EXECUTE IMMEDIATE](/tidb-cloud-lake/sql/execute-immediate.md) + - [SYSTEM FLUSH PRIVILEGES](/tidb-cloud-lake/sql/system-flush-privileges.md) + - [SYSTEM ENABLE / DISABLE EXCEPTION_BACKTRACE](/tidb-cloud-lake/sql/system-enable-disable-exception-backtrace.md) + - SQL 函数 + - [SQL 函数参考](/tidb-cloud-lake/sql/sql-function-reference.md) + - Bitmap 函数 + - [BITMAP_AND](/tidb-cloud-lake/sql/bitmap-and.md) + - [BITMAP_AND_COUNT](/tidb-cloud-lake/sql/bitmap-and-count.md) + - [BITMAP_AND_NOT](/tidb-cloud-lake/sql/bitmap-and-not.md) + - [BITMAP_CARDINALITY](/tidb-cloud-lake/sql/bitmap-cardinality.md) + - [BITMAP_CONTAINS](/tidb-cloud-lake/sql/bitmap-contains.md) + - [BITMAP_COUNT](/tidb-cloud-lake/sql/bitmap-count.md) + - [BITMAP_HAS_ALL](/tidb-cloud-lake/sql/bitmap-has-all.md) + - [BITMAP_HAS_ANY](/tidb-cloud-lake/sql/bitmap-has-any.md) + - [BITMAP_INTERSECT](/tidb-cloud-lake/sql/bitmap-intersect.md) + - [BITMAP_MAX](/tidb-cloud-lake/sql/bitmap-max.md) + - [BITMAP_MIN](/tidb-cloud-lake/sql/bitmap-min.md) + - [BITMAP_NOT](/tidb-cloud-lake/sql/bitmap-not.md) + - [BITMAP_NOT_COUNT](/tidb-cloud-lake/sql/bitmap-not-count.md) + - [BITMAP_OR](/tidb-cloud-lake/sql/bitmap-or.md) + - [BITMAP_OR_COUNT](/tidb-cloud-lake/sql/bitmap-or-count.md) + - [BITMAP_SUBSET_IN_RANGE](/tidb-cloud-lake/sql/bitmap-subset-in-range.md) + - [BITMAP_SUBSET_LIMIT](/tidb-cloud-lake/sql/bitmap-subset-limit.md) + - [BITMAP_TO_ARRAY](/tidb-cloud-lake/sql/bitmap-array.md) + - [BITMAP_UNION](/tidb-cloud-lake/sql/bitmap-union.md) + - [BITMAP_XOR](/tidb-cloud-lake/sql/bitmap-xor.md) + - [BITMAP_XOR_COUNT](/tidb-cloud-lake/sql/bitmap-xor-count.md) + - [Bitmap 函数](/tidb-cloud-lake/sql/bitmap-functions.md) + - [INTERSECT_COUNT](/tidb-cloud-lake/sql/intersect-count.md) + - [SUB_BITMAP](/tidb-cloud-lake/sql/sub-bitmap.md) + - 转换函数 + - [BUILD_BITMAP](/tidb-cloud-lake/sql/build-bitmap.md) + - [CAST::](/tidb-cloud-lake/sql/cast.md) + - [转换函数](/tidb-cloud-lake/sql/conversion-functions.md) + - [TO_BINARY](/tidb-cloud-lake/sql/to-binary.md) + - [TO_BITMAP](/tidb-cloud-lake/sql/to-bitmap.md) + - [TO_BOOLEAN](/tidb-cloud-lake/sql/to-boolean.md) + - [TO_DECIMAL](/tidb-cloud-lake/sql/to-decimal.md) + - [TO_FLOAT32](/tidb-cloud-lake/sql/to-float32.md) + - [TO_FLOAT64](/tidb-cloud-lake/sql/to-float64.md) + - [TO_HEX](/tidb-cloud-lake/sql/to-hex.md) + - [TO_INT16](/tidb-cloud-lake/sql/to-int16.md) + - [TO_INT32](/tidb-cloud-lake/sql/to-int32.md) + - [TO_INT64](/tidb-cloud-lake/sql/to-int64.md) + - [TO_INT8](/tidb-cloud-lake/sql/to-int8.md) + - [TO_STRING](/tidb-cloud-lake/sql/to-string.md) + - [TO_TEXT](/tidb-cloud-lake/sql/to-text.md) + - [TO_UINT16](/tidb-cloud-lake/sql/to-uint16.md) + - [TO_UINT32](/tidb-cloud-lake/sql/to-uint32.md) + - [TO_UINT64](/tidb-cloud-lake/sql/to-uint64.md) + - [TO_UINT8](/tidb-cloud-lake/sql/to-uint8.md) + - [TO_VARCHAR](/tidb-cloud-lake/sql/to-varchar.md) + - [TO_VARIANT](/tidb-cloud-lake/sql/to-variant.md) + - [TRY_CAST](/tidb-cloud-lake/sql/try-cast.md) + - [TRY_TO_BINARY](/tidb-cloud-lake/sql/try-to-binary.md) + - 条件函数 + - [概览](/tidb-cloud-lake/sql/conditional-functions.md) + - [[ NOT ] BETWEEN](/tidb-cloud-lake/sql/between.md) + - [CASE](/tidb-cloud-lake/sql/case.md) + - [COALESCE](/tidb-cloud-lake/sql/coalesce.md) + - [DECODE](/tidb-cloud-lake/sql/decode.md) + - [ERROR_OR](/tidb-cloud-lake/sql/error-or.md) + - [GREATEST](/tidb-cloud-lake/sql/greatest.md) + - [GREATEST_IGNORE_NULLS](/tidb-cloud-lake/sql/greatest-ignore-nulls.md) + - [IF](/tidb-cloud-lake/sql/if.md) + - [IFF](/tidb-cloud-lake/sql/iff.md) + - [IFNULL](/tidb-cloud-lake/sql/ifnull.md) + - [[ NOT ] IN](/tidb-cloud-lake/sql/in.md) + - [IS [ NOT ] DISTINCT FROM](/tidb-cloud-lake/sql/is-distinct-from.md) + - [IS_ERROR](/tidb-cloud-lake/sql/is-error.md) + - [IS_NOT_ERROR](/tidb-cloud-lake/sql/is-not-error.md) + - [IS_NOT_NULL](/tidb-cloud-lake/sql/is-not-null.md) + - [IS_NULL](/tidb-cloud-lake/sql/is-null.md) + - [LEAST](/tidb-cloud-lake/sql/least.md) + - [LEAST_IGNORE_NULLS](/tidb-cloud-lake/sql/least-ignore-nulls.md) + - [NULLIF](/tidb-cloud-lake/sql/nullif.md) + - [NVL](/tidb-cloud-lake/sql/nvl.md) + - [NVL2](/tidb-cloud-lake/sql/nvl2.md) + - 数值函数 + - [概览](/tidb-cloud-lake/sql/numeric-functions.md) + - [ABS](/tidb-cloud-lake/sql/abs.md) + - [ACOS](/tidb-cloud-lake/sql/acos.md) + - [ADD](/tidb-cloud-lake/sql/add.md) + - [ASIN](/tidb-cloud-lake/sql/asin.md) + - [ATAN](/tidb-cloud-lake/sql/atan.md) + - [ATAN2](/tidb-cloud-lake/sql/atan-sql.md) + - [CBRT](/tidb-cloud-lake/sql/cbrt.md) + - [CEIL](/tidb-cloud-lake/sql/ceil.md) + - [CEILING](/tidb-cloud-lake/sql/ceiling.md) + - [COS](/tidb-cloud-lake/sql/cos.md) + - [COT](/tidb-cloud-lake/sql/cot.md) + - [CRC32](/tidb-cloud-lake/sql/crc.md) + - [DEGREES](/tidb-cloud-lake/sql/degrees.md) + - [DIV](/tidb-cloud-lake/sql/div.md) + - [DIV0](/tidb-cloud-lake/sql/div0.md) + - [DIVNULL](/tidb-cloud-lake/sql/divnull.md) + - [EXP](/tidb-cloud-lake/sql/exp.md) + - [FACTORIAL](/tidb-cloud-lake/sql/factorial.md) + - [FLOOR](/tidb-cloud-lake/sql/floor.md) + - [INTDIV](/tidb-cloud-lake/sql/intdiv.md) + - [LN](/tidb-cloud-lake/sql/ln.md) + - [LOG10](/tidb-cloud-lake/sql/log.md) + - [LOG2](/tidb-cloud-lake/sql/log-sql.md) + - [LOG(b, x)](/tidb-cloud-lake/sql/log-b-x.md) + - [LOG(x)](/tidb-cloud-lake/sql/log-x.md) + - [MINUS](/tidb-cloud-lake/sql/minus.md) + - [MOD](/tidb-cloud-lake/sql/mod.md) + - [MODULO](/tidb-cloud-lake/sql/modulo.md) + - [MULTIPLY](/tidb-cloud-lake/sql/multiply.md) + - [NEG](/tidb-cloud-lake/sql/neg.md) + - [NEGATE](/tidb-cloud-lake/sql/negate.md) + - [PI](/tidb-cloud-lake/sql/pi.md) + - [PLUS](/tidb-cloud-lake/sql/plus.md) + - [POW](/tidb-cloud-lake/sql/pow.md) + - [POWER](/tidb-cloud-lake/sql/power.md) + - [RADIANS](/tidb-cloud-lake/sql/radians.md) + - [RAND()](/tidb-cloud-lake/sql/rand.md) + - [RAND(n)](/tidb-cloud-lake/sql/rand-n.md) + - [ROUND](/tidb-cloud-lake/sql/round.md) + - [SIGN](/tidb-cloud-lake/sql/sign.md) + - [SIN](/tidb-cloud-lake/sql/sin.md) + - [SQRT](/tidb-cloud-lake/sql/sqrt.md) + - [SUBTRACT](/tidb-cloud-lake/sql/subtract.md) + - [TAN](/tidb-cloud-lake/sql/tan.md) + - [TRUNC](/tidb-cloud-lake/sql/trunc.md) + - [TRUNCATE](/tidb-cloud-lake/sql/truncate.md) + - 日期与时间函数 + - [概览](/tidb-cloud-lake/sql/date-time-functions.md) + - [ADD_MONTHS](/tidb-cloud-lake/sql/add-months.md) + - [ADD TIME INTERVAL](/tidb-cloud-lake/sql/add-interval.md) + - [AGE](/tidb-cloud-lake/sql/age.md) + - [CONVERT_TIMEZONE](/tidb-cloud-lake/sql/convert-timezone.md) + - [CURRENT_TIMESTAMP](/tidb-cloud-lake/sql/current-timestamp.md) + - [DATE](/tidb-cloud-lake/sql/date.md) + - [DATE_ADD](/tidb-cloud-lake/sql/date-add.md) + - [DATE_BETWEEN](/tidb-cloud-lake/sql/date-between.md) + - [DATE_DIFF](/tidb-cloud-lake/sql/date-diff.md) + - [DATE_FORMAT](/tidb-cloud-lake/sql/date-format.md) + - [DATE_PART](/tidb-cloud-lake/sql/date-part.md) + - [DATE_SUB](/tidb-cloud-lake/sql/date-sub.md) + - [DATE_TRUNC](/tidb-cloud-lake/sql/date-trunc.md) + - [DAY](/tidb-cloud-lake/sql/day.md) + - [EXTRACT](/tidb-cloud-lake/sql/extract.md) + - [LAST_DAY](/tidb-cloud-lake/sql/last-day.md) + - [MILLENNIUM](/tidb-cloud-lake/sql/millennium.md) + - [MONTH](/tidb-cloud-lake/sql/month.md) + - [MONTHS_BETWEEN](/tidb-cloud-lake/sql/months-between.md) + - [NEXT_DAY](/tidb-cloud-lake/sql/next-day.md) + - [NOW](/tidb-cloud-lake/sql/now.md) + - [PREVIOUS_DAY](/tidb-cloud-lake/sql/previous-day.md) + - [QUARTER](/tidb-cloud-lake/sql/quarter.md) + - [STR_TO_DATE](/tidb-cloud-lake/sql/str-to-date.md) + - [STR_TO_TIMESTAMP](/tidb-cloud-lake/sql/str-to-timestamp.md) + - [SUBTRACT TIME INTERVAL](/tidb-cloud-lake/sql/subtract-interval.md) + - [TIME_SLICE](/tidb-cloud-lake/sql/time-slice.md) + - [TIME_SLOT](/tidb-cloud-lake/sql/time-slot.md) + - [TIMESTAMP_DIFF](/tidb-cloud-lake/sql/timestamp-diff.md) + - [TIMEZONE](/tidb-cloud-lake/sql/timezone.md) + - [TO_DATE](/tidb-cloud-lake/sql/to-date.md) + - [TO_DATETIME](/tidb-cloud-lake/sql/datetime.md) + - [TO_DAY_OF_MONTH](/tidb-cloud-lake/sql/to-day-of-month.md) + - [TO_DAY_OF_WEEK](/tidb-cloud-lake/sql/day-week.md) + - [TO_DAY_OF_YEAR](/tidb-cloud-lake/sql/day-year.md) + - [TO_HOUR](/tidb-cloud-lake/sql/hour.md) + - [TO_MINUTE](/tidb-cloud-lake/sql/minute.md) + - [TO_MONDAY](/tidb-cloud-lake/sql/monday.md) + - [TO_MONTH](/tidb-cloud-lake/sql/to-month.md) + - [TO_QUARTER](/tidb-cloud-lake/sql/to-quarter.md) + - [TO_SECOND](/tidb-cloud-lake/sql/second.md) + - [TO_START_OF_DAY](/tidb-cloud-lake/sql/to-start-of-day.md) + - [TO_START_OF_FIFTEEN_MINUTES](/tidb-cloud-lake/sql/start-fifteen-minutes.md) + - [TO_START_OF_FIVE_MINUTES](/tidb-cloud-lake/sql/start-five-minutes.md) + - [TO_START_OF_HOUR](/tidb-cloud-lake/sql/to-start-of-hour.md) + - [TO_START_OF_ISO_YEAR](/tidb-cloud-lake/sql/start-iso-year.md) + - [TO_START_OF_MINUTE](/tidb-cloud-lake/sql/to-start-of-minute.md) + - [TO_START_OF_MONTH](/tidb-cloud-lake/sql/to-start-of-month.md) + - [TO_START_OF_QUARTER](/tidb-cloud-lake/sql/to-start-of-quarter.md) + - [TO_START_OF_SECOND](/tidb-cloud-lake/sql/to-start-of-second.md) + - [TO_START_OF_TEN_MINUTES](/tidb-cloud-lake/sql/start-ten-minutes.md) + - [TO_START_OF_WEEK](/tidb-cloud-lake/sql/to-start-of-week.md) + - [TO_START_OF_YEAR](/tidb-cloud-lake/sql/to-start-of-year.md) + - [TO_TIMESTAMP](/tidb-cloud-lake/sql/to-timestamp.md) + - [TO_TIMESTAMP_TZ](/tidb-cloud-lake/sql/timestamp-tz.md) + - [TO_UNIX_TIMESTAMP](/tidb-cloud-lake/sql/unix-timestamp.md) + - [TO_WEEK_OF_YEAR](/tidb-cloud-lake/sql/to-week-of-year.md) + - [TO_YEAR](/tidb-cloud-lake/sql/to-year.md) + - [TO_YYYYMM](/tidb-cloud-lake/sql/yyyymm.md) + - [TO_YYYYMMDD](/tidb-cloud-lake/sql/yyyymmdd.md) + - [TO_YYYYMMDDHH](/tidb-cloud-lake/sql/yyyymmddhh.md) + - [TO_YYYYMMDDHHMMSS](/tidb-cloud-lake/sql/yyyymmddhhmmss.md) + - [TODAY](/tidb-cloud-lake/sql/today.md) + - [TOMORROW](/tidb-cloud-lake/sql/tomorrow.md) + - [TRUNC](/tidb-cloud-lake/sql/trunc-sql.md) + - [TRY_TO_DATETIME](/tidb-cloud-lake/sql/try-to-datetime.md) + - [TRY_TO_TIMESTAMP](/tidb-cloud-lake/sql/try-to-timestamp.md) + - [WEEK](/tidb-cloud-lake/sql/week.md) + - [WEEKOFYEAR](/tidb-cloud-lake/sql/weekofyear.md) + - [YEAR](/tidb-cloud-lake/sql/year.md) + - [YEARWEEK](/tidb-cloud-lake/sql/yearweek.md) + - [YESTERDAY](/tidb-cloud-lake/sql/yesterday.md) + - 间隔函数 + - [概览](/tidb-cloud-lake/sql/interval-functions.md) + - [EPOCH](/tidb-cloud-lake/sql/epoch.md) + - [TO_CENTURIES](/tidb-cloud-lake/sql/to-centuries.md) + - [TO_DAYS](/tidb-cloud-lake/sql/days.md) + - [TO_DECADES](/tidb-cloud-lake/sql/decades.md) + - [TO_HOURS](/tidb-cloud-lake/sql/hours.md) + - [TO_MICROSECONDS](/tidb-cloud-lake/sql/microseconds.md) + - [TO_MILLENNIA](/tidb-cloud-lake/sql/millennia.md) + - [TO_MILLISECONDS](/tidb-cloud-lake/sql/milliseconds.md) + - [TO_MINUTES](/tidb-cloud-lake/sql/minutes.md) + - [TO_MONTHS](/tidb-cloud-lake/sql/months.md) + - [TO_SECONDS](/tidb-cloud-lake/sql/seconds.md) + - [TO_WEEKS](/tidb-cloud-lake/sql/weeks.md) + - [TO_YEARS](/tidb-cloud-lake/sql/years.md) + - 字符串函数 + - [概览](/tidb-cloud-lake/sql/string-functions-overview.md) + - [ASCII](/tidb-cloud-lake/sql/ascii.md) + - [BIN](/tidb-cloud-lake/sql/bin.md) + - [BIT_LENGTH](/tidb-cloud-lake/sql/bit-length.md) + - [CHAR](/tidb-cloud-lake/sql/char.md) + - [CHAR_LENGTH](/tidb-cloud-lake/sql/char-length.md) + - [CHARACTER_LENGTH](/tidb-cloud-lake/sql/character-length.md) + - [CONCAT](/tidb-cloud-lake/sql/concat.md) + - [CONCAT_WS](/tidb-cloud-lake/sql/concat-ws.md) + - [FROM_BASE64](/tidb-cloud-lake/sql/from-base64.md) + - [FROM_HEX](/tidb-cloud-lake/sql/from-hex.md) + - [GLOB](/tidb-cloud-lake/sql/glob.md) + - [HEX](/tidb-cloud-lake/sql/hex.md) + - [INSERT](/tidb-cloud-lake/sql/insert-sql.md) + - [INSTR](/tidb-cloud-lake/sql/instr.md) + - [JARO_WINKLER](/tidb-cloud-lake/sql/jaro-winkler.md) + - [LCASE](/tidb-cloud-lake/sql/lcase.md) + - [LEFT](/tidb-cloud-lake/sql/left.md) + - [LENGTH](/tidb-cloud-lake/sql/length.md) + - [LENGTH_UTF8](/tidb-cloud-lake/sql/length-utf8.md) + - [LIKE](/tidb-cloud-lake/sql/like.md) + - [LOCATE](/tidb-cloud-lake/sql/locate.md) + - [LOWER](/tidb-cloud-lake/sql/lower.md) + - [LPAD](/tidb-cloud-lake/sql/lpad.md) + - [LTRIM](/tidb-cloud-lake/sql/ltrim.md) + - [MID](/tidb-cloud-lake/sql/mid.md) + - [NOT LIKE](/tidb-cloud-lake/sql/not-like.md) + - [NOT REGEXP](/tidb-cloud-lake/sql/not-regexp.md) + - [NOT RLIKE](/tidb-cloud-lake/sql/not-rlike.md) + - [OCT](/tidb-cloud-lake/sql/oct.md) + - [OCTET_LENGTH](/tidb-cloud-lake/sql/octet-length.md) + - [ORD](/tidb-cloud-lake/sql/ord.md) + - [POSITION](/tidb-cloud-lake/sql/position.md) + - [QUOTE](/tidb-cloud-lake/sql/quote.md) + - [REGEXP](/tidb-cloud-lake/sql/regexp.md) + - [REGEXP_INSTR](/tidb-cloud-lake/sql/regexp-instr.md) + - [REGEXP_LIKE](/tidb-cloud-lake/sql/regexp-like.md) + - [REGEXP_REPLACE](/tidb-cloud-lake/sql/regexp-replace.md) + - [REGEXP_SPLIT_TO_ARRAY](/tidb-cloud-lake/sql/regexp-split-array.md) + - [REGEXP_SPLIT_TO_TABLE](/tidb-cloud-lake/sql/regexp-split-table.md) + - [REGEXP_SUBSTR](/tidb-cloud-lake/sql/regexp-substr.md) + - [REPEAT](/tidb-cloud-lake/sql/repeat.md) + - [REPLACE](/tidb-cloud-lake/sql/replace-sql.md) + - [REVERSE](/tidb-cloud-lake/sql/reverse.md) + - [RIGHT](/tidb-cloud-lake/sql/right.md) + - [RLIKE](/tidb-cloud-lake/sql/rlike.md) + - [RPAD](/tidb-cloud-lake/sql/rpad.md) + - [RTRIM](/tidb-cloud-lake/sql/rtrim.md) + - [SOUNDEX](/tidb-cloud-lake/sql/soundex.md) + - [SOUNDS LIKE](/tidb-cloud-lake/sql/sounds-like.md) + - [SPACE](/tidb-cloud-lake/sql/space.md) + - [SPLIT](/tidb-cloud-lake/sql/split.md) + - [SPLIT_PART](/tidb-cloud-lake/sql/split-part.md) + - [STRCMP](/tidb-cloud-lake/sql/strcmp.md) + - [SUBSTR](/tidb-cloud-lake/sql/substr.md) + - [SUBSTRING](/tidb-cloud-lake/sql/substring.md) + - [TO_BASE64](/tidb-cloud-lake/sql/to-base64.md) + - [TRANSLATE](/tidb-cloud-lake/sql/translate.md) + - [TRIM](/tidb-cloud-lake/sql/trim.md) + - [TRIM_BOTH](/tidb-cloud-lake/sql/trim-both.md) + - [TRIM_LEADING](/tidb-cloud-lake/sql/trim-leading.md) + - [TRIM_TRAILING](/tidb-cloud-lake/sql/trim-trailing.md) + - [UCASE](/tidb-cloud-lake/sql/ucase.md) + - [UNHEX](/tidb-cloud-lake/sql/unhex.md) + - [UPPER](/tidb-cloud-lake/sql/upper.md) + - 聚合函数 + - [概览](/tidb-cloud-lake/sql/aggregate-functions.md) + - [ANY_VALUE](/tidb-cloud-lake/sql/any-value.md) + - [APPROX_COUNT_DISTINCT](/tidb-cloud-lake/sql/approx-count-distinct.md) + - [ARG_MAX](/tidb-cloud-lake/sql/arg-max.md) + - [ARG_MIN](/tidb-cloud-lake/sql/arg-min.md) + - [ARRAY_AGG](/tidb-cloud-lake/sql/array-agg.md) + - [AVG](/tidb-cloud-lake/sql/avg.md) + - [AVG_IF](/tidb-cloud-lake/sql/avg-if.md) + - [bool_and](/tidb-cloud-lake/sql/bool-and.md) + - [bool_or](/tidb-cloud-lake/sql/bool-or.md) + - [COUNT](/tidb-cloud-lake/sql/count.md) + - [COUNT_DISTINCT](/tidb-cloud-lake/sql/count-distinct.md) + - [COUNT_IF](/tidb-cloud-lake/sql/count-if.md) + - [COVAR_POP](/tidb-cloud-lake/sql/covar-pop.md) + - [COVAR_SAMP](/tidb-cloud-lake/sql/covar-samp.md) + - [GROUP_ARRAY_MOVING_AVG](/tidb-cloud-lake/sql/group-array-moving-avg.md) + - [GROUP_ARRAY_MOVING_SUM](/tidb-cloud-lake/sql/group-array-moving-sum.md) + - [GROUP_CONCAT](/tidb-cloud-lake/sql/group-concat.md) + - [HISTOGRAM](/tidb-cloud-lake/sql/histogram.md) + - [JSON_ARRAY_AGG](/tidb-cloud-lake/sql/json-array-agg.md) + - [JSON_OBJECT_AGG](/tidb-cloud-lake/sql/json-object-agg.md) + - [KURTOSIS](/tidb-cloud-lake/sql/kurtosis.md) + - [LISTAGG](/tidb-cloud-lake/sql/listagg.md) + - [MARKOV_TRAIN](/tidb-cloud-lake/sql/markov-train.md) + - [MAX](/tidb-cloud-lake/sql/max.md) + - [MAX_IF](/tidb-cloud-lake/sql/max-if.md) + - [MEDIAN](/tidb-cloud-lake/sql/median.md) + - [MEDIAN_TDIGEST](/tidb-cloud-lake/sql/median-tdigest.md) + - [MIN](/tidb-cloud-lake/sql/min.md) + - [MIN_IF](/tidb-cloud-lake/sql/min-if.md) + - [MODE](/tidb-cloud-lake/sql/mode.md) + - [QUANTILE_CONT](/tidb-cloud-lake/sql/quantile-cont.md) + - [QUANTILE_DISC](/tidb-cloud-lake/sql/quantile-disc.md) + - [QUANTILE_TDIGEST](/tidb-cloud-lake/sql/quantile-tdigest.md) + - [QUANTILE_TDIGEST_WEIGHTED](/tidb-cloud-lake/sql/quantile-tdigest-weighted.md) + - [RETENTION](/tidb-cloud-lake/sql/retention.md) + - [SKEWNESS](/tidb-cloud-lake/sql/skewness.md) + - [ST_COLLECT](/tidb-cloud-lake/sql/st-collect.md) + - [ST_ENVELOPE_AGG](/tidb-cloud-lake/sql/st-envelope-agg.md) + - [ST_INTERSECTION_AGG](/tidb-cloud-lake/sql/st-intersection-agg.md) + - [ST_UNION_AGG](/tidb-cloud-lake/sql/st-union-agg.md) + - [STDDEV_POP](/tidb-cloud-lake/sql/stddev-pop.md) + - [STDDEV_SAMP](/tidb-cloud-lake/sql/stddev-samp.md) + - [STRING_AGG](/tidb-cloud-lake/sql/string-agg.md) + - [SUM](/tidb-cloud-lake/sql/sum.md) + - [SUM_IF](/tidb-cloud-lake/sql/sum-if.md) + - [VAR_POP](/tidb-cloud-lake/sql/var-pop.md) + - [VAR_SAMP](/tidb-cloud-lake/sql/var-samp.md) + - [VARIANCE_POP](/tidb-cloud-lake/sql/variance-pop.md) + - [VARIANCE_SAMP](/tidb-cloud-lake/sql/variance-samp.md) + - [WINDOW_FUNNEL](/tidb-cloud-lake/sql/window-funnel.md) + - 窗口函数 + - [概览](/tidb-cloud-lake/sql/window-functions-overview.md) + - [CUME_DIST](/tidb-cloud-lake/sql/cume-dist.md) + - [DENSE_RANK](/tidb-cloud-lake/sql/dense-rank.md) + - [FIRST](/tidb-cloud-lake/sql/first.md) + - [FIRST_VALUE](/tidb-cloud-lake/sql/first-value.md) + - [LAG](/tidb-cloud-lake/sql/lag.md) + - [LAST](/tidb-cloud-lake/sql/last.md) + - [LAST_VALUE](/tidb-cloud-lake/sql/last-value.md) + - [LEAD](/tidb-cloud-lake/sql/lead.md) + - [NTH_VALUE](/tidb-cloud-lake/sql/nth-value.md) + - [NTILE](/tidb-cloud-lake/sql/ntile.md) + - [PERCENT_RANK](/tidb-cloud-lake/sql/percent-rank.md) + - [RANGE BETWEEN](/tidb-cloud-lake/sql/range-between.md) + - [RANK](/tidb-cloud-lake/sql/rank.md) + - [ROW_NUMBER](/tidb-cloud-lake/sql/row-number.md) + - [ROWS BETWEEN](/tidb-cloud-lake/sql/rows-between.md) + - 地理空间函数 + - [概览](/tidb-cloud-lake/sql/geospatial-functions.md) + - [GEO_DISTANCE](/tidb-cloud-lake/sql/geo-distance.md) + - [GEO_TO_H3](/tidb-cloud-lake/sql/geo-to-h3.md) + - [GEOHASH_DECODE](/tidb-cloud-lake/sql/geohash-decode.md) + - [GEOHASH_ENCODE](/tidb-cloud-lake/sql/geohash-encode.md) + - [GREAT_CIRCLE_ANGLE](/tidb-cloud-lake/sql/great-circle-angle.md) + - [GREAT_CIRCLE_DISTANCE](/tidb-cloud-lake/sql/great-circle-distance.md) + - [H3_CELL_AREA_M2](/tidb-cloud-lake/sql/h3-cell-area-m2.md) + - [H3_CELL_AREA_RADS2](/tidb-cloud-lake/sql/h3-cell-area-rads2.md) + - [H3_DISTANCE](/tidb-cloud-lake/sql/h3-distance.md) + - [H3_EDGE_ANGLE](/tidb-cloud-lake/sql/h3-edge-angle.md) + - [H3_EDGE_LENGTH_KM](/tidb-cloud-lake/sql/h3-edge-length-km.md) + - [H3_EDGE_LENGTH_M](/tidb-cloud-lake/sql/h3-edge-length-m.md) + - [H3_EXACT_EDGE_LENGTH_KM](/tidb-cloud-lake/sql/h3-exact-edge-length-km.md) + - [H3_EXACT_EDGE_LENGTH_M](/tidb-cloud-lake/sql/h3-exact-edge-length-m.md) + - [H3_EXACT_EDGE_LENGTH_RADS](/tidb-cloud-lake/sql/h3-exact-edge-length-rads.md) + - [H3_GET_BASE_CELL](/tidb-cloud-lake/sql/h3-get-base-cell.md) + - [H3_GET_DESTINATION_INDEX_FROM_UNIDIRECTIONAL_EDGE](/tidb-cloud-lake/sql/h3-get-destination-index-unidirectional-edge.md) + - [H3_GET_FACES](/tidb-cloud-lake/sql/h3-get-faces.md) + - [H3_GET_INDEXES_FROM_UNIDIRECTIONAL_EDGE](/tidb-cloud-lake/sql/h3-get-indexes-unidirectional-edge.md) + - [H3_GET_ORIGIN_INDEX_FROM_UNIDIRECTIONAL_EDGE](/tidb-cloud-lake/sql/h3-get-origin-index-unidirectional-edge.md) + - [H3_GET_RESOLUTION](/tidb-cloud-lake/sql/h3-get-resolution.md) + - [H3_GET_UNIDIRECTIONAL_EDGE](/tidb-cloud-lake/sql/h3-get-unidirectional-edge.md) + - [H3_GET_UNIDIRECTIONAL_EDGE_BOUNDARY](/tidb-cloud-lake/sql/h3-get-unidirectional-edge-boundary.md) + - [H3_GET_UNIDIRECTIONAL_EDGES_FROM_HEXAGON](/tidb-cloud-lake/sql/h3-get-unidirectional-edges-hexagon.md) + - [H3_HEX_AREA_KM2](/tidb-cloud-lake/sql/h3-hex-area-km2.md) + - [H3_HEX_AREA_M2](/tidb-cloud-lake/sql/h3-hex-area-m2.md) + - [H3_HEX_RING](/tidb-cloud-lake/sql/h3-hex-ring.md) + - [H3_INDEXES_ARE_NEIGHBORS](/tidb-cloud-lake/sql/h3-indexes-are-neighbors.md) + - [H3_IS_PENTAGON](/tidb-cloud-lake/sql/h3-is-pentagon.md) + - [H3_IS_RES_CLASS_III](/tidb-cloud-lake/sql/h3-is-res-class-iii.md) + - [H3_IS_VALID](/tidb-cloud-lake/sql/h3-is-valid.md) + - [H3_K_RING](/tidb-cloud-lake/sql/h3-k-ring.md) + - [H3_LINE](/tidb-cloud-lake/sql/h3-line.md) + - [H3_NUM_HEXAGONS](/tidb-cloud-lake/sql/h3-num-hexagons.md) + - [H3_TO_CENTER_CHILD](/tidb-cloud-lake/sql/h3-to-center-child.md) + - [H3_TO_CHILDREN](/tidb-cloud-lake/sql/h3-to-children.md) + - [H3_TO_GEO](/tidb-cloud-lake/sql/h3-to-geo.md) + - [H3_TO_GEO_BOUNDARY](/tidb-cloud-lake/sql/h3-to-geo-boundary.md) + - [H3_TO_PARENT](/tidb-cloud-lake/sql/h3-to-parent.md) + - [H3_TO_STRING](/tidb-cloud-lake/sql/h3-to-string.md) + - [H3_UNIDIRECTIONAL_EDGE_IS_VALID](/tidb-cloud-lake/sql/h3-unidirectional-edge-is-valid.md) + - [HAVERSINE](/tidb-cloud-lake/sql/haversine.md) + - [POINT_IN_ELLIPSES](/tidb-cloud-lake/sql/point-in-ellipses.md) + - [POINT_IN_POLYGON](/tidb-cloud-lake/sql/point-in-polygon.md) + - [ST_AREA](/tidb-cloud-lake/sql/st-area.md) + - [ST_ASBINARY](/tidb-cloud-lake/sql/st-asbinary.md) + - [ST_ASEWKB](/tidb-cloud-lake/sql/st-asewkb.md) + - [ST_ASEWKT](/tidb-cloud-lake/sql/st-asewkt.md) + - [ST_ASGEOJSON](/tidb-cloud-lake/sql/st-asgeojson.md) + - [ST_ASTEXT](/tidb-cloud-lake/sql/st-astext.md) + - [ST_ASWKB](/tidb-cloud-lake/sql/st-aswkb.md) + - [ST_ASWKT](/tidb-cloud-lake/sql/st-aswkt.md) + - [ST_AZIMUTH](/tidb-cloud-lake/sql/st-azimuth.md) + - [ST_BUFFER](/tidb-cloud-lake/sql/st-buffer.md) + - [ST_CENTROID](/tidb-cloud-lake/sql/st-centroid.md) + - [ST_CONTAINS](/tidb-cloud-lake/sql/st-contains.md) + - [ST_CONVEXHULL](/tidb-cloud-lake/sql/st-convexhull.md) + - [ST_COVEREDBY](/tidb-cloud-lake/sql/st-coveredby.md) + - [ST_COVERS](/tidb-cloud-lake/sql/st-covers.md) + - [ST_DIFFERENCE](/tidb-cloud-lake/sql/st-difference.md) + - [ST_DIMENSION](/tidb-cloud-lake/sql/st-dimension.md) + - [ST_DISJOINT](/tidb-cloud-lake/sql/st-disjoint.md) + - [ST_DISTANCE](/tidb-cloud-lake/sql/st-distance.md) + - [ST_DWITHIN](/tidb-cloud-lake/sql/st-dwithin.md) + - [ST_ENDPOINT](/tidb-cloud-lake/sql/st-endpoint.md) + - [ST_ENVELOPE](/tidb-cloud-lake/sql/st-envelope.md) + - [ST_EQUALS](/tidb-cloud-lake/sql/st-equals.md) + - [ST_GEOGETRYFROMWKB](/tidb-cloud-lake/sql/st-geogetryfromwkb.md) + - [ST_GEOGFROMEWKB](/tidb-cloud-lake/sql/st-geogfromewkb.md) + - [ST_GEOGFROMGEOHASH](/tidb-cloud-lake/sql/st-geogfromgeohash.md) + - [ST_GEOGFROMTEXT](/tidb-cloud-lake/sql/st-geogfromtext.md) + - [ST_GEOGFROMWKB](/tidb-cloud-lake/sql/st-geogfromwkb.md) + - [ST_GEOGFROMWKT](/tidb-cloud-lake/sql/st-geogfromwkt.md) + - [ST_GEOGPOINTFROMGEOHASH](/tidb-cloud-lake/sql/st-geogpointfromgeohash.md) + - [ST_GEOGRAPHYFROMEWKT](/tidb-cloud-lake/sql/st-geographyfromewkt.md) + - [ST_GEOGRAPHYFROMTEXT](/tidb-cloud-lake/sql/st-geographyfromtext.md) + - [ST_GEOGRAPHYFROMWKB](/tidb-cloud-lake/sql/st-geographyfromwkb.md) + - [ST_GEOGRAPHYFROMWKT](/tidb-cloud-lake/sql/st-geographyfromwkt.md) + - [ST_GEOHASH](/tidb-cloud-lake/sql/st-geohash.md) + - [ST_GEOM_POINT](/tidb-cloud-lake/sql/st-geom-point.md) + - [ST_GEOMETRYFROMEWKB](/tidb-cloud-lake/sql/st-geometryfromewkb.md) + - [ST_GEOMETRYFROMEWKT](/tidb-cloud-lake/sql/st-geometryfromewkt.md) + - [ST_GEOMETRYFROMTEXT](/tidb-cloud-lake/sql/st-geometryfromtext.md) + - [ST_GEOMETRYFROMWKB](/tidb-cloud-lake/sql/st-geometryfromwkb.md) + - [ST_GEOMETRYFROMWKT](/tidb-cloud-lake/sql/st-geometryfromwkt.md) + - [ST_GEOMFROMEWKB](/tidb-cloud-lake/sql/st-geomfromewkb.md) + - [ST_GEOMFROMEWKT](/tidb-cloud-lake/sql/st-geomfromewkt.md) + - [ST_GEOMFROMGEOHASH](/tidb-cloud-lake/sql/st-geomfromgeohash.md) + - [ST_GEOMFROMTEXT](/tidb-cloud-lake/sql/st-geomfromtext.md) + - [ST_GEOMFROMWKB](/tidb-cloud-lake/sql/st-geomfromwkb.md) + - [ST_GEOMFROMWKT](/tidb-cloud-lake/sql/st-geomfromwkt.md) + - [ST_GEOMPOINTFROMGEOHASH](/tidb-cloud-lake/sql/st-geompointfromgeohash.md) + - [ST_HAUSDORFFDISTANCE](/tidb-cloud-lake/sql/st-hausdorffdistance.md) + - [ST_HILBERT](/tidb-cloud-lake/sql/st-hilbert.md) + - [ST_INTERSECTION](/tidb-cloud-lake/sql/st-intersection.md) + - [ST_INTERSECTS](/tidb-cloud-lake/sql/st-intersects.md) + - [ST_ISVALID](/tidb-cloud-lake/sql/st-isvalid.md) + - [ST_LENGTH](/tidb-cloud-lake/sql/st-length.md) + - [ST_MAKE_LINE](/tidb-cloud-lake/sql/st-make-line.md) + - [ST_MAKEGEOMPOINT](/tidb-cloud-lake/sql/st-makegeompoint.md) + - [ST_MAKELINE](/tidb-cloud-lake/sql/st-makeline.md) + - [ST_MAKEPOINT](/tidb-cloud-lake/sql/st-makepoint.md) + - [ST_MAKEPOLYGON](/tidb-cloud-lake/sql/st-makepolygon.md) + - [ST_MAKEPOLYGONORIENTED](/tidb-cloud-lake/sql/st-makepolygonoriented.md) + - [ST_NPOINTS](/tidb-cloud-lake/sql/st-npoints.md) + - [ST_NUMPOINTS](/tidb-cloud-lake/sql/st-numpoints.md) + - [ST_PERIMETER](/tidb-cloud-lake/sql/st-perimeter.md) + - [ST_POINT](/tidb-cloud-lake/sql/st-point.md) + - [ST_POINTN](/tidb-cloud-lake/sql/st-pointn.md) + - [ST_POLYGON](/tidb-cloud-lake/sql/st-polygon.md) + - [ST_SETSRID](/tidb-cloud-lake/sql/st-setsrid.md) + - [ST_SIMPLIFY](/tidb-cloud-lake/sql/st-simplify.md) + - [ST_SRID](/tidb-cloud-lake/sql/st-srid.md) + - [ST_STARTPOINT](/tidb-cloud-lake/sql/st-startpoint.md) + - [ST_SYMDIFFERENCE](/tidb-cloud-lake/sql/st-symdifference.md) + - [ST_TRANSFORM](/tidb-cloud-lake/sql/st-transform.md) + - [ST_UNION](/tidb-cloud-lake/sql/st-union.md) + - [ST_WITHIN](/tidb-cloud-lake/sql/st-within.md) + - [ST_X](/tidb-cloud-lake/sql/st-x.md) + - [ST_XMAX](/tidb-cloud-lake/sql/st-xmax.md) + - [ST_XMIN](/tidb-cloud-lake/sql/st-xmin.md) + - [ST_Y](/tidb-cloud-lake/sql/st-y.md) + - [ST_YMAX](/tidb-cloud-lake/sql/st-ymax.md) + - [ST_YMIN](/tidb-cloud-lake/sql/st-ymin.md) + - [STRING_TO_H3](/tidb-cloud-lake/sql/string-to-h3.md) + - [TO_GEOGRAPHY](/tidb-cloud-lake/sql/to-geography.md) + - [TO_GEOMETRY](/tidb-cloud-lake/sql/geometry.md) + - [TO_STRING](/tidb-cloud-lake/sql/string-geospatial.md) + - 全文搜索函数 + - [概览](/tidb-cloud-lake/sql/full-text-search-functions.md) + - [MATCH](/tidb-cloud-lake/sql/match.md) + - [QUERY](/tidb-cloud-lake/sql/query.md) + - [SCORE](/tidb-cloud-lake/sql/score.md) + - 结构化与半结构化 + - [结构化与半结构化函数](/tidb-cloud-lake/sql/structured-semi-structured-functions.md) + - JSON 函数 + - [概览](/tidb-cloud-lake/sql/json-functions-overview.md) + - [CHECK_JSON](/tidb-cloud-lake/sql/check-json.md) + - [GET](/tidb-cloud-lake/sql/get.md) + - [GET_BY_KEYPATH](/tidb-cloud-lake/sql/get-by-keypath.md) + - [GET_IGNORE_CASE](/tidb-cloud-lake/sql/get-ignore-case.md) + - [GET_PATH](/tidb-cloud-lake/sql/get-path.md) + - [JQ](/tidb-cloud-lake/sql/jq.md) + - [JSON_ARRAY_ELEMENTS](/tidb-cloud-lake/sql/json-array-elements.md) + - [JSON_CONTAINS_IN_LEFT](/tidb-cloud-lake/sql/json-contains-left.md) + - [JSON_EACH](/tidb-cloud-lake/sql/json-each.md) + - [JSON_EXISTS_KEY](/tidb-cloud-lake/sql/json-exists-key.md) + - [JSON_EXTRACT_PATH_TEXT](/tidb-cloud-lake/sql/json-extract-path-text.md) + - [JSON_PATH_EXISTS](/tidb-cloud-lake/sql/json-path-exists.md) + - [JSON_PATH_MATCH](/tidb-cloud-lake/sql/json-path-match.md) + - [JSON_PATH_QUERY](/tidb-cloud-lake/sql/json-path-query.md) + - [JSON_PATH_QUERY_ARRAY](/tidb-cloud-lake/sql/json-path-query-array.md) + - [JSON_PATH_QUERY_FIRST](/tidb-cloud-lake/sql/json-path-query-first.md) + - [JSON_PRETTY](/tidb-cloud-lake/sql/json-pretty.md) + - [JSON_STRIP_NULLS](/tidb-cloud-lake/sql/json-strip-nulls.md) + - [JSON_TO_STRING](/tidb-cloud-lake/sql/json-to-string.md) + - [JSON_TYPEOF](/tidb-cloud-lake/sql/json-typeof.md) + - [PARSE_JSON](/tidb-cloud-lake/sql/parse-json.md) + - [STRIP_NULL_VALUE](/tidb-cloud-lake/sql/strip-null-value.md) + - 数组函数 + - [概览](/tidb-cloud-lake/sql/array-functions.md) + - [ARRAY](/tidb-cloud-lake/sql/array-sql.md) + - [ARRAY_AGGREGATE](/tidb-cloud-lake/sql/array-aggregate.md) + - [ARRAY_ANY](/tidb-cloud-lake/sql/array-any.md) + - [ARRAY_APPEND](/tidb-cloud-lake/sql/array-append.md) + - [ARRAY_APPROX_COUNT_DISTINCT](/tidb-cloud-lake/sql/array-approx-count-distinct.md) + - [ARRAY_AVG](/tidb-cloud-lake/sql/array-avg.md) + - [ARRAY_COMPACT](/tidb-cloud-lake/sql/array-compact.md) + - [ARRAY_CONCAT](/tidb-cloud-lake/sql/array-concat.md) + - [ARRAY_CONSTRUCT](/tidb-cloud-lake/sql/array-construct.md) + - [ARRAY_CONTAINS](/tidb-cloud-lake/sql/array-contains.md) + - [ARRAY_COUNT](/tidb-cloud-lake/sql/array-count.md) + - [ARRAY_DISTINCT](/tidb-cloud-lake/sql/array-distinct.md) + - [ARRAY_EXCEPT](/tidb-cloud-lake/sql/array-except.md) + - [ARRAY_FILTER](/tidb-cloud-lake/sql/array-filter.md) + - [ARRAY_FLATTEN](/tidb-cloud-lake/sql/array-flatten.md) + - [ARRAY_GENERATE_RANGE](/tidb-cloud-lake/sql/array-generate-range.md) + - [ARRAY_GET](/tidb-cloud-lake/sql/array-get.md) + - [ARRAY_INDEXOF](/tidb-cloud-lake/sql/array-indexof.md) + - [ARRAY_INSERT](/tidb-cloud-lake/sql/array-insert.md) + - [ARRAY_INTERSECTION](/tidb-cloud-lake/sql/array-intersection.md) + - [ARRAY_KURTOSIS](/tidb-cloud-lake/sql/array-kurtosis.md) + - [ARRAY_MAX](/tidb-cloud-lake/sql/array-max.md) + - [ARRAY_MEDIAN](/tidb-cloud-lake/sql/array-median.md) + - [ARRAY_MIN](/tidb-cloud-lake/sql/array-min.md) + - [ARRAY_OVERLAP](/tidb-cloud-lake/sql/array-overlap.md) + - [ARRAY_PREPEND](/tidb-cloud-lake/sql/array-prepend.md) + - [ARRAY_REDUCE](/tidb-cloud-lake/sql/array-reduce.md) + - [ARRAY_REMOVE](/tidb-cloud-lake/sql/array-remove.md) + - [ARRAY_REMOVE_FIRST](/tidb-cloud-lake/sql/array-remove-first.md) + - [ARRAY_REMOVE_LAST](/tidb-cloud-lake/sql/array-remove-last.md) + - [ARRAY_REVERSE](/tidb-cloud-lake/sql/array-reverse.md) + - [ARRAY_SIZE](/tidb-cloud-lake/sql/array-size.md) + - [ARRAY_SKEWNESS](/tidb-cloud-lake/sql/array-skewness.md) + - [ARRAY_SLICE](/tidb-cloud-lake/sql/array-slice.md) + - [ARRAY_SORT](/tidb-cloud-lake/sql/array-sort.md) + - [ARRAY_STDDEV_POP](/tidb-cloud-lake/sql/array-stddev-pop.md) + - [ARRAY_STDDEV_SAMP](/tidb-cloud-lake/sql/array-stddev-samp.md) + - [ARRAY_SUM](/tidb-cloud-lake/sql/array-sum.md) + - [ARRAY_TO_STRING](/tidb-cloud-lake/sql/array-to-string.md) + - [JSON_ARRAY_TRANSFORM](/tidb-cloud-lake/sql/json-array-transform.md) + - [ARRAY_UNIQUE](/tidb-cloud-lake/sql/array-unique.md) + - [ARRAYS_ZIP](/tidb-cloud-lake/sql/arrays-zip.md) + - [CONTAINS](/tidb-cloud-lake/sql/contains.md) + - [GET](/tidb-cloud-lake/sql/get-sql.md) + - [RANGE](/tidb-cloud-lake/sql/range.md) + - [SLICE](/tidb-cloud-lake/sql/slice.md) + - [UNNEST](/tidb-cloud-lake/sql/unnest.md) + - 对象函数 + - [对象函数](/tidb-cloud-lake/sql/object-functions.md) + - [OBJECT_CONSTRUCT](/tidb-cloud-lake/sql/object-construct.md) + - [OBJECT_CONSTRUCT_KEEP_NULL](/tidb-cloud-lake/sql/object-construct-keep-null.md) + - [OBJECT_DELETE](/tidb-cloud-lake/sql/object-delete.md) + - [OBJECT_INSERT](/tidb-cloud-lake/sql/object-insert.md) + - [OBJECT_KEYS](/tidb-cloud-lake/sql/object-keys.md) + - [OBJECT_PICK](/tidb-cloud-lake/sql/object-pick.md) + - Map Functions + - [Map 函数](/tidb-cloud-lake/sql/map-functions.md) + - [MAP_CAT](/tidb-cloud-lake/sql/map-cat.md) + - [MAP_CONTAINS_KEY](/tidb-cloud-lake/sql/map-contains-key.md) + - [MAP_DELETE](/tidb-cloud-lake/sql/map-delete.md) + - [MAP_FILTER](/tidb-cloud-lake/sql/map-filter.md) + - [MAP_INSERT](/tidb-cloud-lake/sql/map-insert.md) + - [MAP_KEYS](/tidb-cloud-lake/sql/map-keys.md) + - [MAP_PICK](/tidb-cloud-lake/sql/map-pick.md) + - [MAP_SIZE](/tidb-cloud-lake/sql/map-size.md) + - [MAP_TRANSFORM_KEYS](/tidb-cloud-lake/sql/map-transform-keys.md) + - [MAP_TRANSFORM_VALUES](/tidb-cloud-lake/sql/map-transform-values.md) + - [MAP_VALUES](/tidb-cloud-lake/sql/map-values.md) + - 类型转换 + - [AS_ARRAY](/tidb-cloud-lake/sql/as-array.md) + - [AS_BINARY](/tidb-cloud-lake/sql/as-binary.md) + - [AS_BOOLEAN](/tidb-cloud-lake/sql/as-boolean.md) + - [AS_DATE](/tidb-cloud-lake/sql/as-date.md) + - [AS_DECIMAL](/tidb-cloud-lake/sql/as-decimal.md) + - [AS_FLOAT](/tidb-cloud-lake/sql/as-float.md) + - [AS_INTEGER](/tidb-cloud-lake/sql/as-integer.md) + - [AS_OBJECT](/tidb-cloud-lake/sql/as-object.md) + - [AS_STRING](/tidb-cloud-lake/sql/as-string.md) + - [类型转换函数](/tidb-cloud-lake/sql/type-conversion-functions.md) + - 类型谓词 + - [类型谓词函数](/tidb-cloud-lake/sql/type-predicate-functions.md) + - [IS_ARRAY](/tidb-cloud-lake/sql/is-array.md) + - [IS_BOOLEAN](/tidb-cloud-lake/sql/is-boolean.md) + - [IS_FLOAT](/tidb-cloud-lake/sql/is-float.md) + - [IS_INTEGER](/tidb-cloud-lake/sql/is-integer.md) + - [IS_NULL_VALUE](/tidb-cloud-lake/sql/is-null-value.md) + - [IS_OBJECT](/tidb-cloud-lake/sql/is-object.md) + - [IS_STRING](/tidb-cloud-lake/sql/is-string.md) + - 向量函数 + - [COSINE_DISTANCE](/tidb-cloud-lake/sql/cosine-distance.md) + - [L2_DISTANCE](/tidb-cloud-lake/sql/l2-distance.md) + - [L1_DISTANCE](/tidb-cloud-lake/sql/l1-distance.md) + - [INNER_PRODUCT](/tidb-cloud-lake/sql/inner-product.md) + - [VECTOR_DIMS](/tidb-cloud-lake/sql/vector-dims.md) + - [VECTOR_NORM](/tidb-cloud-lake/sql/vector-norm.md) + - [向量函数](/tidb-cloud-lake/sql/vector-functions.md) + - 散列函数 + - [BLAKE3](/tidb-cloud-lake/sql/blake.md) + - [CITY64WITHSEED](/tidb-cloud-lake/sql/city-withseed.md) + - [散列函数](/tidb-cloud-lake/sql/hash-functions.md) + - [MD5](/tidb-cloud-lake/sql/md.md) + - [SHA](/tidb-cloud-lake/sql/sha.md) + - [SHA1](/tidb-cloud-lake/sql/sha-sql.md) + - [SHA2](/tidb-cloud-lake/sql/sha-functions.md) + - [SIPHASH](/tidb-cloud-lake/sql/siphash.md) + - [SIPHASH64](/tidb-cloud-lake/sql/siphash-sql.md) + - [XXHASH32](/tidb-cloud-lake/sql/xxhash.md) + - [XXHASH64](/tidb-cloud-lake/sql/xxhash-sql.md) + - UUID 函数 + - [概览](/tidb-cloud-lake/sql/uuid-functions.md) + - [GEN_RANDOM_UUID](/tidb-cloud-lake/sql/gen-random-uuid.md) + - [UUID](/tidb-cloud-lake/sql/uuid-sql.md) + - IP 地址函数 + - [IP 地址函数](/tidb-cloud-lake/sql/ip-address-functions.md) + - [INET_ATON](/tidb-cloud-lake/sql/inet-aton.md) + - [INET_NTOA](/tidb-cloud-lake/sql/inet-ntoa.md) + - [IPV4_NUM_TO_STRING](/tidb-cloud-lake/sql/ipv4-num-to-string.md) + - [IPV4_STRING_TO_NUM](/tidb-cloud-lake/sql/ipv4-string-to-num.md) + - [TRY_INET_ATON](/tidb-cloud-lake/sql/try-inet-aton.md) + - [TRY_INET_NTOA](/tidb-cloud-lake/sql/try-inet-ntoa.md) + - [TRY_IPV4_NUM_TO_STRING](/tidb-cloud-lake/sql/try-ipv4-num-to-string.md) + - [TRY_IPV4_STRING_TO_NUM](/tidb-cloud-lake/sql/try-ipv4-string-to-num.md) + - 上下文函数 + - [CONNECTION_ID](/tidb-cloud-lake/sql/connection-id.md) + - [CURRENT_CATALOG](/tidb-cloud-lake/sql/current-catalog.md) + - [CURRENT_USER](/tidb-cloud-lake/sql/current-user.md) + - [DATABASE](/tidb-cloud-lake/sql/database-function.md) + - [上下文函数](/tidb-cloud-lake/sql/context-functions.md) + - [LAST_QUERY_ID](/tidb-cloud-lake/sql/last-query-id.md) + - [VERSION](/tidb-cloud-lake/sql/version.md) + - 系统函数 + - [CLUSTERING_INFORMATION](/tidb-cloud-lake/sql/clustering-information.md) + - [FUSE_BLOCK](/tidb-cloud-lake/sql/fuse-block.md) + - [FUSE_COLUMN](/tidb-cloud-lake/sql/fuse-column.md) + - [FUSE_ENCODING](/tidb-cloud-lake/sql/fuse-encoding.md) + - [FUSE_SEGMENT](/tidb-cloud-lake/sql/fuse-segment.md) + - [FUSE_SNAPSHOT](/tidb-cloud-lake/sql/fuse-snapshot.md) + - [FUSE_STATISTIC](/tidb-cloud-lake/sql/fuse-statistic.md) + - [FUSE_TAG](/tidb-cloud-lake/sql/fuse-tag.md) + - [FUSE_TIME_TRAVEL_SIZE](/tidb-cloud-lake/sql/fuse-time-travel-size.md) + - [FUSE_VIRTUAL_COLUMN](/tidb-cloud-lake/sql/fuse-virtual-column.md) + - [系统函数](/tidb-cloud-lake/sql/system-functions-sql.md) + - 表函数 + - [概览](/tidb-cloud-lake/sql/table-functions.md) + - [INFER_SCHEMA](/tidb-cloud-lake/sql/infer-schema.md) + - [INSPECT_PARQUET](/tidb-cloud-lake/sql/inspect-parquet.md) + - [LIST_STAGE](/tidb-cloud-lake/sql/list-stage.md) + - [GENERATE_SERIES](/tidb-cloud-lake/sql/generate-series.md) + - [FLATTEN](/tidb-cloud-lake/sql/flatten.md) + - [SYSTEM$FUSE_AMEND](/tidb-cloud-lake/sql/system-fuse-amend.md) + - [FUSE_VACUUM_TEMPORARY_TABLE](/tidb-cloud-lake/sql/fuse-vacuum-temporary-table.md) + - [GET_LINEAGE](/tidb-cloud-lake/sql/get-lineage.md) + - [ICEBERG_MANIFEST](/tidb-cloud-lake/sql/iceberg-manifest.md) + - [ICEBERG_SNAPSHOT](/tidb-cloud-lake/sql/iceberg-snapshot.md) + - [POLICY_REFERENCES](/tidb-cloud-lake/sql/policy-references.md) + - [RESULT_SCAN](/tidb-cloud-lake/sql/result-scan.md) + - [SYSTEM$SET_CACHE_CAPACITY](/tidb-cloud-lake/sql/set-cache-capacity.md) + - [SHOW_GRANTS](/tidb-cloud-lake/sql/show-grants-sql.md) + - [SHOW_VARIABLES](/tidb-cloud-lake/sql/show-variables-sql.md) + - [STREAM_STATUS](/tidb-cloud-lake/sql/stream-status.md) + - [TAG_REFERENCES](/tidb-cloud-lake/sql/tag-references.md) + - [TASK_HISTORY](/tidb-cloud-lake/sql/task-history.md) + - 序列函数 + - [概览](/tidb-cloud-lake/sql/sequence-functions-overview.md) + - [NEXTVAL](/tidb-cloud-lake/sql/nextval.md) + - 数据匿名化函数 + - [FEISTEL_OBFUSCATE](/tidb-cloud-lake/sql/feistel-obfuscate.md) + - [数据匿名化函数](/tidb-cloud-lake/sql/data-anonymization-functions.md) + - [MARKOV_GENERATE](/tidb-cloud-lake/sql/markov-generate.md) + - [OBFUSCATE](/tidb-cloud-lake/sql/obfuscate.md) + - 测试函数 + - [测试函数](/tidb-cloud-lake/sql/test-functions.md) + - [SLEEP](/tidb-cloud-lake/sql/sleep.md) + - 其他函数 + - [概览](/tidb-cloud-lake/sql/other-functions.md) + - [ASSUME_NOT_NULL](/tidb-cloud-lake/sql/assume-not-null.md) + - [EXISTS](/tidb-cloud-lake/sql/exists.md) + - [GROUPING](/tidb-cloud-lake/sql/grouping.md) + - [HUMANIZE_NUMBER](/tidb-cloud-lake/sql/humanize-number.md) + - [HUMANIZE_SIZE](/tidb-cloud-lake/sql/humanize-size.md) + - [READ_FILE](/tidb-cloud-lake/sql/read-file.md) + - [REMOVE_NULLABLE](/tidb-cloud-lake/sql/remove-nullable.md) + - [TO_NULLABLE](/tidb-cloud-lake/sql/nullable.md) + - [TYPEOF](/tidb-cloud-lake/sql/typeof.md) + - [存储过程与脚本](/tidb-cloud-lake/sql/stored-procedure-scripting.md) +- 常规参考 + - [架构](/tidb-cloud-lake/guides/tidb-cloud-lake-architecture.md) + - 实现原理深入解析 + - [Fuse Engine](/tidb-cloud-lake/guides/how-fuse-engine-works.md) + - [优化器](/tidb-cloud-lake/guides/how-optimizer-works.md) + - [JSON](/tidb-cloud-lake/guides/how-json-variant-works.md) + - [数据共享](/tidb-cloud-lake/guides/how-data-sharing-works.md) + - [版本](/tidb-cloud-lake/guides/editions.md) + - [平台与 Region](/tidb-cloud-lake/guides/platforms-regions.md) + - 基准测试 + - [数据摄取基准测试](/tidb-cloud-lake/guides/benchmark-data-ingestion.md) + - [TPC-H SF100 基准测试](/tidb-cloud-lake/guides/benchmark-tpch-sf100.md) + - [TPC-H SF1000 基准测试](/tidb-cloud-lake/guides/benchmark-tpch-sf1000.md) +- [支持服务](/tidb-cloud-lake/guides/support-services.md) diff --git a/tidb-cloud-lake/_index.md b/tidb-cloud-lake/_index.md new file mode 100644 index 0000000000000..bee6249265ec7 --- /dev/null +++ b/tidb-cloud-lake/_index.md @@ -0,0 +1,118 @@ +--- +title: TiDB Cloud Lake 文档 +hide_sidebar: true +hide_commit: true +summary: TiDB Cloud Lake 是一项面向分析型工作负载的云原生数据仓库服务。它采用计算与存储分离架构,并支持 ANSI SQL、半结构化数据处理和面向 AI 的工作流。 +--- + + + + + +[TiDB Cloud Lake 概览](https://docs.pingcap.com/zh/tidbcloudlake/lake-overview/) + +[架构](https://docs.pingcap.com/zh/tidbcloudlake/tidb-cloud-lake-architecture/) + +[版本](https://docs.pingcap.com/zh/tidbcloudlake/editions/) + + + + + +[快速入门](https://docs.pingcap.com/zh/tidbcloudlake/lake-quick-start/) + +[从 Snowflake 迁移](https://docs.pingcap.com/zh/tidbcloudlake/migrate-from-snowflake/) + +[使用 Vector 导入 JSON 日志](https://docs.pingcap.com/zh/tidbcloudlake/ingest-json-logs-with-vector-cloud/) + + + + + +[连接概览](https://docs.pingcap.com/zh/tidbcloudlake/connection-overview/) + +[使用 LakeSQL 连接](https://docs.pingcap.com/zh/tidbcloudlake/connect-using-lakesql/) + +[使用 Golang 连接](https://docs.pingcap.com/zh/tidbcloudlake/connect-using-golang/) + +[使用 Tableau 连接](https://docs.pingcap.com/zh/tidbcloudlake/tableau/) + +[使用 AWS PrivateLink 连接](https://docs.pingcap.com/zh/tidbcloudlake/connect-with-aws-privatelink/) + +[使用 Alibaba Cloud PrivateLink 连接](https://docs.pingcap.com/zh/tidbcloudlake/connect-with-alibaba-cloud-privatelink/) + + + + + +[数据集成概览](https://docs.pingcap.com/zh/tidbcloudlake/data-integration-overview/) + +[数据源](https://docs.pingcap.com/zh/tidbcloudlake/data-sources/) + +[集成任务](https://docs.pingcap.com/zh/tidbcloudlake/integration-tasks/) + + + + + +[Stage 概述](https://docs.pingcap.com/zh/tidbcloudlake/stage-overview/) + +[从文件加载](https://docs.pingcap.com/zh/tidbcloudlake/load-from-files/) + +[查询与转换](https://docs.pingcap.com/zh/tidbcloudlake/query-stage/) + +[持续数据管道](https://docs.pingcap.com/zh/tidbcloudlake/continuous-data-pipelines/) + + + + + +[多模态数据分析](https://docs.pingcap.com/zh/tidbcloudlake/multimodal-data-analytics/) + +[SQL 分析](https://docs.pingcap.com/zh/tidbcloudlake/sql-analytics/) + +[向量搜索](https://docs.pingcap.com/zh/tidbcloudlake/vector-search-guide/) + + + + + +[管理成本](https://docs.pingcap.com/zh/tidbcloudlake/manage-costs/) + +[监控使用情况](https://docs.pingcap.com/zh/tidbcloudlake/monitor-usage/) + +[AI-Powered 的功能](https://docs.pingcap.com/zh/tidbcloudlake/ai-powered-features/) + +[性能优化](https://docs.pingcap.com/zh/tidbcloudlake/performance-optimization/) + +[故障排查](https://docs.pingcap.com/zh/tidbcloudlake/troubleshooting/) + + + + + +[安全性与可靠性](https://docs.pingcap.com/zh/tidbcloudlake/security-reliability/) + +[访问控制](https://docs.pingcap.com/zh/tidbcloudlake/access-control/) + +[数据保护策略](https://docs.pingcap.com/zh/tidbcloudlake/data-protection-policies/) + +[使用 AWS IAM Role 进行认证](https://docs.pingcap.com/zh/tidbcloudlake/authenticate-with-aws-iam-role/) + +[合规与安全](https://docs.pingcap.com/zh/tidbcloudlake/compliance-security/) + + + + + +[SQL 语句概览](https://docs.pingcap.com/zh/tidbcloudlake/sql-statements-overview/) + +[价格与计费](https://docs.pingcap.com/zh/tidbcloudlake/pricing-billing/) + +[数据摄取基准测试](https://docs.pingcap.com/zh/tidbcloudlake/benchmark-data-ingestion/) + +[支持服务](https://docs.pingcap.com/zh/tidbcloudlake/support-services/) + + + + diff --git a/tidb-cloud-lake/guides/access-control.md b/tidb-cloud-lake/guides/access-control.md new file mode 100644 index 0000000000000..e529ec5c4d71f --- /dev/null +++ b/tidb-cloud-lake/guides/access-control.md @@ -0,0 +1,22 @@ +--- +title: 访问控制 +summary: 了解 TiDB Cloud Lake 中的访问控制。它结合使用基于角色的访问控制(RBAC)和自主访问控制(DAC)来管理数据库、表、视图等数据对象的权限。 +--- + +# 访问控制 + +{{{ .lake }}} 的访问控制功能同时采用了 [Role-Based Access Control (RBAC)](https://en.wikipedia.org/wiki/Role-based_access_control) 和 [Discretionary Access Control (DAC)](https://en.wikipedia.org/wiki/Discretionary_access_control) 模型。当用户访问 {{{ .lake }}} 中的数据对象时,必须被授予适当的权限或角色,或者拥有该数据对象的所有权。数据对象可以指多种元素,例如数据库、表、视图、stage 或 UDF。 + +![Access control](/media/tidb-cloud-lake/access-control-1.png) + +| 概念 | 描述 | +|-----------|------------------------------------------------------------| +| 权限 | 权限在与 {{{ .lake }}} 中的数据对象交互时起着关键作用。这些权限(如读、写和执行)能够对用户操作进行精细控制,从而确保符合用户需求并维护数据安全。 | +| 角色 | 角色可简化访问控制。角色是分配给用户的预定义权限集合,可简化权限管理。管理员可以根据职责对用户进行分类,从而高效授予权限,而无需逐一进行单独配置。 | +| 所有权 | 所有权是一种用于控制数据访问的特殊权限。当用户拥有某个数据对象时,他们具有最高级别的控制权,可以决定访问权限。这种直接的所有权模型使用户能够管理自己的数据,并控制在 {{{ .lake }}} 环境中谁可以访问或修改这些数据。 | + +本指南介绍相关概念,并提供如何在 {{{ .lake }}} 中管理访问控制的说明: + +- [权限](/tidb-cloud-lake/guides/privileges.md) +- [角色](/tidb-cloud-lake/guides/roles.md) +- [所有权](/tidb-cloud-lake/guides/ownership.md) \ No newline at end of file diff --git a/tidb-cloud-lake/guides/aggregating-index.md b/tidb-cloud-lake/guides/aggregating-index.md new file mode 100644 index 0000000000000..1f1bb326c3639 --- /dev/null +++ b/tidb-cloud-lake/guides/aggregating-index.md @@ -0,0 +1,149 @@ +--- +title: 聚合索引 +summary: 聚合索引通过预计算并存储聚合结果,显著加速分析型查询,避免在常见分析操作中扫描整张表。 +--- + +# 聚合索引 + +聚合索引通过预计算并存储聚合结果,显著加速分析型查询,避免在常见分析操作中扫描整张表。 + +## 它解决了什么问题? {#what-problem-does-it-solve} + +大规模数据集上的分析型查询会面临显著的性能挑战: + +| 问题 | 影响 | 聚合索引解决方案 | +|---------|--------|---------------------------| +| **全表扫描** | SUM、COUNT、MIN、MAX 查询需要扫描数百万行 | 直接读取预计算结果 | +| **重复计算** | 相同的聚合被反复计算 | 结果只存储一次,多次复用 | +| **仪表盘查询缓慢** | 分析仪表盘加载需要数分钟 | 常见指标可实现亚秒级响应 | +| **计算成本高** | 大量聚合负载会消耗资源 | 对缓存结果仅需极少计算 | +| **用户体验差** | 用户需要等待报表和分析结果 | 为商业智能提供即时结果 | + +**示例**:销售分析查询 `SELECT SUM(revenue), COUNT(*) FROM sales WHERE region = 'US'` 需要处理 1 亿行数据。没有聚合索引时,它需要扫描所有美国销售记录;有了聚合索引后,它可以立即返回预计算结果。 + +## 工作原理 {#how-it-works} + +1. **创建索引** → 定义需要预计算的聚合查询 +2. **结果存储** → {{{ .lake }}} 将聚合结果存储在优化后的数据块中 +3. **查询匹配** → 传入的查询会自动使用预计算结果 +4. **自动修改** → 当底层数据发生变化时,结果会刷新 + +## 快速开始 {#quick-setup} + +```sql +-- Create table with sample data +CREATE TABLE sales(region VARCHAR, product VARCHAR, revenue DECIMAL, quantity INT); + +-- Create aggregating index for common analytics +CREATE AGGREGATING INDEX sales_summary AS +SELECT region, SUM(revenue), COUNT(*), AVG(quantity) +FROM sales +GROUP BY region; + +-- Refresh the index (manual mode) +REFRESH AGGREGATING INDEX sales_summary; + +-- Verify the index is used +EXPLAIN SELECT region, SUM(revenue) FROM sales GROUP BY region; +``` + +## 支持的操作 {#supported-operations} + +| ✅ 支持 | ❌ 不支持 | +|-------------|-----------------| +| SUM、COUNT、MIN、MAX、AVG | 窗口函数 | +| GROUP BY 子句 | GROUPING SETS | +| WHERE 过滤条件 | ORDER BY、LIMIT | +| 简单聚合 | 复杂子查询 | + +## 刷新策略 {#refresh-strategies} + +| 策略 | 适用场景 | 配置 | +|----------|-------------|---------------| +| **自动(SYNC)** | 实时分析、小规模数据集 | `CREATE AGGREGATING INDEX ... SYNC` | +| **手动** | 大规模数据集、批处理 | `CREATE AGGREGATING INDEX ...`(默认) | +| **后台(Cloud)** | 生产负载 | 在 {{{ .lake }}} 中自动执行 | + +### 自动刷新与手动刷新 {#automatic-vs-manual-refresh} + +```sql +-- Automatic refresh (updates with every data change) +CREATE AGGREGATING INDEX auto_summary AS +SELECT region, SUM(revenue) FROM sales GROUP BY region SYNC; + +-- Manual refresh (update on demand) +CREATE AGGREGATING INDEX manual_summary AS +SELECT region, SUM(revenue) FROM sales GROUP BY region; + +REFRESH AGGREGATING INDEX manual_summary; +``` + +## 性能示例 {#performance-example} + +以下示例展示了显著的性能提升: + +```sql +-- Prepare data +CREATE TABLE agg(a int, b int, c int); +INSERT INTO agg VALUES (1,1,4), (1,2,1), (1,2,4), (2,2,5); + +-- Create an aggregating index +CREATE AGGREGATING INDEX my_agg_index AS SELECT MIN(a), MAX(c) FROM agg; + +-- Refresh the aggregating index +REFRESH AGGREGATING INDEX my_agg_index; + +-- Verify if the aggregating index works +EXPLAIN SELECT MIN(a), MAX(c) FROM agg; + +-- Key indicators in the execution plan: +-- ├── aggregating index: [SELECT MIN(a), MAX(c) FROM default.agg] +-- ├── rewritten query: [selection: [index_col_0 (#0), index_col_1 (#1)]] +-- This shows the query uses precomputed results instead of scanning raw data +``` + +## 最佳实践 {#best-practices} + +| 实践 | 收益 | +|----------|---------| +| **为常见查询建立索引** | 聚焦于频繁执行的分析查询 | +| **使用手动刷新** | 更好地控制修改时机 | +| **监控索引使用情况** | 使用 EXPLAIN 验证索引是否被利用 | +| **清理未使用的索引** | 删除未被使用的索引 | +| **匹配查询模式** | 索引过滤条件应与实际查询一致 | + +## 管理命令 {#management-commands} + +| 命令 | 用途 | +|---------|---------| +| `CREATE AGGREGATING INDEX` | 创建新的聚合索引 | +| `REFRESH AGGREGATING INDEX` | 使用最新数据修改索引 | +| `DROP AGGREGATING INDEX` | 删除索引(使用 VACUUM TABLE 清理存储) | +| `SHOW AGGREGATING INDEXES` | 列出所有索引 | + +## 重要说明 {#important-notes} + +**适合使用聚合索引的场景:** + +- 频繁的分析型查询(仪表盘、报表) +- 具有重复聚合的大规模数据集 +- 稳定的查询模式 +- 对性能要求高的应用 + +**不适合使用的场景:** + +- 数据频繁变化 +- 一次性的分析型查询 +- 小表上的简单查询 + +## 配置 {#configuration} + +```sql +-- Enable/disable aggregating index feature +SET enable_aggregating_index_scan = 1; -- Enable (default) +SET enable_aggregating_index_scan = 0; -- Disable +``` + +--- + +*聚合索引最适用于大规模数据集上的重复性分析负载。建议从最常用的仪表盘和报表查询开始。* \ No newline at end of file diff --git a/tidb-cloud-lake/guides/ai-powered-features.md b/tidb-cloud-lake/guides/ai-powered-features.md new file mode 100644 index 0000000000000..8733b4c591e5c --- /dev/null +++ b/tidb-cloud-lake/guides/ai-powered-features.md @@ -0,0 +1,32 @@ +--- +title: AI 驱动功能 +summary: 借助 AI 驱动功能,TiDB Cloud Lake 允许你通过自然语言对话获取帮助、支持和解决方案。 +--- + +# AI 驱动功能 + +借助 AI 驱动功能,{{{ .lake }}} 允许你通过自然语言对话获取帮助、支持和解决方案。这些 AI 驱动功能默认启用,但如果你希望禁用它们,可以导航到 **Manage** > **Settings**。 + +## 用于协助的 AI Chat {#ai-chat-for-assistance} + +AI Chat 支持自然语言交互,使信息检索更加直观,并简化问题解决流程。 + +要启动 AI-Chat,请执行以下操作: + +1. 点击侧边栏中的放大镜图标 以打开搜索框。 + +2. 切换到 **Chat** 标签页。 + +3. 输入你的问题。 + +### AI 驱动的 SQL Assistant {#ai-powered-sql-assistant} + +在工作区 (Worksheet) 中编辑 SQL 语句时,可以使用 AI 辅助。你无需从头编写 SQL,AI 可以为你生成。 + +要在编辑 SQL 语句时使用 AI,只需在新行开头输入 "/",然后输入你的查询,例如 "return current time": + +![Alt text](/media/tidb-cloud-lake/ai-worksheet-1.gif) + +你还可以为现有 SQL 语句获取 AI 辅助。为此,请选中你的 SQL 并点击 **Edit**,以指定你希望进行的更改或请求进一步帮助。或者,点击 **Chat** 与 AI 展开对话,以获得更全面的支持。 + +![Alt text](/media/tidb-cloud-lake/ai-worksheet-2.gif) \ No newline at end of file diff --git a/tidb-cloud-lake/guides/amazon-sqs-s3-iam-role.md b/tidb-cloud-lake/guides/amazon-sqs-s3-iam-role.md new file mode 100644 index 0000000000000..a80c9713483fc --- /dev/null +++ b/tidb-cloud-lake/guides/amazon-sqs-s3-iam-role.md @@ -0,0 +1,422 @@ +--- +title: Amazon SQS (S3) - IAM Role (Beta) +summary: 了解如何在 {{{ .lake }}} 中创建 `Amazon SQS (S3) - IAM Role` 数据源。 +--- + +# Amazon SQS (S3) - IAM Role (Beta) + +本页介绍如何创建 `Amazon SQS (S3) - IAM Role` 数据源。该数据源存储访问 Amazon SQS 队列及其对应 S3 存储桶所需的配置,用于消费从 Amazon S3 投递到 SQS 的 S3 对象创建事件。 + +`Amazon SQS (S3) - IAM Role` 仅存储 SQS (S3) 导入所需的连接和授权信息。它本身不会消费消息。实际读取 SQS 消息、解析 S3 ObjectCreated 事件并将数据写入 {{{ .lake }}} 的过程,由 [Amazon SQS (S3) 集成任务](/tidb-cloud-lake/guides/integrate-with-amazon-sqs-s3.md) 执行。 + +## 使用场景 {#use-cases} + +- 集中管理 SQS (S3) 导入所需的队列 URL、Region、IAM Role 和路径作用域 +- 消费 S3 `ObjectCreated` 事件,并将对应的对象数据写入 {{{ .lake }}} +- 使用 S3 事件通知驱动数据导入,而不是仅依赖轮询 S3 路径 +- 当被多个任务引用时,在一个位置统一修改 IAM Role、队列 URL 或路径作用域 + +## 创建 Amazon SQS (S3) - IAM Role {#create-amazon-sqs-s3-iam-role} + +1. 导航到 **Data** > **Data Sources**,然后点击 **Create Data Source**。 +2. 选择 **Amazon SQS (S3) - IAM Role** 作为服务类型,然后填写连接详情: + + | Field | Required | Description | + |-------|----------|-------------| + | **Name** | Yes | 数据源的描述性名称 | + | **Queue URL** | Yes | SQS 标准队列 URL,例如 `https://sqs.us-east-1.amazonaws.com/123456789012/my-queue` | + | **Queue Region** | Yes | SQS 队列所在的 AWS Region,例如 `us-east-1`。S3 存储桶必须与 SQS 队列位于同一 Region | + | **Role ARN** | Yes | 你的 AWS 账户中允许 {{{ .lake }}} 扮演的 IAM Role ARN | + | **External ID** | Yes | 来自 {{{ .lake }}} 控制台的组织 ID,用于 IAM Role 信任策略 | + | **Bucket** | Yes | 发送 ObjectCreated 事件的 S3 存储桶名称 | + | **Object Key Prefix** | No | S3 对象键的前缀过滤器。它应与 S3 通知过滤器匹配 | + | **Object Key Suffix** | No | S3 对象键的后缀过滤器。它应与 S3 通知过滤器匹配 | + +3. 点击 **Test Connectivity** 验证连接。如果测试成功,点击 **OK** 保存数据源。 + + > **Note:** + > + > SQS (S3) 导入使用 AssumeRole 模型。你无需向 {{{ .lake }}} 提供 AWS Access Key 或 Secret Key。相反,你需要在自己的 AWS 账户中创建一个 IAM Role,并在该角色的信任策略中允许 {{{ .lake }}} 平台角色通过 `sts:AssumeRole` 获取临时凭证。 + +## AWS 侧配置概览 {#aws-side-configuration-overview} + +在创建数据源之前,请先在你的 AWS 账户中完成以下配置: + +1. 创建或准备一个 SQS 标准队列。 +2. 配置 SQS 队列策略,允许指定的 S3 存储桶向该队列发送消息。 +3. 配置 S3 存储桶通知,将 `ObjectCreated` 事件发送到 SQS 队列。 +4. 创建一个 IAM Role,允许 {{{ .lake }}} 平台角色通过 `sts:AssumeRole` 访问该角色。 +5. 为该 IAM Role 附加 S3 读权限和 SQS 消费权限。 +6. 上传一个测试对象,并确认 S3 能够将事件投递到 SQS。 + +请先准备以下变量。`AWS_REGION` 必须是 S3 存储桶和 SQS 队列所在的 Region。`EXTERNAL_ID` 是来自 {{{ .lake }}} 平台控制台的组织 ID。 + +```bash +export AWS_REGION="" +export AWS_ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text) + +export BUCKET_NAME="" +export BUCKET_ARN="arn:aws:s3:::$BUCKET_NAME" + +export QUEUE_NAME="" +export ROLE_NAME="platform-s3-sqs-consumer-role" + +export PREFIX="" +export SUFFIX="" + +export PLATFORM_SETUP_ROLE_ARN="" +export PLATFORM_LOAD_ROLE_ARN="" +export EXTERNAL_ID="" +``` + +> **Tip:** +> +> 使用 Platform 提供的角色 ARN:`PLATFORM_SETUP_ROLE_ARN` 是 **Platform setup and validation role** 的 ARN,`PLATFORM_LOAD_ROLE_ARN` 是 **Platform data loading role** 的 ARN。在大多数情况下,你的 IAM Role 信任策略应同时信任这两个平台角色。 + +## 第 1 步:创建或获取 SQS 标准队列 {#step-1-create-or-get-an-sqs-standard-queue} + +创建一个 SQS 标准队列: + +```bash +aws sqs create-queue \ + --region "$AWS_REGION" \ + --queue-name "$QUEUE_NAME" +``` + +获取后续步骤所需的队列 URL 和队列 ARN: + +```bash +export QUEUE_URL=$( + aws sqs get-queue-url \ + --region "$AWS_REGION" \ + --queue-name "$QUEUE_NAME" \ + --query 'QueueUrl' \ + --output text +) + +export QUEUE_ARN=$( + aws sqs get-queue-attributes \ + --region "$AWS_REGION" \ + --queue-url "$QUEUE_URL" \ + --attribute-names QueueArn \ + --query 'Attributes.QueueArn' \ + --output text +) +``` + +我们建议为每个 SQS (S3) 数据源使用专用的 SQS 标准队列。不要将同一个队列复用于其他存储桶、其他前缀/后缀作用域或其他业务事件。 + +## 第 2 步:配置 SQS 队列策略 {#step-2-configure-the-sqs-queue-policy} + +在进行修改前,先备份当前的 SQS 属性: + +```bash +aws sqs get-queue-attributes \ + --region "$AWS_REGION" \ + --queue-url "$QUEUE_URL" \ + --attribute-names Policy QueueArn \ + > "sqs-attributes.backup.$(date +%Y%m%d-%H%M%S).json" +``` + +生成 `queue-policy.json`,仅允许指定的 S3 存储桶发送消息: + +```bash +jq -n \ + --arg policyId "$QUEUE_NAME-policy" \ + --arg queueArn "$QUEUE_ARN" \ + --arg bucketArn "$BUCKET_ARN" \ + --arg accountId "$AWS_ACCOUNT_ID" \ + '{ + Version: "2012-10-17", + Id: $policyId, + Statement: [ + { + Sid: "AllowS3ToSendMessage", + Effect: "Allow", + Principal: { + Service: "s3.amazonaws.com" + }, + Action: "sqs:SendMessage", + Resource: $queueArn, + Condition: { + ArnLike: { + "aws:SourceArn": $bucketArn + }, + StringEquals: { + "aws:SourceAccount": $accountId + } + } + } + ] + }' \ + > queue-policy.json +``` + +应用该策略: + +```bash +jq -n \ + --arg policy "$(jq -c . queue-policy.json)" \ + '{Policy: $policy}' \ + > set-queue-attributes.json + +aws sqs set-queue-attributes \ + --region "$AWS_REGION" \ + --queue-url "$QUEUE_URL" \ + --attributes file://set-queue-attributes.json +``` + +## Step 3: 配置 S3 Bucket Notification {#step-3-configure-s3-bucket-notification} + +在进行修改前,先备份当前的 bucket notification。`put-bucket-notification-configuration` 会替换整个 bucket notification 配置。如果该 bucket 已经有其他通知配置,请先将它们合并,再应用新的配置。 + +```bash +aws s3api get-bucket-notification-configuration \ + --region "$AWS_REGION" \ + --bucket "$BUCKET_NAME" \ + > "bucket-notification.backup.$(date +%Y%m%d-%H%M%S).json" +``` + +生成 `bucket-notification.json`: + +```bash +jq -n \ + --arg id "$QUEUE_NAME" \ + --arg queueArn "$QUEUE_ARN" \ + --arg prefix "$PREFIX" \ + --arg suffix "$SUFFIX" \ + '{ + QueueConfigurations: [ + ( + { + Id: $id, + QueueArn: $queueArn, + Events: [ + "s3:ObjectCreated:*" + ] + } + + + ( + [ + if $prefix != "" then {Name: "prefix", Value: $prefix} else empty end, + if $suffix != "" then {Name: "suffix", Value: $suffix} else empty end + ] as $rules + | if ($rules | length) > 0 + then {Filter: {Key: {FilterRules: $rules}}} + else {} + end + ) + ) + ] + }' \ + > bucket-notification.json +``` + +应用该配置: + +```bash +aws s3api put-bucket-notification-configuration \ + --region "$AWS_REGION" \ + --bucket "$BUCKET_NAME" \ + --notification-configuration file://bucket-notification.json +``` + +检查配置: + +```bash +aws s3api get-bucket-notification-configuration \ + --region "$AWS_REGION" \ + --bucket "$BUCKET_NAME" +``` + +确认 `QueueArn` 指向目标 SQS 队列,`Events` 包含 `s3:ObjectCreated:*`,并且 `FilterRules` 与 {{{ .lake }}} 数据源中配置的 `Object Key Prefix` / `Object Key Suffix` 一致。 + +## Step 4: 创建供 {{{ .lake }}} Assume 的 IAM Role {#step-4-create-an-iam-role-for-lake-to-assume} + +生成 `trust-policy.json`。`ExternalId` 是来自 {{{ .lake }}}(platform)控制台的组织 ID。 + +```bash +jq -n \ + --arg platformSetupRoleArn "$PLATFORM_SETUP_ROLE_ARN" \ + --arg platformLoadRoleArn "$PLATFORM_LOAD_ROLE_ARN" \ + --arg externalId "$EXTERNAL_ID" \ + '{ + Version: "2012-10-17", + Statement: [ + { + Sid: "AllowPlatformSetupAssumeRole", + Effect: "Allow", + Principal: { + AWS: $platformSetupRoleArn + }, + Action: "sts:AssumeRole", + Condition: { + StringEquals: { + "sts:ExternalId": $externalId + } + } + }, + { + Sid: "AllowPlatformLoadAssumeRole", + Effect: "Allow", + Principal: { + AWS: $platformLoadRoleArn + }, + Action: "sts:AssumeRole", + Condition: { + StringEquals: { + "sts:ExternalId": $externalId + } + } + } + ] + }' \ + > trust-policy.json +``` + +创建 IAM Role: + +```bash +aws iam create-role \ + --role-name "$ROLE_NAME" \ + --assume-role-policy-document file://trust-policy.json +``` + +如果该 role 已存在,请备份并修改 trust policy: + +```bash +aws iam get-role \ + --role-name "$ROLE_NAME" \ + --query 'Role.AssumeRolePolicyDocument' \ + --output json \ + > "trust-policy.backup.$(date +%Y%m%d-%H%M%S).json" + +aws iam update-assume-role-policy \ + --role-name "$ROLE_NAME" \ + --policy-document file://trust-policy.json +``` + +## Step 5: 附加 S3/SQS 权限 {#step-5-attach-s3-sqs-permissions} + +生成 `permissions-policy.json`: + +```bash +jq -n \ + --arg bucketArn "$BUCKET_ARN" \ + --arg objectArn "$BUCKET_ARN/*" \ + --arg queueArn "$QUEUE_ARN" \ + '{ + Version: "2012-10-17", + Statement: [ + { + Sid: "S3BucketMetadataAccess", + Effect: "Allow", + Action: [ + "s3:GetBucketLocation", + "s3:ListBucket" + ], + Resource: $bucketArn + }, + { + Sid: "S3ObjectReadAccess", + Effect: "Allow", + Action: [ + "s3:GetObject" + ], + Resource: $objectArn + }, + { + Sid: "SQSConsumeAccess", + Effect: "Allow", + Action: [ + "sqs:ReceiveMessage", + "sqs:DeleteMessage", + "sqs:GetQueueAttributes", + "sqs:ChangeMessageVisibility" + ], + Resource: $queueArn + } + ] + }' \ + > permissions-policy.json +``` + +应用权限: + +```bash +aws iam put-role-policy \ + --role-name "$ROLE_NAME" \ + --policy-name platform-s3-sqs-access \ + --policy-document file://permissions-policy.json +``` + +权限检查清单: + +- SQS 权限的作用域限定为目标队列 ARN。 +- S3 权限的作用域限定为目标 bucket 和对象 ARN。 +- 默认情况下,此策略不需要 S3 写入或删除权限。 +- 如果未来的 SQS(S3)集成任务启用了 **PURGE** 或 **Clean Up Original Files**,即在成功导入后删除源对象,则需要对目标对象路径授予 `s3:DeleteObject` 权限。 + +## 第 6 步:验证 S3 到 SQS {#step-6-verify-s3-to-sqs} + +上传一个与 `PREFIX` / `SUFFIX` 匹配的测试对象: + +```bash +echo 'a,b' > /tmp/sqs-s3-local-test.csv + +aws s3 cp /tmp/sqs-s3-local-test.csv \ + "s3://$BUCKET_NAME/${PREFIX}sqs-s3-local-test-$(date +%s)$SUFFIX" \ + --region "$AWS_REGION" +``` + +从 SQS 接收一条消息: + +```bash +aws sqs receive-message \ + --region "$AWS_REGION" \ + --queue-url "$QUEUE_URL" \ + --max-number-of-messages 1 \ + --wait-time-seconds 10 \ + --visibility-timeout 60 +``` + +确认消息中包含 `Records`,`eventSource` 为 `aws:s3`,`eventName` 为 `ObjectCreated:*`,并且 `Records[].s3.bucket.name` 和 `Records[].s3.object.key` 与测试对象一致。 + +> **注意:** +> +> `receive-message` 不会自动删除消息。它只会在可见性超时时间内暂时隐藏该消息。如果你希望 {{{ .lake }}} 稍后消费这条测试消息,请不要手动删除它。在测试数据源连通性之前,请等待可见性超时过期。 + +## 提供给 {{{ .lake }}} 的信息 {#information-to-provide-to-lake} + +完成 AWS 侧配置后,在 {{{ .lake }}} 中创建数据源时填写以下信息: + +| 参数 | 说明 | +|-----------|-------------| +| `role_arn` | 你的 AWS 账户中允许 {{{ .lake }}} 扮演的 IAM Role ARN | +| `external_id` | 来自 {{{ .lake }}} 控制台的 Organization ID | +| `queue_url` | SQS 标准队列 URL | +| `queue_region` | SQS 队列所在的 Region | +| `bucket` | S3 存储桶名称 | +| `prefix` / `suffix` | 可选。应与 S3 notification filter 匹配 | + +获取 `role_arn` 的命令示例: + +```bash +aws iam get-role \ + --role-name "$ROLE_NAME" \ + --query 'Role.Arn' \ + --output text +``` + +## 配置要求 {#configuration-requirements} + +- S3 存储桶和 SQS 队列应位于同一个 AWS Region。 +- SQS 队列必须是标准队列。不支持 FIFO 队列。 +- SQS 队列应专用于一条 S3 notification rule。不要将其复用于其他存储桶、其他 prefix / suffix 作用域或其他业务事件。 +- S3 notification 中的 bucket、prefix 和 suffix 应与 {{{ .lake }}} 数据源配置保持一致。 +- `put-bucket-notification-configuration` 会替换整个存储桶 notification 配置。应用更改前,请先备份并合并现有配置。 +- S3 event notifications 和 SQS 标准队列都采用至少一次投递,因此消息可能会重复。 + +## 后续步骤 {#next-steps} + +创建此数据源后,你可以使用它来创建 [Amazon SQS (S3) 集成任务](/tidb-cloud-lake/guides/integrate-with-amazon-sqs-s3.md)。 \ No newline at end of file diff --git a/tidb-cloud-lake/guides/audit-trail.md b/tidb-cloud-lake/guides/audit-trail.md new file mode 100644 index 0000000000000..0a876eff35f2b --- /dev/null +++ b/tidb-cloud-lake/guides/audit-trail.md @@ -0,0 +1,113 @@ +--- +title: 审计追踪 +summary: "{{{ .lake }}} system history tables 会自动捕获数据库活动的详细记录,为合规性和安全监控提供完整的审计追踪。" +--- + +# 审计追踪 + +{{{ .lake }}} system history tables 会自动捕获数据库活动的详细记录,为合规性和安全监控提供完整的审计追踪。 + +支持对以下用户活动进行审计: + +- **Query execution** - 完整的 SQL 执行审计追踪(`query_history`) +- **Data access** - 数据库对象访问和修改(`access_history`) +- **Authentication** - 登录尝试和会话跟踪(`login_history`) + +## 可用的审计表 {#available-audit-tables} + +{{{ .lake }}} 提供了三个 system history tables,用于捕获数据库活动的不同方面: + +| Table | Purpose | Key Use Cases | +|-------|---------|---------------| +| [query_history](/tidb-cloud-lake/sql/system-history-query-history.md) | 完整的 SQL 执行审计追踪 | 性能监控、安全审计、合规报告 | +| [access_history](/tidb-cloud-lake/sql/system-history-access-history.md) | 数据库对象访问和修改 | 数据血缘跟踪、合规审计、变更管理 | +| [login_history](/tidb-cloud-lake/sql/system-history-login-history.md) | 身份验证尝试和会话 | 安全监控、失败登录检测、访问模式分析 | + +## 审计使用场景和示例 {#audit-use-cases-examples} + +### 安全监控 {#security-monitoring} + +**监控失败的登录尝试** + +跟踪身份验证失败事件,以识别潜在的安全威胁和未授权的访问尝试。 + +```sql +-- Check for failed login attempts (security audit) +SELECT event_time, user_name, client_ip, error_message +FROM system_history.login_history +WHERE event_type = 'LoginFailed' +ORDER BY event_time DESC; +``` + +示例输出: + +``` +event_time: 2025-06-03 06:07:32.512021 +user_name: root1 +client_ip: 127.0.0.1:62050 +error_message: UnknownUser. Code: 2201, Text = User 'root1'@'%' does not exist. +``` + +### 合规报告 {#compliance-reporting} + +**跟踪数据库模式变更** + +监控 DDL 操作,以满足合规和变更管理要求。 + +```sql +-- Audit DDL operations (compliance tracking) +SELECT query_id, query_start, user_name, object_modified_by_ddl +FROM system_history.access_history +WHERE object_modified_by_ddl != '[]' +ORDER BY query_start DESC; +``` + +`CREATE TABLE` 操作示例: + +``` +query_id: c2c1c7be-cee4-4868-a28e-8862b122c365 +query_start: 2025-06-12 03:31:19.042128 +user_name: root +object_modified_by_ddl: [{"object_domain":"Table","object_name":"default.default.t","operation_type":"Create"}] +``` + +**审计数据访问模式** + +跟踪谁在何时访问了哪些数据,以满足合规和数据治理要求。 + +```sql +-- Track data access for compliance +SELECT query_id, query_start, user_name, base_objects_accessed +FROM system_history.access_history +WHERE base_objects_accessed != '[]' +ORDER BY query_start DESC; +``` + +### 运维监控 {#operational-monitoring} + +**完整的查询执行审计** + +维护所有 SQL 操作的完整记录,包括用户和时间信息。 + +```sql +-- Complete query audit with user and timing information +SELECT query_id, sql_user, query_text, query_start_time, query_duration_ms, client_address +FROM system_history.query_history +WHERE event_date >= TODAY() - INTERVAL 7 DAY +ORDER BY query_start_time DESC; +``` + +示例输出: + +``` +query_id: 4e1f50a9-bce2-45cc-86e4-c7a36b9b8d43 +sql_user: root +query_text: SELECT * FROM t +query_start_time: 2025-06-12 03:31:35.041725 +query_duration_ms: 94 +client_address: 127.0.0.1 +``` + + \ No newline at end of file diff --git a/tidb-cloud-lake/guides/authenticate-with-aws-iam-role.md b/tidb-cloud-lake/guides/authenticate-with-aws-iam-role.md new file mode 100644 index 0000000000000..f27bc6bdde3e7 --- /dev/null +++ b/tidb-cloud-lake/guides/authenticate-with-aws-iam-role.md @@ -0,0 +1,101 @@ +--- +title: 使用 AWS IAM Role 进行认证 +summary: 云原生身份委派(AWS IAM Role、Azure Managed Identity、Google Service Account federation 等)使 {{{ .lake }}} 能够在无需处理原始访问密钥的情况下,获取访问对象存储的短期凭证。这样可以将数据平面的访问控制保留在云服务提供商的控制平面内,同时你仍然拥有每一项权限的所有权。 +--- + +# 使用 AWS IAM Role 进行认证 + +云原生身份委派(AWS IAM Role、Azure Managed Identity、Google Service Account federation 等)使 {{{ .lake }}} 能够在无需处理原始访问密钥的情况下,获取访问对象存储的短期凭证。这样可以将数据平面的访问控制保留在云服务提供商的控制平面内,同时你仍然拥有每一项权限的所有权。 + +## IAM role 的优势 {#iam-role-benefits} + +- 无静态密钥:临时凭证消除了需要轮转或可能泄漏的长期密钥。 +- 最小权限:细粒度策略将 {{{ .lake }}} 限制为只能访问你批准的存储桶和执行你批准的操作。 +- 集中治理:你可以继续通过现有的 IAM 工作流审计和撤销访问。 +- 自动轮转:云服务提供商会刷新令牌,因此即使团队发生变化,集成也能持续工作。 + +## 工作原理 {#how-it-works} + +在 {{{ .lake }}} 支持团队向你的组织提供受信任主体信息后,你需要在自己的云账户中创建一个 IAM role/identity,附加一个允许执行所需对象存储操作的策略(例如读取一组存储桶),并配置 trust policy,使得只有 {{{ .lake }}} 能够使用唯一的 external ID 来 assume 该 role。随后,{{{ .lake }}} 会按需 assume 该 role,使用临时凭证访问你的存储,并在会话过期后自动登出。 + +## 使用 IAM role {#use-iam-role} + +1. 提交一个支持工单,以获取你的 {{{ .lake }}} 组织对应的 IAM role ARN: + + 例如:`arn:aws:iam::123456789012:role/xxxxxxx/tnabcdefg/xxxxxxx-tnabcdefg` + +2. 前往 AWS Console: + + + + 点击 `Create policy`,选择 `Custom trust policy`,然后输入用于 S3 存储桶访问的策略文档: + + ```json + { + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Action": "s3:ListBucket", + "Resource": "arn:aws:s3:::test-bucket-123" + }, + { + "Effect": "Allow", + "Action": "s3:*Object", + "Resource": "arn:aws:s3:::test-bucket-123/*" + } + ] + } + ``` + + 点击 `Next`,输入策略名称:`lake-test`,然后点击 `Create policy` + +3. 前往 AWS Console: + + + + 点击 `Create role`,并在 `Trusted entity type` 中选择 `Custom trust policy`: + + ![Create Role](/media/tidb-cloud-lake/create-role.png) + + 输入 trust policy 文档: + + ```json + { + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Principal": { + "AWS": "arn:aws:iam::123456789012:role/xxxxxxx/tnabcdefg/xxxxxxx-tnabcdefg" + }, + "Condition": { + "StringEquals": { + "sts:ExternalId": "my-external-id-123" + } + }, + "Action": "sts:AssumeRole" + } + ] + } + ``` + + 点击 `Next`,选择之前创建的策略:`lake-test` + + 点击 `Next`,输入 role 名称:`lake-test` + + 点击 `View Role`,并记录 role ARN:`arn:aws:iam::987654321987:role/lake-test` + +4. 在 {{{ .lake }}} cloud worksheet 或 `LakeSQL` 中运行以下 SQL 语句: + + ```sql + CREATE CONNECTION lake_test STORAGE_TYPE = 's3' ROLE_ARN = 'arn:aws:iam::987654321987:role/lake-test' EXTERNAL_ID = 'my-external-id-123'; + + CREATE STAGE lake_test URL = 's3://test-bucket-123' CONNECTION = (CONNECTION_NAME = 'lake_test'); + + SELECT * FROM @lake_test/test.parquet LIMIT 1; + ``` + +> **Note:** +> +> 恭喜!现在你已经可以在 {{{ .lake }}} 中通过 IAM Role 访问你自己的 AWS S3 存储桶。 \ No newline at end of file diff --git a/tidb-cloud-lake/guides/automate-data-loading-with-tasks.md b/tidb-cloud-lake/guides/automate-data-loading-with-tasks.md new file mode 100644 index 0000000000000..365c6d5281118 --- /dev/null +++ b/tidb-cloud-lake/guides/automate-data-loading-with-tasks.md @@ -0,0 +1,225 @@ +--- +title: 使用任务自动化数据加载 +summary: 任务会封装 SQL,使 {{{ .lake }}} 能够按调度或在满足条件时为你运行它。在使用 CREATE TASK 定义任务时,请注意以下可调参数。 +--- + +# 使用任务自动化数据加载 + +任务会封装 SQL,使 {{{ .lake }}} 能够按调度或在满足条件时为你运行它。在使用 [CREATE TASK](/tidb-cloud-lake/sql/create-task.md) 定义任务时,请注意以下可调参数。 + +![alt text](/media/tidb-cloud-lake/task.png) + +- **名称和计算集群** – 每个任务都需要一个计算集群。 + + ```sql + CREATE TASK ingest_orders + WAREHOUSE = 'etl_wh' + AS SELECT 1; + ``` + +- **触发器** – 固定时间间隔、CRON,或 `AFTER another_task`。 + + ```sql + CREATE TASK mytask + WAREHOUSE = 'default' + SCHEDULE = 2 MINUTE + AS ...; + ``` + +- **保护条件** – 仅当谓词为 true 时才运行。 + + ```sql + CREATE TASK mytask + WAREHOUSE = 'default' + WHEN STREAM_STATUS('mystream') = TRUE + AS ...; + ``` + +- **错误处理** – 在失败 N 次后暂停,或发送通知。 + + ```sql + CREATE TASK mytask + WAREHOUSE = 'default' + SUSPEND_TASK_AFTER_NUM_FAILURES = 3 + AS ...; + ``` + +- **SQL 负载** – 放在 `AS` 之后的内容就是任务会执行的内容。 + + ```sql + CREATE TASK bump_age + WAREHOUSE = 'default' + SCHEDULE = USING CRON '0 0 1 1 * *' 'UTC' + AS UPDATE employees SET age = age + 1; + ``` + +## 示例 1:按调度复制 {#example-1-scheduled-copy} + +持续生成传感器数据,将其落地为 Parquet 文件,并加载到表中。请将每条 `CREATE/ALTER TASK` 语句中的 `'etl_wh_small'` 替换为**你的**计算集群名称。 + +### 步骤 1:准备演示对象 {#step-1-prepare-demo-objects} + +```sql +-- Create a playground schema and target table +CREATE DATABASE IF NOT EXISTS task_demo; +USE task_demo; + +CREATE OR REPLACE TABLE sensor_events ( + event_time TIMESTAMP, + sensor_id INT, + temperature DOUBLE, + humidity DOUBLE +); + +-- Stage that will store the generated Parquet files +CREATE OR REPLACE STAGE sensor_events_stage; +``` + +### 步骤 2:任务 1 — 生成文件 {#step-2-task-1-generate-files} + +`task_generate_data` 每分钟向 stage 写入 100 条随机读数。每次执行都会生成一个新的 Parquet 文件,供下游消费者摄取。 + +```sql +CREATE OR REPLACE TASK task_generate_data + WAREHOUSE = 'etl_wh_small' -- replace with your warehouse + SCHEDULE = 1 MINUTE +AS +COPY INTO @sensor_events_stage +FROM ( + SELECT + NOW() AS event_time, + number AS sensor_id, + 20 + RAND() * 5 AS temperature, + 60 + RAND() * 10 AS humidity + FROM numbers(100) +) +FILE_FORMAT = (TYPE = PARQUET); +``` + +### 步骤 3:任务 2 — 加载文件 {#step-3-task-2-load-the-files} + +`task_consume_data` 以相同频率扫描 stage,并将每个新生成的 Parquet 文件复制到 `sensor_events` 表中。`PURGE = TRUE` 子句会清理已被摄取的文件。 + +```sql +CREATE OR REPLACE TASK task_consume_data + WAREHOUSE = 'etl_wh_small' -- replace with your warehouse + SCHEDULE = 1 MINUTE +AS +COPY INTO sensor_events +FROM @sensor_events_stage +PATTERN = '.*[.]parquet' +FILE_FORMAT = (TYPE = PARQUET) +PURGE = TRUE; +``` + +### 步骤 4:恢复任务 {#step-4-resume-tasks} + +```sql +ALTER TASK task_generate_data RESUME; +ALTER TASK task_consume_data RESUME; +``` + +这两个任务在你恢复之前都会处于暂停状态。预计首批文件生成和复制会在接下来的一分钟内发生。 + +### 步骤 5:监控流水线 {#step-5-monitor-the-pipeline} + +```sql +-- Confirm that the tasks are running +SHOW TASKS LIKE 'task_%'; + +-- Inspect files on the stage (should shrink as PURGE removes processed files) +LIST @sensor_events_stage; + +-- Check the ingested rows +SELECT * +FROM sensor_events +ORDER BY event_time DESC +LIMIT 5; + +-- Review recent executions for troubleshooting +SELECT * +FROM task_history('task_consume_data', 5); + +-- Change configuration later if needed +ALTER TASK task_consume_data + SCHEDULE = 30 SECOND, + WAREHOUSE = 'etl_wh_medium'; -- replace with your warehouse +``` + +测试完成后,你可以使用 `ALTER TASK ... SUSPEND` 暂停任一任务。 + +### 步骤 6:修改任务 {#step-6-update-tasks} + +你可以修改调度、计算集群,甚至 SQL 负载,而无需删除任务: + +```sql +-- Tweak the schedule and warehouse +ALTER TASK task_consume_data + SCHEDULE = 30 SECOND, + WAREHOUSE = 'etl_wh_medium'; -- replace with your warehouse + +-- Update the SQL payload (replace the existing body) +ALTER TASK task_consume_data + AS +COPY INTO sensor_events +FROM @sensor_events_stage +FILE_FORMAT = (TYPE = PARQUET); + +-- Resume after edits (tasks suspend when their SQL changes) +ALTER TASK task_consume_data RESUME; + +-- Review execution history for verification +SELECT * +FROM task_history('task_consume_data', 5) +ORDER BY completed_time DESC; +``` + +`TASK_HISTORY` 会返回状态、时间信息和查询 ID,便于你再次验证修改结果。 + +## 示例 2:由 Stream 触发的 Merge {#example-2-stream-triggered-merge} + +使用 `WHEN STREAM_STATUS(...)` 仅在 stream 有新行时触发。复用示例 1 中的 `sensor_events` 表。 + +### 步骤 1:创建 stream 和 latest 表 {#step-1-create-stream-latest-table} + +```sql +-- Create a stream on the sensor table (Standard mode to capture every mutation) +CREATE OR REPLACE STREAM sensor_events_stream + ON TABLE sensor_events + APPEND_ONLY = false; + +-- Target table that keeps only the latest copy of each row +CREATE OR REPLACE TABLE sensor_events_latest AS +SELECT * +FROM sensor_events +WHERE 1 = 0; +``` + +### 第 2 步:创建条件任务 {#step-2-create-the-conditional-task} + +```sql +CREATE OR REPLACE TASK task_stream_merge + WAREHOUSE = 'etl_wh_small' -- replace with your warehouse + SCHEDULE = 1 MINUTE + WHEN STREAM_STATUS('task_demo.sensor_events_stream') = TRUE +AS +INSERT INTO sensor_events_latest +SELECT * +FROM sensor_events_stream; + +ALTER TASK task_stream_merge RESUME; +``` + +### 第 3 步:验证行为 {#step-3-verify-the-behavior} + +```sql +SELECT * +FROM sensor_events_latest +ORDER BY event_time DESC +LIMIT 5; + +SELECT * +FROM task_history('task_stream_merge', 5); +``` + +只有当 `STREAM_STATUS('.')` 返回 `TRUE` 时,任务才会触发。请始终为 stream 添加其所属数据库前缀(例如 `task_demo.sensor_events_stream`),这样无论当前 schema 是什么,任务都能正确解析它;并且在每个 `CREATE/ALTER TASK` 中使用你自己的 Warehouse 名称。 \ No newline at end of file diff --git a/tidb-cloud-lake/guides/aws-credentials.md b/tidb-cloud-lake/guides/aws-credentials.md new file mode 100644 index 0000000000000..0089480f1d2da --- /dev/null +++ b/tidb-cloud-lake/guides/aws-credentials.md @@ -0,0 +1,35 @@ +--- +title: Amazon S3 - 凭证 +summary: 本页介绍如何创建 `Amazon S3 - Credentials` 数据源。该数据源用于存储访问 Amazon S3 所需的凭证,并可在多个 S3 集成任务之间复用。 +--- + +# Amazon S3 - 凭证 + +本页介绍如何创建 `Amazon S3 - Credentials` 数据源。该数据源用于存储访问 Amazon S3 所需的凭证,并可在多个 S3 集成任务之间复用。 + +## 使用场景 {#use-cases} + +- 为多个 S3 导入任务管理同一组 AWS Access Key 和 Secret Key 凭证 +- 避免在每个任务中重复输入相同的 S3 访问凭证 +- 在凭证轮转时集中修改凭证 + +## 创建 Amazon S3 - 凭证 {#create-amazon-s3-credentials} + +1. 进入 **Data** > **Data Sources**,然后点击 **Create Data Source**。 +2. 选择 **Amazon S3 - Credentials** 作为服务类型,然后填写凭证信息: + + | 字段 | 必填 | 说明 | + |-------|----------|-------------| + | **Name** | 是 | 此数据源的描述性名称 | + | **Access Key** | 是 | AWS Access Key ID | + | **Secret Key** | 是 | AWS Secret Access Key | + +3. 点击 **Test Connectivity** 以验证凭证。如果测试成功,点击 **OK** 保存数据源。 + +## 权限要求 {#permission-requirements} + +AWS 凭证必须具有目标 S3 存储桶的读访问权限。如果下游任务会启用 **Clean Up Original Files**,则该凭证还必须具有写入和删除权限。 + +## 后续步骤 {#next-steps} + +创建此数据源后,你可以使用它来创建 [Amazon S3 集成任务](/tidb-cloud-lake/guides/integrate-with-amazon-s3.md)。 diff --git a/tidb-cloud-lake/guides/benchmark-data-ingestion.md b/tidb-cloud-lake/guides/benchmark-data-ingestion.md new file mode 100644 index 0000000000000..3e8fb952bdf30 --- /dev/null +++ b/tidb-cloud-lake/guides/benchmark-data-ingestion.md @@ -0,0 +1,185 @@ +--- +title: "{{{ .lake }}} vs. Snowflake: 数据摄取基准测试" +summary: 本页展示了 {{{ .lake }}} 与 Snowflake 在数据摄取性能和成本方面的基准对比,重点关注 TPC-H SF100 数据集加载、ClickBench Hits 数据集加载以及新鲜度基准测试。 +--- + +# {{{ .lake }}} vs. Snowflake: 数据摄取基准测试 + +## 概览 {#overview} + +我们进行了四项具体的基准测试,以评估 {{{ .lake }}} 与 Snowflake: + +1. **TPC-H SF100 数据集加载**:重点比较大规模数据集(100GB,约 6 亿行)的加载性能和成本。 +2. **ClickBench Hits 数据集加载**:测试宽表数据集(76GB,约 1 亿行,105 列)的加载效率,重点关注高列数带来的挑战。 +3. **1 秒新鲜度**:衡量平台在严格的 1 秒新鲜度要求下摄取数据的能力。 +4. **5 秒新鲜度**:比较平台在 5 秒新鲜度约束下的数据摄取能力。 + +## 平台 {#platforms} + +- **[Snowflake](https://snowflake.com)**:知名的云数据平台,强调可扩展计算和数据共享。 +- **[{{{ .lake }}}](https://tidbcloud.com)**:云原生数据仓库,专注于扩展性和成本效益。 + +## 基准测试条件 {#benchmark-conditions} + +在 `Small-Size` 计算集群上进行测试,并使用同一个 S3 存储桶中的数据。 + +> **Note:** +> +> 此比较基于 Snowflake Gen1 标准计算集群(`GENERATION = '1'`)。 + +## 性能与成本对比 {#performance-and-cost-comparison} + +- **TPC-H SF100 数据**:与 Snowflake 相比,{{{ .lake }}} 可将成本降低 **48%**。 +- **ClickBench Hits 数据**:{{{ .lake }}} 实现了 **84%** 的成本降低。 +- **1 秒新鲜度**:{{{ .lake }}} 的数据加载量是 Snowflake 的 **400 倍**。 +- **5 秒新鲜度**:{{{ .lake }}} 的数据加载量超过 **27 倍**。 + +## 数据摄取基准测试 {#data-ingestion-benchmarks} + +![Data loading benchmark](/media/tidb-cloud-lake/data-loading-benchmark.png) + +### TPC-H SF100 数据集 {#tpc-h-sf100-dataset} + +| 指标 | Snowflake | {{{ .lake }}} | 描述 | +| -------------- | --------- | -------------- | ---------------------- | +| **Total Time** | 695s | 446s | 加载数据集所需的时间。 | +| **Total Cost** | $0.77 | $0.40 | 数据加载的成本。 | + +- Data Volume: 100GB +- Rows: Approx. 600 million + +### ClickBench Hits 数据集 {#clickbench-hits-dataset} + +| 指标 | Snowflake | {{{ .lake }}} | 描述 | +| -------------- | --------- | -------------- | ---------------------- | +| **Total Time** | 51m 17s | 9m 58s | 加载数据集所需的时间。 | +| **Total Cost** | $3.42 | $0.53 | 数据加载的成本。 | + +- Data Volume: 76GB +- Rows: Approx. 100 million +- Table Width: 105 columns + +## 新鲜度基准测试 {#freshness-benchmarks} + +![Freshness benchmark](/media/tidb-cloud-lake/freshness-benchmark.png) + +### 1 秒新鲜度基准测试 {#1-second-freshness-benchmark} + +评估在 1 秒新鲜度要求内成功摄取的数据量。 + +| 指标 | Snowflake | {{{ .lake }}} | 描述 | +| -------------- | --------- | -------------- | ----------------------------------- | +| **Total Time** | 1s | 1s | 数据加载时间窗口。 | +| **Total Rows** | 100 Rows | 40,000 Rows | 在 1 秒内成功摄取的数据量。 | + +### 5 秒新鲜度基准测试 {#5-second-freshness-benchmark} + +评估在 5 秒新鲜度要求内可摄取的数据量。 + +| 指标 | Snowflake | {{{ .lake }}} | 描述 | +| -------------- | ----------- | -------------- | ----------------------------------- | +| **Total Time** | 5s | 5s | 数据加载时间窗口。 | +| **Total Rows** | 90,000 Rows | 2,500,000 Rows | 在 5 秒内成功摄取的数据量。 | + +## 复现基准测试 {#reproduce-the-benchmark} + +你可以按照以下步骤复现该基准测试。 + +### 基准测试环境 {#benchmark-environment} + +该基准测试在相似条件下对 Snowflake 和 {{{ .lake }}} 进行了测试: + +| 参数 | Snowflake | {{{ .lake }}} | +| -------------- | -------------------------------------------------------- | ----------------------------------------- | +| 计算集群大小 | 小型 | 小型 | +| 价格 | [$4/hour](https://www.snowflake.com/en/pricing-options/) | [$3.2/hour](https://www.pingcap.com/pricing/) | +| AWS Region | us-east-2 | us-east-2 | +| 存储 | AWS S3 | AWS S3 | + +- TPC-H SF100 数据集来源于 [Amazon Redshift](https://github.com/awslabs/amazon-redshift-utils/tree/master/src/CloudDataWarehouseBenchmark/Cloud-DWB-Derived-from-TPCH)。 +- ClickBench 数据集来源于 [ClickBench](https://github.com/ClickHouse/ClickBench)。 + +### 前提条件 {#prerequisites} + +- 拥有一个 [Snowflake account](https://signup.snowflake.com) +- 创建一个 [{{{ .lake }}} account](https://tidbcloud.com/) + +### 数据摄取基准测试 {#data-ingestion-benchmark} + +可以按照以下步骤复现数据摄取基准测试: + +
+ TPC-H Data Loading + +1. **Snowflake Data Load**: + + - 登录你的 [Snowflake account](https://app.snowflake.com/)。 + - 创建与 TPC-H schema 对应的表。[SQL Script](https://lakesql-bin.tidbcloud.com/datasets/tpch/tpch-100/snowflake/setup.sql)。 + - 使用 `COPY INTO` 命令从 AWS S3 加载数据。[SQL Script](https://lakesql-bin.tidbcloud.com/datasets/tpch/tpch-100/snowflake/setup.sql)。 + +2. **{{{ .lake }}} Data Load**: + + - 登录你的 [{{{ .lake }}} account](https://tidbcloud.com)。 + - 按照 TPC-H schema 创建所需的表。[SQL Script](https://lakesql-bin.tidbcloud.com/datasets/tpch/tpch-100/lake/setup.sql)。 + - 使用与 Snowflake 类似的方法从 AWS S3 加载数据。[SQL Script](https://lakesql-bin.tidbcloud.com/datasets/tpch/tpch-100/lake/setup.sql)。 + +
+ +
+ ClickBench Hits Data Loading + +1. **Snowflake Data Load**: + + - 登录你的 [Snowflake account](https://app.snowflake.com/)。 + - 创建与 `hits` schema 对应的表。[SQL Script](https://lakesql-bin.tidbcloud.com/datasets/tpch/hits/snowflake/schema.sql)。 + - 使用 `COPY INTO` 命令从 AWS S3 加载数据。[SQL Script](https://lakesql-bin.tidbcloud.com/datasets/tpch/hits/snowflake/copy.sql)。 + +2. **{{{ .lake }}} Data Load**: + + - 登录你的 [{{{ .lake }}} account](https://tidbcloud.com)。 + - 按照 `hits` schema 创建所需的表。[SQL Script](https://lakesql-bin.tidbcloud.com/datasets/tpch/hits/lake/schema.sql)。 + - 使用与 Snowflake 类似的方法从 AWS S3 加载数据。[SQL Script](https://lakesql-bin.tidbcloud.com/datasets/tpch/hits/lake/copy.sql)。 + +
+ +### 新鲜度基准测试 {#freshness-benchmark} + +可以按照以下步骤复现新鲜度基准测试的数据生成和摄取过程: + +1. 在 {{{ .lake }}} 中创建一个 [外部 Stage](/tidb-cloud-lake/sql/create-stage.md#example-2-create-external-stage-with-connection)。 + + ```sql + CREATE STAGE hits_unload_stage + URL = 's3://unload/files/' + CONNECTION = ( + ACCESS_KEY_ID = '', + SECRET_ACCESS_KEY = '' + ); + ``` + +2. 将数据卸载到 external stage。 + + ```sql + CREATE or REPLACE FILE FORMAT tsv_unload_format_gzip + TYPE = TSV, + COMPRESSION = gzip; + + COPY INTO @hits_unload_stage + FROM ( + SELECT * + FROM hits limit + ) + FILE_FORMAT = (FORMAT_NAME = 'tsv_unload_format_gzip') + DETAILED_OUTPUT = true; + ``` + +3. 将数据从 external stage 加载到 `hits` 表。 + + ```sql + COPY INTO hits + FROM @hits_unload_stage + PATTERN = '.*[.]tsv.gz' + FILE_FORMAT = (TYPE = TSV, COMPRESSION=auto); + ``` + +4. 从仪表板中查看结果。 diff --git a/tidb-cloud-lake/guides/benchmark-tpch-sf100.md b/tidb-cloud-lake/guides/benchmark-tpch-sf100.md new file mode 100644 index 0000000000000..1d068896ab257 --- /dev/null +++ b/tidb-cloud-lake/guides/benchmark-tpch-sf100.md @@ -0,0 +1,168 @@ +--- +title: "TPC-H Benchmark: {{{ .lake }}} vs. Snowflake" +summary: 本指南基于 TPC-H SF100 数据集,对 {{{ .lake }}} 与 Snowflake 的性能和成本进行了对比。内容包括数据加载与查询执行的基准测试,以及复现结果的操作说明。 +--- + +# TPC-H Benchmark: {{{ .lake }}} vs. Snowflake + +## 快速概览 {#quick-overview} + +### TPC-H {#tpc-h} + +TPC-H 基准测试是评估决策支持系统的标准,重点关注复杂查询和数据维护。本分析使用 TPC-H SF100(SF1 = 600 万行)数据集对 {{{ .lake }}} 与 Snowflake 进行对比。该数据集包含 100GB 数据,以及分布在 22 个查询中的约 6 亿行数据。 + +> **Note:** +> +> TPC Benchmark™ 和 TPC-H™ 是 Transaction Processing Performance Council([TPC](http://www.tpc.org))的商标。我们的基准测试虽然受 TPC-H 启发,但不能与官方 TPC-H 结果直接比较。 + +### Snowflake 和 {{{ .lake }}} {#snowflake-and-lake} + +- **[Snowflake](https://www.snowflake.com)**:Snowflake 以其先进特性而闻名,例如存储与计算分离、按需可扩展计算、数据共享以及克隆能力。 + +- **[{{{ .lake }}}](https://www.tidbcloud.com)**:{{{ .lake }}} 提供与 Snowflake 类似的功能。作为云原生数据仓库,它同样实现了存储与计算分离,并可按需提供可扩展计算能力。 + + 它将自己定位为 Snowflake 的一种现代化且更具成本效益的替代方案,尤其适用于大规模分析场景。 + +## 性能和成本对比 {#performance-and-cost-comparison} + +- **数据加载成本**:与 Snowflake 相比,{{{ .lake }}} 在数据加载方面实现了 **48% 的成本降低**。 +- **查询执行成本**:在查询执行方面,{{{ .lake }}} 比 Snowflake 大约 **便宜 35%**(冷运行;热运行约为 27%)。 + +> **Note:** +> +> 本基准测试对 Snowflake 和 {{{ .lake }}} 均使用默认设置,未进行任何特殊调优。本次对比基于 Snowflake Gen1 standard warehouses(`GENERATION = '1'`)。同时请记住,**不要只听我们的一面之词——我们鼓励你亲自运行并验证这些结果。** + +### 数据加载基准测试 {#data-loading-benchmark} + +![TPC-H SF100 data loading benchmark](/media/tidb-cloud-lake/tpch-sf100-data-loading-benchmark.png) + +| 表 | Snowflake (总计 695s,成本 $0.77) | {{{ .lake }}} (总计 446s,成本 $0.40) | 行数 | +| ---------------- | --------------------------- | -------------------------------- | ----------- | +| customer | 18.137 | 13.436 | 15,000,000 | +| lineitem | 477.740 | 305.812 | 600,037,902 | +| nation | 1.347 | 0.708 | 25 | +| orders | 103.088 | 64.323 | 150,000,000 | +| part | 19.908 | 12.192 | 20,000,000 | +| partsupp | 67.410 | 45.346 | 80,000,000 | +| region | 0.743 | 0.725 | 5 | +| supplier | 3.000 | 3.687 | 10,000,000 | +| **总时间** | **695s** | **446s** | | +| **总成本** | **$0.77** | **$0.40** | | +| **存储大小** | **20.8GB** | **24.5GB** | | + +### 查询基准测试:冷运行 {#query-benchmark-cold-run} + +![TPC-H SF100 Cold Run Benchmark](/media/tidb-cloud-lake/tpch-sf100-cold-run-benchmark.png) + +| 查询 | Snowflake(总计 207s,成本 $0.23) | {{{ .lake }}}(总计 166s,成本 $0.15) | +| -------------- | --------------------------------- | -------------------------------------- | +| TPC-H 1 | 11.703 | 8.036 | +| TPC-H 2 | 4.524 | 3.786 | +| TPC-H 3 | 8.908 | 6.040 | +| TPC-H 4 | 8.108 | 4.462 | +| TPC-H 5 | 9.202 | 7.014 | +| TPC-H 6 | 1.237 | 3.234 | +| TPC-H 7 | 9.082 | 7.345 | +| TPC-H 8 | 10.886 | 8.976 | +| TPC-H 9 | 18.152 | 13.340 | +| TPC-H 10 | 13.525 | 12.891 | +| TPC-H 11 | 2.582 | 2.183 | +| TPC-H 12 | 10.099 | 8.839 | +| TPC-H 13 | 13.458 | 7.206 | +| TPC-H 14 | 8.001 | 4.612 | +| TPC-H 15 | 8.737 | 4.621 | +| TPC-H 16 | 4.864 | 1.645 | +| TPC-H 17 | 5.363 | 14.315 | +| TPC-H 18 | 19.971 | 12.058 | +| TPC-H 19 | 9.893 | 12.579 | +| TPC-H 20 | 8.538 | 8.836 | +| TPC-H 21 | 16.439 | 12.270 | +| TPC-H 22 | 3.744 | 1.926 | +| **总时间** | **207s** | **166s** | +| **总成本** | **$0.23** | **$0.15** | + +### 查询基准测试:热运行 {#query-benchmark-hot-run} + +![TPC-H SF100 Hot Run Benchmark](/media/tidb-cloud-lake/tpch-sf100-hot-run-benchmark.png) + +| 查询 | Snowflake(总计 138s,成本 $0.15) | {{{ .lake }}}(总计 124s,成本 $0.11) | +| -------------- | ---------------------------------- | --------------------------------------- | +| TPC-H 1 | 8.934 | 7.568 | +| TPC-H 2 | 3.018 | 3.125 | +| TPC-H 3 | 6.089 | 5.234 | +| TPC-H 4 | 4.914 | 3.392 | +| TPC-H 5 | 5.800 | 4.857 | +| TPC-H 6 | 0.891 | 2.142 | +| TPC-H 7 | 5.381 | 4.389 | +| TPC-H 8 | 5.724 | 5.887 | +| TPC-H 9 | 10.283 | 9.621 | +| TPC-H 10 | 10.368 | 8.524 | +| TPC-H 11 | 1.165 | 1.364 | +| TPC-H 12 | 7.052 | 5.352 | +| TPC-H 13 | 12.829 | 6.180 | +| TPC-H 14 | 3.288 | 2.725 | +| TPC-H 15 | 3.475 | 2.748 | +| TPC-H 16 | 4.094 | 1.124 | +| TPC-H 17 | 4.203 | 13.757 | +| TPC-H 18 | 18.583 | 11.630 | +| TPC-H 19 | 3.888 | 7.881 | +| TPC-H 20 | 6.379 | 5.797 | +| TPC-H 21 | 10.287 | 9.806 | +| TPC-H 22 | 1.573 | 1.122 | +| **总时间** | **138s** | **124s** | +| **总成本** | **$0.15** | **$0.11** | + +## 复现基准测试 {#reproduce-the-benchmark} + +你可以按照以下步骤复现该基准测试。 + +### 基准测试环境 {#benchmark-environment} + +该基准测试在相似条件下对 Snowflake 和 {{{ .lake }}} 进行了测试: + +| 参数 | Snowflake | {{{ .lake }}} | +| -------------- | -------------------------------------------------------- | ----------------------------------------- | +| 计算集群 (Warehouse) 大小 | Small | Small | +| 价格 | [$4/hour](https://www.snowflake.com/en/pricing-options/) | [$3.2/hour](https://www.pingcap.com/pricing) | +| AWS Region | us-east-2 | us-east-2 | +| 存储 | AWS S3 | AWS S3 | + +- TPC-H SF100 数据集来源于 [Amazon Redshift](https://github.com/awslabs/amazon-redshift-utils/tree/master/src/CloudDataWarehouseBenchmark/Cloud-DWB-Derived-from-TPCH),在未进行任何特定调优的情况下被加载到 {{{ .lake }}} 和 Snowflake 中。 + +### 基准测试方法 {#benchmark-methodology} + +该基准测试中的查询执行包含冷运行和热运行两种方式: + +1. **Cold Run**:在执行查询之前,先暂停并恢复数据仓库。 +2. **Hot Run**:数据仓库不暂停,使用本地磁盘缓存。 + +### 前提条件 {#prerequisites} + +- 拥有一个 [Snowflake account](https://signup.snowflake.com) +- 创建一个 [{{{ .lake }}} account](https://tidbcloud.com) + +### 数据加载 {#data-loading} + +1. **Snowflake Data Load**: + + - 登录你的 [Snowflake account](https://app.snowflake.com/)。 + - 创建与 TPC-H schema 对应的表。[SQL Script](https://lakesql-bin.tidbcloud.com/datasets/tpch/tpch-100/snowflake/setup.sql)。 + - 使用 `COPY INTO` 命令从 AWS S3 加载数据。[SQL Script](https://lakesql-bin.tidbcloud.com/datasets/tpch/tpch-100/snowflake/setup.sql)。 + +2. **{{{ .lake }}} Data Load**: + + - 登录你的 [{{{ .lake }}} account](https://tidbcloud.com)。 + - 按照 TPC-H schema 创建所需的表。[SQL Script](https://lakesql-bin.tidbcloud.com/datasets/tpch/tpch-100/lake/setup.sql)。 + - 使用与 Snowflake 类似的方法从 AWS S3 加载数据。[SQL Script](https://lakesql-bin.tidbcloud.com/datasets/tpch/tpch-100/lake/setup.sql)。 + +### TPC-H 查询 {#tpc-h-queries} + +1. **Snowflake Queries**: + + - 登录你的 [Snowflake account](https://app.snowflake.com/)。 + - 运行 TPC-H 查询。[SQL Script](https://lakesql-bin.tidbcloud.com/datasets/tpch/tpch-100/snowflake/queries.sql)。 + +2. **{{{ .lake }}} Queries**: + + - 登录你的 [{{{ .lake }}} account](https://tidbcloud.com)。 + - 运行 TPC-H 查询。[SQL Script](https://lakesql-bin.tidbcloud.com/datasets/tpch/tpch-100/lake/queries.sql)。 \ No newline at end of file diff --git a/tidb-cloud-lake/guides/benchmark-tpch-sf1000.md b/tidb-cloud-lake/guides/benchmark-tpch-sf1000.md new file mode 100644 index 0000000000000..dc761ba53718b --- /dev/null +++ b/tidb-cloud-lake/guides/benchmark-tpch-sf1000.md @@ -0,0 +1,73 @@ +--- +title: "TPC-H SF1000 (1TB): {{{ .lake }}} Warehouse Size Benchmark" +summary: 本指南展示了使用 TPC-H SF1000 数据集时,Small、Medium 和 Large {{{ .lake }}} 计算集群的性能对比。内容包括各计算集群规格的查询执行时间,以及复现基准测试结果的说明。 +--- + +# TPC-H SF1000 (1TB): {{{ .lake }}} Warehouse Size Benchmark + +本页对比了在相同 TPC-H SF1000 工作负载下,Small、Medium 和 Large {{{ .lake }}} 计算集群 (Warehouse)。SF1000 通常用于表示约 1TB 的 TPC-H 数据。 + +## 数据集规模 {#dataset-scale} + +TPC-H Scale Factor 1000 (SF1000) 表示大约 1TB 的生成数据。该数据集包含 8 张标准 TPC-H 表,总计约 60 亿行数据。 + +| 表 | 行数 | +|---|---:| +| customer | 150,000,000 | +| lineitem | 6,000,000,000 | +| nation | 25 | +| orders | 1,500,000,000 | +| part | 200,000,000 | +| partsupp | 800,000,000 | +| region | 5 | +| supplier | 10,000,000 | + +> **Note:** +> +> TPC Benchmark™ 和 TPC-H™ 是 Transaction Processing Performance Council([TPC](http://www.tpc.org))的商标。本测试受 TPC-H 启发,但并非官方 TPC-H 结果。 + +## 概要 {#summary} + +| 计算集群 (Warehouse) 大小 | 总时间 | 相比 Small 的加速比 | 相比前一大小的加速比 | +|---|---:|---:|---:| +| Small | 1173.32s | 1.00x | — | +| Medium | 537.93s | 2.18x | 2.18x | +| Large | 285.96s | 4.10x | 1.88x | + +![TPC-H SF1000 Warehouse Size Benchmark](/media/tidb-cloud-lake/tpch-sf1000-warehouse-size-benchmark.png) + +Medium 比 Small 快约 2.18 倍。Large 比 Small 快约 4.10 倍,并且可在 5 分钟内完成全部 22 个查询的工作负载。 + +## 查询详情 {#query-details} + +单位:秒。数值越低越好。 + +| 查询 | 小 | 中 | 大 | 小 → 中 | 中 → 大 | +|---:|---:|---:|---:|---:|---:| +| Q1 | 31.61 | 19.93 | 10.33 | 1.59x | 1.93x | +| Q2 | 10.00 | 7.15 | 5.52 | 1.40x | 1.30x | +| Q3 | 73.07 | 24.50 | 17.75 | 2.98x | 1.38x | +| Q4 | 177.60 | 17.22 | 16.39 | 10.31x | 1.05x | +| Q5 | 300.78 | 17.69 | 11.22 | 17.00x | 1.58x | +| Q6 | 13.93 | 4.46 | 2.19 | 3.12x | 2.04x | +| Q7 | 33.08 | 18.08 | 9.78 | 1.83x | 1.85x | +| Q8 | 31.37 | 17.81 | 10.90 | 1.76x | 1.63x | +| Q9 | 102.01 | 45.41 | 29.52 | 2.25x | 1.54x | +| Q10 | 40.84 | 31.18 | 23.05 | 1.31x | 1.35x | +| Q11 | 5.91 | 3.59 | 2.20 | 1.65x | 1.63x | +| Q12 | 23.74 | 11.81 | 8.70 | 2.01x | 1.36x | +| Q13 | 57.78 | 34.52 | 23.78 | 1.67x | 1.45x | +| Q14 | 38.45 | 9.84 | 5.18 | 3.91x | 1.90x | +| Q15 | 13.22 | 8.18 | 4.82 | 1.62x | 1.70x | +| Q16 | 4.77 | 3.25 | 2.27 | 1.47x | 1.43x | +| Q17 | 20.77 | 11.29 | 5.87 | 1.84x | 1.92x | +| Q18 | 90.78 | 158.89 | 17.24 | 0.57x | 9.22x | +| Q19 | 20.36 | 10.86 | 8.22 | 1.87x | 1.32x | +| Q20 | 25.34 | 10.07 | 4.94 | 2.52x | 2.04x | +| Q21 | 52.85 | 64.57 | 61.19 | 0.82x | 1.06x | +| Q22 | 5.06 | 7.64 | 4.90 | 0.66x | 1.56x | +| 总计 | 1173.32 | 537.93 | 285.96 | 2.18x | 1.88x | + +## 说明 {#notes} + +随着计算集群规格的增大,整体工作负载的扩展表现十分明显。由于查询形态、执行计划、调度以及缓存行为等因素,某些单独查询的扩展表现可能不会呈线性增长。 \ No newline at end of file diff --git a/tidb-cloud-lake/guides/choose-a-udf-type.md b/tidb-cloud-lake/guides/choose-a-udf-type.md new file mode 100644 index 0000000000000..30960a2cfae69 --- /dev/null +++ b/tidb-cloud-lake/guides/choose-a-udf-type.md @@ -0,0 +1,351 @@ +--- +title: 选择用户定义函数类型 +summary: 了解如何根据返回形式、运行时和运维需求,在 TiDB Cloud Lake 中选择 SQL、聚合、表或外部 UDF。 +--- + +# 选择用户定义函数类型 + +用户定义函数(UDF)可让你封装内置 SQL 函数未提供的可复用逻辑。它们可以用于统一业务规则、简化复杂查询、实现自定义聚合、将值展开为多行,或将 SQL 查询连接到独立托管的 Python 服务。 + +在创建 UDF 之前,请先查看 [SQL 函数参考](/tidb-cloud-lake/sql/sql-function-reference.md)。内置函数通常能提供最简单的实现、最低的执行开销以及最小的运维负担。 + +## 为什么使用 UDF {#why-use-udfs} + +随着分析型工作负载不断增长,相同的转换逻辑往往会出现在许多查询中。将同一个表达式复制到每个查询里,会让行为一致性更难保证,也更难安全地发布变更。 + +UDF 适用于以下任务: + +- 标准化数据清洗、校验和业务计算; +- 封装参数化 SQL 查询; +- 实现需要中间状态的自定义聚合; +- 调用 Python 库、专有逻辑或机器学习模型; +- 将专用计算能力与计算集群 (Warehouse) 独立扩缩容。 + +一个 UDF 应当只承担一个明确职责。数据移动、调度、流状态、跨连续事件流的连接以及工作流编排,应当放在相应的 Lake SQL、Stream、Task 或集成功能中处理,而不是放在 UDF 内部。 + +## 了解 UDF 生态 {#understand-the-udf-ecosystem} + +{{{ .lake }}} 提供了多种 UDF 执行模型。它们在返回形式、语言、托管方式和运维责任方面各不相同。 + +| UDF 类型 | 实现 | 输出 | 托管 | 典型用途 | +| --- | --- | --- | --- | --- | +| SQL 标量 UDF | SQL 表达式 | 每个输入行一个值 | 由 {{{ .lake }}} 管理 | 格式化、计算和可重用条件 | +| 脚本标量 UDF | Python 或 JavaScript | 每个输入行一个值 | 由 {{{ .lake }}} 管理 | 业务规则、验证和结构化数据处理 | +| WebAssembly 标量 UDF | WebAssembly 模块 | 每个输入行一个值 | 由 {{{ .lake }}} 管理 | 编译为 WebAssembly 的计算密集型逻辑 | +| 聚合 UDF | Python 或 JavaScript | 每个组一个值 | 由 {{{ .lake }}} 管理 | 自定义有状态聚合 | +| SQL 表 UDF | SQL 查询 | 一个结果集 | 由 {{{ .lake }}} 管理 | 可重用的参数化查询 | +| 外部标量 UDF | Python UDF Server | 每个输入行一个值 | 由您托管 | 库、模型和专有服务 | +| 外部表 UDF | Python UDF Server | 多列或多行 | 由您托管 | 分词、扩展和记录生成 | + +聚合 UDF 和表 UDF 解决的是不同问题。聚合 UDF 会消费多行并返回一个值。表 UDF 则返回一个结果集。{{{ .lake }}} 不提供同时结合这两种执行模型的 Python 表聚合 UDF。 + +## 选择最简单的执行模型 {#choose-the-simplest-execution-model} + +选择实现时,建议按以下顺序进行: + +1. 如果内置函数已经能提供所需行为,优先使用内置函数。 +2. 如果 SQL 能清晰表达该逻辑,使用 SQL 标量 UDF 或表 UDF。 +3. 如果是应在 {{{ .lake }}} 内运行的脚本逻辑,使用内嵌 Python 或 JavaScript 标量 UDF。 +4. 如果是以编译模块形式交付的计算密集型标量逻辑,使用 WebAssembly。 +5. 如果计算需要自定义聚合状态,使用聚合 UDF。 +6. 如果逻辑依赖远程服务、GPU 或独立扩缩容,使用外部 UDF。 + +以下问题可以帮助你缩小选择范围: + +| 问题 | 推荐选项 | +| --- | --- | +| 一个 SQL 表达式能产生结果吗? | SQL scalar UDF | +| 行级别逻辑是否需要 Python 或 JavaScript? | Script scalar UDF | +| 计算密集型行级别逻辑是否需要已编译、可移植的模块? | WebAssembly scalar UDF | +| SQL 查询是否需要返回多行? | SQL table UDF | +| 是否必须将多个输入行组合成一个自定义结果? | Aggregate UDF | +| 一个输入是否需要产生多行由 Python 生成的结果? | External table UDF | +| 该逻辑是否需要 Python 包、模型、网络调用或单独的计算资源? | External scalar or table UDF | + +## 使用 SQL 标量 UDF 实现可复用转换 {#use-sql-scalar-udfs-for-reusable-transformations} + +SQL 标量 UDF 会将每一行输入映射为一个值。它非常适合用于计算、字符串规范化和条件业务规则。 + +### 规范化电话号码 {#normalize-phone-numbers} + +以下函数会移除格式化字符,以便下游查询统一使用一种电话号码表示形式: + +```sql +CREATE FUNCTION normalize_phone(phone VARCHAR) +RETURNS VARCHAR +AS $$ REGEXP_REPLACE(phone, '[^0-9]', '') $$; + +SELECT normalize_phone('+1 (415) 555-0100'); +``` + +### 应用折扣 {#apply-a-discount} + +以下函数将折扣计算集中管理: + +```sql +CREATE FUNCTION apply_discount( + price DECIMAL(10, 2), + rate DECIMAL(5, 2) +) +RETURNS DECIMAL(10, 2) +AS $$ price * (1 - rate) $$; + +SELECT apply_discount(100, 0.15); +``` + +当共享业务规则发生变化时,使用 [ALTER FUNCTION](/tidb-cloud-lake/sql/alter-function.md)。这样,调用该函数的查询就会使用新的定义,而无需重复编写表达式。 + +完整语法请参见 [CREATE SCALAR FUNCTION](/tidb-cloud-lake/sql/create-scalar-function.md)。 + +## 使用 Python 标量 UDF 处理数据逻辑 {#use-python-scalar-udfs-for-data-processing-logic} + +当逻辑需要控制流、Python 标准库,或需要使用难以用 SQL 表达的包时,Python 标量 UDF 非常有用。 + +以下函数会规范化地址中的空白和大小写: + +```sql +CREATE FUNCTION normalize_address(value VARCHAR) +RETURNS VARCHAR +LANGUAGE python +HANDLER = 'normalize_address' +AS $$ +def normalize_address(value): + return " ".join(value.strip().upper().split()) +$$; + +SELECT normalize_address(' 123 Main Street '); +``` + +Python UDF 还可以使用 `PACKAGES` 指定 PyPI 依赖,并使用 `IMPORTS` 引用存储在 stage 中的文件。请尽量保持依赖精简,以便函数环境更容易复现和维护。 + +## 使用 JavaScript 标量 UDF 进行 JSON 转换 {#use-javascript-scalar-udfs-for-json-transformations} + +JavaScript 非常适合对象和 JSON 转换,尤其是在相关逻辑已经存在于应用代码库中的情况下。 + +以下函数会规范化电子邮件地址并移除敏感字段: + +```sql +CREATE FUNCTION clean_profile(value VARIANT) +RETURNS VARIANT +LANGUAGE javascript +HANDLER = 'cleanProfile' +AS $$ +export function cleanProfile(value) { + const result = { ...value }; + if (typeof result.email === 'string') { + result.email = result.email.trim().toLowerCase(); + } + delete result.ssn; + return result; +} +$$; +``` + +请保持输入和返回 schema 稳定。对象结构的变化可能会影响每一个调用该函数的查询。 + +## 使用 WebAssembly UDF 实现编译逻辑 {#use-webassembly-udfs-for-compiled-logic} + +WebAssembly UDF 将编译后的代码封装为可移植模块。它适用于计算密集型标量逻辑,尤其是在编译实现比脚本运行时更合适时。 + +将实现所需 Arrow UDF 接口的模块上传到某个 stage,然后注册其 handler: + +```sql +CREATE FUNCTION fib_wasm(value INT) +RETURNS INT +LANGUAGE wasm +HANDLER = 'fib' +AS $$ @my_wasm_stage/arrow_udf_example.wasm $$; + +SELECT fib_wasm(10); +``` + +该模块必须导出指定名称的 handler,并使用与 SQL 兼容的输入和输出类型。在将该函数发布给其他用户之前,请先使用具有代表性的值对编译产物进行测试。 + +## 使用聚合 UDF 实现自定义有状态计算 {#use-aggregate-udfs-for-custom-stateful-calculations} + +聚合 UDF 用于定义如何: + +1. 创建初始聚合状态; +2. 将每一行输入添加到状态中; +3. 合并分布式执行产生的部分状态; +4. 将最终状态转换为单个结果。 + +以下 Python 聚合会对值求和。对于这个特定计算,更推荐使用内置的 `SUM`,但该示例展示了自定义聚合所需的生命周期: + +```sql +CREATE FUNCTION py_total(value BIGINT) +STATE { total BIGINT } +RETURNS BIGINT +LANGUAGE python +AS $$ +class State: + def __init__(self): + self.total = 0 + +def create_state(): + return State() + +def accumulate(state, value): + state.total += value + return state + +def merge(left, right): + left.total += right.total + return left + +def finish(state): + return state.total +$$; + +SELECT py_total(number) FROM numbers(5); +``` + +聚合 UDF 支持 Python 和 JavaScript。仅当内置聚合函数无法表达所需的状态转换或最终处理逻辑时,才应使用它们。更多示例,请参见 [CREATE AGGREGATE FUNCTION](/tidb-cloud-lake/sql/create-aggregate-function.md)。 + +## 使用 SQL 表 UDF 复用结果集 {#use-sql-table-udfs-for-reusable-result-sets} + +SQL 表 UDF 封装一个 SQL 查询,并返回行和列。它适用于可复用的过滤条件、小型报表数据集以及参数化转换。 + +```sql +CREATE FUNCTION small_numbers(max_value INT) +RETURNS TABLE(value UINT64, doubled UINT64) +AS $$ + SELECT number AS value, number * 2 AS doubled + FROM numbers(10) + WHERE number < max_value +$$; + +SELECT * FROM small_numbers(3); +``` + +函数体是一个 SQL 查询。它不接受 `LANGUAGE python`。如果需要返回由 Python 生成的行,请使用外部表 UDF。 + +完整语法请参见 [CREATE TABLE FUNCTION](/tidb-cloud-lake/sql/create-table-function.md)。 + +## 使用外部 Python UDF 实现专用逻辑 {#use-external-python-udfs-for-specialized-logic} + +[`tidbcloudlake-udf`](https://pypi.org/project/tidbcloudlake-udf/) 包提供了一个 Python UDF Server,用于外部标量 UDF 和表 UDF。Python 进程运行在你的基础设施上,因此你可以使用自定义包、专有代码、GPU 计算以及独立扩缩容。 + +### 使用 Python 规范化地址 {#normalize-addresses-with-python} + +安装 SDK: + +```shell +python3 -m pip install tidbcloudlake-udf +``` + +定义 handler 并启动服务器: + +```python +from tidbcloudlake_udf import UDFServer, udf + + +@udf( + input_types=["VARCHAR"], + result_type="VARCHAR", + skip_null=True, +) +def normalize_address(value: str) -> str: + return " ".join(value.strip().upper().split()) + + +if __name__ == "__main__": + server = UDFServer("0.0.0.0:8815") + server.add_function(normalize_address) + server.serve() +``` + +部署服务器并将其加入 allowlist 后,注册该 handler: + +```sql +CREATE FUNCTION normalize_address(value VARCHAR) +RETURNS VARCHAR +LANGUAGE python +HANDLER = 'normalize_address' +ADDRESS = 'https://udf.example.com'; +``` + +### 将文本展开为多行 {#expand-text-into-rows} + +外部表 UDF 在 `result_type` 中使用输出列列表: + +```python +@udf( + input_types=["VARCHAR"], + result_type=[("token", "VARCHAR")], + skip_null=True, +) +def split_words(value: str): + return [{"token": token} for token in value.split()] +``` + +注册并调用该表 handler: + +```sql +CREATE FUNCTION split_words(value VARCHAR) +RETURNS TABLE(token VARCHAR) +LANGUAGE python +HANDLER = 'split_words' +ADDRESS = 'https://udf.example.com'; + +SELECT * FROM split_words('external UDF server'); +``` + +有关完整的服务器、部署、并发和注册工作流,请参见 [CREATE FUNCTION](/tidb-cloud-lake/sql/create-function.md)。 + +## 安全部署外部 UDF {#deploy-external-udfs-securely} + +在注册外部函数之前: + +- 将 UDF Server 部署到公共 HTTPS 端点。 +- 联系 TiDB Cloud Support,将该端点主机名添加到你的租户 UDF server allowlist 中。 +- 在网关层配置认证、容量、超时、高可用、升级和监控。 +- 将凭据保存在服务器部署环境中,而不是 SQL 函数定义里。 + +SQL `ADDRESS` 必须包含公共端点。服务器进程可以在其部署环境内部监听 `0.0.0.0`,但对于 Cloud 查询服务的调用来说,`localhost` 和 `0.0.0.0` 都不是有效地址。 + +外部 UDF 会增加网络延时。对于对延时敏感的逐行调用,应尽量保持调用轻量;在可能的情况下进行批处理;并避免在单个查询中重复调用同一个高开销函数。 + +## 比较性能与运维要求 {#compare-performance-and-operations} + +性能取决于函数复杂度、输入大小、包启动、计算集群 (Warehouse) 资源、网络延时、批大小以及 UDF Server 容量。在其他产品或部署中测得的结果,不能用于预测 Lake 的性能。 + +| UDF 类型 | 主要开销 | 运维责任 | +| --- | --- | --- | +| SQL 标量 UDF | SQL 表达式求值 | 由 {{{ .lake }}} 管理 | +| Python 或 JavaScript 标量 UDF | 脚本运行时和依赖关系初始化 | 由 {{{ .lake }}} 管理 | +| WebAssembly 标量 UDF | 模块加载和已编译函数执行 | 由 {{{ .lake }}} 管理 | +| 聚合 UDF | 脚本运行时和状态序列化 | 由 {{{ .lake }}} 管理 | +| SQL 表 UDF | 查询执行 | 由 {{{ .lake }}} 管理 | +| 外部 UDF | 网络传输和外部计算 | 由 {{{ .lake }}} 和你的 UDF Server 部署共同负责 | + +请使用具有代表性的数据和并发,对实际函数进行基准测试。测量查询延时、吞吐、错误处理、冷启动以及外部服务饱和情况。 + +## 遵循 UDF 最佳实践 {#follow-udf-best-practices} + +- 在引入脚本或服务之前,优先使用内置函数和 SQL。 +- 在可能的情况下,让每个函数保持确定性且职责单一。 +- 显式定义 NULL 行为,并测试可为空输入。 +- 使用精确的输入和返回类型,避免不必要的类型转换。 +- 对于聚合 UDF,应让 `merge` 满足结合性,以便安全地合并部分状态。 +- 对于外部 UDF,可对面向批处理的库使用 `batch_mode`,对 I/O 密集型逐行处理使用 `io_threads`。 +- 设置 `max_concurrency`,防止外部依赖过载。 +- 将外部 handler 变更视为服务 API 变更,并以与已注册 SQL 定义兼容的方式进行部署。 +- 对用户托管服务器监控错误、延时、饱和度和依赖关系健康状态。 +- 同时移除未使用的 UDF 注册项和服务器 handler。 + +## 开始使用 {#get-started} + +根据所需输出选择下一步: + +- [CREATE SCALAR FUNCTION](/tidb-cloud-lake/sql/create-scalar-function.md):用于可复用的 SQL 表达式。 +- [CREATE AGGREGATE FUNCTION](/tidb-cloud-lake/sql/create-aggregate-function.md):用于自定义 Python 或 JavaScript 聚合状态。 +- [CREATE TABLE FUNCTION](/tidb-cloud-lake/sql/create-table-function.md):用于可复用的 SQL 结果集。 +- [CREATE FUNCTION](/tidb-cloud-lake/sql/create-function.md):用于外部 Python 标量和表 handler。 +- [外部 AI 函数](/tidb-cloud-lake/guides/external-ai-functions.md):用于模型推导示例。 + +## 相关资源 {#related-resources} + +- [用户定义函数](/tidb-cloud-lake/sql/user-defined-function.md) +- [外部函数](/tidb-cloud-lake/sql/external-function.md) +- [`tidbcloud/lake-udf` on GitHub](https://github.com/tidbcloud/lake-udf) \ No newline at end of file diff --git a/tidb-cloud-lake/guides/cluster-key-performance.md b/tidb-cloud-lake/guides/cluster-key-performance.md new file mode 100644 index 0000000000000..5061df0c4b450 --- /dev/null +++ b/tidb-cloud-lake/guides/cluster-key-performance.md @@ -0,0 +1,163 @@ +--- +title: Cluster Key +summary: Cluster key 提供自动数据组织能力,可显著提升大表上的查询性能。{{{ .lake }}} 在后台无缝且持续地管理所有聚簇操作——你只需定义 cluster key,其余工作由 {{{ .lake }}} 处理。 +--- + +# Cluster Key + +Cluster key 提供自动数据组织能力,可显著提升大表上的查询性能。{{{ .lake }}} 在后台无缝且持续地管理所有聚簇操作——你只需定义 cluster key,其余工作由 {{{ .lake }}} 处理。 + +## 它解决了什么问题? {#what-problem-does-it-solve} + +如果大表没有经过合理组织,会带来显著的性能和维护挑战: + +| 问题 | 影响 | 自动聚簇解决方案 | +|---------|--------|------------------------------| +| **Full Table Scans** | 查询即使只筛选部分数据,也需要读取整张表 | 自动组织数据,只读取相关的数据块 | +| **Random Data Access** | 相似数据分散存储在各处 | 持续将相关数据归组到一起 | +| **Slow Filter Queries** | `WHERE` 子句会扫描不必要的行 | 自动完全跳过无关的数据块 | +| **High I/O Costs** | 读取大量未使用的数据 | 自动将数据传输量降到最低 | +| **Manual Maintenance** | 需要监控并手动对表重新聚簇 | 零维护——后台自动优化 | +| **Resource Management** | 必须为聚簇操作分配计算资源 | {{{ .lake }}} 自动处理所有聚簇资源 | + +**示例**:一个包含数百万商品的电商表。如果没有聚簇,执行 `WHERE category IN ('Electronics', 'Computers')` 查询时,必须扫描所有商品类别。通过按 category 自动聚簇后,{{{ .lake }}} 会持续将 Electronics 和 Computers 商品归组在一起,只需扫描 2 个数据块,而不是 1000+ 个数据块。 + +## 自动聚簇的优势 {#benefits-of-automatic-clustering} + +**易于维护**:{{{ .lake }}} 无需你再执行以下操作: + +- 监控已聚簇表的状态 +- 手动触发重新聚簇操作 +- 为聚簇指定计算资源 +- 安排维护时间窗口 + +**工作方式**:定义 cluster key 后,{{{ .lake }}} 会自动: + +- 监控 DML 操作带来的表变更 +- 评估表何时会从重新聚簇中受益 +- 在后台执行聚簇优化 +- 持续维护最佳的数据组织状态 + +你需要做的只是为每张表定义一个聚簇键(如果适用),之后所有维护工作都由 {{{ .lake }}} 自动管理。 + +## 工作原理 {#how-it-works} + +Cluster key 会根据指定列将数据组织到存储块(Parquet 文件)中: + +![Cluster Key Visualization](/media/tidb-cloud-lake/clustered.png) + +1. **数据组织** → 将相似值归组到相邻的数据块中 +2. **创建元信息** → 存储数据块到值的映射,以便快速查找 +3. **查询优化** → 查询时只读取相关的数据块 +4. **性能提升** → 扫描更少的行,更快返回结果 + +## 快速设置 {#quick-setup} + +```sql +-- Create table with cluster key +CREATE TABLE sales ( + order_id INT, + order_date TIMESTAMP, + region VARCHAR, + amount DECIMAL +) CLUSTER BY (region); + +-- Or add cluster key to existing table +ALTER TABLE sales CLUSTER BY (region, order_date); +``` + +## 选择合适的 Cluster Key {#choosing-the-right-cluster-key} + +根据最常见的查询过滤条件选择列: + +| 查询模式 | 推荐的 cluster key | 示例 | +|---------------|------------------------|---------| +| 按单列过滤 | 该列 | `CLUSTER BY (region)` | +| 按多列过滤 | 多列组合 | `CLUSTER BY (region, category)` | +| 日期范围查询 | 日期/时间戳列 | `CLUSTER BY (order_date)` | +| 高基数列 | 使用表达式减少取值数量 | `CLUSTER BY (DATE(created_at))` | + +### 好的与不好的 Cluster Key {#good-vs-bad-cluster-keys} + +| ✅ 良好选择 | ❌ 不佳选择 | +|----------------|----------------| +| 经常用于过滤的列 | 很少使用的列 | +| 中等基数(100-10K 个值) | 布尔列(取值太少) | +| 日期/时间列 | 唯一 ID 列(取值太多) | +| Region、类别、状态 | 随机列或哈希列 | + +## 监控性能 {#monitoring-performance} + +```sql +-- Check clustering effectiveness +SELECT * FROM clustering_information('database_name', 'table_name'); + +-- Key metrics to watch: +-- average_depth: Lower is better (< 2 ideal) +-- average_overlaps: Lower is better +-- block_depth_histogram: More blocks at depth 1-2 +``` + +## 何时重新聚簇 {#when-to-re-cluster} + +随着数据变化,表会逐渐变得无序: + +```sql +-- Check if re-clustering is needed +SELECT IF(average_depth > 2 * LEAST(GREATEST(total_block_count * 0.001, 1), 16), + 'Re-cluster needed', + 'Clustering is good') +FROM clustering_information('your_database', 'your_table'); + +-- Re-cluster the table +ALTER TABLE your_table RECLUSTER; +``` + +## 性能调优 {#performance-tuning} + +### 自定义块大小 {#custom-block-size} + +调整块大小以获得更好的性能: + +```sql +-- Smaller blocks = fewer rows per query +ALTER TABLE sales SET OPTIONS( + ROW_PER_BLOCK = 100000, + BLOCK_SIZE_THRESHOLD = 52428800 +); +``` + +### 自动重新聚簇 {#automatic-re-clustering} + +- `COPY INTO` 和 `REPLACE INTO` 会自动触发重新聚簇 +- 定期监控聚簇指标 +- 当 `average_depth` 变得过高时重新聚簇 + +## 最佳实践 {#best-practices} + +| 做法 | 好处 | +|----------|---------| +| **从简单开始** | 先使用单列 cluster key | +| **监控指标** | 定期检查 clustering_information | +| **测试性能** | 对比聚簇前后的查询速度 | +| **定期重新聚簇** | 在数据变更后保持聚簇效果 | +| **考虑成本** | 聚簇会消耗计算资源 | + +## 重要说明 {#important-notes} + +**适合使用 Cluster Key 的场景:** + +- 大表(数百万行以上) +- 存在慢查询性能问题 +- 频繁执行基于过滤条件的查询 +- 分析型工作负载 + +**不适合使用的场景:** + +- 小表 +- 随机访问模式 +- 数据频繁变化 + +--- + +*对于具有可预测过滤模式、且经常被查询的大表,cluster key 的效果最明显。建议从最常见的 WHERE 子句列开始。* diff --git a/tidb-cloud-lake/guides/compliance-security.md b/tidb-cloud-lake/guides/compliance-security.md new file mode 100644 index 0000000000000..7a5f8b38f0271 --- /dev/null +++ b/tidb-cloud-lake/guides/compliance-security.md @@ -0,0 +1,61 @@ +--- +title: 合规与安全 +summary: "{{{ .lake }}} 以安全为核心构建,通过多层安全防护、加密标准和合规认证,为您的数据提供全面保护。" +--- + +# 合规与安全 + +{{{ .lake }}} 以安全为核心构建,通过多层安全防护、加密标准和合规认证,为您的数据提供全面保护。 + +## 安全 {#security} + +{{{ .lake }}} 实现了多层安全机制,以保护您的数据并控制对资源的访问: + +### 访问控制 {#access-control} + +{{{ .lake }}} 使用一套全面的访问控制系统,结合了以下机制: + +- **Role-Based Access Control (RBAC)**:通过分配给用户的角色管理权限 +- **Discretionary Access Control (DAC)**:允许资源所有者直接授予权限 + +### 数据保护 {#data-protection} + +**Masking Policy**:通过控制不同用户查看数据的显示方式来保护敏感数据,帮助您在允许授权访问的同时满足隐私法规要求。 + +**Network Policy**:控制哪些 IP 地址可以连接到您的 {{{ .lake }}} 资源,使您能够将访问限制在特定网络或位置。 + +**Password Policy**:通过可自定义的长度、复杂度和轮换要求来强制使用高强度密码,以防止未授权访问。 + +### 安全连接 {#secure-connectivity} + +**PrivateLink**:支持在您的 VPC 与 {{{ .lake }}} 之间建立私有连接,而无需将流量暴露到公共互联网。有关设置说明,请参阅[使用 AWS PrivateLink 连接](/tidb-cloud-lake/guides/connect-with-aws-privatelink.md)或[使用 Alibaba Cloud PrivateLink 连接](/tidb-cloud-lake/guides/connect-with-alibaba-cloud-privatelink.md)。 + +## 加密 {#encryption} + +### TLS 1.2 {#tls-12} + +我们为所有通信提供端到端加密。所有客户数据流都仅通过 HTTPS 传输。从客户端到 {{{ .lake }}} API gateway 的连接均使用 TLS 1.2 加密,以确保: + +- 传输过程中的数据机密性 +- 防止中间人攻击 +- 安全的客户端-服务器通信 + +### 存储加密 {#storage-encryption} + +{{{ .lake }}} Enterprise 支持在 Object Storage Service (OSS) 中进行服务端加密。此功能支持您为存储在 OSS 中的数据启用服务端加密,从而增强数据安全性和隐私保护。您可以选择最适合自身需求的加密方式: + +- AES-256 加密 +- 客户管理密钥 (CMK) +- 硬件安全模块 (HSM) 集成选项 + +## 合规 {#compliance} + +在 {{{ .lake }}},我们将数据安全和隐私放在首位,并已获得多项关键合规认证,以证明我们对保护您数据的承诺。我们的安全实践会定期接受独立第三方审计,以确保符合业界最高标准。 + +### SOC 2 Type II {#soc-2-type-ii} + +我们已成功获得 SOC 2 Type II 合规认证,并经过独立审计机构验证。该认证确认我们的系统符合 American Institute of Certified Public Accountants (AICPA) 关于安全性、可用性、处理完整性、机密性和隐私的信任服务准则。我们持续监控并改进运营控制措施,以维持这一标准。 + +### GDPR {#gdpr} + +{{{ .lake }}} 遵循《通用数据保护条例》(GDPR)。这是欧盟为保护个人隐私和个人数据而制定的法规。我们的合规实践包括严格执行数据隐私保护、采用强大的加密措施,以及定期开展隐私审计,以确保欧盟范围内用户的权利和数据隐私得到保护。 \ No newline at end of file diff --git a/tidb-cloud-lake/guides/connect-using-golang.md b/tidb-cloud-lake/guides/connect-using-golang.md new file mode 100644 index 0000000000000..a3b40685ddf57 --- /dev/null +++ b/tidb-cloud-lake/guides/connect-using-golang.md @@ -0,0 +1,99 @@ +--- +title: 使用 Golang 连接 TiDB Cloud Lake +summary: 本页介绍如何使用 Golang 连接 TiDB Cloud Lake。 +--- + +# 使用 Golang 连接 TiDB Cloud Lake + +官方 Go 驱动提供了标准的 `database/sql` 接口,可与现有 Go 应用无缝集成。 + +## 安装 {#installation} + +```bash +go get github.com/tidbcloud/lake-go +``` + +**Connection String**:有关 DSN 格式和示例,请参见[驱动概览](/tidb-cloud-lake/guides/driver-overview.md)。 + +--- + +## 主要特性 {#key-features} + +- ✅ **标准接口**:完全兼容 `database/sql` +- ✅ **连接池**:内置连接管理 +- ✅ **批量操作**:通过事务高效执行批量插入 +- ✅ **类型安全**:提供全面的 Go 类型映射 + +## 数据类型映射 {#data-type-mappings} + +| {{{ .lake }}} | Go | 说明 | +|----------|----|---------| +| **整数型** | | | +| `TINYINT` | `int8` | | +| `SMALLINT` | `int16` | | +| `INT` | `int32` | | +| `BIGINT` | `int64` | | +| `TINYINT UNSIGNED` | `uint8` | | +| `SMALLINT UNSIGNED` | `uint16` | | +| `INT UNSIGNED` | `uint32` | | +| `BIGINT UNSIGNED` | `uint64` | | +| **浮点型** | | | +| `FLOAT` | `float32` | | +| `DOUBLE` | `float64` | | +| **其他类型** | | | +| `DECIMAL` | `decimal.Decimal` | 需要 decimal 包 | +| `STRING` | `string` | | +| `DATE` | `time.Time` | | +| `TIMESTAMP` | `time.Time` | | +| `ARRAY(T)` | `string` | JSON 编码 | +| `TUPLE(...)` | `string` | JSON 编码 | +| `VARIANT` | `string` | JSON 编码 | +| `BITMAP` | `string` | Base64 编码 | + +--- + +## 基本用法 {#basic-usage} + +```go +import ( + "database/sql" + "fmt" + "log" + + _ "github.com/tidbcloud/lake-go" +) + +// Connect to {{{ .lake }}} +db, err := sql.Open("lake", "") +if err != nil { + log.Fatal(err) +} +defer db.Close() + +// DDL: Create table +_, err = db.Exec("CREATE TABLE users (id INT, name STRING)") +if err != nil { + log.Fatal(err) +} + +// Write: Insert data +_, err = db.Exec("INSERT INTO users VALUES (?, ?)", 1, "Alice") +if err != nil { + log.Fatal(err) +} + +// Query: Select data +var id int +var name string +err = db.QueryRow("SELECT id, name FROM users WHERE id = ?", 1).Scan(&id, &name) +if err != nil { + log.Fatal(err) +} + +fmt.Printf("User: %d, %s\n", id, name) +``` + +## 资源 {#resources} + +- **GitHub 仓库**:[lake-go](https://github.com/tidbcloud/lake-go) +- **示例**:[GitHub Examples](https://github.com/tidbcloud/lake-go/tree/main/examples) \ No newline at end of file diff --git a/tidb-cloud-lake/guides/connect-using-java.md b/tidb-cloud-lake/guides/connect-using-java.md new file mode 100644 index 0000000000000..824c5252c545f --- /dev/null +++ b/tidb-cloud-lake/guides/connect-using-java.md @@ -0,0 +1,128 @@ +--- +title: 使用 Java 连接 TiDB Cloud Lake +summary: 本页介绍如何使用 Java 连接 TiDB Cloud Lake。 +--- + +# 使用 Java 连接 TiDB Cloud Lake + +官方 JDBC 驱动提供标准的 JDBC 4.0 兼容性,可与 Java 应用程序无缝集成。 + +## 安装 {#installation} + +### Maven {#maven} + +```xml + + com.tidbcloud + lake-jdbc + 0.4.6 + +``` + +### Gradle {#gradle} + +```gradle +implementation 'com.tidbcloud:lake-jdbc:0.4.6' +``` + +**Connection String**:有关 DSN 格式和示例,请参见[驱动概览](/tidb-cloud-lake/guides/driver-overview.md)。 + +## 关键特性 {#key-features} + +- ✅ **JDBC 4.0 Compatible**:支持标准 JDBC 接口 +- ✅ **Connection Pooling**:内置连接管理 +- ✅ **Prepared Statements**:高效的参数化查询 +- ✅ **Batch Operations**:支持批量插入和修改操作 + +## 数据类型映射 {#data-type-mappings} + +| {{{ .lake }}} | Java | 说明 | +|----------|------|---------| +| **整数型** | | | +| `TINYINT` | `Byte` | | +| `SMALLINT` | `Short` | | +| `INT` | `Integer` | | +| `BIGINT` | `Long` | | +| `TINYINT UNSIGNED` | `Short` | | +| `SMALLINT UNSIGNED` | `Integer` | | +| `INT UNSIGNED` | `Long` | | +| `BIGINT UNSIGNED` | `BigInteger` | | +| **浮点数** | | | +| `FLOAT` | `Float` | | +| `DOUBLE` | `Double` | | +| `DECIMAL` | `BigDecimal` | 保留精度 | +| **其他类型** | | | +| `BOOLEAN` | `Boolean` | | +| `STRING` | `String` | | +| `DATE` | `Date` | | +| `TIMESTAMP` | `Timestamp` | | +| `ARRAY(T)` | `String` | JSON 编码 | +| `TUPLE(...)` | `String` | JSON 编码 | +| `MAP(K,V)` | `String` | JSON 编码 | +| `VARIANT` | `String` | JSON 编码 | +| `BITMAP` | `String` | Base64 编码 | + +--- + +## 基本用法 {#basic-usage} + +```java +import java.sql.*; + +// Connect to {{{ .lake }}} +Connection conn = DriverManager.getConnection(""); + +// DDL: Create table +Statement stmt = conn.createStatement(); +stmt.execute("CREATE TABLE users (id INT, name STRING, email STRING)"); + +// Write: Insert data +PreparedStatement pstmt = conn.prepareStatement("INSERT INTO users VALUES (?, ?, ?)"); +pstmt.setInt(1, 1); +pstmt.setString(2, "Alice"); +pstmt.setString(3, "alice@example.com"); +int result = pstmt.executeUpdate(); + +// Write: Insert data with executeBatch +pstmt = conn.prepareStatement("INSERT INTO users VALUES (?, ?, ?)"); +pstmt.setInt(1, 2); +pstmt.setString(2, "Bob"); +pstmt.setString(3, "Bob@example.com"); +pstmt.addBatch(); +pstmt.setInt(1, 3); +pstmt.setString(2, "John"); +pstmt.setString(3, "John@example.com"); +pstmt.addBatch(); +int[] results = pstmt.executeBatch(); + +// Query: Select data +ResultSet rs = stmt.executeQuery("SELECT id, name, email FROM users WHERE id = 1"); +while (rs.next()) { + System.out.println("User: " + rs.getInt("id") + ", " + + rs.getString("name") + ", " + + rs.getString("email")); +} + +// Close connections +rs.close(); +stmt.close(); +pstmt.close(); +conn.close(); +``` + +## 配置参考 {#configuration-reference} + +有关完整的 lake-jdbc 驱动配置选项,包括: + +- 连接字符串参数 +- SSL/TLS 配置 +- 身份验证方法 +- 性能调优参数 + +请参阅[官方 lake-jdbc Connection Guide](https://github.com/tidbcloud/lake-jdbc/blob/main/docs/Connection.md)。 + +## 资源 {#resources} + +- **Maven Central**:[lake-jdbc](https://repo1.maven.org/maven2/com/tidbcloud/lake-jdbc/) +- **GitHub Repository**:[lake-jdbc](https://github.com/tidbcloud/lake-jdbc) +- **JDBC Documentation**:[Oracle JDBC Guide](https://docs.oracle.com/javase/tutorial/jdbc/) \ No newline at end of file diff --git a/tidb-cloud-lake/guides/connect-using-lakesql.md b/tidb-cloud-lake/guides/connect-using-lakesql.md new file mode 100644 index 0000000000000..bc427608db011 --- /dev/null +++ b/tidb-cloud-lake/guides/connect-using-lakesql.md @@ -0,0 +1,671 @@ +--- +title: 使用 LakeSQL 连接到 TiDB Cloud Lake +summary: LakeSQL 是专为 {{{ .lake }}} 设计的命令行工具。它允许用户建立与 {{{ .lake }}} 的连接,并直接在 CLI 窗口中执行查询。 +--- + +# 使用 LakeSQL 连接到 TiDB Cloud Lake + +[LakeSQL](https://github.com/tidbcloud/lakesql) 是专为 {{{ .lake }}} 设计的命令行工具。它允许用户建立与 {{{ .lake }}} 的连接,并直接在 CLI 窗口中执行查询。 + +LakeSQL 特别适合偏好命令行接口并且需要经常使用 {{{ .lake }}} 的用户。借助 LakeSQL,用户可以轻松高效地管理数据库、表和数据,并便捷地执行各种查询和操作。 + +## 安装 LakeSQL {#installing-lakesql} + +LakeSQL 提供了多种安装方式,以适配不同的平台和使用偏好。你可以从以下各节中选择适合自己的方法,或者从 [LakeSQL release page](https://github.com/tidbcloud/lakesql/releases) 下载安装包进行手动安装。 + +### Shell 脚本 {#shell-script} + +LakeSQL 提供了便捷的 Shell 安装脚本。你可以选择以下两种方式之一: + +#### 默认安装 {#default-installation} + +将 LakeSQL 安装到用户的主目录 (~/.lakesql): + +```bash +curl -fsSL https://lakesql-bin.tidbcloud.com/install/lakesql.sh | bash +``` + +```bash title='Example:' +# highlight-next-line +curl -fsSL https://lakesql-bin.tidbcloud.com/install/lakesql.sh | bash + + L A K E S Q L + Installer + +-------------------------------------------------------------------------------- +Website: https://tidbcloud.com +Docs: https://docs.pingcap.com/tidbcloudlake/ +Github: https://github.com/tidbcloud/lakesql +-------------------------------------------------------------------------------- + +>>> We'll be installing LakeSQL via a pre-built archive at https://lakesql-bin.tidbcloud.com/lakesql/v0.22.2/ +>>> Ready to proceed? (y/n) + +>>> Please enter y or n. +>>> y + +-------------------------------------------------------------------------------- + +>>> Downloading LakeSQL archive via https://lakesql-bin.tidbcloud.com/lakesql/v0.22.2/lakesql-aarch64-apple-darwin.tar.gz ✓ +>>> Unpacking archive to /Users/eric/.lakesql ... ✓ +>>> Adding LakeSQL path to /Users/eric/.zprofile ✓ +>>> Adding LakeSQL path to /Users/eric/.profile ✓ +>>> Install succeeded! 🚀 +>>> To start LakeSQL: + + lakesql --help + +>>> More information at https://github.com/tidbcloud/lakesql +``` + +#### 使用 `--prefix` 自定义安装 {#custom-installation-with-prefix} + +将 LakeSQL 安装到指定目录(例如 /usr/local): + +```bash +curl -fsSL https://lakesql-bin.tidbcloud.com/install/lakesql.sh | bash -s -- -y --prefix /usr/local +``` + +```bash title='Example:' +# highlight-next-line +curl -fsSL https://lakesql-bin.tidbcloud.com/install/lakesql.sh | bash -s -- -y --prefix /usr/local + L A K E S Q L + Installer + +-------------------------------------------------------------------------------- +Website: https://tidbcloud.com +Docs: https://docs.pingcap.com +Github: https://github.com/tidbcloud/lakesql +-------------------------------------------------------------------------------- + +>>> Downloading LakeSQL via https://lakesql-bin.tidbcloud.com/lakesql/v0.22.2/lakesql-aarch64-apple-darwin.tar.gz ✓ +>>> Unpacking archive to /usr/local ... ✓ +>>> Install succeeded! 🚀 +>>> To start LakeSQL: + + lakesql --help + +>>> More information at https://github.com/tidbcloud/lakesql +``` + +### Homebrew(适用于 macOS) {#homebrew-for-macos} + +在 macOS 上,你可以使用 Homebrew 通过一条简单的命令轻松安装 LakeSQL: + +```bash +brew install tidbcloud/homebrew-tap/lakesql +``` + +### Apt(适用于 Ubuntu/Debian) {#apt-for-ubuntu-debian} + +在 Ubuntu 和 Debian 系统上,你可以使用 Apt 包管理器安装 LakeSQL: + +```bash +curl -fsSL https://lakesql-bin.tidbcloud.com/keys/lakesql-archive-keyring.gpg \ + | sudo tee /usr/share/keyrings/lakesql-archive-keyring.gpg >/dev/null +echo "deb [signed-by=/usr/share/keyrings/lakesql-archive-keyring.gpg] https://lakesql-bin.tidbcloud.com/apt stable main" \ + | sudo tee /etc/apt/sources.list.d/lakesql.list >/dev/null +sudo apt-get update +sudo apt-get install -y lakesql +``` + +### Cargo(Rust 包管理器) {#cargo-rust-package-manager} + +要使用 Cargo 安装 LakeSQL,可以使用 `cargo-binstall` 工具,或者通过提供的命令从源码构建。 + +> **Note:** +> +> 在使用 Cargo 安装之前,请确保你的计算机上已安装完整的 Rust 工具链以及 `cargo` 命令。如果尚未安装,请参考 [https://rustup.rs/](https://rustup.rs/) 上的安装指南。 + +**使用 cargo-binstall** + +请参考 [Cargo B(inary)Install - Installation](https://github.com/cargo-bins/cargo-binstall#installation) 安装 `cargo-binstall`,并启用 `cargo binstall ` 子命令。 + +```bash +cargo binstall lakesql +``` + +**从源码构建** + +从源码构建时,某些依赖项可能涉及编译 C/C++ 代码。请确保你的计算机上已安装 GCC/G++ 或 Clang 工具链。 + +```bash +cargo install lakesql +``` + +## 用户认证 {#user-authentication} + +对于连接到 {{{ .lake }}},你可以使用默认的 `cloudapp` 用户,或者使用通过 [CREATE USER](/tidb-cloud-lake/sql/create-user.md) 命令创建的 SQL 用户。请注意,你用于登录 [{{{ .lake }}} console](https://app.lake.tidbcloud.com) 的用户账户不能用于连接到 {{{ .lake }}}。 + +## 使用 LakeSQL 连接 {#connecting-with-lakesql} + +LakeSQL 支持连接到 {{{ .lake }}} 实例。 + +### 使用 DSN 自定义连接 {#customize-connections-with-a-dsn} + +DSN(Data Source Name)是一种简单而强大的方式,可让你在 LakeSQL 中使用单个 URI 风格的字符串来配置和管理 {{{ .lake }}} 连接。通过这种方式,你可以将凭证和连接设置直接嵌入到环境中,从而简化连接过程。 + +#### DSN 格式和参数 {#dsn-format-and-parameters} + +```bash title='DSN Format' +lake[+flight]://user[:password]@host[:port]/[database][?sslmode=disable][&arg1=value1] +``` + +| 常见 DSN 参数 | 描述 | +|-----------------------|--------------------------------------| +| `tenant` | 租户 ID,仅适用于 {{{ .lake }}}。 | +| `warehouse` | 计算集群名称,仅适用于 {{{ .lake }}}。 | +| `sslmode` | 如果不使用 TLS,则设置为 `disable`。 | +| `tls_ca_file` | 自定义根 CA 证书路径。 | +| `connect_timeout` | 连接超时时间(秒)。 | + +| RestAPI 客户端参数 | 描述 | +|-----------------------------|-------------------------------------------------------------------------------------------------------------------------------| +| `wait_time_secs` | 页面请求等待时间,默认为 `1`。 | +| `max_rows_in_buffer` | 页面缓冲区中的最大行数。 | +| `max_rows_per_page` | 单个页面响应的最大行数。 | +| `page_request_timeout_secs` | 单个页面请求的超时时间,默认为 `30`。 | +| `presign` | 为数据加载启用 presign。可选值:`auto`、`detect`、`on`、`off`。默认值为 `auto`(仅对 {{{ .lake }}} 启用)。 | + +| FlightSQL 客户端参数 | 描述 | +|-----------------------------|----------------------------------------------------------------------| +| `query_timeout` | 查询超时时间(秒)。 | +| `tcp_nodelay` | 默认为 `true`。 | +| `tcp_keepalive` | TCP keepalive 时间(秒)(默认值为 `3600`,设置为 `0` 可禁用)。 | +| `http2_keep_alive_interval` | keep-alive 间隔时间(秒),默认值为 `300`。 | +| `keep_alive_timeout` | keep-alive 超时时间(秒),默认值为 `20`。 | +| `keep_alive_while_idle` | 默认为 `true`。 | + +#### DSN 示例 {#dsn-examples} + +```bash +# Local connection using HTTP API with presign detection +lake://root:@localhost:8000/?sslmode=disable&presign=detect + +# {{{ .lake }}} connection with tenant and warehouse info +lake://user1:password1@tnxxxx--default.gw.aws-us-east-2.default.tidbcloud.com:443/benchmark?enable_dphyp=1 + +# Local connection using FlightSQL API +lake+flight://root:@localhost:8900/database1?connect_timeout=10 +``` + +### 连接到 {{{ .lake }}} {#connect-to-lake} + +连接到 {{{ .lake }}} 的最佳实践是从 {{{ .lake }}} 获取你的 DSN,并将其导出为环境变量。要获取 DSN,请执行以下操作: + +1. 登录 {{{ .lake }}},然后在 **Overview** 页面点击 **Connect**。 + +2. 选择你要连接的数据库和计算集群 (Warehouse)。 + +3. 你的 DSN 会在 **Examples** 部分自动生成。在 DSN 下方,你会看到一段 LakeSQL 代码片段,它会将 DSN 导出为名为 `LAKESQL_DSN` 的环境变量,并使用正确的配置启动 LakeSQL。你可以直接将其复制并粘贴到终端中。 + + ```bash title='Example' + export LAKESQL_DSN="lake://cloudapp:******@tn3ftqihs.gw.aws-us-east-2.default.tidbcloud.com:443/information_schema?warehouse=small-xy2t" + lakesql + ``` + +## LakeSQL 设置 {#lakesql-settings} + +LakeSQL 提供了一系列设置,用于定义如何展示查询结果: + +| 设置 | 描述 | +| -------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `display_pretty_sql` | 设置为 `true` 时,SQL 查询会以更美观的方式格式化显示,从而更易于阅读和理解。 | +| `prompt` | 命令行接口中显示的提示符,通常用于指示当前访问的用户、计算集群和数据库。 | +| `progress_color` | 指定进度指示器使用的颜色,例如在执行需要一定时间才能完成的查询时。 | +| `show_progress` | 设置为 `true` 时,会显示进度指示器,以展示长时间运行的查询或操作的进度。 | +| `show_stats` | 如果为 `true`,则在每次执行查询后显示查询统计信息,例如执行时间、读取的行数和处理的字节数。 | +| `max_display_rows` | 设置查询结果输出中显示的最大行数。 | +| `max_col_width` | 设置每列显示渲染的最大字符宽度。小于 3 的值会禁用该限制。 | +| `max_width` | 设置整个显示输出的最大字符宽度。值为 0 时,默认使用终端窗口的宽度。 | +| `output_format` | 设置用于显示查询结果的格式(`table`, `csv`, `tsv`, `null`)。 | +| `expand` | 控制查询输出是以单条记录形式显示,还是以表格形式显示。可选值:`on`、`off` 和 `auto`。 | +| `multi_line` | 决定是否允许 SQL 查询使用多行输入。设置为 `true` 时,查询可以跨多行书写,以提高可读性。 | +| `replace_newline` | 指定是否将查询结果输出中的换行符替换为空格。这可以避免显示中出现非预期的换行。 | + +有关各项设置的详细信息,请参阅以下参考内容: + +### `display_pretty_sql` {#display-pretty-sql} + +`display_pretty_sql` 设置用于控制 SQL 查询是否以视觉上格式化的方式显示。设置为 `false` 时,如下面第一个查询所示,SQL 查询不会为了美观而进行格式化。相反,设置为 `true` 时,如第二个查询所示,SQL 查询会以更美观的方式格式化显示,从而更易于阅读和理解。 + +```shell title='Example:' +// highlight-next-line +root@localhost:8000/default> !set display_pretty_sql false +root@localhost:8000/default> SELECT TO_STRING(ST_ASGEOJSON(ST_GEOMETRYFROMWKT('SRID=4326;LINESTRING(400000 6000000, 401000 6010000)'))) AS pipeline_geojson; +┌─────────────────────────────────────────────────────────────────────────┐ +│ pipeline_geojson │ +│ String │ +├─────────────────────────────────────────────────────────────────────────┤ +│ {"coordinates":[[400000,6000000],[401000,6010000]],"type":"LineString"} │ +└─────────────────────────────────────────────────────────────────────────┘ +1 row read in 0.063 sec. Processed 1 row, 1 B (15.76 rows/s, 15 B/s) + +// highlight-next-line +root@localhost:8000/default> !set display_pretty_sql true +root@localhost:8000/default> SELECT TO_STRING(ST_ASGEOJSON(ST_GEOMETRYFROMWKT('SRID=4326;LINESTRING(400000 6000000, 401000 6010000)'))) AS pipeline_geojson; + +SELECT + TO_STRING( + ST_ASGEOJSON( + ST_GEOMETRYFROMWKT( + 'SRID=4326;LINESTRING(400000 6000000, 401000 6010000)' + ) + ) + ) AS pipeline_geojson + +┌─────────────────────────────────────────────────────────────────────────┐ +│ pipeline_geojson │ +│ String │ +├─────────────────────────────────────────────────────────────────────────┤ +│ {"coordinates":[[400000,6000000],[401000,6010000]],"type":"LineString"} │ +└─────────────────────────────────────────────────────────────────────────┘ +1 row read in 0.087 sec. Processed 1 row, 1 B (11.44 rows/s, 11 B/s) +``` + +### `prompt` {#prompt} + +`prompt` 设置用于控制命令行接口提示符的格式。在下面的示例中,它最初被设置为显示用户和计算集群(`{user}@{warehouse}`)。更新为 `{user}@{warehouse}/{database}` 后,提示符现在会包含用户、计算集群和数据库。 + +```shell title='Example:' +// highlight-next-line +root@localhost:8000/default> !set prompt {user}@{warehouse} +root@localhost:8000 !configs +Settings { + display_pretty_sql: true, + prompt: "{user}@{warehouse}", + progress_color: "cyan", + show_progress: true, + show_stats: true, + max_display_rows: 40, + max_col_width: 1048576, + max_width: 1048576, + output_format: Table, + quote_style: Necessary, + expand: Off, + time: None, + multi_line: true, + replace_newline: true, +} +// highlight-next-line +root@localhost:8000 !set prompt {user}@{warehouse}/{database} +root@localhost:8000/default +``` + +### `progress_color` {#progress-color} + +`progress_color` 设置用于控制查询执行期间进度指示器使用的颜色。在此示例中,颜色已设置为 `blue`: + +```shell title='Example:' +// highlight-next-line +root@localhost:8000/default> !set progress_color blue +``` + +### `show_progress` {#show-progress} + +设置为 `true` 时,会在查询执行期间显示进度信息。进度信息包括已处理的行数、查询中的总行数、每秒处理的行数、已处理的内存量,以及每秒处理的内存速度。 + +```shell title='Example:' +// highlight-next-line +root@localhost:8000/default> !set show_progress true +root@localhost:8000/default> select * from numbers(1000000000000000); +⠁ [00:00:08] Processing 18.02 million/1 quadrillion (2.21 million rows/s), 137.50 MiB/7.11 PiB (16.88 MiB/s) ░ +``` + +### `show_stats` {#show-stats} + +`show_stats` 设置用于控制是否在每次执行查询后显示查询统计信息。设置为 `false` 时,如下面示例中的第一个查询所示,不会显示查询统计信息。相反,设置为 `true` 时,如第二个查询所示,会在每次执行查询后显示查询统计信息,例如执行时间、读取的行数和处理的字节数。 + +```shell title='Example:' +// highlight-next-line +root@localhost:8000/default> !set show_stats false +root@localhost:8000/default> select now(); +┌────────────────────────────┐ +│ now() │ +│ Timestamp │ +├────────────────────────────┤ +│ 2024-04-23 23:27:11.538673 │ +└────────────────────────────┘ +// highlight-next-line +root@localhost:8000/default> !set show_stats true +root@localhost:8000/default> select now(); +┌────────────────────────────┐ +│ now() │ +│ Timestamp │ +├────────────────────────────┤ +│ 2024-04-23 23:49:04.754296 │ +└────────────────────────────┘ +1 row read in 0.045 sec. Processed 1 row, 1 B (22.26 rows/s, 22 B/s) +``` + +### `max_display_rows` {#max-display-rows} + +`max_display_rows` 设置用于控制查询结果输出中显示的最大行数。在下面的示例中,当其设置为 `5` 时,查询结果中最多只显示 5 行。其余行会以 (5 shown) 标示。 + +```shell title='Example:' +// highlight-next-line +root@localhost:8000/default> !set max_display_rows 5 +root@localhost:8000/default> SELECT * FROM system.configs; +┌──────────────────────────────────────────────────────┐ +│ group │ name │ value │ description │ +│ String │ String │ String │ String │ +├───────────┼──────────────────┼─────────┼─────────────┤ +│ query │ tenant_id │ default │ │ +│ query │ cluster_id │ default │ │ +│ query │ num_cpus │ 0 │ │ +│ · │ · │ · │ · │ +│ · │ · │ · │ · │ +│ · │ · │ · │ · │ +│ storage │ cos.endpoint_url │ │ │ +│ storage │ cos.root │ │ │ +│ 176 rows │ │ │ │ +│ (5 shown) │ │ │ │ +└──────────────────────────────────────────────────────┘ +176 rows read in 0.059 sec. Processed 176 rows, 10.36 KiB (2.98 thousand rows/s, 175.46 KiB/s) +``` + +### `max_col_width` & `max_width` {#max-col-width-max-width} + +设置 `max_col_width` 和 `max_width` 分别用于指定单个列以及整个显示输出允许的最大字符宽度。以下示例将列显示宽度设置为 10 个字符,并将整个显示宽度设置为 100 个字符: + +```sql title='Example:' +// highlight-next-line +root@localhost:8000/default> .max_col_width 10 +// highlight-next-line +root@localhost:8000/default> .max_width 100 +root@localhost:8000/default> select * from system.settings; +┌──────────────────────────────────────────────────────────────────────────────────────────────────┐ +│ name │ value │ default │ range │ level │ description │ type │ +│ String │ String │ String │ String │ String │ String │ String │ +├────────────┼─────────┼─────────┼──────────┼─────────┼───────────────────────────────────┼────────┤ +│ acquire... │ 15 │ 15 │ None │ DEFAULT │ Sets the maximum timeout in se... │ UInt64 │ +│ aggrega... │ 0 │ 0 │ None │ DEFAULT │ Sets the maximum amount of mem... │ UInt64 │ +│ aggrega... │ 0 │ 0 │ [0, 100] │ DEFAULT │ Sets the maximum memory ratio ... │ UInt64 │ +│ auto_co... │ 50 │ 50 │ None │ DEFAULT │ Threshold for triggering auto ... │ UInt64 │ +│ collation │ utf8 │ utf8 │ ["utf8"] │ DEFAULT │ Sets the character collation. ... │ String │ +│ · │ · │ · │ · │ · │ · │ · │ +│ · │ · │ · │ · │ · │ · │ · │ +│ · │ · │ · │ · │ · │ · │ · │ +│ storage... │ 1048576 │ 1048576 │ None │ DEFAULT │ Sets the byte size of the buff... │ UInt64 │ +│ table_l... │ 10 │ 10 │ None │ DEFAULT │ Sets the seconds that the tabl... │ UInt64 │ +│ timezone │ UTC │ UTC │ None │ DEFAULT │ Sets the timezone. │ String │ +│ unquote... │ 0 │ 0 │ None │ DEFAULT │ Determines whether {{{ .lake }}} tr... │ UInt64 │ +│ use_par... │ 0 │ 0 │ [0, 1] │ DEFAULT │ This setting is deprecated │ UInt64 │ +│ 96 rows │ │ │ │ │ │ │ +│ (10 shown) │ │ │ │ │ │ │ +└──────────────────────────────────────────────────────────────────────────────────────────────────┘ +96 rows read in 0.040 sec. Processed 96 rows, 16.52 KiB (2.38 thousand rows/s, 410.18 KiB/s) +``` + +### `output_format` {#output-format} + +通过将 `output_format` 设置为 `table`、`csv`、`tsv` 或 `null`,你可以控制查询结果的格式。`table` 格式会以带列标题的表格形式展示结果;`csv` 和 `tsv` 格式则分别提供逗号分隔值和制表符分隔值;`null` 格式则会完全抑制输出格式化。 + +```shell title='Example:' +// highlight-next-line +root@localhost:8000/default> !set output_format table +root@localhost:8000/default> show users; +┌────────────────────────────────────────────────────────────────────────────┐ +│ name │ hostname │ auth_type │ is_configured │ default_role │ disabled │ +│ String │ String │ String │ String │ String │ Boolean │ +├────────┼──────────┼─────────────┼───────────────┼───────────────┼──────────┤ +│ root │ % │ no_password │ YES │ account_admin │ false │ +└────────────────────────────────────────────────────────────────────────────┘ +1 row read in 0.032 sec. Processed 1 row, 113 B (31.02 rows/s, 3.42 KiB/s) + +// highlight-next-line +root@localhost:8000/default> !set output_format csv +root@localhost:8000/default> show users; +root,%,no_password,YES,account_admin,false +1 row read in 0.062 sec. Processed 1 row, 113 B (16.03 rows/s, 1.77 KiB/s) + +// highlight-next-line +root@localhost:8000/default> !set output_format tsv +root@localhost:8000/default> show users; +root % no_password YES account_admin false +1 row read in 0.076 sec. Processed 1 row, 113 B (13.16 rows/s, 1.45 KiB/s) + +// highlight-next-line +root@localhost:8000/default> !set output_format null +root@localhost:8000/default> show users; +1 row read in 0.036 sec. Processed 1 row, 113 B (28.1 rows/s, 3.10 KiB/s) +``` + +### `expand` {#expand} + +`expand` 设置用于控制查询输出是显示为单独的记录,还是以表格格式显示。当 `expand` 设置为 `auto` 时,系统会根据查询返回的行数自动决定输出的显示方式。如果查询只返回一行,则输出会显示为单条记录。 + +```shell title='Example:' +// highlight-next-line +root@localhost:8000/default> !set expand on +root@localhost:8000/default> show users; +-[ RECORD 1 ]----------------------------------- + name: root + hostname: % + auth_type: no_password +is_configured: YES + default_role: account_admin + disabled: false + +1 row read in 0.055 sec. Processed 1 row, 113 B (18.34 rows/s, 2.02 KiB/s) + +// highlight-next-line +root@localhost:8000/default> !set expand off +root@localhost:8000/default> show users; +┌────────────────────────────────────────────────────────────────────────────┐ +│ name │ hostname │ auth_type │ is_configured │ default_role │ disabled │ +│ String │ String │ String │ String │ String │ Boolean │ +├────────┼──────────┼─────────────┼───────────────┼───────────────┼──────────┤ +│ root │ % │ no_password │ YES │ account_admin │ false │ +└────────────────────────────────────────────────────────────────────────────┘ +1 row read in 0.046 sec. Processed 1 row, 113 B (21.62 rows/s, 2.39 KiB/s) + +// highlight-next-line +root@localhost:8000/default> !set expand auto +root@localhost:8000/default> show users; +-[ RECORD 1 ]----------------------------------- + name: root + hostname: % + auth_type: no_password +is_configured: YES + default_role: account_admin + disabled: false + +1 row read in 0.037 sec. Processed 1 row, 113 B (26.75 rows/s, 2.95 KiB/s) +``` + +### `multi_line` {#multi-line} + +当 `multi_line` 设置为 `true` 时,允许跨多行输入内容。因此,SQL 查询中的每个子句都可以单独占一行,从而提升可读性和条理性。 + +```shell title='Example:' +// highlight-next-line +root@localhost:8000/default> !set multi_line true; +root@localhost:8000/default> SELECT * +> FROM system.configs; +┌──────────────────────────────────────────────────────┐ +│ group │ name │ value │ description │ +│ String │ String │ String │ String │ +├───────────┼──────────────────┼─────────┼─────────────┤ +│ query │ tenant_id │ default │ │ +│ query │ cluster_id │ default │ │ +│ query │ num_cpus │ 0 │ │ +│ · │ · │ · │ · │ +│ · │ · │ · │ · │ +│ · │ · │ · │ · │ +│ storage │ cos.endpoint_url │ │ │ +│ storage │ cos.root │ │ │ +│ 176 rows │ │ │ │ +│ (5 shown) │ │ │ │ +└──────────────────────────────────────────────────────┘ +176 rows read in 0.060 sec. Processed 176 rows, 10.36 KiB (2.91 thousand rows/s, 171.39 KiB/s) +``` + +### `replace_newline` {#replace-newline} + +`replace_newline` 设置用于确定是否将输出中的换行符 (`\n`) 替换为字面字符串 (`\\n`)。在下面的示例中,`replace_newline` 设置为 `true`。因此,当选择字符串 `'Hello\nWorld'` 时,换行符 (`\n`) 会被替换为字面字符串 (`\\n`)。也就是说,输出不会显示实际的换行,而是将 `'Hello\nWorld'` 显示为 `'Hello\\nWorld'`: + +```shell title='Example:' +// highlight-next-line +root@localhost:8000/default> !set replace_newline true +root@localhost:8000/default> SELECT 'Hello\nWorld' AS message; +┌──────────────┐ +│ message │ +│ String │ +├──────────────┤ +│ Hello\nWorld │ +└──────────────┘ +1 row read in 0.056 sec. Processed 1 row, 1 B (18 rows/s, 17 B/s) + +// highlight-next-line +root@localhost:8000/default> !set replace_newline false; +root@localhost:8000/default> SELECT 'Hello\nWorld' AS message; +┌─────────┐ +│ message │ +│ String │ +├─────────┤ +│ Hello │ +│ World │ +└─────────┘ +1 row read in 0.067 sec. Processed 1 row, 1 B (14.87 rows/s, 14 B/s) +``` + +### 配置 LakeSQL 设置 {#configuring-lakesql-settings} + +你可以通过以下方式配置 LakeSQL 设置: + +- 使用 `!set ` 命令。更多信息,请参见[实用命令](#utility-commands)。 + +- 在配置文件 `~/.config/lakesql/config.toml` 中添加并配置设置。为此,打开该文件,并在 `[settings]` 部分下添加你的设置。以下示例将 `max_display_rows` 设置为 10,并将 `max_width` 设置为 100: + +```toml title='Example:' +... +[settings] +max_display_rows = 10 +max_width = 100 +... +``` + +- 在运行时配置设置:启动 LakeSQL 后,使用 `. ` 格式指定设置。请注意,以这种方式配置的设置仅在当前会话中生效。 + +```shell title='Example:' +root@localhost:8000/default> .max_display_rows 10 +root@localhost:8000/default> .max_width 100 +``` + +## Utility Commands {#utility-commands} + +LakeSQL 提供了多种命令,帮助用户简化工作流程并自定义使用体验。以下是 LakeSQL 中可用命令的概览: + +| 命令 | 描述 | +| ------------------------ | ---------------------------- | +| `!exit` | 退出 LakeSQL。 | +| `!quit` | 退出 LakeSQL。 | +| `!configs` | 显示当前的 LakeSQL 设置。 | +| `!set ` | 修改 LakeSQL 设置。 | +| `!source ` | 执行 SQL 文件。 | + +有关各个命令的示例,请参见以下参考信息: + +### `!exit` {#exit} + +断开与 {{{ .lake }}} 的连接并退出 LakeSQL。 + +```shell title='Example:' +➜ ~ lakesql +Welcome to LakeSQL 0.17.0-homebrew. +Connecting to localhost:8000 as user root. +Connected to {{{ .lake }}} Query v1.2.427-nightly-b1b622d406(rust-1.77.0-nightly-2024-04-20T22:12:35.318382488Z) + +// highlight-next-line +root@localhost:8000/default> !exit +Bye~ +``` + +### `!quit` {#quit} + +断开与 {{{ .lake }}} 的连接并退出 LakeSQL。 + +```shell title='Example:' +➜ ~ lakesql +Welcome to LakeSQL 0.17.0-homebrew. +Connecting to localhost:8000 as user root. +Connected to {{{ .lake }}} Query v1.2.427-nightly-b1b622d406(rust-1.77.0-nightly-2024-04-20T22:12:35.318382488Z) + +// highlight-next-line +root@localhost:8000/default> !quit +Bye~ +➜ ~ +``` + +### `!configs` {#configs} + +显示当前的 LakeSQL 设置。 + +```shell title='Example:' +// highlight-next-line +root@localhost:8000/default> !configs +Settings { + display_pretty_sql: true, + prompt: "{user}@{warehouse}/{database}> ", + progress_color: "cyan", + show_progress: true, + show_stats: true, + max_display_rows: 40, + max_col_width: 1048576, + max_width: 1048576, + output_format: Table, + quote_style: Necessary, + expand: Off, + time: None, + multi_line: true, + replace_newline: true, +} +``` + +### `!set ` {#set} + +修改 LakeSQL 设置。 + +```shell title='Example:' +root@localhost:8000/default> !set display_pretty_sql false +``` + +### `!source ` {#source} + +执行 SQL 文件。 + +```shell title='Example:' +➜ ~ more ./desktop/test.sql +CREATE TABLE test_table ( + id INT, + name VARCHAR(50) +); + +INSERT INTO test_table (id, name) VALUES (1, 'Alice'); +INSERT INTO test_table (id, name) VALUES (2, 'Bob'); +INSERT INTO test_table (id, name) VALUES (3, 'Charlie'); +➜ ~ lakesql +Welcome to LakeSQL 0.17.0-homebrew. +Connecting to localhost:8000 as user root. +Connected to {{{ .lake }}} Query v1.2.427-nightly-b1b622d406(rust-1.77.0-nightly-2024-04-20T22:12:35.318382488Z) + +// highlight-next-line +root@localhost:8000/default> !source ./desktop/test.sql +root@localhost:8000/default> SELECT * FROM test_table; + +SELECT + * +FROM + test_table + +┌────────────────────────────────────┐ +│ id │ name │ +│ Nullable(Int32) │ Nullable(String) │ +├─────────────────┼──────────────────┤ +│ 1 │ Alice │ +│ 2 │ Bob │ +│ 3 │ Charlie │ +└────────────────────────────────────┘ +3 rows read in 0.064 sec. Processed 3 rows, 81 B (46.79 rows/s, 1.23 KiB/s) +``` diff --git a/tidb-cloud-lake/guides/connect-using-node-js.md b/tidb-cloud-lake/guides/connect-using-node-js.md new file mode 100644 index 0000000000000..36d58bbed8534 --- /dev/null +++ b/tidb-cloud-lake/guides/connect-using-node-js.md @@ -0,0 +1,86 @@ +--- +title: 使用 Node.js 连接 TiDB Cloud Lake +summary: 本页介绍如何使用 Node.js 连接 TiDB Cloud Lake。 +--- + +# 使用 Node.js 连接 TiDB Cloud Lake + +官方 Node.js 驱动为现代 JavaScript 应用提供 TypeScript 支持和基于 Promise 的 API。 + +## 安装 {#installation} + +```bash +npm install tidbcloudlake-driver +``` + +**Connection String**:有关 DSN 格式和示例,请参见[驱动概览](/tidb-cloud-lake/guides/driver-overview.md)。 + +--- + +## 主要特性 {#key-features} + +- ✅ **TypeScript Support**:包含完整的 TypeScript 定义 +- ✅ **Promise-based API**:支持现代 async/await +- ✅ **Streaming Results**:高效处理大型结果集 +- ✅ **Connection Pooling**:内置连接管理 + +## 数据类型映射 {#data-type-mappings} + +| {{{ .lake }}} | Node.js | 说明 | +|----------|---------|-------| +| **基本类型** | | | +| `BOOLEAN` | `boolean` | | +| `TINYINT` | `number` | | +| `SMALLINT` | `number` | | +| `INT` | `number` | | +| `BIGINT` | `number` | | +| `FLOAT` | `number` | | +| `DOUBLE` | `number` | | +| `DECIMAL` | `string` | 保留精度 | +| `STRING` | `string` | | +| **日期/时间** | | | +| `DATE` | `Date` | | +| `TIMESTAMP` | `Date` | | +| **复杂类型** | | | +| `ARRAY(T)` | `Array` | | +| `TUPLE(...)` | `Array` | | +| `MAP(K,V)` | `Object` | | +| `VARIANT` | `string` | JSON 编码 | +| `BINARY` | `Buffer` | | +| `BITMAP` | `string` | Base64 编码 | + +--- + +## 基本用法 {#basic-usage} + +```javascript +const { Client } = require('tidbcloudlake-driver'); + +// Connect to {{{ .lake }}} +const client = new Client(''); +const conn = await client.getConn(); + +// DDL: Create table +await conn.exec(`CREATE TABLE users ( + id INT, + name STRING, + email STRING +)`); + +// Write: Insert data +await conn.exec("INSERT INTO users VALUES (?, ?, ?)", [1, "Alice", "alice@example.com"]); + +// Query: Select data +const rows = await conn.queryIter("SELECT id, name, email FROM users WHERE id = ?", [1]); +for await (const row of rows) { + console.log(row.values()); +} + +conn.close(); +``` + +## 资源 {#resources} + +- **NPM Package**:[tidbcloudlake-driver](https://www.npmjs.com/package/tidbcloudlake-driver) +- **GitHub Repository**:[tidbcloudlake-driver](https://github.com/tidbcloud/lakesql/tree/main/bindings/nodejs) +- **TypeScript Definitions**:包中已包含 \ No newline at end of file diff --git a/tidb-cloud-lake/guides/connect-using-python.md b/tidb-cloud-lake/guides/connect-using-python.md new file mode 100644 index 0000000000000..c26be099a02d2 --- /dev/null +++ b/tidb-cloud-lake/guides/connect-using-python.md @@ -0,0 +1,139 @@ +--- +title: 使用 Python 连接 TiDB Cloud Lake +summary: 本页介绍如何使用 Python 连接 TiDB Cloud Lake。 +--- + +# 使用 Python 连接 TiDB Cloud Lake + +使用我们支持同步和异步操作的官方驱动,通过 Python 连接 {{{ .lake }}}。 + +## 快速开始 {#quick-start} + +选择你偏好的方式: + +| 软件包 | 最适合 | 安装 | +|---------|----------|-------------| +| **tidbcloudlake-driver** | 直接进行数据库操作,async/await | `pip install tidbcloudlake-driver` | + +**Connection String**:有关 DSN 格式和示例,请参见[驱动概览](/tidb-cloud-lake/guides/driver-overview.md)。 + +--- + +## tidbcloudlake-driver {#tidbcloudlake-driver} + +### 特性 {#features} + +- ✅ **原生性能**:直接连接到 {{{ .lake }}} +- ✅ **支持 Async/Sync**:可根据你的编程风格进行选择 +- ✅ **兼容 PEP 249**:标准 Python DB API +- ✅ **类型安全**:完整的 Python 类型映射 + +### 同步用法 {#synchronous-usage} + +```python +from tidbcloudlake_driver import BlockingLakeClient + +# Connect and execute +client = BlockingLakeClient('') +cursor = client.cursor() + +# DDL: Create table +cursor.execute("CREATE TABLE users (id INT, name STRING)") + +# Write: Insert data +cursor.execute("INSERT INTO users VALUES (?, ?)", (1, 'Alice')) + +# Query: Read data +# Query: Read data +cursor.execute("SELECT * FROM users") + +# Get column names +# cursor.description returns a list of tuples, where the first element is the column name +print(f"Columns: {[desc[0] for desc in cursor.description]}") + +for row in cursor.fetchall(): + # row is a tidbcloudlake_driver.Row object + # Access by column name + print(f"id: {row['id']}, name: {row['name']}") + +cursor.close() +``` + +### 使用 Row 对象 {#working-with-row-objects} + +`Row` 对象支持多种访问模式和方法: + +```python +for row in cursor.fetchall(): + # 1. Access by column name (Recommended) + print(f"Name: {row['name']}") + + # 2. Access by index + print(f"First column: {row[0]}") + + # 3. Convert to tuple + print(f"Values: {row.values()}") + + # 4. Explicit methods + print(row.get_by_field('name')) + print(row.get_by_index(0)) +``` + +### 异步用法 {#asynchronous-usage} + +```python +import asyncio +from tidbcloudlake_driver import AsyncLakeClient + +async def main(): + client = AsyncLakeClient('lake://root:root@localhost:8000/?sslmode=disable') + conn = await client.get_conn() + + # DDL: Create table + await conn.exec("CREATE TABLE users (id INT, name STRING)") + + # Write: Insert data + await conn.exec("INSERT INTO users VALUES (?, ?)", (1, 'Alice')) + + # Query: Read data + rows = await conn.query_iter("SELECT * FROM users") + async for row in rows: + print(row.values()) + + await conn.close() + +asyncio.run(main()) +``` + +## 数据类型映射 {#data-type-mappings} + +| {{{ .lake }}} | Python | 说明 | +|----------|--------|-------| +| **数值类型** | | | +| `BOOLEAN` | `bool` | | +| `TINYINT` | `int` | | +| `SMALLINT` | `int` | | +| `INT` | `int` | | +| `BIGINT` | `int` | | +| `FLOAT` | `float` | | +| `DOUBLE` | `float` | | +| `DECIMAL` | `decimal.Decimal` | 保留精度 | +| **日期/时间** | | | +| `DATE` | `datetime.date` | | +| `TIMESTAMP` | `datetime.datetime` | | +| `INTERVAL` | `datetime.timedelta` | | +| **文本/二进制** | | | +| `VARCHAR` | `str` | UTF-8 编码 | +| `BINARY` | `bytes` | | +| **复杂类型** | | | +| `ARRAY` | `list` | 支持嵌套结构 | +| `TUPLE` | `tuple` | | +| `MAP` | `dict` | | +| `VARIANT` | `str` | JSON 编码 | +| `BITMAP` | `str` | Base64 编码 | +| `GEOMETRY` | `str` | WKT 格式 | + +## 资源 {#resources} + +- **PyPI**: [tidbcloudlake-driver](https://pypi.org/project/tidbcloudlake-driver/) +- **GitHub**: [tidbcloudlake-driver](https://github.com/tidbcloud/lakesql/tree/main/bindings/python) \ No newline at end of file diff --git a/tidb-cloud-lake/guides/connect-using-rust.md b/tidb-cloud-lake/guides/connect-using-rust.md new file mode 100644 index 0000000000000..b0b401094d547 --- /dev/null +++ b/tidb-cloud-lake/guides/connect-using-rust.md @@ -0,0 +1,111 @@ +--- +title: 使用 Rust 连接 TiDB Cloud Lake +summary: 本页介绍如何使用 Rust 连接 TiDB Cloud Lake。 +--- + +# 使用 Rust 连接 TiDB Cloud Lake + +官方 Rust driver 为 Rust 应用提供原生连接能力,支持 async/await,并具备全面的类型安全。 + +## 安装 {#installation} + +将 driver 添加到你的 `Cargo.toml` 中: + +```toml +[dependencies] +lake-driver = "0.1.5-alpha.2" +tokio = { version = "1", features = ["full"] } +``` + +**Connection String**:有关 DSN 格式和示例,请参见[驱动概览](/tidb-cloud-lake/guides/driver-overview.md)。 + +--- + +## 主要特性 {#key-features} + +- ✅ **Async/Await Support**:专为现代 Rust 异步编程构建 +- ✅ **Type Safety**:结合 Rust 类型系统的强类型映射 +- ✅ **Connection Pooling**:高效的连接管理 +- ✅ **Stage Operations**:向 {{{ .lake }}} stages 上传/下载数据 +- ✅ **Streaming Results**:高效处理大型结果集 + +## 数据类型映射 {#data-type-mappings} + +### 基本类型 {#basic-types} + +| {{{ .lake }}} | Rust | 备注 | +| --------- | --------------------- | ------------------------ | +| BOOLEAN | bool | | +| TINYINT | i8, u8 | | +| SMALLINT | i16, u16 | | +| INT | i32, u32 | | +| BIGINT | i64, u64 | | +| FLOAT | f32 | | +| DOUBLE | f64 | | +| DECIMAL | String | 保留精度 | +| VARCHAR | String | UTF-8 编码 | +| BINARY | `Vec` | | + +### 日期/时间类型 {#date-time-types} + +| {{{ .lake }}} | Rust | 备注 | +| --------- | --------------------- | ------------------------ | +| DATE | chrono::NaiveDate | 需要 chrono crate | +| TIMESTAMP | chrono::NaiveDateTime | 需要 chrono crate | + +### 复杂类型 {#complex-types} + +| {{{ .lake }}} | Rust | 说明 | +| ----------- | --------------- | ------------------------ | +| ARRAY[T] | `Vec` | 支持嵌套数组 | +| TUPLE[T, U] | (T, U) | 多元素元组 | +| MAP[K, V] | `HashMap` | 键值映射 | +| VARIANT | String | JSON 编码 | +| BITMAP | String | Base64 编码 | +| GEOMETRY | String | WKT 格式 | + +--- + +## 基本用法 {#basic-usage} + +以下是一个简单示例,演示 DDL、写入和查询操作: + +```rust +use lake_driver::Client; +use tokio_stream::StreamExt; + +#[tokio::main] +async fn main() -> Result<(), Box> { + // Connect to TiDB Cloud Lake + let client = Client::new("".to_string()); + let conn = client.get_conn().await?; + + // DDL: Create table + conn.exec("CREATE TABLE IF NOT EXISTS users (id INT, name VARCHAR, created_at TIMESTAMP)") + .await?; + + // Write: Insert data + conn.exec("INSERT INTO users VALUES (1, 'Alice', '2023-12-01 10:00:00')") + .await?; + conn.exec("INSERT INTO users VALUES (2, 'Bob', '2023-12-01 11:00:00')") + .await?; + + // Query: Select data + let mut rows = conn.query_iter("SELECT id, name, created_at FROM users ORDER BY id") + .await?; + + while let Some(row) = rows.next().await { + let (id, name, created_at): (i32, String, chrono::NaiveDateTime) = + row?.try_into()?; + println!("User {}: {} (created: {})", id, name, created_at); + } + + Ok(()) +} +``` + +## 资源 {#resources} + +- **Crates.io**: [lake-driver](https://crates.io/crates/lake-driver) +- **GitHub Repository**: [LakeSQL/driver](https://github.com/tidbcloud/lakesql/tree/main/driver) +- **Rust Documentation**: [docs.rs/lake-driver](https://docs.rs/lake-driver) \ No newline at end of file diff --git a/tidb-cloud-lake/guides/connect-with-alibaba-cloud-privatelink.md b/tidb-cloud-lake/guides/connect-with-alibaba-cloud-privatelink.md new file mode 100644 index 0000000000000..0be9079d38441 --- /dev/null +++ b/tidb-cloud-lake/guides/connect-with-alibaba-cloud-privatelink.md @@ -0,0 +1,59 @@ +--- +title: 使用 Alibaba Cloud PrivateLink 连接到 TiDB Cloud Lake +summary: 配置 Alibaba Cloud 私有端点,启用其自定义域名,并验证到 TiDB Cloud Lake 的私有连接。 +--- + +# 使用 Alibaba Cloud PrivateLink 连接到 TiDB Cloud Lake + +本文档介绍如何配置 Alibaba Cloud 私有端点、启用其自定义域名,并验证到 TiDB Cloud Lake 的私有连接。 + +## 设置 Alibaba Cloud PrivateLink {#set-up-alibaba-cloud-privatelink} + +1. 从 **Connect to {{{ .lake }}}** 对话框中获取端点服务名称。 + + 例如:`com.aliyuncs.privatelink.ap-northeast-1.epsrv-6weddzcbkanrx5sc2zv4` + +2. 准备一个安全组,允许入站 TCP 流量通过 443 端口。 + + ![允许 HTTPS 流量的安全组](/media/tidb-cloud-lake/alibaba-privatelink-security-group.png) + +3. 在 [Alibaba Cloud VPC 控制台](https://vpc.console.aliyun.com/endpoint/ap-northeast-1/endpoints/new)中创建一个端点。本示例使用 Japan (Tokyo)。 + + 输入步骤 1 中的端点服务名称,然后点击 **Verify**。 + + ![使用 Lake 端点服务名称创建端点](/media/tidb-cloud-lake/alibaba-privatelink-create-endpoint.png) + + 确认设置后,点击页面底部的创建按钮。 + +4. 在端点详情页面,启用 **Custom Domain Name**。 + + ![启用自定义域名](/media/tidb-cloud-lake/alibaba-privatelink-custom-domain-name.png) + +5. 从你的 VPC 中的 Elastic Compute Service (ECS) 实例验证端点连接。 + + 1. 在 TiDB Cloud Lake 首页,点击 **Connect**。在 **Connect to TiDB Cloud** 对话框中,复制 **Connection Information** 下的 **Host** 值。 + + ![从连接信息中复制 TiDB Cloud Lake 主机](/media/tidb-cloud-lake/alibaba-privatelink-connection-host.png) + + 2. 将 `LAKE_HOST` 设置为你复制的主机,然后运行以下命令: + + ```shell + LAKE_HOST='' + + getent ahostsv4 "$LAKE_HOST" + + curl --noproxy '*' -4 -sS -o /dev/null \ + -w 'remote_ip=%{remote_ip}\ntls_verify=%{ssl_verify_result}\n' \ + "https://$LAKE_HOST" + ``` + + 3. 在 Alibaba Cloud VPC 控制台中,打开端点详情页面,找到分配给端点弹性网卡(ENI)的私有 IP 地址。确认 `getent ahostsv4` 返回的每个 IPv4 地址都是端点 ENI 的私有 IP 地址,并且 `remote_ip` 与其中一个地址匹配。这表明已测试的到 TiDB Cloud Lake 的连接使用的是 Alibaba Cloud PrivateLink,而不会遍历公共互联网。`tls_verify=0` 表示 HTTPS 证书验证成功。 + + 4. 检查区域网关的健康状态。以 Japan (Tokyo) Region 为例: + + ```shell + curl --noproxy '*' -sS \ + https://gw.aliyun-ap-northeast-1.default.lake.tidbcloud.com/status + ``` + + 如果响应中包含 `"status": "ok"`,则表示该区域网关可用。 \ No newline at end of file diff --git a/tidb-cloud-lake/guides/connect-with-aws-privatelink.md b/tidb-cloud-lake/guides/connect-with-aws-privatelink.md new file mode 100644 index 0000000000000..0e52133c5c2e3 --- /dev/null +++ b/tidb-cloud-lake/guides/connect-with-aws-privatelink.md @@ -0,0 +1,67 @@ +--- +title: 使用 AWS PrivateLink 连接到 TiDB Cloud Lake +summary: 主流云厂商提供的 PrivateLink 风格私有端点(AWS PrivateLink、Azure Private Link、Google Private Service Connect 等)使你能够通过自身网络边界内的私有 IP 地址访问 TiDB Cloud Lake,因此流量无需遍历公共互联网。这可以让你的数据集、凭证和管理操作始终保留在云服务商骨干网络中,并与现有网络策略保持一致。 +--- + +# 使用 AWS PrivateLink 连接到 TiDB Cloud Lake + +主流云厂商提供的 PrivateLink 风格私有端点(AWS PrivateLink、Azure Private Link、Google Private Service Connect 等)使你能够通过自身网络边界内的私有 IP 地址访问 {{{ .lake }}},因此流量无需遍历公共互联网。这可以让你的数据集、凭证和管理操作始终保留在云服务商骨干网络中,并与现有网络策略保持一致。 + +## 优势 {#benefits} + +- 网络隔离:流量始终不会离开你的 VPC/VPN 边界,从而避免暴露到公共端点。 +- 合规就绪:更容易满足禁止互联网出口的内部审计和行业要求。 +- 稳定的性能:流量通过云服务商骨干网络传输,而不是不可预测的互联网路由。 +- 简化控制:复用现有的安全组、路由表和监控来管理访问。 + +## 工作原理 {#how-it-works} + +从 **Connect to {{{ .lake }}}** 对话框中获取 PrivateLink 服务名称,然后创建一个指向该服务的私有端点。云服务商会自动分配私有 IP 地址并接受该端点;启用私有 DNS 后,你的 {{{ .lake }}} 域名会解析到这些地址,因此每个会话都会通过安全的私有路径进行。 + +## 如何设置 AWS PrivateLink {#how-to-setup-aws-privatelink} + +1. 验证你的 VPC 设置。 + + 确保已勾选 `Enable DNS resolution` 和 `Enable DNS hostnames`。 + +2. 从 **Connect to {{{ .lake }}}** 对话框中获取要连接的服务名称: + + 例如:`com.amazonaws.vpce.us-east-2.vpce-svc-0123456789abcdef0`。 + +3. 准备一个开放 tcp 443 端口的安全组: + + ![Security Group](/media/tidb-cloud-lake/security-group.png) + +4. 前往 AWS Console: + + : + + 点击 `Create endpoint`: + + ![Create Endpoint Button](/media/tidb-cloud-lake/create-endpoint-1.png) + + ![Create Endpoint Sheet](/media/tidb-cloud-lake/create-endpoint-2.png) + + 选择之前创建的安全组 `HTTPS`: + + ![Create Endpoint SG](/media/tidb-cloud-lake/create-endpoint-3.png) + +5. 等待 PrivateLink 创建完成。 + +6. 修改私有 DNS 名称设置: + + ![DNS Menu](/media/tidb-cloud-lake/dns-1.png) + + 启用私有 DNS 名称: + + ![DNS Sheet](/media/tidb-cloud-lake/dns-2.png) + + 等待更改生效。 + +7. 验证通过 PrivateLink 访问 {{{ .lake }}}: + + Gateway 域名会解析为 VPC 内部 IP 地址。 + + > **Note:** + > + > 恭喜!你已成功通过 AWS PrivateLink 连接到 {{{ .lake }}}。 \ No newline at end of file diff --git a/tidb-cloud-lake/guides/connection-overview.md b/tidb-cloud-lake/guides/connection-overview.md new file mode 100644 index 0000000000000..9798be96f165e --- /dev/null +++ b/tidb-cloud-lake/guides/connection-overview.md @@ -0,0 +1,49 @@ +--- +title: 连接到 TiDB Cloud Lake +summary: TiDB Cloud Lake 支持多种连接方法,以适应不同的使用场景。以下所有选项同时适用于 **TiDB Cloud Lake** 和 **self-hosted {{{ .lake }}}**。 +--- + +# 连接到 TiDB Cloud Lake + +{{{ .lake }}} 支持多种连接方法,以适应不同的使用场景。 + +## 快速选择 {#quick-selection} + +| 我想要... | 推荐 | +|-------------|-------------| +| 以交互方式运行 SQL 查询 | **LakeSQL** (CLI) | +| 构建应用程序 | 特定语言的 **Driver** | +| 创建仪表板和报表 | **BI/可视化工具** | + +## 连接字符串 {#connection-strings} + +| 部署 | 格式 | +|------------|--------| +| **{{{ .lake }}}** | `lake://:@.gw..default.tidbcloud.com:443/?warehouse=` | + +> **提示:** +> +> **{{{ .lake }}}**:登录 → 点击 **Connect** → 复制生成的 DSN + +## SQL 客户端 {#sql-clients} + +| 工具 | 类型 | 最适用场景 | +|------|------|----------| +| [LakeSQL](/tidb-cloud-lake/guides/connect-using-lakesql.md) | CLI | 开发者、脚本编写、自动化 | + +## 驱动 {#drivers} + +| 语言 | 指南 | 使用场景 | +|----------|-------|----------| +| Go | [Golang 驱动程序](/tidb-cloud-lake/guides/connect-using-golang.md) | 后端服务、微服务 | +| Python | [Python 连接器](/tidb-cloud-lake/guides/connect-using-python.md) | 数据科学、分析、机器学习 | +| Node.js | [Node.js 驱动程序](/tidb-cloud-lake/guides/connect-using-node-js.md) | Web 应用程序 | +| Java | [JDBC 驱动程序](/tidb-cloud-lake/guides/connect-using-java.md) | 企业应用程序 | +| Rust | [Rust 驱动程序](/tidb-cloud-lake/guides/connect-using-rust.md) | 系统编程 | + +## 可视化工具 {#visualization-tools} + +| 工具 | 类型 | +|------|------| +| [Tableau](/tidb-cloud-lake/guides/tableau.md) | 商业智能 | +| [Deepnote](/tidb-cloud-lake/guides/deepnote.md) | 协作式 Notebook | \ No newline at end of file diff --git a/tidb-cloud-lake/guides/continuous-data-pipelines.md b/tidb-cloud-lake/guides/continuous-data-pipelines.md new file mode 100644 index 0000000000000..68c17811349c8 --- /dev/null +++ b/tidb-cloud-lake/guides/continuous-data-pipelines.md @@ -0,0 +1,28 @@ +--- +title: 持续数据管道 +summary: 在 {{{ .lake }}} 中使用两种原语构建端到端的变更数据捕获(CDC)流程。 +--- + +# 持续数据管道 + +在 {{{ .lake }}} 中使用两种原语构建端到端的变更数据捕获(CDC)流程: + +- **Streams** 会捕获每一次 INSERT/UPDATE/DELETE,直到你将其消费。 +- **Tasks** 会按调度运行 SQL,或在 stream 报告有新行时运行 SQL。 + +## 快速导航 {#quick-navigation} + +- [示例 1:仅追加 Stream 复制](/tidb-cloud-lake/guides/track-and-transform-data-via-streams.md#example-1-append-only-stream) – 捕获插入操作并将其消费到另一张表中。 +- [示例 2:标准 Stream 修改](/tidb-cloud-lake/guides/track-and-transform-data-via-streams.md#example-2-standard-stream-updates--deletes) – 了解修改/删除如何呈现,以及为什么一个 stream 只能由一个消费者清空。 +- [示例 3:增量 Stream 指标](/tidb-cloud-lake/guides/track-and-transform-data-via-streams.md#example-3-incremental-stream-join) – 使用 `WITH CONSUME` 连接多个 stream,按批次计算增量。 +- [示例 1:定时复制 Task](/tidb-cloud-lake/guides/automate-data-loading-with-tasks.md#example-1-scheduled-copy) – 使用两个周期性 task 生成并加载文件。 +- [示例 2:由 Stream 触发的合并](/tidb-cloud-lake/guides/automate-data-loading-with-tasks.md#example-2-stream-triggered-merge) – 仅当 `STREAM_STATUS` 为 true 时触发 task。 + +## 为什么在 {{{ .lake }}} 中使用 CDC {#why-cdc-in-lake} + +- **轻量** – stream 仅保留最新的变更集,而不会复制整张表。 +- **事务性** – stream 消费会与你的 SQL 语句一起成功提交或回滚。 +- **增量** – 使用 `WITH CONSUME` 重复运行同一查询时,只会处理新行。 +- **可调度** – task 让你能够将已经用 SQL 表达的复制、合并或告警逻辑自动化。 + +建议先阅读 stream 示例,再将其与 task 结合起来,实现管道自动化。 \ No newline at end of file diff --git a/tidb-cloud-lake/guides/dashboards.md b/tidb-cloud-lake/guides/dashboards.md new file mode 100644 index 0000000000000..adaf62c908747 --- /dev/null +++ b/tidb-cloud-lake/guides/dashboards.md @@ -0,0 +1,59 @@ +--- +title: 仪表板 +summary: 仪表板用于通过多种图表类型展示查询结果,包括计分卡、饼图、柱状图和折线图。这些图表基于查询结果生成。你可以在工作区中执行查询后,根据查询结果创建图表。刷新仪表板会重新执行与图表对应的查询,从而使用最新结果更新图表。 +--- + +# 仪表板 + +仪表板用于通过多种图表类型展示查询结果,包括 **scorecards**、**pie charts**、**bar charts** 和 **line charts**。这些图表基于查询结果生成。你可以在工作区 (Worksheet) 中执行查询后,根据查询结果创建图表。刷新仪表板会重新执行与图表对应的查询,从而使用最新结果更新图表。 + +![Alt text](/media/tidb-cloud-lake/dashboard.png) + +## 创建仪表板 {#creating-a-dashboard} + +在 {{{ .lake }}} 中,你可以根据需要创建多个仪表板。一个仪表板可以包含一个或多个图表。每个单独的图表都对应一个特定的查询结果,但它可以被集成到多个仪表板中。 + +**创建仪表板的方法如下**: + +1. 在工作区中,运行一个你希望基于其查询结果生成图表的查询。 + +2. 在结果区域中,点击 **Chart** 标签页。 + + ![Alt text](/media/tidb-cloud-lake/chart-btn.png) + +3. 在 **Chart** 标签页中,从右侧下拉菜单中选择一种图表类型。然后,使用下拉列表下方 **Data** 和 **Style** 标签页中的选项来指定数据并自定义图表外观。 + + 请注意,这些聚合函数有助于对查询结果中的原始数据进行汇总,并揭示有价值的模式。可用的聚合函数会因你选择的不同数据类型和图表类型而有所不同。 + + | 函数 | 描述 | + |----------------------|----------------------------------------------------------------| + | None | 不对数据进行任何更改。 | + | Count | 计算查询结果中该字段的记录数(不包括包含 NULL 和 '' 值的记录)。 | + | Min | 计算查询结果中的最小值。 | + | Max | 计算查询结果中的最大值。 | + | Median | 计算查询结果中的中位数。 | + | Sum | 计算查询结果中数值的总和。 | + | Average | 计算查询结果中数值数据的平均值。 | + | Mode | 识别查询结果中出现频率最高的值。 | + +4. 返回 {{{ .lake }}} 首页,在左侧导航菜单中选择 **Dashboards**,然后点击 **New Dashboard**。 + +5. 在新建的仪表板中,点击 **Add Chart**。将左侧面板中的图表拖放到仪表板上。如果左侧面板中有多个可用图表,你可以根据需要拖入任意数量的图表。 + +> **Note:** +> +> 在工作区中根据查询结果生成图表后,请避免在同一个工作区中运行其他查询,否则可能会导致该图表在仪表板上不可用。 + +## 共享仪表板 {#sharing-a-dashboard} + +你可以将仪表板共享给组织中的所有人或特定个人。为此,点击你想要共享的仪表板上的省略号按钮 ,然后选择 **Share**。 + +![alt text](/media/tidb-cloud-lake/dashboard-share.png) + +共享仪表板时,你可以选择以下权限级别之一,以控制其他人如何访问它: + +- **Read Only**:可以查看仪表板,但不能进行更改,也不能运行查询来获取最新结果。 +- **Execute**:可以运行查询以获取最新结果,或与仪表板交互,但不能修改它。 +- **Edit**:可以修改仪表板,包括更改查询以及仪表板展示结果的方式。 + +要查看其他人共享给你的仪表板,请点击侧边栏中的 **Dashboards**,然后点击右侧的 **Shared with Me** 标签页。 diff --git a/tidb-cloud-lake/guides/data-integration-overview.md b/tidb-cloud-lake/guides/data-integration-overview.md new file mode 100644 index 0000000000000..f3226dad2ff5e --- /dev/null +++ b/tidb-cloud-lake/guides/data-integration-overview.md @@ -0,0 +1,40 @@ +--- +title: 数据集成概览 +summary: {{{ .lake }}} 中的数据集成功能提供了一个可视化、无代码的接口,用于将外部系统中的数据导入或同步到 {{{ .lake }}}。 +--- + +# 数据集成概览 + +{{{ .lake }}} 中的数据集成功能提供了一个可视化、无代码的接口,用于将外部系统中的数据导入、同步或消费到 {{{ .lake }}} 中。该功能围绕两个关键概念展开:**数据源** 和 **集成任务**。 + +## 关键概念 {#key-concepts} + +| 概念 | 说明 | +|---------|-------------| +| [数据源](/tidb-cloud-lake/guides/data-sources.md) | 可复用的连接设置或凭证,用于访问外部系统或发送通知,例如 AWS Access Key / Secret Key、MySQL hostname / username / password、SQS (S3) queue URL、Kafka broker addresses,或 FeiShu bot webhook。 | +| [集成任务](/tidb-cloud-lake/guides/integration-tasks.md) | 可执行的任务,用于定义数据来源、任务将数据写入到哪里或如何保存结果、使用哪些运行时参数,以及如何启动和监控任务。 | + +数据源本身不会移动数据。它们仅存储访问外部系统所需的信息。集成任务才是实际执行导入、快照、持续同步或消息消费的单元。 + +> **注意:** +> +> 运行数据集成任务会产生服务托管费用。{{{ .lake }}} 会根据服务的实际运行时间按秒计费。详情请参见[服务托管定价](/tidb-cloud-lake/guides/pricing-billing.md#service-hosting-pricing)。 + +并非每个数据源都对应一个数据摄取任务。例如,`FeiShuBot` 用于通知,而不是将源数据加载到 {{{ .lake }}} 中。 + +## 支持的集成任务类型 {#supported-integration-task-types} + +| 任务类型 | 说明 | +|-----------|-------------| +| [Amazon S3](/tidb-cloud-lake/guides/integrate-with-amazon-s3.md) | 从 Amazon S3 导入 CSV、Parquet 或 NDJSON 文件,支持一次性或持续摄取。 | +| [Amazon SQS (S3) (Beta)](/tidb-cloud-lake/guides/integrate-with-amazon-sqs-s3.md) | 从 SQS 队列中消费 S3 对象创建事件,并将相应的对象数据写入 {{{ .lake }}}。 | +| [MySQL](/tidb-cloud-lake/guides/integrate-with-mysql.md) | 使用 `Snapshot`、`CDC Only` 或 `Snapshot + CDC` 模式同步 MySQL 中的表数据。 | +| [PostgreSQL](/tidb-cloud-lake/guides/integrate-with-postgresql.md) | 使用 `Snapshot`、`CDC Only` 或 `Snapshot + CDC` 模式同步 PostgreSQL 中的表数据。 | +| [Kafka Consumer Integration Task (Beta)](/tidb-cloud-lake/guides/integrate-with-kafka.md) | 持续消费 Kafka topic 中的消息,并将消息内容保存到内部对象存储中。 | + +## 推荐流程 {#recommended-flow} + +1. 在[数据源](/tidb-cloud-lake/guides/data-sources.md)页面创建并测试可复用的连接设置。 +2. 在[集成任务](/tidb-cloud-lake/guides/integration-tasks.md)页面查看支持的任务类型及其适用场景。 +3. 阅读特定任务的指南,配置数据源、预览数据,并配置结果位置或结果查看方法。 +4. 使用[任务管理](/tidb-cloud-lake/guides/task-management.md)页面启动任务、检查状态并排查执行问题。 \ No newline at end of file diff --git a/tidb-cloud-lake/guides/data-lifecycle.md b/tidb-cloud-lake/guides/data-lifecycle.md new file mode 100644 index 0000000000000..cd2f7725e7104 --- /dev/null +++ b/tidb-cloud-lake/guides/data-lifecycle.md @@ -0,0 +1,79 @@ +--- +title: TiDB Cloud Lake 中的数据生命周期 +summary: "{{{ .lake }}} 支持常见的数据定义语言(DDL)和数据操纵语言(DML)命令,让你能够轻松管理数据库。无论是组织、存储、查询、修改还是删除数据,{{{ .lake }}} 都遵循你所熟悉的行业标准。" +--- + +# TiDB Cloud Lake 中的数据生命周期 + +{{{ .lake }}} 支持常见的数据定义语言(DDL)和数据操纵语言(DML)命令,让你能够轻松管理数据库。无论是组织、存储、查询、修改还是删除数据,{{{ .lake }}} 都遵循你所熟悉的行业标准。 + +## {{{ .lake }}} 对象 {#lake-objects} + +{{{ .lake }}} 支持以下对象的创建和修改: + +- 数据库 +- 表 +- 外部表 +- Stream +- 视图 +- 索引 +- Stage +- 文件格式 +- 连接 +- 用户定义函数(UDF) +- 外部函数 +- 用户 +- 角色 +- 授权 +- 计算集群 (Warehouse) +- 任务 +- [快照标签](/tidb-cloud-lake/sql/table-versioning.md#snapshot-tags) + +## 组织数据 {#organizing-data} + +将数据组织到数据库和表中。 + +关键命令: + +- [`CREATE DATABASE`](/tidb-cloud-lake/sql/create-database.md):用于创建新数据库。 +- [`ALTER DATABASE`](/tidb-cloud-lake/sql/alter-database.md):用于修改现有数据库。 +- [`CREATE TABLE`](/tidb-cloud-lake/sql/create-table.md):用于创建新表。 +- [`ALTER TABLE`](/tidb-cloud-lake/sql/alter-table.md):用于修改现有表。 + +## 存储数据 {#storing-data} + +直接将数据添加到表中。{{{ .lake }}} 还支持将外部文件中的数据导入到其表中。 + +关键命令: + +- [`INSERT`](/tidb-cloud-lake/sql/insert.md):用于向表中添加数据。 +- [`COPY INTO
`](/tidb-cloud-lake/sql/copy-into-table.md):用于从外部文件导入数据。 + +## 查询数据 {#querying-data} + +当数据已存入表后,可以使用 `SELECT` 查看和分析数据。 + +关键命令: + +- [`SELECT`](/tidb-cloud-lake/sql/select.md):用于从表中获取数据。 + +## 处理数据 {#working-with-data} + +当数据位于 {{{ .lake }}} 中后,你可以根据需要对其进行修改、替换、合并或删除。 + +关键命令: + +- [`UPDATE`](/tidb-cloud-lake/sql/update.md):用于修改表中的数据。 +- [`REPLACE`](/tidb-cloud-lake/sql/replace.md):用于替换现有数据。 +- [`MERGE`](/tidb-cloud-lake/sql/merge.md):用于通过比较主表与源表或子查询之间的数据,无缝执行插入、修改和删除操作。 +- [`DELETE`](/tidb-cloud-lake/sql/delete.md):用于从表中删除数据。 + +## 删除数据 {#removing-data} + +{{{ .lake }}} 支持删除特定数据,也支持删除整个表和数据库。 + +关键命令: + +- [`TRUNCATE TABLE`](/tidb-cloud-lake/sql/truncate-table.md):用于清空表中的数据而不删除表结构。 +- [`DROP TABLE`](/tidb-cloud-lake/sql/drop-table.md):用于删除表。 +- [`DROP DATABASE`](/tidb-cloud-lake/sql/drop-database.md):用于删除数据库。 \ No newline at end of file diff --git a/tidb-cloud-lake/guides/data-lineage.md b/tidb-cloud-lake/guides/data-lineage.md new file mode 100644 index 0000000000000..6c5107e3b200b --- /dev/null +++ b/tidb-cloud-lake/guides/data-lineage.md @@ -0,0 +1,114 @@ +--- +title: 数据血缘 +summary: 了解如何在 {{{ .lake }}} 中启用和探索数据血缘。 +--- + +# 数据血缘 + +数据血缘展示了数据如何从源对象流向目标对象。你可以使用它来理解依赖关系、评估变更影响、排查数据管道问题,以及将派生列追溯到其来源。 + +{{{ .lake }}} 会记录对象级和列级两种关系: + +- **上游血缘** 用于识别为某个对象提供数据的表、视图或 stage。 +- **下游血缘** 用于识别消费某个对象数据的对象。 +- **列血缘** 用于将源列映射到派生出的目标列。 + +![Table and column lineage in {{{ .lake }}}](/media/tidb-cloud-lake/data-lineage.png) + +## 启用数据血缘 {#enable-data-lineage} + +{{{ .lake }}} 会为支持 **Lineage** 标签页的计算集群 (Warehouse) 管理血缘配置(**Data** > **Databases** > **databaseName** > **tableName**)。 + +## 生成血缘 {#generate-lineage} + +启用血缘后,{{{ .lake }}} 会自动记录由以下操作创建的关系,例如 `CREATE TABLE ... AS SELECT`、`CREATE VIEW`、`INSERT ... SELECT`、多表 `INSERT`、`REPLACE`、`MERGE` 和 `COPY`。对于 stream,系统会将其解析为其底层表。 + +以下示例会创建一条两跳的血缘路径: + +```sql +CREATE OR REPLACE DATABASE lineage_demo; + +CREATE OR REPLACE TABLE lineage_demo.fact_orders ( + order_id BIGINT, + customer_id BIGINT, + amount DECIMAL(12, 2), + order_time TIMESTAMP +); + +CREATE OR REPLACE TABLE lineage_demo.agg_customer_sales AS +SELECT + customer_id, + sum(amount) AS total_amount, + count(*) AS order_count, + max(order_time) AS last_order_time +FROM lineage_demo.fact_orders +GROUP BY customer_id; + +CREATE OR REPLACE TABLE lineage_demo.customer_segments AS +SELECT + customer_id, + total_amount, + order_count, + if(total_amount >= 1000, 'high_value', 'standard') AS segment, + now() AS updated_at +FROM lineage_demo.agg_customer_sales; +``` + +## 探索血缘 {#explore-lineage} + +在 {{{ .lake }}} 中,在 Database Explorer 中打开一个表或视图,然后选择 **Lineage** 标签页。图中会显示上游和下游对象;如果列血缘可用,还会显示列之间的连接关系。 + +如需使用 SQL 获取血缘信息,请使用 [`GET_LINEAGE`](/tidb-cloud-lake/sql/get-lineage.md) 表函数: + +```sql +SELECT + distance, + source_object_database, + source_object_name, + target_object_database, + target_object_name +FROM GET_LINEAGE( + 'lineage_demo.agg_customer_sales', + 'TABLE', + 'UPSTREAM', + 2 +) +ORDER BY distance; +``` + +对于列级血缘,请限定列名并使用 `COLUMN` 域: + +```sql +SELECT + distance, + source_object_name, + source_column_name, + target_object_name, + target_column_name +FROM GET_LINEAGE( + 'lineage_demo.customer_segments.segment', + 'COLUMN', + 'UPSTREAM', + 2 +) +ORDER BY distance; +``` + +## 刷新现有视图的血缘 {#refresh-lineage-for-existing-views} + +在启用血缘之后创建的视图会被自动跟踪。对于已经包含视图的部署,在启用血缘后,可以先预览缺失或过期的关系,然后再刷新它们: + +```sql +REFRESH LINEAGE FOR ALL VIEWS DRY RUN; +REFRESH LINEAGE FOR ALL VIEWS; +``` + +刷新操作会为 `default` catalog 中的所有视图校正血缘信息。它只会报告需要变更或无法处理的视图;未发生变化的视图不会显示。该命令需要全局 `SUPER` 权限。有关输出详情,请参见 [`REFRESH LINEAGE`](/tidb-cloud-lake/sql/refresh-lineage.md)。 + +## 限制 {#limitations} + +- `GET_LINEAGE` 最多只能遍历五跳。 +- 系统对象和 `information_schema` 对象不会作为血缘源被纳入。 +- stage 会参与对象级血缘,但暂存文件字段无法提供稳定的列级映射。 +- 外部 catalog 对象可以作为端点出现,但不会跨越外部 catalog 边界继续遍历。 +- 结果仅包含当前角色可见的对象。 \ No newline at end of file diff --git a/tidb-cloud-lake/guides/data-protection-policies.md b/tidb-cloud-lake/guides/data-protection-policies.md new file mode 100644 index 0000000000000..b4a8162ef279a --- /dev/null +++ b/tidb-cloud-lake/guides/data-protection-policies.md @@ -0,0 +1,204 @@ +--- +title: 数据保护策略 +summary: 了解掩码策略和行访问策略,它们无需修改存储值即可保护敏感信息。 +--- + +# 数据保护策略 + +{{{ .lake }}} 在查询时保护敏感数据,而不会更改存储的值: + +| 策略 | 它的作用 | +|--------|----------------| +| [脱敏策略](/tidb-cloud-lake/guides/masking-policy.md) | 转换列值——未授予权限的用户看到的是脱敏数据 | +| [行访问策略](/tidb-cloud-lake/guides/row-access-policy.md) | 过滤整行——未授予权限的用户永远看不到这些行 | + +两者对应用程序都是透明的:无需修改代码,无需额外视图,无需复制数据。 + +## 选择合适的策略 {#choose-the-right-policy} + +| 场景 | 用途 | +|----------|-----| +| 隐藏整行 | 行访问 | +| 保留该行,但对某一列脱敏 | 脱敏 | +| 不同角色看到同一列的不同精度 | 脱敏 | +| 多租户 / 区域隔离 | 行访问 | +| 按角色进行时间窗口控制 | 行访问 | +| 隐藏 JSON / VARIANT 中的键 | 脱敏 | +| 行隔离 + 列脱敏 | 两者都用(但不能用于同一列) | + +示例:一个包含 phone、amount 和 region 的 `orders` 表。 + +| 要求 | 策略 | +|-------------|--------| +| 支持团队只能看到其所在 region | 基于 `region` 的行访问 | +| 分析师看到 `138****1234` | 基于 `phone` 的掩码 | +| 管理员看到所有内容 | 通过两种策略的角色 | + +## 它们如何协同工作 {#how-they-work-together} + +``` +Query + → Row Access Policy filters rows + → Masking Policy transforms surviving columns + → Result returned +``` + +行过滤先执行。掩码仅应用于剩余的行。 + +| | 掩码 | 行访问 | +|---|---|---| +| 作用域 | 列值 | 整行 | +| 返回类型 | 与列类型匹配 | BOOLEAN | +| 限制 | 每列一个 | 每表一个 | +| 影响 | `SELECT` | `SELECT`, `UPDATE`, `DELETE`, `MERGE` | +| 存储的数据 / `INSERT` | 不变 / 不过滤 | 不变 / 不过滤 | + +同一张表可以同时使用两者。同一个 **column** 不能同时绑定到两者。 + +```sql +-- Rows: sales only see their region +CREATE ROW ACCESS POLICY rap_region +AS (r STRING) RETURNS BOOLEAN -> +CASE + WHEN is_role_in_session('admin') THEN true + ELSE is_role_in_session(r) +END; + +ALTER TABLE customers ADD ROW ACCESS POLICY rap_region ON (region); + +-- Columns: non-HR see redacted SSN +CREATE MASKING POLICY mask_ssn +AS (val STRING) RETURNS STRING -> +CASE + WHEN is_role_in_session('hr') THEN val + ELSE '***-**-****' +END; + +ALTER TABLE customers MODIFY COLUMN ssn SET MASKING POLICY mask_ssn; +``` + +## 端到端:职责分离 {#end-to-end-separation-of-duties} + +将 RBAC 与这两种策略结合使用,使创建者、应用者和读取者彼此分离。 + +| 角色 | 工作 | 可见内容 | +|------|-----|------| +| `security_admin` | 创建 / 拥有策略 | 没有表 SELECT 权限 | +| `data_engineer` | 拥有表,附加策略 | 所有行,原始 phone | +| `analyst_apac` | 分析 APAC | APAC 行,phone 已脱敏 | +| `support_global` | 全局支持 | 所有行,原始 phone | + +```sql +-- account_admin: roles, users, CREATE privileges +CREATE ROLE security_admin; +CREATE ROLE data_engineer; +CREATE ROLE analyst_apac; +CREATE ROLE support_global; + +CREATE USER sec_user IDENTIFIED BY 'password123'; +CREATE USER eng_user IDENTIFIED BY 'password123'; +CREATE USER analyst_user IDENTIFIED BY 'password123'; +CREATE USER support_user IDENTIFIED BY 'password123'; + +GRANT ROLE security_admin TO USER sec_user; +GRANT ROLE data_engineer TO USER eng_user; +GRANT ROLE analyst_apac TO USER analyst_user; +GRANT ROLE support_global TO USER support_user; + +GRANT CREATE DATABASE ON *.* TO ROLE data_engineer; +GRANT CREATE MASKING POLICY ON *.* TO ROLE security_admin; +GRANT CREATE ROW ACCESS POLICY ON *.* TO ROLE security_admin; +GRANT GRANT ON *.* TO ROLE security_admin; + +-- data_engineer: table ownership +SET ROLE data_engineer; +CREATE DATABASE ecommerce; +CREATE TABLE ecommerce.orders ( + order_id INT, + customer_name STRING, + phone STRING, + region STRING, + amount DECIMAL(10,2), + created_at TIMESTAMP +); +INSERT INTO ecommerce.orders VALUES + (1, 'Alice', '13812345678', 'APAC', 299.00, '2025-01-15 10:00:00'), + (2, 'Bob', '14987654321', 'EMEA', 150.00, '2025-01-16 11:00:00'), + (3, 'Charlie', '13698765432', 'APAC', 520.00, '2025-01-17 09:30:00'), + (4, 'Diana', '15012349876', 'AMER', 89.00, '2025-01-18 14:00:00'); + +-- security_admin: create policies (auto OWNERSHIP) +SET ROLE security_admin; +SET enable_experimental_row_access_policy = 1; + +CREATE MASKING POLICY mask_phone +AS (val STRING) RETURNS STRING -> +CASE + WHEN is_role_in_session('data_engineer') OR is_role_in_session('support_global') THEN val + ELSE CONCAT(SUBSTRING(val, 1, 3), '****', SUBSTRING(val, 8)) +END; + +CREATE ROW ACCESS POLICY rap_region +AS (r STRING) RETURNS BOOLEAN -> +CASE + WHEN is_role_in_session('data_engineer') OR is_role_in_session('support_global') THEN true + WHEN is_role_in_session('analyst_apac') AND r = 'APAC' THEN true + ELSE false +END; + +GRANT APPLY ON MASKING POLICY mask_phone TO ROLE data_engineer; +GRANT APPLY ON ROW ACCESS POLICY rap_region TO ROLE data_engineer; + +-- data_engineer: attach (needs table ALTER + policy APPLY) +SET ROLE data_engineer; +SET enable_experimental_row_access_policy = 1; +ALTER TABLE ecommerce.orders MODIFY COLUMN phone SET MASKING POLICY mask_phone; +ALTER TABLE ecommerce.orders ADD ROW ACCESS POLICY rap_region ON (region); + +-- account_admin: grant table access through roles +GRANT USAGE ON ecommerce.* TO ROLE analyst_apac; +GRANT USAGE ON ecommerce.* TO ROLE support_global; +GRANT SELECT ON ecommerce.orders TO ROLE analyst_apac; +GRANT SELECT ON ecommerce.orders TO ROLE support_global; +``` + +结果: + +| 角色 | 行 | 电话 | +|------|------|-------| +| `analyst_apac` | 仅 APAC | 已脱敏 (`138****5678`) | +| `support_global` | 全部 | 原始值 | +| `security_admin` | — | 权限被拒绝(无 SELECT 权限) | + +```sql +SET ROLE analyst_apac; +SELECT * FROM ecommerce.orders; +-- Alice / Charlie only, phones masked + +SET ROLE support_global; +SELECT * FROM ecommerce.orders; +-- all 4 rows, phones visible + +SET ROLE security_admin; +SELECT * FROM ecommerce.orders; +-- ERROR: Permission denied +``` + +回收该角色后,无需更改表授权即可移除访问权限: + +```sql +REVOKE ROLE analyst_apac FROM USER analyst_user; +``` + +**经验法则:** + +- 创建策略 ≠ 查询数据;附加策略需要同时具备策略 `APPLY` 和表 `ALTER` +- 优先将权限授予角色,而不是用户 +- 创建者角色会自动获得 OWNERSHIP +- `CREATE MASKING/ROW ACCESS POLICY` 是授予给角色,而不是用户 +- 使用 `SHOW GRANTS ON MASKING POLICY ...`、`SHOW GRANTS ON ROW ACCESS POLICY ...` 和 `POLICY_REFERENCES(...)` 进行审计 + +## 后续步骤 {#next-steps} + +- [脱敏策略](/tidb-cloud-lake/guides/masking-policy.md) — 条件掩码、VARIANT 键 +- [行访问策略](/tidb-cloud-lake/guides/row-access-policy.md) — 向量 / RAG 可见性、时间窗口、DML \ No newline at end of file diff --git a/tidb-cloud-lake/guides/data-protection.md b/tidb-cloud-lake/guides/data-protection.md new file mode 100644 index 0000000000000..8c51be9ebc81c --- /dev/null +++ b/tidb-cloud-lake/guides/data-protection.md @@ -0,0 +1,23 @@ +--- +title: TiDB Cloud Lake 中的数据保护 +summary: TiDB Cloud Lake 的 Continuous Data Protection (CDP) 提供易于使用的功能,帮助你的数据免受误操作、恶意行为和软件问题的影响。即使数据因意外或人为原因被更改、丢失或损坏,也能确保始终可以恢复。 +--- + +# TiDB Cloud Lake 中的数据保护 + +{{{ .lake }}} 的 Continuous Data Protection (CDP) 提供易于使用的功能,帮助你的数据免受误操作、恶意行为和软件问题的影响。即使数据因意外或人为原因被更改、丢失或损坏,也能确保始终可以恢复。 + +## {{{ .lake }}} 中的 CDP 功能 {#cdp-features-in-lake} + +- [网络策略](/tidb-cloud-lake/guides/network-policy.md) + - 根据互联网地址设置谁可以访问 {{{ .lake }}}。这有助于保护你的数据安全。 + +- [访问控制](/tidb-cloud-lake/guides/access-control.md) + - 决定谁可以查看或使用 {{{ .lake }}} 的不同部分。帮助保持有序并确保安全。 + + \ No newline at end of file diff --git a/tidb-cloud-lake/guides/data-purge-and-recycle.md b/tidb-cloud-lake/guides/data-purge-and-recycle.md new file mode 100644 index 0000000000000..5d05ffa719614 --- /dev/null +++ b/tidb-cloud-lake/guides/data-purge-and-recycle.md @@ -0,0 +1,139 @@ +--- +title: 数据清理与回收 +summary: 在 {{{ .lake }}} 中,执行 `DROP`、`TRUNCATE` 或 `DELETE` 命令时,数据不会被立即删除。这使得 {{{ .lake }}} 的时间旅行功能得以实现,允许你访问数据的先前状态。不过,这种方式也意味着在执行这些操作后,存储空间不会被自动释放。 +--- + +# 数据清理与回收 + +## 概述 {#overview} + +在 {{{ .lake }}} 中,执行 `DROP`、`TRUNCATE` 或 `DELETE` 命令时,数据不会被立即删除。这使得 {{{ .lake }}} 的时间旅行功能得以实现,允许你访问数据的先前状态。不过,这种方式也意味着在执行这些操作后,存储空间不会被自动释放。 + +``` +Before DELETE: After DELETE: After VACUUM: ++----------------+ +----------------+ +----------------+ +| Current Data | | New Version | | Current Data | +| | | (After DELETE) | | (After DELETE) | ++----------------+ +----------------+ +----------------+ +| Historical Data| | Historical Data| | | +| (Time Travel) | | (Original Data)| | | ++----------------+ +----------------+ +----------------+ + Storage not freed Storage freed +``` + +## VACUUM 命令与清理范围 {#vacuum-commands-and-cleanup-scope} + +{{{ .lake }}} 提供了三种 VACUUM 命令,它们的**清理范围各不相同**。了解每种命令会清理哪些内容,对于数据管理至关重要。 + +``` +VACUUM DROP TABLE +├── Target: Dropped tables (after DROP TABLE command) +├── S3 Storage: ✅ Removes ALL data (files, segments, blocks, indexes, statistics) +├── Meta Service: ✅ Removes ALL metadata (schema, permissions, records) +└── Result: Complete table removal - CANNOT be recovered + +VACUUM TABLE +├── Target: Historical data and orphan files for active tables +├── S3 Storage: ✅ Removes old snapshots, orphan segments/blocks, indexes/stats +├── Meta Service: ❌ Preserves table structure and current metadata +└── Result: Table stays active, only history cleaned + +VACUUM TEMPORARY FILES +├── Target: Temporary spill files from queries (joins, sorts, aggregates) +├── S3 Storage: ✅ Removes temp files from crashed/interrupted queries +├── Meta Service: ❌ No metadata (temp files don't have any) +└── Result: Storage cleanup only, rarely needed +``` + +--- + +> **🚨 关键提示**:只有 `VACUUM DROP TABLE` 会影响 meta service。其他命令只会清理存储文件。 + +## 使用 VACUUM 命令 {#using-vacuum-commands} + +VACUUM 命令族是在 {{{ .lake }}} 中清理数据的主要方法。 + +### VACUUM DROP TABLE {#vacuum-drop-table} + +从存储和元信息中永久移除已删除的表。 + +```sql +VACUUM DROP TABLE [FROM ] [DRY RUN [SUMMARY]] [LIMIT ]; +``` + +**选项:** + +- `FROM `:限制为特定数据库 +- `DRY RUN [SUMMARY]`:预览将要移除的文件,而不实际删除它们 +- `LIMIT `:限制要执行 vacuum 的文件数量 + +**示例:** + +```sql +-- Preview files that would be removed +VACUUM DROP TABLE DRY RUN; + +-- Preview summary of files that would be removed +VACUUM DROP TABLE DRY RUN SUMMARY; + +-- Remove dropped tables from the "default" database +VACUUM DROP TABLE FROM default; + +-- Remove up to 1000 files from dropped tables +VACUUM DROP TABLE LIMIT 1000; +``` + +### VACUUM TABLE {#vacuum-table} + +移除活动表的历史数据和孤儿文件(仅清理存储)。 + +```sql +VACUUM TABLE [DRY RUN [SUMMARY]]; +``` + +**选项:** + +- `DRY RUN [SUMMARY]`:预览将要移除的文件,而不实际删除它们 + +**示例:** + +```sql +-- Preview files that would be removed +VACUUM TABLE my_table DRY RUN; + +-- Preview summary of files that would be removed +VACUUM TABLE my_table DRY RUN SUMMARY; + +-- Remove historical data from my_table +VACUUM TABLE my_table; +``` + +### VACUUM TEMPORARY FILES {#vacuum-temporary-files} + +移除查询执行期间创建的临时 spill 文件。 + +```sql +VACUUM TEMPORARY FILES; +``` + +> **Note:** +> +> 在正常运行期间通常很少需要使用,因为 {{{ .lake }}} 会自动处理清理。通常只有在 {{{ .lake }}} 在查询执行期间发生崩溃时,才需要手动清理。 + +## 调整数据保留时间 {#adjusting-data-retention-time} + +VACUUM 命令会移除早于 `DATA_RETENTION_TIME_IN_DAYS` 设置的数据文件。默认情况下,{{{ .lake }}} 会保留 1 天(24 小时)的历史数据。你可以调整此设置: + +```sql +-- Change retention period to 2 days +SET GLOBAL DATA_RETENTION_TIME_IN_DAYS = 2; + +-- Check current retention setting +SHOW SETTINGS LIKE 'DATA_RETENTION_TIME_IN_DAYS'; +``` + +| 版本 | 默认保留期 | 最大保留期 | +| ---------------------------------------- | ----------------- | ---------------- | +| {{{ .lake }}} 社区版和企业版 | 1 天(24 小时) | 90 天 | +| {{{ .lake }}}(个人版) | 1 天(24 小时) | 1 天(24 小时) | +| {{{ .lake }}}(商业版) | 1 天(24 小时) | 90 天 | \ No newline at end of file diff --git a/tidb-cloud-lake/guides/data-sources.md b/tidb-cloud-lake/guides/data-sources.md new file mode 100644 index 0000000000000..fb338592be750 --- /dev/null +++ b/tidb-cloud-lake/guides/data-sources.md @@ -0,0 +1,40 @@ +--- +title: 数据源 +summary: {{{ .lake }}} 中的数据源表示与外部系统的连接。它存储访问外部系统所需的凭证和连接详细信息,并可在多个集成任务或通知场景中复用。 +--- + +# 数据源 + +{{{ .lake }}} 中的数据源表示与外部系统的连接。它存储访问外部系统所需的凭证和连接详细信息,并可在多个集成任务或通知场景中复用。 + +数据源本身不会执行同步。它的作用是集中管理访问设置,这样你就不需要在每个任务中重复输入账户、密码、密钥或通知端点。 + +## 支持的数据源类型 {#supported-data-source-types} + +| 类型 | 用途 | +|------|---------| +| [Amazon S3 - 凭证](/tidb-cloud-lake/guides/aws-credentials.md) | 存储访问 Amazon S3 所需的 Access Key 和 Secret Key。这些凭证可在多个 S3 导入任务中复用。 | +| [Amazon SQS (S3) - IAM Role (Beta)](/tidb-cloud-lake/guides/amazon-sqs-s3-iam-role.md) | 存储 SQS (S3) 摄取所需的 queue URL、Region、IAM Role 和 S3 path scope。它可用于消费 S3 对象创建事件。 | +| [MySQL - Credentials](/tidb-cloud-lake/guides/mysql-credentials.md) | 存储访问 MySQL 所需的主机、端口、用户名、密码和数据库信息。这些设置可在多个 MySQL 同步任务中复用。 | +| [PostgreSQL - Credentials](/tidb-cloud-lake/guides/postgresql-credentials.md) | 存储访问 PostgreSQL 所需的主机、端口、用户名、密码和数据库信息。这些设置可在多个 PostgreSQL 同步任务中复用。 | +| [FeiShuBot](/tidb-cloud-lake/guides/feishubot.md) | 存储用于任务失败通知及类似场景的飞书机器人 webhook 和消息模板。 | +| [Kafka - 凭证(Beta)](/tidb-cloud-lake/guides/kafka-credentials.md) | 存储访问 Kafka 所需的 broker 地址、认证方法和连接凭证。这些设置可供 Kafka Consumer 任务复用。 | + +并非每个数据源都对应一个集成任务。例如,`FeiShuBot` 用于通知配置,而 `Amazon S3 - Credentials`、`Amazon SQS (S3) - IAM Role`、`MySQL - Credentials`、`PostgreSQL - Credentials` 和 `Kafka - Credentials` 则由实际的导入、同步或事件消费任务引用。 + +## 管理数据源 {#managing-data-sources} + +导航到 **Data** > **Data Sources**。在此页面中,你可以: + +- 查看所有已配置的数据源 +- 创建新数据源 +- 编辑或删除现有数据源 +- 测试连接以验证凭证 + +> **Tip:** +> +> 在保存数据源之前运行 **Test Connectivity**,以尽早发现无效凭证、权限缺失或网络限制等问题。 + +## 后续步骤 {#next-steps} + +创建数据源后,你可以根据其用途,在[集成任务](/tidb-cloud-lake/guides/integration-tasks.md)或通知配置中引用它。 \ No newline at end of file diff --git a/tidb-cloud-lake/guides/deepnote.md b/tidb-cloud-lake/guides/deepnote.md new file mode 100644 index 0000000000000..533ed31c4b1b0 --- /dev/null +++ b/tidb-cloud-lake/guides/deepnote.md @@ -0,0 +1,42 @@ +--- +title: 使用 Deepnote 连接到 TiDB Cloud Lake +summary: Deepnote 让你能够与朋友和同事在同一平台上实时协作,轻松开展数据科学项目,帮助你更快地将想法和分析转化为产品。Deepnote 基于浏览器构建,因此你可以在任何平台(Windows、Mac、Linux 或 Chromebook)上使用它。无需下载,并且每天都会向你推送更新。所有更改都会被即时保存。 +--- + +# 使用 Deepnote 连接到 TiDB Cloud Lake + +[Deepnote](https://deepnote.com) 让你能够与朋友和同事在同一平台上实时协作,轻松开展数据科学项目,帮助你更快地将想法和分析转化为产品。Deepnote 基于浏览器构建,因此你可以在任何平台(Windows、Mac、Linux 或 Chromebook)上使用它。无需下载,并且每天都会向你推送更新。所有更改都会被即时保存。 + +你可以通过 Deepnote 与 ClickHouse 兼容的集成,并使用安全连接,将 Deepnote 连接到 {{{ .lake }}}。 + +## 教程:与 Deepnote 集成 {#tutorial-integrating-with-deepnote} + +本教程将指导你完成将 {{{ .lake }}} 与 Deepnote 集成的过程。 + +### 步骤 1:设置环境 {#step-1-set-up-environment} + +请确保你可以登录到你的 {{{ .lake }}} 账户,并获取某个计算集群 (Warehouse) 的连接信息。更多详情,请参见[连接到计算集群](/tidb-cloud-lake/guides/warehouse.md#connecting-to-a-warehouse)。 + +### 步骤 2:连接到 {{{ .lake }}} {#step-2-connect-to-lake} + +1. 登录 Deepnote;如果你还没有账户,请先创建一个。 + +2. 点击左侧边栏中 **INTEGRATIONS** 右侧的 **+**,然后选择 **ClickHouse**。 + + ![与 ClickHouse 集成](/media/tidb-cloud-lake/integration-clickhouse.png) + +3. 使用你的连接信息填写各个字段。 + + | 参数 | 说明 | + | ---------------- | ---------------------------------- | + | Integration name | 例如,`TiDB Cloud Lake` | + | Host name | 从连接信息中获取 | + | Port | `443` | + | Username | `cloudapp` | + | Password | 从连接信息中获取 | + +4. 创建一个 notebook。 + +5. 在 notebook 中,进入 **SQL** 部分,然后选择你之前创建的连接。 + +现在一切就绪!有关如何使用该工具,请参阅 Deepnote 文档。 diff --git a/tidb-cloud-lake/guides/driver-overview.md b/tidb-cloud-lake/guides/driver-overview.md new file mode 100644 index 0000000000000..c90a2b6eff048 --- /dev/null +++ b/tidb-cloud-lake/guides/driver-overview.md @@ -0,0 +1,51 @@ +--- +title: 使用驱动连接 TiDB Cloud Lake +summary: 可用于连接 TiDB Cloud Lake 的官方驱动概览。 +--- + +# 使用驱动连接 TiDB Cloud Lake + +{{{ .lake }}} 为多种编程语言提供了官方驱动,使你能够从应用程序连接到 {{{ .lake }}} 并与之交互。 + +## 快速开始 {#quick-start} + +1. **选择你的语言** - 可从 Python、Go、Node.js、Java 或 Rust 中选择 +2. **获取连接字符串** - 使用下面的 DSN 格式 +3. **安装并连接** - 按照对应驱动的文档进行操作 + +## 连接字符串(DSN) {#connection-string-dsn} + +所有 {{{ .lake }}} 驱动都使用相同的 DSN(Data Source Name)格式: + +``` +lake://user:pwd@host[:port]/[database][?sslmode=disable][&arg1=value1] +``` + +> **注意:** +> +> `user:pwd` 指的是 {{{ .lake }}} 中的 SQL 用户。请参见 [CREATE USER](/tidb-cloud-lake/sql/create-user.md) 以创建用户并授予权限。 + +### 连接示例 {#connection-examples} + +| 部署 | 连接字符串 | +| ------------------ | -------------------------------------------------------- | +| **{{{ .lake }}}** | `lake://user:pwd@host:443/database?warehouse=wh` | + +### 参数参考 {#parameters-reference} + +| 参数 | 描述 | {{{ .lake }}} | 示例 | +| ----------- | -------------- | -------------- | ----------------------- | +| `sslmode` | SSL 模式 | 不使用 | `?sslmode=disable` | +| `warehouse` | 计算集群名称 | 必填 | `?warehouse=compute_wh` | + +> **{{{ .lake }}}**:[获取连接信息 →](/tidb-cloud-lake/guides/warehouse.md#obtaining-connection-information) + +## 可用驱动 {#available-drivers} + +| 语言 | 软件包 | 关键特性 | +| ----------------------- | ------------------------------------------- | ----------------------------------------------------------------------------- | +| **[Python](/tidb-cloud-lake/guides/connect-using-python.md)** | `tidbcloudlake-driver`
`lake-sqlalchemy` | • 支持同步/异步
• SQLAlchemy 方言
• 兼容 PEP 249 | +| **[Go](/tidb-cloud-lake/guides/connect-using-golang.md)** | `lake-go` | • database/sql 接口
• 连接池
• 批量操作 | +| **[Node.js](/tidb-cloud-lake/guides/connect-using-node-js.md)** | `tidbcloudlake-driver` | • TypeScript 支持
• 基于 Promise 的 API
• 流式结果 | +| **[Java](/tidb-cloud-lake/guides/connect-using-java.md)** | `lake-jdbc` | • 兼容 JDBC 4.0
• 连接池
• 预处理语句 | +| **[Rust](/tidb-cloud-lake/guides/connect-using-rust.md)** | `lake-driver` | • 支持 Async/await
• 类型安全查询
• 零拷贝反序列化 | diff --git a/tidb-cloud-lake/guides/editions.md b/tidb-cloud-lake/guides/editions.md new file mode 100644 index 0000000000000..9bf3da7a67cb5 --- /dev/null +++ b/tidb-cloud-lake/guides/editions.md @@ -0,0 +1,96 @@ +--- +title: 版本 +summary: "{{{ .lake }}} 提供三个版本:Personal、Business 和 Dedicated,您可以根据不同需求进行选择,以满足广泛的使用场景并确保不同用例下的最佳性能。" +--- + +# 版本 + +{{{ .lake }}} 提供三个版本:**Personal**、**Business** 和 **Dedicated**,您可以根据不同需求进行选择,以满足广泛的使用场景并确保不同用例下的最佳性能。 + +有关定价信息,请参见 [价格与计费](/tidb-cloud-lake/guides/pricing-billing.md)。有关这些版本之间的详细功能列表,请参见 [功能列表](#feature-lists)。 + +## 功能列表 {#feature-lists} + +以下是 {{{ .lake }}} 不同版本的功能列表: + +### 发布管理 {#release-management} + +| 功能 | Personal | Business | Dedicated | +|----------|----------|----------|-----------| +| 提前访问每周发布的新版本,可在每次版本部署到生产账户之前用于额外的测试/验证。 | | ✓ | ✓ | + +### 安全与治理 {#security-governance} + +| 功能 | Personal | Business | Dedicated | +|----------|----------|----------|-----------| +| SOC 2 Type II 认证。 | ✓ | ✓ | ✓ | +| GDPR | ✓ | ✓ | ✓ | +| 所有数据自动加密。 | ✓ | ✓ | ✓ | +| 对象级访问控制。 | ✓ | ✓ | ✓ | +| 标准 Time Travel(最长 1 天),用于访问/恢复已修改和已删除的数据。 | ✓ | ✓ | ✓ | +| 通过 Fail-Safe 对已修改/已删除的数据进行容灾(在 Time Travel 之外额外保留 7 天)。 | ✓ | ✓ | ✓ | +| **扩展 Time Travel**。 | | 90 days | 90 days | +| 列级安全,可对表或视图中的列应用脱敏策略。 | ✓ | ✓ | ✓ | +| 通过 Account Usage ACCESS_HISTORY 视图审计用户访问历史。 | ✓ | ✓ | ✓ | +| **支持使用 AWS PrivateLink 私有连接到 {{{ .lake }}} 服务**。 | | ✓ | ✓ | +| **专用元信息存储和计算资源池(用于虚拟计算集群 (Warehouse))**。 | | | ✓ | + +### 计算资源 {#compute-resource} + +| 功能 | Personal | Business | Dedicated | +|----------|----------|----------|-----------| +| 虚拟计算集群 (Warehouse),用于隔离查询和数据加载工作负载的独立计算集群。 | ✓ | ✓ | ✓ | +| 多集群扩缩容 | | ✓ | ✓ | +| 用于监控虚拟 Warehouse credit 使用情况的资源监视器。 | ✓ | ✓ | ✓ | + +### SQL 支持 {#sql-support} + +| 功能 | Personal | Business | Dedicated | +|----------|----------|----------|-----------| +| 标准 SQL,包括 SQL:1999 中定义的大多数 DDL 和 DML。 | ✓ | ✓ | ✓ | +| 高级 DML,例如多表 INSERT、MERGE 和 multi-merge。 | ✓ | ✓ | ✓ | +| 广泛支持标准数据类型。 | ✓ | ✓ | ✓ | +| 原生支持半结构化数据(JSON、ORC、Parquet)。 | ✓ | ✓ | ✓ | +| 原生支持地理空间数据。 | ✓ | ✓ | ✓ | +| 原生支持非结构化数据。 | ✓ | ✓ | ✓ | +| 表列中字符串/文本数据的排序规则。 | ✓ | ✓ | ✓ | +| 多语句事务。 | ✓ | ✓ | ✓ | +| 用户定义函数(UDF),支持 JavaScript、Python 和 WebAssembly。 | | ✓ | ✓ | +| 外部函数,用于将 {{{ .lake }}} 扩展到其他开发平台。 | ✓ | ✓ | ✓ | +| 用于外部函数的 Amazon API Gateway 私有端点。 | ✓ | ✓ | ✓ | +| 外部表,用于引用云存储数据湖中的数据。 | ✓ | ✓ | ✓ | +| 支持对超大表中的数据进行聚簇以提升查询性能,并自动维护聚簇。 | ✓ | ✓ | ✓ | +| 针对点查查询的搜索优化,并自动维护。 | ✓ | ✓ | ✓ | +| 物化视图,并自动维护结果。 | ✓ | ✓ | ✓ | +| Iceberg 表,用于引用云存储数据湖中的数据。 | ✓ | ✓ | ✓ | +| Schema detection,用于自动检测 staged 半结构化数据文件集合中的 schema 并获取列定义。 | ✓ | ✓ | ✓ | +| Schema evolution,用于自动演进表结构,以支持从数据源接收到的新数据结构。 | ✓ | ✓ | ✓ | +| 支持[使用外部位置创建表](/tidb-cloud-lake/sql/create-external-table.md)。 | ✓ | ✓ | ✓ | +| 支持 [ATTACH TABLE](/tidb-cloud-lake/sql/attach-table.md)。 | ✓ | ✓ | ✓ | + +### 接口与工具 {#interfaces-tools} + +| 功能 | Personal | Business | Dedicated | +|----------|----------|----------|-----------| +| 新一代 SQL 工作区,用于高级查询开发、数据分析和可视化。 | ✓ | ✓ | ✓ | +| LakeSQL,一种命令行客户端,用于构建/测试查询、加载/卸载批量数据以及自动化 DDL 操作。 | ✓ | ✓ | ✓ | +| Rust、Python、Java、Node.js、.js、PHP 和 Go 的编程接口。 | ✓ | ✓ | ✓ | +| 原生支持 JDBC。 | ✓ | ✓ | ✓ | +| 丰富的生态系统,可连接 ETL、BI 以及其他第三方供应商和技术。 | ✓ | ✓ | ✓ | + +### 数据导入与导出 {#data-import-export} + +| 功能 | Personal | Business | Dedicated | +|----------|----------|----------|-----------| +| 从分隔符平面文件(CSV、TSV 等)和半结构化数据文件(JSON、ORC、Parquet)进行批量加载。 | ✓ | ✓ | ✓ | +| 批量卸载到分隔符平面文件和 JSON 文件。 | ✓ | ✓ | ✓ | +| 持续微批加载。 | ✓ | ✓ | ✓ | +| 用于低延时加载流式数据的流式处理。 | ✓ | ✓ | ✓ | +| 用于从 Apache Kafka topic 加载数据的 {{{ .lake }}} Connector for Kafka。 | ✓ | ✓ | ✓ | + +### 数据管道 {#data-pipelines} + +| 功能 | Personal | Business | Dedicated | +|----------|----------|----------|-----------| +| 用于跟踪表变更的 Streams。 | ✓ | ✓ | ✓ | +| 用于调度执行 SQL 语句的 Tasks,通常与表 Streams 配合使用。 | ✓ | ✓ | ✓ | diff --git a/tidb-cloud-lake/guides/external-ai-functions.md b/tidb-cloud-lake/guides/external-ai-functions.md new file mode 100644 index 0000000000000..9d541c210eded --- /dev/null +++ b/tidb-cloud-lake/guides/external-ai-functions.md @@ -0,0 +1,78 @@ +--- +title: 外部 AI 函数 +summary: 通过将 {{{ .lake }}} 与您自己的基础设施连接,构建强大的 AI/ML 能力。外部函数让您能够部署自定义模型、利用 GPU 加速,并与任何 ML 框架集成,同时确保数据安全。 +--- + +# 外部 AI 函数 + +通过将 {{{ .lake }}} 与您自己的基础设施连接,构建强大的 AI/ML 能力。外部函数让您能够部署自定义模型、利用 GPU 加速,并与任何 ML 框架集成,同时确保数据安全。 + +## 关键能力 {#key-capabilities} + +| 功能 | 优势 | +|---------|----------| +| **自定义模型** | 使用任何开源或专有的 AI/ML 模型 | +| **GPU 加速** | 部署在配备 GPU 的机器上,以实现更快的推理 | +| **数据隐私** | 将数据保留在您的基础设施内部 | +| **扩展性** | 独立扩缩容和资源优化 | +| **灵活性** | 支持任何编程语言和 ML 框架 | + +## 工作原理 {#how-it-works} + +1. **Create AI Server**:使用 Python 和 [`tidbcloudlake-udf`](https://pypi.org/project/tidbcloudlake-udf/) 构建您的 AI/ML 服务器 +2. **Register Function**:使用 `CREATE FUNCTION` 将您的服务器连接到 {{{ .lake }}} +3. **Use in SQL**:直接在 SQL 查询中调用您的自定义 AI 函数 + +## 示例:文本嵌入函数 {#example-text-embedding-function} + +```python +# Simple embedding UDF server demo +from tidbcloudlake_udf import udf, UDFServer +from sentence_transformers import SentenceTransformer + +# Load pre-trained model +model = SentenceTransformer('all-mpnet-base-v2') # 768-dimensional vectors + +@udf( + input_types=["STRING"], + result_type="ARRAY(FLOAT)", +) +def ai_embed_768(inputs: list[str], headers) -> list[list[float]]: + """Generate 768-dimensional embeddings for input texts""" + try: + # Process inputs in a single batch + embeddings = model.encode(inputs) + # Convert to list format + return [embedding.tolist() for embedding in embeddings] + except Exception as e: + print(f"Error generating embeddings: {e}") + # Return empty lists in case of error + return [[] for _ in inputs] + +if __name__ == '__main__': + print("Starting embedding UDF server on port 8815...") + server = UDFServer("0.0.0.0:8815") + server.add_function(ai_embed_768) + server.serve() +``` + +```sql +-- Register the external function in {{{ .lake }}} +CREATE OR REPLACE FUNCTION ai_embed_768 (STRING) + RETURNS ARRAY(FLOAT) + LANGUAGE PYTHON + HANDLER = 'ai_embed_768' + ADDRESS = 'https://your-ml-server.example.com'; + +-- Use the custom embedding in queries +SELECT + id, + title, + cosine_distance( + ai_embed_768(content), + ai_embed_768('machine learning techniques') + ) AS similarity +FROM articles +ORDER BY similarity ASC +LIMIT 5; +``` \ No newline at end of file diff --git a/tidb-cloud-lake/guides/fail-safe.md b/tidb-cloud-lake/guides/fail-safe.md new file mode 100644 index 0000000000000..bfdc7562c13f4 --- /dev/null +++ b/tidb-cloud-lake/guides/fail-safe.md @@ -0,0 +1,67 @@ +--- +title: Fail-Safe +summary: Fail-Safe 是指旨在从对象存储中恢复丢失或被意外删除数据的机制。 +--- + +# Fail-Safe + +Fail-Safe 是指旨在从对象存储中恢复丢失或被意外删除数据的机制。 + +- 存储兼容性:目前,Fail-Safe 仅支持与 S3 兼容的存储类型。 +- 存储桶版本控制:要使 Fail-Safe 生效,必须启用存储桶版本控制。请注意,在启用版本控制之前创建的数据*无法*通过此方法恢复。 + +## 实现 Fail-Safe {#implementing-fail-safe} + +{{{ .lake }}} 提供了 [SYSTEM$FUSE_AMEND](/tidb-cloud-lake/sql/system-fuse-amend.md) 表函数来启用 Fail-Safe 恢复。该函数允许你在启用存储桶版本控制时,从与 S3 兼容的存储桶中恢复数据。 + +## 使用示例 {#usage-example} + +下面通过一个分步示例说明如何使用 [SYSTEM$FUSE_AMEND](/tidb-cloud-lake/sql/system-fuse-amend.md) 函数从 S3 恢复表数据: + +1. 为存储桶 `lake-doc` 启用版本控制。 + +2. 创建一个外部表,并将表数据存储在 `lake-doc` 存储桶中的 `fail-safe` 文件夹下。 + + ```sql + CREATE TABLE t(a INT) + 's3://lake-doc/fail-safe/' + CONNECTION = (access_key_id ='' secret_access_key =''); + + -- Insert sample data + INSERT INTO t VALUES (1), (2), (3); + ``` + + 如果你现在打开存储桶中的 `fail-safe` 文件夹,就可以看到数据已经存在。 + +3. 删除 `fail-safe` 文件夹中的所有子文件夹及其文件,以模拟数据丢失。 + +4. 删除后尝试查询该表会返回错误: + + ```sql + SELECT * FROM t; + + error: APIError: ResponseError with 3001: NotFound (persistent) at read, context: { uri: https://s3.us-east-2.amazonaws.com/lake-doc/fail-safe/1/1502/_b/3f84d636dc6c40508720d1cde20d4f3b_v2.parquet, response: Parts { status: 404, version: HTTP/1.1, headers: {"x-amz-request-id": "FYSJNZX1X16T91HN", "x-amz-id-2": "EI+NQjyRlSk8jlU64EASKodjvOkzuAlhZ1CYo0nIenzOH6DP7t6mMWh7raj4mUiOxW18NQesxmA=", "x-amz-delete-marker": "true", "x-amz-version-id": "ngecunzFP0pir0ysXlbR_eJafaTPl1oh", "content-type": "application/xml", "transfer-encoding": "chunked", "date": "Mon, 09 Sep 2024 02:01:57 GMT", "server": "AmazonS3"} }, service: s3, path: 1/1502/_b/3f84d636dc6c40508720d1cde20d4f3b_v2.parquet, range: 4-47 } => S3Error { code: "NoSuchKey", message: "The specified key does not exist.", resource: "", request_id: "FYSJNZX1X16T91HN" } + ``` + +5. 使用 system$fuse_amend 恢复表数据: + + ```sql + CALL system$fuse_amend('default', 't'); + + -[ RECORD 1 ]----------------------------------- + result: Ok + ``` + +6. 验证表数据已恢复: + + ```sql + SELECT * FROM t; + + ┌─────────────────┐ + │ a │ + ├─────────────────┤ + │ 1 │ + │ 2 │ + │ 3 │ + └─────────────────┘ + ``` \ No newline at end of file diff --git a/tidb-cloud-lake/guides/feishubot.md b/tidb-cloud-lake/guides/feishubot.md new file mode 100644 index 0000000000000..ce46933cdce98 --- /dev/null +++ b/tidb-cloud-lake/guides/feishubot.md @@ -0,0 +1,113 @@ +--- +title: FeiShuBot +summary: 本页介绍如何创建 `FeiShuBot` 数据源。该数据源用于存储飞书机器人 webhook 和消息模板,适用于任务失败通知等场景。 +--- + +# FeiShuBot + +本页介绍如何创建 `FeiShuBot` 数据源。该数据源用于存储飞书机器人 webhook 和消息模板,通常用于任务失败通知。 + +## 使用场景 {#use-cases} + +- 在任务运行失败时向飞书群发送通知 +- 在多个任务之间复用同一套机器人配置和消息模板 +- 集中管理通知端点和消息格式 + +## 创建 FeiShuBot {#create-feishubot} + +1. 进入 **Data** > **Data Sources**,然后点击 **Create Data Source**。 +2. 选择 **FeiShuBot** 作为服务类型,然后填写以下字段: + + | 字段 | 必填 | 描述 | + |-------|----------|-------------| + | **Name** | 是 | 该数据源的描述性名称。仅支持字母、数字和下划线 | + | **URL** | 是 | 自定义飞书机器人 webhook URL | + | **Warehouse** | 是 | 用于创建 `NOTIFICATION INTEGRATION` 的计算集群 | + | **Payload** | 是 | 消息负载类型。目前仅支持 `Task Error` | + | **Template** | 是 | 自定义消息模板 | + +3. 点击 **Test Connectivity** 验证配置。如果测试成功,点击 **OK** 保存数据源。 + +## 用法 {#usage} + +`FeiShuBot` 可与 SQL Task 的 `ERROR_INTEGRATION` 属性一起使用,也可以在控制台的任务流 (Task Flow) UI 中通过 **Error Notification** 引用。 + +### 设置 SQL Task 属性 {#set-a-sql-task-property} + +设置 Task 的 `ERROR_INTEGRATION` 属性。在以下示例中,数据源名称为 `test_1`: + +```sql +CREATE TASK my_daily_task + WAREHOUSE = 'compute_wh' + SCHEDULE = USING CRON '0 0 9 * * *' 'America/Los_Angeles' + COMMENT = 'Daily summary task' + ERROR_INTEGRATION = 'test_1' +AS + INSERT INTO summary_table SELECT * FROM source_table; +``` + +### 在任务流 UI 中配置 {#configure-it-in-the-task-flow-ui} + +在创建或编辑页面中,将 **Error Notification** 设置为对应的 `FeiShuBot` 数据源。 + +### 自定义任务错误模板 {#customize-the-task-error-template} + +默认模板: + +```text +**[ALERT] {{ .MessageType }} - {{ .TaskName }}** +--- +taskId: {{ .TaskId }} +taskName: {{ .TaskName }} +tenantId: {{ .TenantId }} + +Messages: {{ range .Messages }} +- runId: {{ .RunId }} + queryId: {{ .QueryId }} + error: {{ .ErrorKind }} ({{ .ErrorCode }}) + message: {{ .ErrorMessage }} {{ end }} + +--- +{{ .Timestamp }} +``` + +收到的消息示例如下: + +![FeiShu notification example](/media/tidb-cloud-lake/feishubot-example.png) + +自定义模板支持: + +- Markdown 内容 +- Golang 模板语法 + +可用变量如下: + +```golang +type ErrorIntegrationPayload struct { + Version string `json:"version"` + MessageId string `json:"messageId"` + MessageType string `json:"messageType"` + Timestamp time.Time `json:"timestamp"` + TenantId string `json:"tenantId"` + TaskName string `json:"taskName"` + TaskId string `json:"taskId"` + RootTaskName string `json:"rootTaskName"` + RootTaskId string `json:"rootTaskId"` + Messages []*ErrorMessage `json:"messages"` +} + +type ErrorMessage struct { + RunId string `json:"runId"` + ScheduledTime time.Time `json:"scheduledTime"` + QueryStartTime *time.Time `json:"queryStartTime"` + CompletedTime *time.Time `json:"completedTime"` + QueryId string `json:"queryId"` + ErrorKind string `json:"errorKind"` + ErrorCode string `json:"errorCode"` + ErrorMessage string `json:"errorMessage"` +} +``` + +## 注意事项 {#notes} + +`FeiShuBot` 是一种面向通知的数据源,不用于将业务数据加载到 {{{ .lake }}} 中。 diff --git a/tidb-cloud-lake/guides/full-text-index.md b/tidb-cloud-lake/guides/full-text-index.md new file mode 100644 index 0000000000000..40dd13fbda6a2 --- /dev/null +++ b/tidb-cloud-lake/guides/full-text-index.md @@ -0,0 +1,287 @@ +--- +title: 全文索引 +summary: 全文索引(倒排索引)通过将词项映射到文档,在大型文档集合中自动实现极速文本搜索,无需缓慢的全表扫描。 +--- + +# 全文索引 + +> **注意:** +> +> 想要查看可动手实践的演练?参见 [JSON 与搜索指南](/tidb-cloud-lake/guides/json-search.md)。 + +## 全文索引:自动实现极速文本搜索 {#full-text-index-automatic-lightning-fast-text-search} + +全文索引(倒排索引)通过将词项映射到文档,在大型文档集合中自动实现极速文本搜索,无需缓慢的全表扫描。 + +## 它解决了什么问题? {#what-problem-does-it-solve} + +大型数据集上的文本搜索操作面临显著的性能挑战: + +| 问题 | 影响 | 全文索引解决方案 | +|---------|--------|-------------------------| +| **缓慢的 LIKE 查询** | `WHERE content LIKE '%keyword%'` 扫描整个表 | 直接查找词项,跳过无关文档 | +| **全表扫描** | 每次文本搜索都会读取所有行 | 只读包含搜索词项的文档 | +| **糟糕的搜索体验** | 用户需要等待数秒/数分钟才能获得搜索结果 | 亚秒级搜索响应时间 | +| **搜索能力有限** | 仅支持基本模式匹配 | 高级功能:模糊搜索、相关性评分 | +| **高资源占用** | 文本搜索消耗过多的 CPU/内存 | 索引搜索仅需极少资源 | + +**示例**:在 1000 万条日志中搜索 "kubernetes error"。如果没有全文索引,则需要扫描全部 1000 万行。使用全文索引后,可以直接找到约 1000 个匹配文档,几乎瞬间返回结果。 + +## 工作原理 {#how-it-works} + +全文索引会创建从词项到文档的倒排映射: + +| 术语 | 文档 ID | +|------|-------------| +| "kubernetes" | 101, 205, 1847 | +| "error" | 101, 892, 1847 | +| "pod" | 205, 1847, 2901 | + +当搜索 "kubernetes error" 时,索引会找到同时包含这两个词项的文档(101、1847),而无需扫描整张表。 + +## 快速设置 {#quick-setup} + +```sql +-- Create table with text content +CREATE TABLE logs(id INT, message TEXT, timestamp TIMESTAMP); + +-- Create full-text index - automatically indexes new data +CREATE INVERTED INDEX logs_message_idx ON logs(message); + +-- One-time refresh needed only for existing data before index creation +REFRESH INVERTED INDEX logs_message_idx ON logs; + +-- Search using MATCH function - fully automatic optimization +SELECT * FROM logs WHERE MATCH(message, 'error kubernetes'); +``` + +**自动索引管理**: + +- **New Data**:插入时会自动建立索引,无需手动操作 +- **Existing Data**:仅对创建索引前已存在的数据需要执行一次刷新 +- **Ongoing Maintenance**:{{{ .lake }}} 会自动维护最佳搜索性能 + +## 搜索函数 {#search-functions} + +| 函数 | 用途 | 示例 | +|----------|---------|---------| +| `MATCH(column, 'terms')` | 基本文本搜索 | `MATCH(content, 'database performance')` | +| `QUERY('column:terms')` | 高级查询语法 | `QUERY('title:"full text" AND content:search')` | +| `SCORE()` | 相关性评分 | `SELECT *, SCORE() FROM docs WHERE MATCH(...)` | + +## 高级搜索功能 {#advanced-search-features} + +### 模糊搜索 {#fuzzy-search} + +```sql +-- Find documents even with typos (fuzziness=1 allows 1 character difference) +SELECT * FROM logs WHERE MATCH(message, 'kubernetes', 'fuzziness=1'); +``` + +### 相关性评分 {#relevance-scoring} + +```sql +-- Get results with relevance scores, filter by minimum score +SELECT id, message, SCORE() as relevance +FROM logs +WHERE MATCH(message, 'critical error') AND SCORE() > 0.5 +ORDER BY SCORE() DESC; +``` + +### 复杂查询 {#complex-queries} + +```sql +-- Advanced query syntax with boolean operators +SELECT * FROM docs WHERE QUERY('title:"user guide" AND content:(tutorial OR example)'); +``` + +## 完整示例 {#complete-example} + +本示例演示了如何在 Kubernetes 日志数据上创建全文搜索索引,并使用多种函数进行搜索: + +```sql +-- Create a table with a computed column +CREATE TABLE k8s_logs ( + event_id INT, + event_data VARIANT, + event_timestamp TIMESTAMP, + event_message VARCHAR AS (event_data['message']::VARCHAR) STORED +); + +-- Create an inverted index on the "event_message" column +CREATE INVERTED INDEX event_message_fulltext ON k8s_logs(event_message); + +-- Insert comprehensive sample data +INSERT INTO k8s_logs (event_id, event_data, event_timestamp) +VALUES + (1, + PARSE_JSON('{ + "message": "Pod scheduled", + "object_type": "Pod", + "name": "frontend-1", + "namespace": "production", + "node": "node-01", + "status": "Scheduled" + }'), + '2024-04-08T08:00:00Z'); + +INSERT INTO k8s_logs (event_id, event_data, event_timestamp) +VALUES + (2, + PARSE_JSON('{ + "message": "Deployment scaled", + "object_type": "Deployment", + "name": "backend", + "namespace": "development", + "replicas": 3 + }'), + '2024-04-08T09:15:00Z'); + +INSERT INTO k8s_logs (event_id, event_data, event_timestamp) +VALUES + (3, + PARSE_JSON('{ + "message": "Node condition changed", + "object_type": "Node", + "name": "node-02", + "condition": "Ready", + "status": "True" + }'), + '2024-04-08T10:30:00Z'); + +INSERT INTO k8s_logs (event_id, event_data, event_timestamp) +VALUES + (4, + PARSE_JSON('{ + "message": "ConfigMap updated", + "object_type": "ConfigMap", + "name": "app-config", + "namespace": "default", + "change": "data update" + }'), + '2024-04-08T11:45:00Z'); + +INSERT INTO k8s_logs (event_id, event_data, event_timestamp) +VALUES + (5, + PARSE_JSON('{ + "message": "PersistentVolume claim created", + "object_type": "PVC", + "name": "storage-claim", + "namespace": "storage", + "status": "Bound", + "volume": "pv-logs" + }'), + '2024-04-08T12:00:00Z'); + +-- Basic search for events containing "PersistentVolume" +SELECT + event_id, + event_message +FROM + k8s_logs +WHERE + MATCH(event_message, 'PersistentVolume'); + +-[ RECORD 1 ]----------------------------------- + event_id: 5 +event_message: PersistentVolume claim created + +-- Verify index usage with EXPLAIN +EXPLAIN SELECT event_id, event_message FROM k8s_logs WHERE MATCH(event_message, 'PersistentVolume'); + +-[ EXPLAIN ]----------------------------------- +Filter +├── output columns: [k8s_logs.event_id (#0), k8s_logs.event_message (#3)] +├── filters: [k8s_logs._search_matched (#4)] +├── estimated rows: 5.00 +└── TableScan + ├── table: default.default.k8s_logs + ├── output columns: [event_id (#0), event_message (#3), _search_matched (#4)] + ├── read rows: 1 + ├── read size: < 1 KiB + ├── partitions total: 5 + ├── partitions scanned: 1 + ├── pruning stats: [segments: , blocks: ] + ├── push downs: [filters: [k8s_logs._search_matched (#4)], limit: NONE] + └── estimated rows: 5.00 + +-- Advanced search with relevance scoring +SELECT + event_id, + event_message, + event_timestamp, + SCORE() +FROM + k8s_logs +WHERE + SCORE() > 0.5 + AND QUERY('event_message:"PersistentVolume claim created"'); + +-[ RECORD 1 ]----------------------------------- + event_id: 5 + event_message: PersistentVolume claim created +event_timestamp: 2024-04-08 12:00:00 + score(): 0.86304635 + +-- Fuzzy search example (handles typos) +SELECT + event_id, event_message, event_timestamp +FROM + k8s_logs +WHERE + match('event_message', 'PersistentVolume claim create', 'fuzziness=1'); + +-[ RECORD 1 ]----------------------------------- + event_id: 5 + event_message: PersistentVolume claim created +event_timestamp: 2024-04-08 12:00:00 +``` + +**示例要点:** + +- `inverted pruning: 5 to 1` 表示索引将扫描的块数从 5 个减少到 1 个 +- 相关性评分有助于根据匹配质量对结果进行排序 +- 模糊搜索即使在存在拼写错误时也能找到结果(`create` 与 `created`) + +## 最佳实践 {#best-practices} + +| 做法 | 好处 | +|----------|---------| +| **为经常搜索的列建立索引** | 为搜索查询中常用的列建立索引 | +| **使用 MATCH 代替 LIKE** | 利用索引自动带来的性能优势 | +| **监控索引使用情况** | 使用 EXPLAIN 验证索引是否被使用 | +| **考虑多个索引** | 不同列可以分别拥有独立的索引 | + +## 关键命令 {#essential-commands} + +| 命令 | 用途 | 何时使用 | +|---------|---------|-------------| +| `CREATE INVERTED INDEX name ON table(column)` | 创建新的全文索引 | 初始设置时使用 - 对新数据自动生效 | +| `REFRESH INVERTED INDEX name ON table` | 为现有数据建立索引 | 仅对索引创建前已存在的数据执行一次 | +| `DROP INVERTED INDEX name ON table` | 删除索引 | 当不再需要该索引时使用 | + +## 重要说明 {#important-notes} + +**适合使用全文索引的场景:** + +- 大型文本数据集(文档、日志、评论) +- 频繁执行文本搜索操作 +- 需要高级搜索功能(模糊搜索、评分) +- 对性能要求较高的搜索应用 + +**不适合使用的场景:** + +- 小型文本数据集 +- 仅需要精确字符串匹配 +- 很少执行搜索操作 + +## 索引限制 {#index-limitations} + +- 每一列只能属于一个倒排索引 +- 在数据插入后需要刷新索引(如果数据在索引创建前已存在) +- 索引数据会占用额外的存储空间 + +--- + +*全文索引对于需要在大型文档集合上实现快速、复杂文本搜索能力的应用至关重要。* diff --git a/tidb-cloud-lake/guides/geo-analytics.md b/tidb-cloud-lake/guides/geo-analytics.md new file mode 100644 index 0000000000000..2eeba31b4f28f --- /dev/null +++ b/tidb-cloud-lake/guides/geo-analytics.md @@ -0,0 +1,254 @@ +--- +title: 地理空间分析 +summary: CityDrive 会为每个已标记帧记录精确的 GPS 位置以及到信号源的距离。这些地理空间数据来自行车记录仪的 GPS 模块,并与视频关键帧的时间戳精确对齐。运维团队仅通过 SQL 就能回答“这件事发生在哪里?”。 +--- + +# 地理空间分析 + +> **场景:** CityDrive 会为每个已标记帧记录精确的 GPS 位置以及到信号源的距离。这些地理空间数据来自行车记录仪的 GPS 模块,并与视频关键帧的时间戳精确对齐。运维团队仅通过 SQL 就能回答“这件事发生在哪里?”。 + +`frame_geo_points` 和 `signal_contact_points` 与本指南其余部分使用相同的 `video_id`/`frame_id` 键,因此你可以直接从 SQL 指标切换到地图,而无需复制数据。 + +## 1. 创建位置表 {#1-create-location-tables} + +如果你已经完成 JSON 指南中的步骤,这些表已经存在。下面的代码片段展示了它们的结构以及一些深圳样例数据。 + +```sql +CREATE OR REPLACE TABLE frame_geo_points ( + video_id STRING, + frame_id STRING, + position_wgs84 GEOMETRY, + solution_grade INT, + source_system STRING, + created_at TIMESTAMP +); + +INSERT INTO frame_geo_points VALUES + ('VID-20250101-001','FRAME-0101',TO_GEOMETRY('SRID=4326;POINT(114.0579123456789 22.543123456789)'),104,'fusion_gnss','2025-01-01 08:15:21'), + ('VID-20250101-001','FRAME-0102',TO_GEOMETRY('SRID=4326;POINT(114.0610987654321 22.546098765432)'),104,'fusion_gnss','2025-01-01 08:33:54'), + ('VID-20250101-002','FRAME-0201',TO_GEOMETRY('SRID=4326;POINT(114.104012345678 22.559456789012)'),104,'fusion_gnss','2025-01-01 11:12:02'), + ('VID-20250102-001','FRAME-0301',TO_GEOMETRY('SRID=4326;POINT(114.082265432109 22.53687654321)'),104,'fusion_gnss','2025-01-02 09:44:18'), + ('VID-20250103-001','FRAME-0401',TO_GEOMETRY('SRID=4326;POINT(114.119501234567 22.544365432101)'),104,'fusion_gnss','2025-01-03 21:18:07'); + +CREATE OR REPLACE TABLE signal_contact_points ( + node_id STRING, + signal_position GEOMETRY, + video_id STRING, + frame_id STRING, + frame_position GEOMETRY, + distance_m DOUBLE, + created_at TIMESTAMP +); + +INSERT INTO signal_contact_points VALUES + ('SIG-0001', TO_GEOMETRY('SRID=4326;POINT(114.058500123456 22.543800654321)'), 'VID-20250101-001', 'FRAME-0101', TO_GEOMETRY('SRID=4326;POINT(114.0579123456789 22.543123456789)'), 0.012345, '2025-01-01 08:15:30'), + ('SIG-0002', TO_GEOMETRY('SRID=4326;POINT(114.118900987654 22.544800123456)'), 'VID-20250103-001', 'FRAME-0401', TO_GEOMETRY('SRID=4326;POINT(114.119501234567 22.544365432101)'), 0.008765, '2025-01-03 21:18:20'); + +-- Frames and JSON tables these queries join against (same rows as SQL & Search guides). +CREATE OR REPLACE TABLE frame_events ( + frame_id STRING, + video_id STRING, + frame_index INT, + collected_at TIMESTAMP, + event_tag STRING, + risk_score DOUBLE, + speed_kmh DOUBLE +); + +INSERT INTO frame_events VALUES + ('FRAME-0101', 'VID-20250101-001', 125, '2025-01-01 08:15:21', 'hard_brake', 0.81, 32.4), + ('FRAME-0102', 'VID-20250101-001', 416, '2025-01-01 08:33:54', 'pedestrian', 0.67, 24.8), + ('FRAME-0201', 'VID-20250101-002', 298, '2025-01-01 11:12:02', 'lane_merge', 0.74, 48.1), + ('FRAME-0301', 'VID-20250102-001', 188, '2025-01-02 09:44:18', 'hard_brake', 0.59, 52.6), + ('FRAME-0401', 'VID-20250103-001', 522, '2025-01-03 21:18:07', 'night_lowlight', 0.63, 38.9), + ('FRAME-0501', 'VID-MISSING-001', 10, '2025-01-04 10:00:00', 'sensor_fault', 0.25, 15.0); + +CREATE OR REPLACE TABLE frame_metadata_catalog ( + doc_id STRING, + meta_json VARIANT, + captured_at TIMESTAMP, + INVERTED INDEX idx_meta_json (meta_json) +); + +INSERT INTO frame_metadata_catalog VALUES + ('FRAME-0101', PARSE_JSON('{"scene":{"weather_code":"rain","lighting":"day"},"camera":{"sensor_view":"roof"},"vehicle":{"speed_kmh":32.4},"detections":{"objects":[{"type":"vehicle","confidence":0.88},{"type":"brake_light","confidence":0.64}]},"media_meta":{"tagging":{"labels":["hard_brake","rain","downtown_loop"]}}}'), '2025-01-01 08:15:21'), + ('FRAME-0102', PARSE_JSON('{"scene":{"weather_code":"rain","lighting":"day"},"camera":{"sensor_view":"roof"},"vehicle":{"speed_kmh":24.8},"detections":{"objects":[{"type":"pedestrian","confidence":0.92},{"type":"bike","confidence":0.35}]},"media_meta":{"tagging":{"labels":["pedestrian","swerve","crosswalk"]}}}'), '2025-01-01 08:33:54'), + ('FRAME-0201', PARSE_JSON('{"scene":{"weather_code":"overcast","lighting":"day"},"camera":{"sensor_view":"front"},"vehicle":{"speed_kmh":48.1},"detections":{"objects":[{"type":"lane_merge","confidence":0.74},{"type":"vehicle","confidence":0.41}]},"media_meta":{"tagging":{"labels":["lane_merge","urban"]}}}'), '2025-01-01 11:12:02'), + ('FRAME-0301', PARSE_JSON('{"scene":{"weather_code":"clear","lighting":"day"},"camera":{"sensor_view":"front"},"vehicle":{"speed_kmh":52.6},"detections":{"objects":[{"type":"vehicle","confidence":0.82},{"type":"hard_brake","confidence":0.59}]},"media_meta":{"tagging":{"labels":["hard_brake","highway"]}}}'), '2025-01-02 09:44:18'), + ('FRAME-0401', PARSE_JSON('{"scene":{"weather_code":"lightfog","lighting":"night"},"camera":{"sensor_view":"rear"},"vehicle":{"speed_kmh":38.9},"detections":{"objects":[{"type":"traffic_light","confidence":0.78},{"type":"vehicle","confidence":0.36}]},"media_meta":{"tagging":{"labels":["night_lowlight","traffic_light"]}}}'), '2025-01-03 21:18:07'); +``` + +文档:[地理空间类型](/tidb-cloud-lake/sql/geospatial.md)。 + +--- + +## 2. 空间过滤 {#2-spatial-filters} + +你可以测量每个帧与市中心某个关键坐标点之间的距离,或者检查它是否落在某个多边形内部。当你需要米级距离时,请转换为 SRID 3857。 + +```sql +SELECT l.frame_id, + l.video_id, + f.event_tag, + ST_DISTANCE( + ST_TRANSFORM(l.position_wgs84, 3857), + ST_TRANSFORM(TO_GEOMETRY('SRID=4326;POINT(114.0600 22.5450)'), 3857) + ) AS meters_from_hq +FROM frame_geo_points AS l +JOIN frame_events AS f USING (frame_id) +WHERE ST_DISTANCE( + ST_TRANSFORM(l.position_wgs84, 3857), + ST_TRANSFORM(TO_GEOMETRY('SRID=4326;POINT(114.0600 22.5450)'), 3857) + ) <= 400 +ORDER BY meters_from_hq; +``` + +示例输出: + +``` +frame_id | video_id | event_tag | meters_from_hq +FRAME-0102| VID-20250101-001 | pedestrian | 180.277138577 +FRAME-0101| VID-20250101-001 | hard_brake | 324.291965923 +``` + +提示:调试时可以添加 `ST_ASTEXT(l.geom)`,或者切换到 [`HAVERSINE`](/tidb-cloud-lake/sql/geospatial-functions.md#distance--measurements) 来进行大圆距离计算。 + +```sql +WITH school_zone AS ( + SELECT TO_GEOMETRY('SRID=4326;POLYGON(( + 114.0505 22.5500, + 114.0630 22.5500, + 114.0630 22.5420, + 114.0505 22.5420, + 114.0505 22.5500 + ))') AS poly +) +SELECT l.frame_id, + l.video_id, + f.event_tag +FROM frame_geo_points AS l +JOIN frame_events AS f USING (frame_id) +CROSS JOIN school_zone +WHERE ST_CONTAINS(poly, l.position_wgs84); +``` + +示例输出: + +``` +frame_id | video_id | event_tag +FRAME-0101| VID-20250101-001 | hard_brake +FRAME-0102| VID-20250101-001 | pedestrian +``` + +--- + +## 3. 六边形聚合 {#3-hex-aggregations} + +将高风险帧聚合到六边形存储桶中,以便用于仪表板展示。 + +```sql +SELECT GEO_TO_H3(ST_X(position_wgs84), ST_Y(position_wgs84), 8) AS h3_cell, + COUNT(*) AS frame_count, + AVG(f.risk_score) AS avg_risk +FROM frame_geo_points AS l +JOIN frame_events AS f USING (frame_id) +GROUP BY h3_cell +ORDER BY avg_risk DESC; +``` + +示例输出: + +``` +h3_cell | frame_count | avg_risk +613635011200942079| 1 | 0.81 +613635011532292095| 1 | 0.74 +613635011238690815| 1 | 0.67 +613635015391051775| 1 | 0.63 +613635011309993983| 1 | 0.59 +``` + +文档:[H3 函数](/tidb-cloud-lake/sql/geospatial-functions.md#h3-indexing--conversion)。 + +--- + +## 4. 交通上下文 {#4-traffic-context} + +将 `signal_contact_points` 与 `frame_geo_points` 进行关联,以验证已存储的指标,或将空间谓词与 JSON 搜索结合使用。 + +```sql +SELECT t.node_id, + t.video_id, + t.frame_id, + ST_DISTANCE(t.signal_position, t.frame_position) AS recomputed_distance, + t.distance_m AS stored_distance, + l.source_system +FROM signal_contact_points AS t +JOIN frame_geo_points AS l USING (frame_id) +WHERE t.distance_m < 0.03 -- roughly < 30 meters depending on SRID +ORDER BY t.distance_m; +``` + +示例输出: + +``` +node_id | video_id | frame_id | recomputed_distance | stored_distance | source_system +SIG-0002| VID-20250103-001 | FRAME-0401| 0.000741116 | 0.008765 | fusion_gnss +SIG-0001| VID-20250101-001 | FRAME-0101| 0.000896705 | 0.012345 | fusion_gnss +``` + +```sql +WITH near_junction AS ( + SELECT frame_id + FROM frame_geo_points + WHERE ST_DISTANCE( + ST_TRANSFORM(position_wgs84, 3857), + ST_TRANSFORM(TO_GEOMETRY('SRID=4326;POINT(114.0830 22.5370)'), 3857) + ) <= 200 +) +SELECT f.frame_id, + f.event_tag, + meta.meta_json['media_meta']['tagging']['labels'] AS labels +FROM near_junction nj +JOIN frame_events AS f USING (frame_id) +JOIN frame_metadata_catalog AS meta + ON meta.doc_id = nj.frame_id +WHERE QUERY('meta_json.media_meta.tagging.labels:hard_brake'); +``` + +示例输出: + +``` +frame_id | event_tag | labels +FRAME-0301| hard_brake | ["hard_brake","highway"] +``` + +这种模式允许你先按地理位置进行过滤,再对筛选后保留下来的帧应用 JSON 搜索。 + +--- + +## 5. 发布热力图视图 {#5-publish-a-heatmap-view} + +将地理热力图暴露给 BI 或 GIS 工具,而无需重新运行高开销 SQL。 + +```sql +CREATE OR REPLACE VIEW v_citydrive_geo_heatmap AS +SELECT GEO_TO_H3(ST_X(position_wgs84), ST_Y(position_wgs84), 7) AS h3_cell, + COUNT(*) AS frames, + AVG(f.risk_score) AS avg_risk +FROM frame_geo_points AS l +JOIN frame_events AS f USING (frame_id) +GROUP BY h3_cell; +``` + +示例输出: + +``` +h3_cell | frames | avg_risk +609131411584057343| 1 | 0.81 +609131411919601663| 1 | 0.74 +609131411617611775| 1 | 0.67 +609131415778361343| 1 | 0.63 +609131411684720639| 1 | 0.59 +``` + +{{{ .lake }}} 现在可以基于完全相同的 `video_id` 同时提供向量、文本和空间查询,因此调查团队再也不需要在不同的数据处理管道之间进行对账。 \ No newline at end of file diff --git a/tidb-cloud-lake/guides/how-data-sharing-works.md b/tidb-cloud-lake/guides/how-data-sharing-works.md new file mode 100644 index 0000000000000..a17f59320b206 --- /dev/null +++ b/tidb-cloud-lake/guides/how-data-sharing-works.md @@ -0,0 +1,142 @@ +--- +title: TiDB Cloud Lake 数据共享的工作原理 +summary: 不同团队需要同一份数据中的不同部分。传统方案需要多次复制数据——成本高且难以维护。 +--- + +# TiDB Cloud Lake 数据共享的工作原理 + +## 什么是数据共享? {#what-is-data-sharing} + +不同团队需要同一份数据中的不同部分。传统方案需要多次复制数据——成本高且难以维护。 + +{{{ .lake }}} 的 **[ATTACH TABLE](/tidb-cloud-lake/sql/attach-table.md)** 优雅地解决了这个问题:无需复制数据,即可为同一份数据创建多个“视图”。这得益于 {{{ .lake }}} 的 **真正的计算存储分离**——无论使用云存储还是本地对象存储,都能实现:**一次存储,随处访问**。 + +你可以将 ATTACH TABLE 理解为计算机中的快捷方式——它指向原始文件,而不会复制文件本身。 + +``` + Object Storage (S3, MinIO, Azure, etc.) + ┌─────────────┐ + │ Your Data │ + └──────┬──────┘ + │ + ┌───────────────────────┼───────────────────────┐ + │ │ │ + ▼ ▼ ▼ +┌─────────────┐ ┌─────────────┐ ┌─────────────┐ +│ Marketing │ │ Finance │ │ Sales │ +│ Team View │ │ Team View │ │ Team View │ +└─────────────┘ └─────────────┘ └─────────────┘ +``` + +## 如何使用 ATTACH TABLE {#how-to-use-attach-table} + +**步骤 1:找到你的数据位置** + +```sql +SELECT snapshot_location FROM FUSE_SNAPSHOT('default', 'company_sales'); +-- Result: 1/23351/_ss/... → Data at s3://your-bucket/1/23351/ +``` + +**步骤 2:创建团队专属视图** + +```sql +-- Marketing: Customer behavior analysis +ATTACH TABLE marketing_view (customer_id, product, amount, order_date) +'s3://your-bucket/1/23351/' CONNECTION = (ACCESS_KEY_ID = 'xxx', SECRET_ACCESS_KEY = 'yyy'); + +-- Finance: Revenue tracking +ATTACH TABLE finance_view (order_id, amount, profit, order_date) +'s3://your-bucket/1/23351/' CONNECTION = (ACCESS_KEY_ID = 'xxx', SECRET_ACCESS_KEY = 'yyy'); + +-- HR: Employee info without salaries +ATTACH TABLE hr_employees (employee_id, name, department) +'s3://data/1/23351/' CONNECTION = (...); + +-- Development: Production structure without sensitive data +ATTACH TABLE dev_customers (customer_id, country, created_date) +'s3://data/1/23351/' CONNECTION = (...); +``` + +**步骤 3:独立查询** + +```sql +-- Marketing analyzes trends +SELECT product, COUNT(*) FROM marketing_view GROUP BY product; + +-- Finance tracks profit +SELECT order_date, SUM(profit) FROM finance_view GROUP BY order_date; +``` + +## 主要优势 {#key-benefits} + +**实时修改**:当源数据发生变化时,所有附加表都会立即看到这些变化 + +```sql +INSERT INTO company_sales VALUES (1001, 501, 'Laptop', 1299.99, 299.99, 'user@email.com', '2025-01-20'); +SELECT COUNT(*) FROM marketing_view WHERE order_date = '2024-01-20'; -- Returns: 1 +``` + +**列级安全性**:团队只能看到自己需要的数据——Marketing 看不到 profit,Finance 看不到客户邮箱 + +**强一致性**:绝不会读到部分修改,始终看到完整快照——非常适合财务报表和合规场景 + +**完整性能**:所有索引都会自动生效,速度与普通表相同 + +## 为什么这很重要 {#why-this-matters} + +| 传统方式 | {{{ .lake }}} ATTACH TABLE | +|---------------------|----------------------| +| 多份数据副本 | 所有人共享单一副本 | +| ETL 延迟、同步问题 | 实时,始终最新 | +| 维护复杂 | 零维护 | +| 副本越多,安全风险越高 | 细粒度列访问 | +| 因数据移动而变慢 | 在原始数据上完整优化 | + +## 底层工作原理 {#how-it-works-under-the-hood} + +``` +Query: SELECT product, SUM(amount) FROM marketing_view GROUP BY product + +┌─────────────────────────────────────────────────────────────────┐ +│ Query Execution Flow │ +└─────────────────────────────────────────────────────────────────┘ + + User Query + │ + ▼ +┌───────────────────┐ ┌─────────────────────────────────────┐ +│ 1. Read Snapshot │───►│ s3://bucket/1/23351/_ss/ │ +│ Metadata │ │ Get current table state │ +└───────────────────┘ └─────────────────────────────────────┘ + │ + ▼ +┌───────────────────┐ ┌─────────────────────────────────────┐ +│ 2. Apply Column │───►│ Filter: customer_id, product, │ +│ Filter │ │ amount, order_date │ +└───────────────────┘ └─────────────────────────────────────┘ + │ + ▼ +┌───────────────────┐ ┌─────────────────────────────────────┐ +│ 3. Check Stats & │───►│ • Segment min/max values │ +│ Indexes │ │ • Bloom filters │ +└───────────────────┘ │ • Aggregate indexes │ + │ └─────────────────────────────────────┘ + ▼ +┌───────────────────┐ ┌─────────────────────────────────────┐ +│ 4. Smart Data │───►│ Skip irrelevant blocks │ +│ Fetching │ │ Download only needed data from _b/ │ +└───────────────────┘ └─────────────────────────────────────┘ + │ + ▼ +┌───────────────────┐ ┌─────────────────────────────────────┐ +│ 5. Local │───►│ Full optimization & parallelism │ +│ Execution │ │ Process with all available indexes │ +└───────────────────┘ └─────────────────────────────────────┘ + │ + ▼ + Results: Product sales summary +``` + +多个 {{{ .lake }}} 集群可以同时执行这一流程而无需协调——这正是真正的计算存储分离在发挥作用。 + +ATTACH TABLE 代表了一种根本性的转变:**从为每种使用场景复制数据,转变为一份数据配合多个视图**。无论是在云环境还是本地环境中,{{{ .lake }}} 的架构都能在保持企业级一致性和安全性的同时,实现强大而高效的数据共享。 \ No newline at end of file diff --git a/tidb-cloud-lake/guides/how-fuse-engine-works.md b/tidb-cloud-lake/guides/how-fuse-engine-works.md new file mode 100644 index 0000000000000..b98777243045b --- /dev/null +++ b/tidb-cloud-lake/guides/how-fuse-engine-works.md @@ -0,0 +1,227 @@ +--- +title: Fuse Engine 的工作原理 +summary: Fuse Engine 是 {{{ .lake }}} 的核心存储引擎,经过优化,可在云对象存储上高效管理 PB 级数据。默认情况下,在 {{{ .lake }}} 中创建的表会自动使用该引擎(ENGINE=FUSE)。其设计灵感来自 Git,基于快照的设计支持强大的数据版本管理功能(如 Time Travel),并通过高级裁剪和索引提供高查询性能。 +--- + +# Fuse Engine 的工作原理 + +## Fuse Engine {#fuse-engine} + +Fuse Engine 是 {{{ .lake }}} 的核心存储引擎,经过优化,可在**云对象存储**上高效管理 **PB 级**数据。默认情况下,在 {{{ .lake }}} 中创建的表会自动使用该引擎(`ENGINE=FUSE`)。其设计灵感来自 Git,基于快照的设计支持强大的数据版本管理功能(如 Time Travel),并通过高级裁剪和索引提供**高查询性能**。 + +本文将介绍它的核心概念及其工作原理。 + +## 核心概念 {#core-concepts} + +Fuse Engine 使用三种核心结构来组织数据,这与 Git 的方式类似: + +* **Snapshots(类似 Git Commits):** 不可变引用,通过指向特定的 Segments 来定义表在某一时刻的状态。支持 Time Travel。 +* **Segments(类似 Git Trees):** 由多个 Blocks 组成的集合,并带有用于快速跳过数据(裁剪)的汇总统计信息。可在多个 Snapshots 之间共享。 +* **Blocks(类似 Git Blobs):** 不可变数据文件(Parquet 格式),保存实际的行数据以及详细的列级统计信息,用于细粒度裁剪。 + +``` + Table HEAD + │ + ▼ + ┌───────────────┐ ┌───────────────┐ ┌───────────────┐ + │ SEGMENT A │◄────│ SNAPSHOT 2 │────►│ SEGMENT B │ + │ │ │ Previous: │ │ │ + └───────┬───────┘ │ SNAPSHOT 1 │ └───────┬───────┘ + │ └───────────────┘ │ + │ │ │ + │ ▼ │ + │ ┌───────────────┐ │ + │ │ SNAPSHOT 1 │ │ + │ │ │ │ + │ └───────────────┘ │ + │ │ + ▼ ▼ + ┌───────────────┐ ┌───────────────┐ + │ BLOCK 1 │ │ BLOCK 2 │ + │ (cloud.txt) │ │(warehouse.txt)│ + └───────────────┘ └───────────────┘ +``` + +## 写入如何工作 {#how-writing-works} + +当你向表中添加数据时,Fuse Engine 会创建一条对象链。下面我们分步骤来看这个过程: + +### 第 1 步:创建表 {#step-1-create-a-table} + +```sql +CREATE TABLE git(file VARCHAR, content VARCHAR); +``` + +此时,表已经存在,但还不包含任何数据: + +``` +(Empty table with no data) +``` + +### 第 2 步:插入第一条数据 {#step-2-insert-first-data} + +```sql +INSERT INTO git VALUES('cloud.txt', '2022/05/06, Datalake, Cloud'); +``` + +第一次插入后,Fuse Engine 会创建初始的 snapshot、segment 和 block: + +``` + Table HEAD + │ + ▼ + ┌───────────────┐ + │ SNAPSHOT 1 │ + │ │ + └───────┬───────┘ + │ + ▼ + ┌───────────────┐ + │ SEGMENT A │ + │ │ + └───────┬───────┘ + │ + ▼ + ┌───────────────┐ + │ BLOCK 1 │ + │ (cloud.txt) │ + └───────────────┘ +``` + +### 第 3 步:插入更多数据 {#step-3-insert-more-data} + +```sql +INSERT INTO git VALUES('warehouse.txt', '2022/05/07, Datalake, Warehouse'); +``` + +当插入更多数据时,Fuse Engine 会创建一个新的 snapshot,它同时引用原有的 segment 和一个新的 segment: + +``` + Table HEAD + │ + ▼ + ┌───────────────┐ ┌───────────────┐ ┌───────────────┐ + │ SEGMENT A │◄────│ SNAPSHOT 2 │────►│ SEGMENT B │ + │ │ │ Previous: │ │ │ + └───────┬───────┘ │ SNAPSHOT 1 │ └───────┬───────┘ + │ └───────────────┘ │ + │ │ │ + │ ▼ │ + │ ┌───────────────┐ │ + │ │ SNAPSHOT 1 │ │ + │ │ │ │ + │ └───────────────┘ │ + │ │ + ▼ ▼ + ┌───────────────┐ ┌───────────────┐ + │ BLOCK 1 │ │ BLOCK 2 │ + │ (cloud.txt) │ │(warehouse.txt)│ + └───────────────┘ └───────────────┘ +``` + +## 读取如何工作 {#how-reading-works} + +当你查询数据时,Fuse Engine 会使用智能裁剪来高效定位所需数据: + +``` +Query: SELECT * FROM git WHERE file = 'cloud.txt'; + + Table HEAD + │ + ▼ + ┌───────────────┐ ┌───────────────┐ ┌───────────────┐ + │ SEGMENT A │◄────│ SNAPSHOT 2 │────►│ SEGMENT B │ + │ CHECK │ │ │ │ CHECK │ + └───────┬───────┘ └───────────────┘ └───────────────┘ + │ ✗ + │ (Skip - doesn't contain + │ 'cloud.txt') + ▼ + ┌───────────────┐ + │ BLOCK 1 │ + │ CHECK │ + └───────┬───────┘ + │ + │ ✓ (Contains 'cloud.txt') + ▼ + Read this block +``` + +### 智能裁剪过程 {#smart-pruning-process} + +``` +┌─────────────────────────────────────────┐ +│ Query: WHERE file = 'cloud.txt' │ +└─────────────────┬───────────────────────┘ + │ + ▼ +┌─────────────────────────────────────────┐ +│ Check SEGMENT A │ +│ Min file value: 'cloud.txt' │ +│ Max file value: 'cloud.txt' │ +│ │ +│ Result: ✓ Might contain 'cloud.txt' │ +└─────────────────┬───────────────────────┘ + │ + ▼ +┌─────────────────────────────────────────┐ +│ Check SEGMENT B │ +│ Min file value: 'warehouse.txt' │ +│ Max file value: 'warehouse.txt' │ +│ │ +│ Result: ✗ Cannot contain 'cloud.txt' │ +└─────────────────┬───────────────────────┘ + │ + ▼ +┌─────────────────────────────────────────┐ +│ Check BLOCK 1 in SEGMENT A │ +│ Min file value: 'cloud.txt' │ +│ Max file value: 'cloud.txt' │ +│ │ +│ Result: ✓ Contains 'cloud.txt' │ +└─────────────────┬───────────────────────┘ + │ + ▼ +┌─────────────────────────────────────────┐ +│ Read only BLOCK 1 │ +└─────────────────────────────────────────┘ +``` + +## 基于快照的功能 {#snapshot-based-features} + +Fuse Engine 的快照架构支持强大的数据管理能力: + +### Time Travel {#time-travel} + +查询任意时间点的数据状态。支持数据分支、打标签和治理,并提供完整的审计跟踪与错误恢复能力。 + +### 零拷贝 Schema Evolution {#zero-copy-schema-evolution} + +在**不重写任何底层数据文件**的情况下,修改表结构(添加列、删除列、重命名、修改类型)。 + +- 这些变更都是仅修改元信息的操作,并记录在新的快照中。 +- 该过程是即时的,无需停机,并且避免了高成本的数据迁移任务。旧数据仍可使用其原始 schema 进行访问。 + +## 用于查询加速的高级索引(Fuse Engine) {#advanced-indexing-for-query-acceleration-fuse-engine} + +除了基于统计信息的基本 block/segment pruning 之外,Fuse Engine 还提供了专用的二级索引,以进一步加速特定的查询模式: + +| 索引类型 | 简要描述 | 可加速的查询类似... | 示例查询片段 | +| :------------------ | :-------------------------------------------------------- | :-------------------------------------------------- | :-------------------------------------- | +| **聚合索引** | 为指定分组预计算聚合结果 | 更快的 `COUNT`、`SUM`、`AVG`... + `GROUP BY` | `SELECT COUNT(*)... GROUP BY city` | +| **全文索引** | 用于文本内快速关键字搜索的倒排索引 | 使用 `MATCH` 的文本搜索(例如日志) | `WHERE MATCH(log_entry, 'error')` | +| **JSON 索引** | 为 JSON 文档中的特定路径/键建立索引 | 按特定 JSON 路径/值进行过滤 | `WHERE event_data:user.id = 123` | +| **布隆过滤器索引** | 使用概率性检查快速跳过不匹配的 block | 快速点查询(`=`)和 `IN` 列表过滤 | `WHERE user_id = 'xyz'` | + +## 对比:{{{ .lake }}} Fuse Engine 与 Apache Iceberg {#comparison-lake-fuse-engine-vs-apache-iceberg} + +_**注意:** 此对比专门聚焦于**表格式特性**。作为 {{{ .lake }}} 的原生表格式,Fuse 会持续演进,以提升**易用性和性能**。表中展示的是当前特性;后续可能会发生变化。_ + +| 功能 | Apache Iceberg | {{{ .lake }}} Fuse Engine | +| :---------------------- | :--------------------------------- | :----------------------------------- | +| **元信息结构** | Manifest Lists -> Manifest Files -> Data Files | **快照** -> Segments -> Blocks | +| **统计级别** | 文件级(+Partition) | **多级别**(快照、Segment、Block)→ 更精细的 pruning | +| **裁剪能力** | 良好(文件/Partition 统计信息) | **优秀**(多级统计信息 + 二级索引) | +| **Schema Evolution** | 支持(元信息变更) | **零拷贝**(仅元信息,即时) | +| **数据聚簇** | 排序(写入时) | **自动**优化(后台) | +| **流式支持** | 基础流式摄取 | **高级增量**(Insert/Update 跟踪) | \ No newline at end of file diff --git a/tidb-cloud-lake/guides/how-json-variant-works.md b/tidb-cloud-lake/guides/how-json-variant-works.md new file mode 100644 index 0000000000000..16831954cecfc --- /dev/null +++ b/tidb-cloud-lake/guides/how-json-variant-works.md @@ -0,0 +1,193 @@ +--- +title: TiDB Cloud Lake JSON(Variant)的工作原理 +summary: TiDB Cloud Lake 通过将原生二进制布局与自动 JSON 索引相结合,重新定义了 JSON 分析,使半结构化数据能够像一等列一样工作。 +--- + +# TiDB Cloud Lake JSON(Variant)的工作原理 + +另请参阅: + +- [Variant 数据类型](/tidb-cloud-lake/sql/variant.md) +- [半结构化函数](/tidb-cloud-lake/guides/load-semi-structured-data.md) + +{{{ .lake }}} 通过将原生二进制布局与自动 JSON 索引相结合,重新定义了 JSON 分析,使半结构化数据能够像一等列一样工作。 + +## 为什么 Variant 很重要 {#why-variant-matters} + +{{{ .lake }}} 在保持 JSON 灵活性的同时提供 MPP 速度:你可以按原样导入文档,使用熟悉的 SQL 进行查询,而引擎会在幕后将性能相关的工作串联起来。之所以能够做到这一点,依赖于两个支柱: + +- 紧凑的 **JSONB** 布局让执行引擎能够感知类型。 +- 自动 **virtual columns**——{{{ .lake }}} 的 JSON 索引——无需手动操作即可暴露热点路径。 + +从存储到查询,本文档其余部分将说明这两个理念如何将原始 JSON 负载(例如 `orders.data`)转换为经过优化的类型化列。 + +## JSON 存储布局 {#json-storage-layout} + +{{{ .lake }}} 以 JSONB 格式存储 Variant 值,这是一种针对分析场景优化的二进制格式。实际效果包括: + +- **类型化存储** – 数字、布尔值、时间戳和 decimal 会保持原生类型,因此比较操作能够保持二进制安全。 +- **可预测的布局** – 字段带有长度前缀和规范化的键顺序,从而消除重复解析的开销。 +- **零拷贝访问** – 操作符在扫描和排序期间直接读取 JSONB 缓冲区,而不是重新构建 JSON 文本。 + +每个 Variant 列都会保留原始 JSONB 文档以确保保真度。当像 `data['user']['id']` 这样的路径反复出现时,{{{ .lake }}} 会将它们收纳到类型化的 sidecar 列中,以便进行下推的处理。 + +## 自动生成 JSON 索引 {#automatic-json-index-generation} + +当新数据进入 {{{ .lake }}} 时,一个轻量级索引流水线会立即扫描 JSON block,以发现值得物化为 virtual columns 的热点路径——也就是 {{{ .lake }}} 内置的 JSON 索引。 + +### 导入流程 {#ingestion-flow} + +{{{ .lake }}} 会检查传入批次,并将重复出现的访问模式转换为类型化列: + +``` +┌───────────────────────────────────────────────┐ +│ Variant Ingestion Flow │ +├──────────────┬────────────────────────────────┤ +│ Sample Rows │ Peek at the first rows in block │ +│ Detect Paths │ Keep stable leaf key paths │ +│ Infer Types │ Pick native column types │ +│ Materialize │ Write values to virtual Parquet │ +│ Register │ Attach metadata to base column │ +└──────────────┴────────────────────────────────┘ +``` + +### 轻量化设计 {#lightweight-by-design} + +该流水线依赖少量轻量级启发式规则: + +``` +┌─────────────────────────────┬──────────────────────────────────────────────┐ +│ Step │ Heuristic │ +├─────────────────────────────┼──────────────────────────────────────────────┤ +│ Sampling │ Inspect only the first 10 rows of each block │ +│ Null & non-leaf filtering │ Skip paths dominated by NULL or pointing to │ +│ │ objects/arrays │ +│ Stability check │ Promote only leaf paths that stay consistent │ +│ │ across the sample (max 1,000 per block) │ +│ Deduplication │ Use hashing to avoid analysing the same path │ +│ │ repeatedly │ +│ Fallback │ Keep the original JSONB document when no │ +│ │ candidate survives │ +└─────────────────────────────┴──────────────────────────────────────────────┘ +``` + +结果是:你只需加载一次 JSON,重复出现的模式就会悄然转换为经过优化的类型化列,无需 DDL,也无需调优。 + +### Virtual columns 就是自动 JSON 索引 {#virtual-columns-are-automatic-json-indexes} + +在这里,“virtual column” 本质上就是 **{{{ .lake }}} 的 JSON 索引**。导入流程会判断诸如 `data['items'][0]['price']` 这样的路径是否足够稳定,推导原生类型,并将这些值连同元信息一起写入列式 sidecar——无需 DDL,也无需任何参数调节。嵌套 JSON 仍然以紧凑的 JSONB 形式保留,而原语路径则会变成原生数字、字符串或布尔值。 + +``` +Raw JSON block ──(auto sampling)──▶ Candidate paths ──(stable?)──▶ JSON index +``` + +与构建单独的 B-tree 不同,{{{ .lake }}} 会将某个 JSON 路径的值快照到列式结构中: + +``` +JSON Path ───────────▶ Virtual Column (typed values + stats + location) +``` + +在查询期间,规划器可以像命中索引一样直接跳转到这些预提取的值;如果索引项缺失,仍然可以回退到完整 JSON。 + +### JSON 索引元信息 {#json-index-metadata} + +与每个 block 一起存储的元信息会汇总这些额外列: + +``` +┌────────────────────────────┬───────────────────────┐ +│ Virtual Column Metadata │ Example │ +├────────────────────────────┼───────────────────────┤ +│ Column Id & JSON Path │ v123 -> ['user']['id'] │ +│ Type Code │ UInt64 / String │ +│ Byte Offset & Length │ Where values live │ +│ Row Count │ Matches base block │ +│ Statistics │ Min / Max / NDV │ +└────────────────────────────┴───────────────────────┘ +``` + +写入器会将这些细节打包进表快照,并将 sidecar 与主 block 一起存储。每个条目都会记录 JSON 路径、原生类型、字节偏移和统计信息,以便 {{{ .lake }}} 在需要时直接跳转到提取后的值——或者回退到原始 JSON。 + +## 使用 JSON 索引执行查询 {#query-execution-with-json-indexes} + +一旦索引存在,读路径就简化为三个快速决策: + +``` +┌──────────────┐ rewrite paths ┌────────────────────┐ +│ SQL Planner │------------------>│ Virtual Column Map │ +└──────┬───────┘ └─────────┬──────────┘ + │ pushdown request │ per-block check + ▼ ▼ +┌──────────────┐ has virtual? ┌────────────────────┐ +│ Fuse Storage │----------------->│ Virtual File Read │ +└──────┬───────┘ │ └─────────┬──────────┘ + │ no └------------------┘ fallback + ▼ +┌──────────────┐ +│ JSONB Reader │ +└──────┬───────┘ + ▼ +┌──────────────┐ +│ Query Output │ +└──────────────┘ +``` + +- 在规划阶段,只要元信息表明索引存在,{{{ .lake }}} 就会将 `get_by_keypath` 之类的调用重写为直接读取 virtual column。 +- 如果 virtual column 存在,存储层就会命中它,并且只读取对应的 Parquet 切片;如果所有请求的路径都已建立索引,甚至可以跳过原始 JSON 列。 +- 否则,它会回退到在 JSONB 列上计算 `get_by_keypath`,从而保持语义不变。 +- 过滤、投影和统计信息都基于原生类型运行,而不是重新解析 JSON 字符串。 + +在幕后,{{{ .lake }}} 会跟踪每个 virtual column 是由哪个 JSON 路径生成的,因此它能够准确判断何时可以跳过原始文档,何时需要重新打开它。 + +## 使用 Variant 数据 {#working-with-variant-data} + +由于索引工作都在幕后自动完成,你可以使用熟悉的语法和函数与 Variant 列交互。 + +### 查看 virtual columns {#inspect-virtual-columns} + +使用 [`SHOW VIRTUAL COLUMNS`](/tidb-cloud-lake/sql/show-virtual-columns.md) 可以列出表中自动生成的 virtual columns,以便在需要时验证 {{{ .lake }}} 已将哪些 JSON 路径物化。 + +### 访问语法 {#access-syntax} + +{{{ .lake }}} 同时支持 Snowflake 风格和 PostgreSQL 风格的选择器;无论你偏好哪种风格,引擎都会通过同一个 key-path 解析器处理它们,并复用 JSON 索引。继续以 `orders` 为例,你可以像下面这样访问嵌套字段: + +```sql title="Snowflake-style examples" +SELECT data['user']['profile']['name'], + data:user:profile.settings.theme, + data['items'][0]['price'] +FROM orders; +``` + +```sql title="PostgreSQL-style examples" +SELECT data->'user'->'profile'->>'name', + data#>>'{user,profile,settings,theme}', + data @> '{"user":{"id":123}}' +FROM orders; +``` + +### 函数亮点 {#function-highlights} + +除了路径访问器之外,{{{ .lake }}} 还提供了丰富的 Variant 工具集: + +- **解析与类型转换**: `parse_json`, `try_parse_json`, `to_variant`, `to_jsonb_binary` +- **导航与投影**: `get_path`, `get_by_keypath`, `flatten`, arrow (`->`, `->>`), path (`#>`, `#>>`) and containment operators (`@>`, `?`) +- **修改**: `object_insert`, `object_remove_keys`, concatenation (`||`), `array_*` helpers +- **分析**: `json_extract_keys`, `json_length`, `jsonb_array_elements`, 以及诸如 `json_array_agg` 之类的聚合函数 + +所有函数都直接在向量化引擎内部的 JSONB 缓冲区上运行。 + +## 性能特征 {#performance-characteristics} + +- 与原始 JSON 扫描相比的内部基准测试结果: + - 单路径查找:**约 3× 更快**,扫描数据量减少 **约 26×**。 + - 多路径投影:**约 1.4× 更快**,读取数据量减少 **约 5.5×**。 + - 谓词下推可与 bloom/inverted indexes 组合使用,以裁剪 block。 +- JSON 结构越稳定,越多路径能够满足索引条件。 + +## {{{ .lake }}} 在 Variant 数据上的优势 {#lake-advantages-for-variant-data} + +- **Snowflake-compatible surface area** – 可以原样迁移现有查询和 UDF。 +- **原生 JSONB 执行** – 类型化编码加上向量化操作符可避免字符串搬运。 +- **自动 JSON 索引** – 采样、元信息和下推让半结构化数据具备结构化数据般的体验。 +- **运维效率** – Virtual block 与常规 Fuse block 共享生命周期工具,使存储和计算保持可预测。 + +借助自动 JSON 索引,{{{ .lake }}} 缩小了灵活文档与高性能分析之间的差距——半结构化数据在你的计算集群中成为一等公民。 \ No newline at end of file diff --git a/tidb-cloud-lake/guides/how-optimizer-works.md b/tidb-cloud-lake/guides/how-optimizer-works.md new file mode 100644 index 0000000000000..5ca6f58ed1529 --- /dev/null +++ b/tidb-cloud-lake/guides/how-optimizer-works.md @@ -0,0 +1,252 @@ +--- +title: TiDB Cloud Lake 优化器如何工作 +summary: "{{{ .lake }}} 的查询优化器会协调一系列转换,将 SQL 文本变为可执行计划。优化器会构建查询的抽象表示,并结合实时统计信息,应用基于规则的重写,探索不同的连接方案,最终选择成本最低的物理运算符。" +--- + +# TiDB Cloud Lake 优化器如何工作 + +{{{ .lake }}} 的查询优化器会协调一系列转换,将 SQL 文本变为可执行计划。优化器会构建查询的抽象表示,并结合实时统计信息,应用基于规则的重写,探索不同的连接方案,最终选择成本最低的物理运算符。 + +同一套优化器流水线支撑分析报表、JSON 搜索、向量检索和地理空间搜索——**{{{ .lake }}} 维护着一个能够理解其存储的所有数据类型的统一优化器。** + +## 是什么让 {{{ .lake }}} 的优化器高效运转 {#what-makes-lake-s-optimizer-tick} + +- 统计信息会自动保持最新:写入数据时,{{{ .lake }}} 会立即维护行数、值范围和 NDV,因此优化器无需任何手动维护,就能使用最新信息进行选择率估算、连接顺序决策和成本计算。 +- 先处理形态,再计算成本:在进行全局搜索之前,这条流水线会先做去相关、谓词/限制下推以及聚合拆分,从而缩小搜索空间,并将更多工作下推到存储层。 +- DP + Cascades 协同工作:DPhpy 用于寻找较优的连接顺序;基于 memo 的 Cascades 阶段则在同一个 SExpr memo 上选择成本最低的物理运算符。 +- 从设计上就感知分布式:规划阶段会决定采用本地执行还是分布式执行,并将广播重写为基于键的 shuffle,以避免热点。 + +## 示例查询 {#example-query} + +我们将使用下面这条分析查询,并展示每个 stage 如何对其进行转换。 + +```sql +WITH recent_orders AS ( + SELECT * + FROM orders + WHERE order_date >= DATE_TRUNC('month', today()) - INTERVAL '3' MONTH + AND fulfillment_status <> 'CANCELLED' +) +SELECT c.region, + COUNT(*) AS order_count, + COUNT(o.id) AS row_count, + COUNT(DISTINCT o.product_id) AS product_count, + MIN(o.total_amount) AS min_amount, + AVG(o.total_amount) AS avg_amount +FROM recent_orders o +JOIN customers c ON o.customer_id = c.id +LEFT JOIN products p ON o.product_id = p.id +WHERE c.status = 'ACTIVE' + AND o.total_amount > 0 + AND p.is_active = TRUE + AND EXISTS ( + SELECT 1 + FROM support_tickets t + WHERE t.customer_id = c.id + AND t.created_at > DATE_TRUNC('month', today()) - INTERVAL '1' MONTH + ) +GROUP BY c.region +HAVING COUNT(*) > 100 +ORDER BY order_count DESC +LIMIT 10; +``` + +## 阶段 1:准备与统计信息 {#phase-1-prep-stats} + +阶段 1 会让查询更易于推理,并为成本计算准备所需的数据。对于我们的示例,优化器会执行以下具体步骤: + +### 1. 展平子查询 {#1-flatten-the-subquery} + +将 `EXISTS (...)` 检查转换为常规连接,这样流水线的其余部分就能看到一棵统一的连接树。 + +``` +# Before (correlated) +customers ─┐ + ├─ JOIN ─ orders +support ───┘ │ + └─ EXISTS (references customers) + +# After (semi-join) +customers ─┐ +support ───┴─ SEMI JOIN ─ orders +``` + +等价 SQL(语义保持不变): + +```sql +FROM ( + SELECT * + FROM orders + WHERE order_date >= DATE_TRUNC('month', today()) - INTERVAL '3' MONTH + AND fulfillment_status <> 'CANCELLED' +) o +JOIN customers c ON o.customer_id = c.id +LEFT JOIN products p ON o.product_id = p.id +JOIN ( + SELECT DISTINCT customer_id + FROM support_tickets + WHERE created_at > DATE_TRUNC('month', today()) - INTERVAL '1' MONTH +) t ON t.customer_id = c.id +``` + +### 2. 检查元信息捷径 {#2-check-metadata-shortcuts} + +如果像 `MIN(o.total_amount)` 这样的聚合没有任何过滤条件,优化器会直接从表统计信息中获取结果,而不是扫描数据: + +``` +-- Conceptual replacement when no filters apply +SELECT MIN(total_amount) +FROM orders + +# becomes + +SELECT table_stats.min_total_amount +``` + +在我们的查询中存在过滤条件,因此仍然保留真实计算。 + +### 3. 附加统计信息 {#3-attach-statistics} + +在规划期间,{{{ .lake }}} 会为被扫描的表收集行数、值范围和去重计数。SQL 本身不会发生变化,但后续的选择率估算和成本估算将保持准确,而无需任何 `ANALYZE` 作业。 + +### 4. 规范化聚合 {#4-normalize-aggregates} + +附加统计信息后,优化器会重写可共享计数器的聚合。`COUNT(o.id)` 会变为 `COUNT(*)`,这样引擎就能为这两种用法维护同一个计数器。只有 SELECT 列表会发生变化: + +```sql +SELECT c.region, + COUNT(*) AS order_count, + COUNT(*) AS row_count, -- was COUNT(o.id) + COUNT(DISTINCT o.product_id) AS product_count, + MIN(o.total_amount) AS min_amount, + AVG(o.total_amount) AS avg_amount +... +``` + +## 阶段 2:细化逻辑计划 {#phase-2-refine-the-logic} + +阶段 2 会执行有针对性的重写,只保留真正需要的工作: + +### 1. 下推过滤条件/限制 {#1-push-filters-limits-down} + +``` +# Before +Filter (o.total_amount > 0) +└─ Scan (recent_orders) + +# After +Scan (recent_orders, pushdown_predicates=[total_amount > 0]) +``` + +带有限制的排序也会进一步收紧: + +``` +# Before +Limit (10) +└─ Sort (order_count DESC) + └─ Join (...) + +# After +Sort (order_count DESC) +└─ Limit (10) + └─ Join (...) +``` + +### 2. 删除冗余 {#2-drop-redundancies} + +``` +# Before +Filter (1 = 1 AND c.status = 'ACTIVE') +└─ ... + +# After +Filter (c.status = 'ACTIVE') +└─ ... +``` + +### 3. 拆分聚合 {#3-split-aggregates} + +``` +# Before +Aggregate (COUNT/AVG) +└─ Scan (recent_orders) + +# After +Aggregate (final) +└─ Aggregate (partial) + └─ Scan (recent_orders) +``` + +部分聚合会尽量靠近数据执行,然后再由一个最终步骤合并结果。 + +### 4. 将过滤条件下推到 CTE 中 {#4-push-filters-into-the-cte} + +只引用 CTE 列的谓词会被下推到 `recent_orders` 的定义内部,从而在连接之前先缩小数据规模: + +```sql +WITH recent_orders AS ( + SELECT * + FROM orders + WHERE order_date >= DATE_TRUNC('month', today()) - INTERVAL '3' MONTH + AND fulfillment_status <> 'CANCELLED' + AND total_amount > 0 -- pushed from outer query +) +``` + +## 阶段 3:成本与物理计划 {#phase-3-cost-physical-plan} + +在拥有整洁的逻辑计划和最新统计信息后,优化器会做出三个决策: + +### 1. 选择连接顺序 {#1-choose-the-join-order} + +由统计信息引导的动态规划程序(`DPhpyOptimizer`)会评估连接排列组合。它倾向于在较小且经过过滤的表(`customers`、`products`、`support_tickets`)上构建哈希表,而让大型事实表(`recent_orders`)对其进行探测: + +``` + customers products + \ / + HASH JOIN (build) + | + recent_orders (probe) + | + SEMI JOIN support_tickets +``` + +### 2. 收紧连接语义 {#2-tighten-join-semantics} + +基于规则的处理阶段会调整上面发现的连接。 + +#### a. 将安全的 LEFT 连接转换为 INNER 连接 {#a-turn-safe-left-joins-into-inner-joins} + +我们的查询以 `LEFT JOIN products p` 开始,但谓词 `p.is_active = TRUE` 保证只保留与 product 匹配的行。优化器会将连接类型改写为: + +``` +# Before +recent_orders ──⊗── products (LEFT) + filter: p.is_active = TRUE + +# After +recent_orders ──⋈── products (INNER) +``` + +#### b. 删除重复谓词 {#b-drop-duplicate-predicates} + +如果某个连接条件重复出现(例如 `o.customer_id = c.id` 被列出两次),`DeduplicateJoinConditionOptimizer` 只保留一份,这样执行器只需计算一次。 + +#### c. 按需交换连接两侧 {#c-optionally-swap-join-sides} + +如果仍然启用了连接重排序,`CommuteJoin` 可以交换连接输入,从而让优化器与期望的 build/probe 方向保持一致(例如,确保较小的表构建哈希表,或匹配某种分布策略): + +``` +# Before # After (smaller table builds) +customers ──⋈── recent_orders recent_orders ──⋈── customers +``` + +### 3. 选择物理计划和分布方式 {#3-pick-the-physical-plan-and-distribution} + +`CascadesOptimizer` 使用 {{{ .lake }}} 的成本模型,在哈希、归并或嵌套循环实现之间进行选择。该流水线还会决定计划是否应保持本地执行;如果有可用的计算集群 (Warehouse) 集群,且连接规模较大,则会将广播交换重写为哈希 shuffle,以便更均匀地分摊工作负载。最后的清理步骤会删除冗余的投影和未使用的 CTE。 + +## 可观测性 {#observability} + +- `EXPLAIN` 显示最终优化后的计划。 +- `EXPLAIN PIPELINE` 展示执行拓扑结构。 +- `SET enable_optimizer_trace = 1` 会在查询日志中记录优化器的每一步。 \ No newline at end of file diff --git a/tidb-cloud-lake/guides/integrate-with-amazon-s3.md b/tidb-cloud-lake/guides/integrate-with-amazon-s3.md new file mode 100644 index 0000000000000..36a80face49c0 --- /dev/null +++ b/tidb-cloud-lake/guides/integrate-with-amazon-s3.md @@ -0,0 +1,136 @@ +--- +title: Amazon S3 集成任务 +summary: Amazon S3 数据集成使你能够将 S3 存储桶中的文件导入到 {{{ .lake }}}。它支持 CSV、Parquet 和 NDJSON 文件格式,并可选择一次性导入或自动轮询新文件的持续摄取。 +--- + +# Amazon S3 集成任务 + +本页介绍如何创建一个 Amazon S3 集成任务,将 S3 存储桶中的文件导入到 {{{ .lake }}}。支持 CSV、Parquet 和 NDJSON 文件格式,并且该任务可配置为一次性导入或持续摄取。 + +如果你需要先创建可复用的 AWS 凭证,请参见 [Amazon S3 - 凭证](/tidb-cloud-lake/guides/aws-credentials.md)。 + +## 支持的文件格式 {#supported-file-formats} + +| 格式 | 描述 | +|---------|--------------------------------------------------------------------| +| CSV | 逗号分隔值,支持可配置的分隔符和表头 | +| Parquet | 列式存储格式,适用于分析型工作负载,效率较高 | +| NDJSON | 按行分隔的 JSON,每行一个 JSON 对象 | + +## 前提条件 {#prerequisites} + +- 已创建 **Amazon S3 - Credentials** 数据源 +- AWS 凭证对目标 S3 存储桶具有读访问权限 +- 如果计划启用 **Clean Up Original Files**,这些凭证还需要写入和删除权限 + +## 创建 S3 集成任务 {#creating-an-s3-integration-task} + +### 步骤 1:基本信息 {#step-1-basic-info} + +1. 进入 **Data** > **Data Integration**,然后点击 **Create Task**。 + +2. 选择一个 S3 数据源,然后配置基本设置: + + | 字段 | 必填 | 描述 | + |--------------------|----------|--------------------------------------------------------------------------------------------------| + | **Data Source** | 是 | 从下拉列表中选择一个已有的 **Amazon S3 - Credentials** 数据源 | + | **Name** | 是 | 此集成任务的名称 | + | **File Path** | 是 | 带可选通配符模式的 S3 URI(例如:`s3://mybucket/data/2025-*.csv`) | + | **File Type** | 自动 | 根据文件扩展名自动检测。支持:CSV、Parquet、NDJSON | + +#### CSV 选项 {#csv-options} + +当文件类型为 CSV 时,可使用以下附加选项: + +| 字段 | 默认值 | 描述 | +|----------------------|---------|----------------------------------------------------------------| +| **Record Delimiter** | `\n` | 行分隔符。可选值:`\n`、`\r`、`\r\n` | +| **Field Delimiter** | `,` | 列分隔符。支持自定义值 | +| **Has Header** | Yes | 第一行是否包含列名。如果禁用,列将自动命名为 `c1`、`c2`、`c3` 等。 | + +#### 文件路径模式 {#file-path-patterns} + +文件路径支持使用通配符模式来匹配多个文件: + +``` +s3://mybucket/data/2025-*.csv # All CSV files starting with "2025-" +s3://mybucket/logs/*.parquet # All Parquet files in the logs directory +s3://mybucket/events/data.ndjson # A single specific file +``` + +### 步骤 2:预览数据 {#step-2-preview-data} + +配置完基本设置后,点击 **Next** 以预览源数据。 + +![S3 Preview Data](/media/tidb-cloud-lake/s3-task-preview-step.png) + +系统会读取第一个匹配的文件并显示: + +- 包含列名和类型的示例数据 +- 匹配文件列表(最多 25 个文件)及其大小 + +> **Note:** +> +> 预览时会跳过大于 10GB 的文件。仅显示前 25 个匹配文件。 + +### 步骤 3:设置目标表 {#step-3-set-target-table} + +在 {{{ .lake }}} 中配置目标位置: + +| 字段 | 描述 | +|---------------------|--------------------------------------------------------------------| +| **Warehouse** | 选择用于运行导入的目标 {{{ .lake }}} 计算集群 (Warehouse) | +| **Target Database** | 选择 {{{ .lake }}} 中的目标数据库 | +| **Target Table** | {{{ .lake }}} 中的表名 | + +![S3 Set Target Table](/media/tidb-cloud-lake/s3-task-set-target-table.png) + +系统会自动从源文件中检测列。你可以在继续之前查看并编辑列名和类型。 + +#### 摄取选项 {#ingestion-options} + +| 选项 | 默认值 | 描述 | +|------------------------------|----------|--------------------------------------------------------------------------------------------------| +| **Continuous Ingestion** | On | 启用后,系统会定期(每 30 秒)轮询 S3 路径并导入新文件 | +| **Error Handling** | Abort | **Abort**:遇到第一个错误时停止。**Continue**:跳过失败的行并继续导入 | +| **Clean Up Original Files** | Off | 启用后,在成功导入后从 S3 删除源文件 | +| **Allow Duplicate Imports** | Off | 启用后,允许重新导入已经导入过的文件 | + +> **Tip:** +> +> 当新文件会定期添加到 S3 路径,并且你希望它们自动加载到 {{{ .lake }}} 时,请启用 **Continuous Ingestion**。对于一次性导入,请禁用此选项。 + +点击 **Create** 完成集成任务创建。 + +## 任务行为 {#task-behavior} + +| 持续摄取 | 行为 | +|----------------------|---------------------------------------------------------------------------------------------------| +| On | 持续运行,每 30 秒轮询一次 S3 以查找新文件,并自动导入这些文件。 | +| Off | 仅导入一次匹配的文件后停止。除非启用了 **Allow Duplicate Imports**,否则已导入的文件会被跳过。 | + +## 高级配置 {#advanced-configuration} + +### 持续摄取 {#continuous-ingestion} + +启用后,任务会作为一个长期运行的进程,定期扫描 S3 路径中的新文件。每个周期会执行以下操作: + +1. 列出与文件路径模式匹配的对象 +2. 识别尚未导入的新文件 +3. 使用 `COPY INTO` 将新文件导入目标表 +4. 在任务历史中记录导入结果 + +这对于上游系统持续向 S3 写入新文件的数据管道非常有用。 + +### 错误处理 {#error-handling} + +- **Abort**(默认):导入在遇到第一个错误时停止。当数据质量至关重要,并且你希望在继续之前先调查问题时,请使用此选项。 +- **Continue**:跳过导致错误的行,并继续导入其余数据。当允许部分导入并且你希望最大化数据吞吐时,请使用此选项。 + +### 清理原始文件(PURGE) {#clean-up-original-files-purge} + +启用后,源文件在成功导入到 {{{ .lake }}} 后会从 S3 中删除。这有助于管理存储成本并防止重复处理。请确保你的 AWS 凭证在目标存储桶上具有 `s3:DeleteObject` 权限。 + +### 允许重复导入(FORCE) {#allow-duplicate-imports-force} + +默认情况下,系统会跟踪哪些文件已经导入,并在后续运行中跳过这些文件。启用此选项后,无论这些匹配文件之前是否已被导入,系统都会强制重新导入所有匹配文件。当你需要在 schema 变更或数据修正后重新加载数据时,此功能非常有用。 diff --git a/tidb-cloud-lake/guides/integrate-with-amazon-sqs-s3.md b/tidb-cloud-lake/guides/integrate-with-amazon-sqs-s3.md new file mode 100644 index 0000000000000..b162c2501099e --- /dev/null +++ b/tidb-cloud-lake/guides/integrate-with-amazon-sqs-s3.md @@ -0,0 +1,110 @@ +--- +title: Amazon SQS (S3) 集成任务(Beta) +summary: 了解如何创建 Amazon SQS (S3) 集成任务,该任务从 SQS 队列消费 S3 对象创建事件,并将对应的对象数据写入 {{{ .lake }}}。 +--- + +# Amazon SQS (S3) 集成任务(Beta) + +本文介绍如何创建 Amazon SQS (S3) 集成任务。该任务从 SQS 队列消费 S3 对象创建事件,并将对应的对象数据写入 {{{ .lake }}}。 + +该任务专为 S3 事件驱动的数据摄取而设计。上游系统将对象写入 S3 后,S3 会向 SQS 发送 `ObjectCreated` 事件。{{{ .lake }}} 通过 AssumeRole 消费 SQS 消息,并根据事件中的 bucket 和对象键将数据写入 {{{ .lake }}}。 + +如果你需要先创建可复用的 SQS (S3) 连接设置,请参见 [Amazon SQS (S3) - IAM Role (Beta)](/tidb-cloud-lake/guides/amazon-sqs-s3-iam-role.md)。 + +## 使用场景 {#use-cases} + +- 基于 S3 `ObjectCreated` 事件自动摄取新写入的 S3 对象 +- 使用 S3 事件通知驱动数据摄取,减少新文件到达后的延时 +- 避免仅依赖轮询 S3 路径来发现新文件 + +## 工作流程 {#workflow} + +1. 上游系统将对象写入 S3 存储桶。 +2. S3 Event Notification 将 `ObjectCreated` 事件发送到一个 SQS 标准队列。 +3. {{{ .lake }}} 通过用户配置的 IAM Role 从 SQS 队列读取消息。 +4. 任务解析消息中的 S3 事件记录。 +5. 任务根据 S3 事件记录中的 bucket、对象键和文件格式,将数据写入 {{{ .lake }}} 目标表。 +6. 写入成功后,任务会从队列中删除已处理的 SQS 消息。 + +> **Note:** +> +> S3 事件通知和 SQS 标准队列都可能产生重复消息。{{{ .lake }}} 会处理失败重试。如果你的业务逻辑要求严格去重,请基于对象信息、事件时间、`sequencer` 或 SQS message ID 设计下游去重逻辑。 + +## 前提条件 {#prerequisites} + +在创建 SQS (S3) 集成任务之前,请确保: + +- 已创建 **Amazon SQS (S3) - IAM Role** 数据源 +- S3 存储桶已配置 `ObjectCreated` 事件通知,并将事件发送到目标 SQS 队列 +- SQS 队列策略允许 Amazon S3 调用 `sqs:SendMessage` +- 用户 IAM Role 允许 {{{ .lake }}} 平台角色通过 `sts:AssumeRole` 访问该角色 +- 用户 IAM Role 具有读取目标 S3 对象和消费目标 SQS 队列的权限 +- SQS 队列中包含标准 S3 Event Notification 格式的消息 +- S3 通知中的 bucket、prefix 和 suffix 与数据源配置一致 + +## 创建 SQS (S3) 集成任务 {#creating-an-sqs-s3-integration-task} + +### 第 1 步:基本信息 {#step-1-basic-info} + +1. 进入 **Data** > **Data Integration**,然后点击 **Create Task**。 +2. 选择一个 SQS (S3) 数据源,然后配置基本参数: + + | 字段 | 必填 | 描述 | + |-------|----------|-------------| + | **Data Source** | 是 | 从下拉列表中选择一个现有的 **Amazon SQS (S3) - IAM Role** 数据源 | + | **Name** | 是 | 集成任务名称 | + | **File Format** | 是 | S3 对象的文件格式,例如 CSV、Parquet 或 NDJSON | + | **Object Key Prefix** | 否 | 仅处理具有指定前缀的对象事件,例如 `raw/events/`。该值应与数据源和 S3 通知过滤器一致 | + | **Object Key Suffix** | 否 | 仅处理具有指定后缀的对象事件,例如 `.json` 或 `.parquet`。该值应与数据源和 S3 通知过滤器一致 | + + > **Tip:** + > + > 建议先在 S3 Event Notification 中配置 prefix 或 suffix 过滤器,并与数据源和任务中的过滤器保持一致。这样可以减少无关消息进入 SQS。 + +### 第 2 步:预览数据 {#step-2-preview-data} + +完成基本设置后,点击 **Next** 预览源数据。 + +预览结果与 [Amazon S3 集成任务](/tidb-cloud-lake/guides/integrate-with-amazon-s3.md) 相同。系统会根据 SQS (S3) 配置定位对应的 S3 对象,读取文件内容,并显示: + +- 包含列名和数据类型的样例数据 +- 匹配到的 S3 对象列表及对象大小 + +> **Note:** +> +> 如果当前路径作用域内没有可预览的 S3 对象,预览页面可能不会显示样例数据。请上传一个符合目标 prefix / suffix 的测试对象,然后重试预览。 + +### 第 3 步:设置目标表 {#step-3-set-target-table} + +在 {{{ .lake }}} 中配置目标位置: + +| 字段 | 描述 | +|-------|-------------| +| **Warehouse** | 选择用于运行 SQS (S3) 集成任务的 {{{ .lake }}} 计算集群 | +| **Target Database** | 选择 {{{ .lake }}} 中的目标数据库 | +| **Target Table** | 要写入数据的目标表名称 | + +系统会根据预览的 S3 对象内容推导列名和数据类型。继续之前,你可以查看并编辑目标表结构。如果要写入现有表,请选择目标表并验证列映射。 + +点击 **Create** 创建集成任务。 + +## 任务行为 {#task-behavior} + +SQS (S3) 集成任务是一个持续运行的任务。启动后,它会定期从 SQS 队列读取消息,并将数据写入目标表,直到被手动下线。 + +| 场景 | 行为 | +|----------|----------| +| 队列中存在消息 | 读取消息,解析 S3 事件记录,并根据事件中的对象信息将数据写入目标表 | +| 写入成功 | 删除对应的 SQS 消息,以避免重复处理 | +| 写入失败 | 不删除对应的 SQS 消息,以便后续重试 | +| 消息格式不是有效的 S3 Event Notification | 记录错误,并跳过处理或下线任务 | +| 任务被手动下线 | 下线轮询并保存当前任务状态 | + +## 与 Amazon S3 集成任务的区别 {#difference-from-amazon-s3-integration-task} + +| 任务类型 | 处理对象 | 写入 {{{ .lake }}} 的数据 | 典型使用场景 | +|-----------|------------------|--------------------------|------------------| +| Amazon S3 Integration Task | S3 file content | CSV、Parquet 或 NDJSON 文件中的业务数据 | 文件数据导入 | +| Amazon SQS (S3) Integration Task | SQS 中的 S3 ObjectCreated 事件 | 与事件对应的 S3 对象数据 | 自动摄取新对象,事件驱动导入 | + +如果你的目标是定期扫描某个 S3 路径并导入文件内容,请使用 Amazon S3 Integration Task。如果你的目标是基于 S3 ObjectCreated 事件触发数据摄取,请使用 Amazon SQS (S3) Integration Task。 diff --git a/tidb-cloud-lake/guides/integrate-with-kafka.md b/tidb-cloud-lake/guides/integrate-with-kafka.md new file mode 100644 index 0000000000000..3b1416c99ea7f --- /dev/null +++ b/tidb-cloud-lake/guides/integrate-with-kafka.md @@ -0,0 +1,131 @@ +--- +title: Kafka Consumer Integration Task (Beta) +summary: 创建 Kafka Consumer 任务,持续消费 Kafka topic 中的消息,并将消息内容保存到内部对象存储(租户 Stage)。 +--- + +# Kafka Consumer Integration Task (Beta) + +本文介绍如何创建 Kafka Consumer 任务,以持续消费 Kafka topic 中的消息,并将消息内容保存到内部对象存储(租户 Stage)。 + +与 S3、MySQL 或 PostgreSQL 数据集成任务不同,Kafka Consumer 任务不会直接写入常规目标表。任务创建并启动后,你可以使用 `@kafka_consumer//` stage 路径查看已保存的消息对象,并通过 SQL 查询其内容。 + +如果你需要先创建可复用的 Kafka 连接设置,请参见 [Kafka - 凭证(Beta)](/tidb-cloud-lake/guides/kafka-credentials.md)。 + +## 使用场景 {#use-cases} + +- 持续从 Kafka topic 中摄取 JSON 消息 +- 先将 Kafka 消息落盘到内部对象存储,再通过下游 SQL 进行查询或处理 +- 为实时或准实时数据流水线保留原始 Kafka 消息对象 + +## 工作流 {#workflow} + +1. 上游系统将消息写入 Kafka topic。 +2. Kafka Consumer 任务从指定的 topic 中读取消息。 +3. 任务将消息批量保存到内部对象存储(租户 Stage)。 +4. 用户通过 `@kafka_consumer//` 查看生成的对象。 +5. 用户从 stage 查询消息内容,并根据需要执行下游加载或转换。 + +> **注意:** +> +> Kafka Consumer 任务保存的是包含 Kafka 消息内容的对象文件。如果你需要将消息写入业务表,请基于 stage 查询结果执行下游 `INSERT INTO ... SELECT`、`COPY INTO` 或其他处理。 + +## 前提条件 {#prerequisites} + +在创建 Kafka Consumer 任务之前,请确保: + +- 已创建 **Kafka - Credentials** 数据源 +- 平台可以通过网络访问 Kafka broker +- Kafka 数据源中的认证方法、TLS 设置和账户信息正确 +- Kafka 用户具有读取目标 topic 的权限 +- 目标 topic 中的消息与任务中选择的 **Data Format** 一致 + +## 创建 Kafka Consumer 任务 {#creating-a-kafka-consumer-task} + +### 第 1 步:基本信息 {#step-1-basic-info} + +1. 进入 **Data** > **Data Integration**,然后点击 **Create Task**。 +2. 选择一个 Kafka 数据源,然后配置基本参数: + + | 字段 | 必填 | 描述 | + |-------|----------|-------------| + | **Data Source** | 是 | 从下拉列表中选择一个已有的 **Kafka - Credentials** 数据源 | + | **Name** | 是 | Kafka Consumer 任务名称 | + | **Topics** | 是 | 要消费的 Kafka topic。多个 topic 之间用逗号分隔,例如 `topic-1,topic-2` | + | **Data Format** | 是 | Kafka 消息的数据格式。目前为 **JSON** | + | **Start Position** | 是 | 当不存在已提交的偏移时的起始位置。支持 **Latest** 和 **Earliest** | + | **Max Batch Bytes** | 否 | 每批的最大数据大小。默认值为 **16 MiB** | + | **Max Batch Wait Interval** | 否 | 每批的最大等待时间。默认值为 **1 Minute** | + + > **注意:** + > + > **Latest** 仅消费新消息,而 **Earliest** 从 Kafka 中最早保留的消息开始消费。该设置仅在 Consumer Group 没有已提交偏移时生效,不会重置已有偏移。 + +### 第 2 步:预览数据 {#step-2-preview-data} + +完成基本设置后,点击 **Next** 进入 **Preview Data Info**。 + +系统会尝试从指定的 Kafka topic 中读取示例消息。如果有可用消息,页面会显示 1 到 2 条 JSON 消息,供你验证 topic、数据格式和消息结构。 + +如果没有可预览的消息,页面会显示 **No sample data available**。你仍然可以继续创建任务,但建议检查这些 topic 是否已包含消息,以及所选 **Start Position** 是否能够读取到示例数据。 + +### 第 3 步:查看结果 {#step-3-result-viewing} + +在 **Result Viewing** 步骤中,选择用于运行 Kafka Consumer 任务的计算集群 (Warehouse)。 + +任务启动后,会读取 Kafka 消息并将其保存到内部对象存储(租户 Stage)。页面会提供 SQL 示例。你可以使用 `LIST @kafka_consumer//` 查看生成的对象,并使用 stage 查询读取消息内容。 + +```sql +-- List stage objects: +LIST @kafka_consumer//; + +-- Query object data (replace with the correct PATTERN path): +SELECT $1 +FROM @kafka_consumer ( + FILE_FORMAT=>'ndjson', + PATTERN=>'/year=YYYY/month=MM/day=DD/hour=HH/.*[.]ndjson' +); +``` + +点击 **Create** 创建任务。 + +## 任务行为 {#task-behavior} + +Kafka Consumer 任务会持续运行。启动后,它会从指定的 topic 中消费消息,并将其批量保存为内部对象存储中的对象文件,直到你手动停止该任务。 + +| 场景 | 行为 | +|----------|----------| +| topics 中存在新消息 | 读取消息并将其写入租户 Stage | +| 批次大小达到 **Max Batch Bytes** | 将当前批次写入对象存储 | +| 等待时间达到 **Max Batch Wait Interval** | 即使当前批次未达到大小限制,也会将其写入对象存储 | +| 写入操作成功 | 保存消费进度,以便后续继续消费 | +| 你手动下线任务 | 停止消费,并保留已保存的消息对象 | + +## 查询已保存的消息 {#query-saved-messages} + +Kafka Consumer 任务会将消息对象保存在 `@kafka_consumer//` 路径下。任务启动并写入对象后,打开任务详情页并切换到 **Data Browsing** 页签,即可按 UTC 小时查看对象数量和对象列表。 + +你也可以先使用 SQL 列出对象,再根据实际路径查询其内容: + +```sql +LIST @kafka_consumer//; +``` + +```sql +SELECT $1 +FROM @kafka_consumer ( + FILE_FORMAT=>'ndjson', + PATTERN=>'/year=YYYY/month=MM/day=DD/hour=HH/.*[.]ndjson' +); +``` + +如果你需要将消息写入业务表,请基于查询结果继续执行下游转换或加载。 + +## 高级配置 {#advanced-configuration} + +### 运行时大小 {#runtime-size} + +Kafka Consumer 任务支持修改运行时大小。在修改 Runtime Size 之前,请先停止任务,然后通过 **Edit** 菜单打开编辑页面,在 **Runtime Size** 部分选择合适的运行时大小并保存更改。重启任务后,任务将以新的运行时大小运行。 + +> **注意:** +> +> 可用的运行时大小和价格取决于你的计费方案。请以控制台中显示的选项和定价文档为准。 diff --git a/tidb-cloud-lake/guides/integrate-with-mysql.md b/tidb-cloud-lake/guides/integrate-with-mysql.md new file mode 100644 index 0000000000000..c116b305f1860 --- /dev/null +++ b/tidb-cloud-lake/guides/integrate-with-mysql.md @@ -0,0 +1,195 @@ +--- +title: MySQL Integration Task +summary: MySQL 数据集成支持将 MySQL 数据库中的数据实时同步到 {{{ .lake }}},支持全量 `Snapshot` 导入、持续 `Change Data Capture (CDC)`,或两者结合。 +--- + +# MySQL Integration Task + +本页介绍如何创建一个 MySQL 集成任务,将 MySQL 数据库中的数据同步到 {{{ .lake }}}。MySQL 任务支持全量 `Snapshot` 导入、持续 `Change Data Capture (CDC)`,或两者结合。 + +如果你需要先创建可复用的 MySQL 连接设置,请参见 [MySQL - Credentials](/tidb-cloud-lake/guides/mysql-credentials.md)。 + +## Sync Modes {#sync-modes} + +| 同步模式 | 描述 | +|----------------|--------------------------------------------------------------------------------------------------------------| +| Snapshot | 对源表执行一次性全量数据导入。适用于初始数据迁移或周期性批量导入。 | +| CDC Only | 持续捕获 MySQL binlog 中的实时变更(插入、修改、删除)。合并操作需要主键。 | +| Snapshot + CDC | 先执行全量快照,然后无缝切换到持续 CDC。推荐用于大多数使用场景。 | + +## Prerequisites {#prerequisites} + +在设置 MySQL 数据集成之前,请确保你的 MySQL 实例满足以下要求: + +- 已创建 **MySQL - Credentials** 数据源 +- 目标 MySQL 实例可从 {{{ .lake }}} 访问 + +### Enable Binlog {#enable-binlog} + +对于所有同步模式,都需要启用 MySQL 二进制日志。对于 **CDC Only** 和 **Snapshot + CDC**,二进制日志**必须**使用 `ROW` 格式和 `FULL` 行镜像: + +```ini title='my.cnf' +[mysqld] +server-id=1 +log-bin=mysql-bin +binlog-format=ROW +binlog-row-image=FULL +``` + +修改配置后,重启 MySQL 使更改生效。 + +### Create a Dedicated User (Recommended) {#create-a-dedicated-user-recommended} + +创建一个具有数据复制所需权限的 MySQL 用户: + +```sql +CREATE USER 'lake_cdc'@'%' IDENTIFIED BY 'your_password'; +GRANT SELECT, REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'lake_cdc'@'%'; +FLUSH PRIVILEGES; +``` + +### Network Access {#network-access} + +确保 MySQL 实例可从 {{{ .lake }}} 访问。检查防火墙规则和安全组,允许 MySQL 端口上的入站连接。 + +## Creating a MySQL Integration Task {#creating-a-mysql-integration-task} + +### Step 1: Basic Info {#step-1-basic-info} + +1. 进入 **Data** > **Data Integration**,然后点击 **Create Task**。 + + ![Data Integration Page](/media/tidb-cloud-lake/dataintegration-page-with-create-button.png) + +2. 配置基本设置: + + | 字段 | 必填 | 描述 | + |----------------------------|-------------|--------------------------------------------------------------------------------------------------| + | **Data Source** | Yes | 从下拉列表中选择一个已有的 **MySQL - Credentials** 数据源 | + | **Name** | Yes | 此集成任务的名称 | + | **Source Database** | — | 根据所选数据源自动显示 | + | **Source Table** | Yes | 选择要从 MySQL 数据库同步的表 | + | **Sync Mode** | Yes | 从 **Snapshot**、**CDC Only** 或 **Snapshot + CDC** 中选择 | + | **Primary Key** | Conditional | 用于合并操作的唯一标识列。CDC Only 和 Snapshot + CDC 模式下必填 | + | **Sync Interval** | Yes | 写入操作之间的间隔(秒)(默认值:3) | + | **Batch Size** | No | 每批处理的行数 | + | **Allow Delete** | No | 是否允许在 CDC 中执行 DELETE 操作。适用于 CDC Only 和 Snapshot + CDC 模式 | + + ![Create Task - Basic Info](/media/tidb-cloud-lake/create-mysql-task-step1-basic-info.png) + +#### Snapshot Mode Options {#snapshot-mode-options} + +使用 **Snapshot** 模式时,还可以配置以下选项: + +- **Snapshot WHERE Condition**:在快照期间用于过滤数据的 SQL WHERE 子句(例如 `created_at > '2024-01-01'`)。这样你可以只导入源数据的一个子集。 + +- **Archive Schedule**:启用周期性归档后,系统会按重复调度自动运行快照。启用后,会显示以下字段: + +| 字段 | 描述 | +|---------------------|--------------------------------------------------------------------------| +| **Cron Expression** | cron 格式的调度表达式(例如 `0 1 * * *` 表示每天凌晨 1:00) | +| **Timezone** | 调度使用的时区(默认值:UTC) | +| **Mode** | 归档频率 — **Daily**、**Weekly** 或 **Monthly** | +| **Time Column** | 用于按时间分区归档的时间列(例如 `created_at`) | + +### Step 2: Preview Data {#step-2-preview-data} + +配置完基本设置后,点击 **Next** 预览源数据。 + +![Preview Data](/media/tidb-cloud-lake/create-mysql-task-preview-data-step.png) + +系统会从所选 MySQL 表中获取一行示例数据,并显示列名和数据类型。继续之前,请检查数据,确保选择了正确的表和列。 + +### Step 3: Set Target Table {#step-3-set-target-table} + +在 {{{ .lake }}} 中配置目标位置: + +| 字段 | 描述 | +|---------------------|--------------------------------------------------------------------| +| **Warehouse** | 选择用于运行同步任务的目标 {{{ .lake }}} 计算集群 (Warehouse) | +| **Target Database** | 选择 {{{ .lake }}} 中的目标数据库 | +| **Target Table** | {{{ .lake }}} 中的表名(默认为源表名) | + +![Set Target Table](/media/tidb-cloud-lake/dataintegration-mysql-set-target-table.png) + +系统会自动将源列映射到目标表结构。检查列映射后,点击 **Create** 完成集成任务创建。 + +## Task Behavior by Sync Mode {#task-behavior-by-sync-mode} + +| 同步模式 | 行为 | +|----------------|---------------------------------------------------------------------------------------------------| +| Snapshot | 运行一次,并在全量数据导入完成后自动下线。 | +| CDC Only | 持续运行,捕获实时变更,直到手动下线。 | +| Snapshot + CDC | 先完成初始快照,然后切换到持续 CDC,直到手动下线。 | + +对于 CDC 任务,下线时会将当前 binlog 位置保存为检查点,因此在重启后,任务可以从上次中断的位置继续运行。 + +## Sync Mode Details {#sync-mode-details} + +### Snapshot {#snapshot} + +Snapshot 模式会对源表执行一次性全量读,并将所有数据导入到 {{{ .lake }}} 中的目标表。 + +**Use cases:** + +- 从 MySQL 到 {{{ .lake }}} 的初始数据迁移 +- 周期性全量数据刷新 +- 带 WHERE 条件过滤的一次性数据导入 + +**Features:** + +- 支持通过 WHERE 条件过滤,仅导入部分数据 +- 支持为重复快照配置周期性归档调度 +- 任务完成后会自动下线 + +### CDC (Change Data Capture) {#cdc-change-data-capture} + +CDC 模式会持续监控 MySQL binlog,并捕获源表中的实时行级变更(INSERT、UPDATE、DELETE)。 + +**Use cases:** + +- 实时数据复制 +- 使 {{{ .lake }}} 与业务 MySQL 数据库保持同步 +- 事件驱动的数据管道 + +**How it works:** + +1. 使用唯一的 server ID 连接到 MySQL binlog +2. 实时捕获行级变更 +3. 将变更写入 {{{ .lake }}} 中的原始暂存表 +4. 使用主键定期将变更合并到目标表 +5. 保存检查点(binlog 位置)以便故障恢复 + +> **Note:** +> +> CDC 模式要求启用 MySQL binlog 且使用 ROW 格式,并且必须指定主键(唯一列)。MySQL 用户必须具有 `REPLICATION SLAVE` 和 `REPLICATION CLIENT` 权限。 + +### Snapshot + CDC {#snapshot-cdc} + +该模式结合了两种方式:先对源表执行全量快照,然后无缝切换到 CDC 模式以持续捕获变更。对于大多数数据集成场景,这是推荐模式,因为它既能确保完整的初始数据导入,又能提供后续持续的实时同步。 + +## Advanced Configuration {#advanced-configuration} + +### Primary Key {#primary-key} + +主键用于指定 CDC 期间 MERGE 操作所使用的唯一标识列。当捕获到变更事件时,{{{ .lake }}} 会使用该键来判断是插入新行还是修改现有行。通常,这应当是源表的主键。 + +### Sync Interval {#sync-interval} + +同步间隔(秒)用于控制将捕获到的变更合并到目标表的频率。较短的间隔可以带来更低的延时,但可能会增加资源使用。默认值 3 秒适用于大多数工作负载。 + +### Batch Size {#batch-size} + +用于控制数据加载期间每批处理的行数。调整该值有助于优化大表的吞吐。留空则使用系统默认值。 + +### Allow Delete {#allow-delete} + +启用后(CDC 模式下默认启用),从 MySQL binlog 捕获到的 DELETE 操作会应用到 {{{ .lake }}} 中的目标表。禁用后,删除操作会被忽略,目标表会保留所有历史记录。这适用于需要保留完整审计轨迹的场景。 + +### Archive Schedule {#archive-schedule} + +对于 Snapshot 模式,你可以配置周期性归档,使系统按重复调度自动运行快照。这适用于需要定期刷新数据、但又不希望承担持续 CDC 开销的场景。 + +- **Cron Expression**:用于调度的标准 cron 格式(例如 `0 1 * * *` 表示每天凌晨 1:00) +- **Mode**:选择 **Daily**、**Weekly** 或 **Monthly** 归档 +- **Time Column**:指定用于基于时间分区的列(例如 `created_at`) +- **Timezone**:设置调度使用的时区(默认值:UTC) diff --git a/tidb-cloud-lake/guides/integrate-with-postgresql.md b/tidb-cloud-lake/guides/integrate-with-postgresql.md new file mode 100644 index 0000000000000..fc5f0e3254448 --- /dev/null +++ b/tidb-cloud-lake/guides/integrate-with-postgresql.md @@ -0,0 +1,196 @@ +--- +title: PostgreSQL 集成任务 +summary: 本页介绍如何创建一个 PostgreSQL 集成任务,将 PostgreSQL 数据库中的数据同步到 {{{ .lake }}}。 +--- + +# PostgreSQL 集成任务 + +本页介绍如何创建一个 PostgreSQL 集成任务,将 PostgreSQL 数据库中的数据同步到 {{{ .lake }}}。PostgreSQL 任务支持全量 `Snapshot` 导入、持续的 `Change Data Capture (CDC)`,或两者结合使用。 + +如果你需要先创建可复用的 PostgreSQL 连接设置,请参见 [PostgreSQL - Credentials](/tidb-cloud-lake/guides/postgresql-credentials.md)。 + +## 同步模式 {#sync-modes} + +| 同步模式 | 描述 | +|----------------|--------------------------------------------------------------------------------------------------------------| +| Snapshot | 对源表执行一次性全量数据导入。适用于初始数据迁移或周期性批量导入。 | +| CDC Only | 通过 PostgreSQL 逻辑复制持续捕获实时变更(插入、修改、删除)。合并操作需要主键。 | +| Snapshot + CDC | 先执行一次完整快照,然后无缝切换到持续 CDC。推荐用于大多数使用场景。 | + +## 前提条件 {#prerequisites} + +在设置 PostgreSQL 数据集成之前,请确保你的 PostgreSQL 实例满足以下要求: + +- 已创建 **PostgreSQL - Credentials** 数据源 +- 目标 PostgreSQL 实例可从 {{{ .lake }}} 访问 +- PostgreSQL 版本为 10 或更高 + +### 启用逻辑复制 {#enable-logical-replication} + +对于 CDC 和 Snapshot + CDC 模式,必须将 PostgreSQL WAL (Write-Ahead Log) 配置为 logical 级别: + +```ini title='postgresql.conf' +wal_level = logical +max_replication_slots = 4 +max_wal_senders = 4 +``` + +修改配置后,重启 PostgreSQL 使更改生效。 + +### 创建专用用户(推荐) {#create-a-dedicated-user-recommended} + +创建一个具有数据复制所需权限的 PostgreSQL 用户: + +```sql +CREATE USER lake_cdc WITH PASSWORD 'your_password' REPLICATION; +GRANT CONNECT ON DATABASE your_database TO lake_cdc; +GRANT USAGE ON SCHEMA public TO lake_cdc; +GRANT SELECT ON ALL TABLES IN SCHEMA public TO lake_cdc; +ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO lake_cdc; +``` + +### 创建发布和复制槽(CDC 必需) {#create-publication-and-replication-slot-required-for-cdc} + +对于 CDC 和 Snapshot + CDC 模式,必须存在发布和复制槽。由于 `CREATE PUBLICATION ... FOR ALL TABLES` 需要超级用户权限,而添加单独的表又需要表所有权,因此在启动 CDC 任务之前,应由数据库所有者或超级用户创建这些对象。 + +请以超级用户或数据库所有者身份运行以下命令: + +```sql +-- Create a publication that includes the tables you want to replicate +CREATE PUBLICATION bend_cdc_pub FOR ALL TABLES; + +-- Create a logical replication slot +SELECT * FROM pg_create_logical_replication_slot('bend_cdc_slot', 'pgoutput'); + +-- Grant the dedicated user permission to use the replication slot +ALTER ROLE lake_cdc WITH REPLICATION; +``` + +> **Note:** +> +> 如果你只需要复制特定表而不是所有表,可以使用: +> +> ```sql +> CREATE PUBLICATION bend_cdc_pub FOR TABLE table1, table2; +> ``` +> +> 这样可以避免超级用户要求,但仍然需要对所列出的表拥有所有权。 + +### 网络访问 {#network-access} + +请确保 PostgreSQL 实例可从 {{{ .lake }}} 访问。检查防火墙规则和安全组设置,允许 PostgreSQL 端口上的入站连接。 + +## 创建 PostgreSQL 集成任务 {#creating-a-postgresql-integration-task} + +### 第 1 步:基本信息 {#step-1-basic-info} + +1. 进入 **Data** > **Data Integration**,然后点击 **Create Task**。 + +2. 配置基本设置: + + | 字段 | 必填 | 描述 | + |----------------------------|-------------|--------------------------------------------------------------------------------------------------| + | **Data Source** | Yes | 从下拉列表中选择一个现有的 **PostgreSQL - Credentials** 数据源 | + | **Name** | Yes | 此集成任务的名称 | + | **Source Database** | — | 根据所选数据源自动显示 | + | **Source Table** | Yes | 选择要从 PostgreSQL 数据库同步的表 | + | **Sync Mode** | Yes | 从 **Snapshot**、**CDC Only** 或 **Snapshot + CDC** 中选择 | + | **Primary Key** | Conditional | 用于合并操作的唯一标识列。CDC Only 和 Snapshot + CDC 模式下必填 | + | **Sync Interval** | Yes | 写入操作之间的时间间隔(秒)(默认值:3) | + | **Batch Size** | No | 每批处理的行数 | + | **Allow Delete** | No | 是否允许在 CDC 中执行 DELETE 操作。适用于 CDC Only 和 Snapshot + CDC 模式 | + +#### Snapshot 模式选项 {#snapshot-mode-options} + +使用 **Snapshot** 模式时,还可以使用以下附加选项: + +- **Snapshot WHERE Condition**:在执行快照时用于过滤数据的 SQL WHERE 子句(例如,`created_at > '2024-01-01'`)。这样你可以只导入源数据的一个子集。 + +### 第 2 步:预览数据 {#step-2-preview-data} + +配置完基本设置后,点击 **Next** 预览源数据。 + +系统会从所选 PostgreSQL 表中获取一行示例数据,并显示列名和数据类型。在继续之前,请检查数据以确保选择了正确的表和列。 + +### 第 3 步:设置目标表 {#step-3-set-target-table} + +在 {{{ .lake }}} 中配置目标位置: + +| 字段 | 描述 | +|---------------------|--------------------------------------------------------------------| +| **Warehouse** | 选择用于运行同步任务的目标 {{{ .lake }}} 计算集群 (Warehouse) | +| **Target Database** | 选择 {{{ .lake }}} 中的目标数据库 | +| **Target Table** | {{{ .lake }}} 中的表名(默认为源表名) | + +系统会自动将源列映射到目标表结构。检查列映射后,点击 **Create** 完成集成任务创建。 + +## 按同步模式划分的任务行为 {#task-behavior-by-sync-mode} + +| 同步模式 | 行为 | +|----------------|---------------------------------------------------------------------------------------------------| +| Snapshot | 运行一次,并在全量数据导入完成后自动下线。 | +| CDC Only | 持续运行,捕获实时变更,直到手动下线。 | +| Snapshot + CDC | 先完成初始快照,然后切换到持续 CDC,直到手动下线。 | + +对于 CDC 任务,下线时会将当前 LSN (Log Sequence Number) 保存为检查点,因此在重启后,任务可以从上次停止的位置继续运行。 + +## 同步模式详情 {#sync-mode-details} + +### Snapshot {#snapshot} + +Snapshot 模式会对源表执行一次性全量读,并将所有数据加载到 {{{ .lake }}} 中的目标表。 + +**Use cases:** + +- 从 PostgreSQL 到 {{{ .lake }}} 的初始数据迁移 +- 周期性的全量数据刷新 +- 使用 WHERE 条件过滤的一次性数据导入 + +**Features:** + +- 支持使用 WHERE 条件过滤以导入部分数据 +- 任务完成后会自动下线 + +### CDC (Change Data Capture) {#cdc-change-data-capture} + +CDC 模式通过逻辑复制持续监控 PostgreSQL WAL (Write-Ahead Log),并从源表中捕获实时的行级变更(INSERT、UPDATE、DELETE)。 + +**Use cases:** + +- 实时数据复制 +- 使 {{{ .lake }}} 与业务 PostgreSQL 数据库保持同步 +- 事件驱动的数据管道 + +**How it works:** + +1. 使用逻辑复制槽连接到 PostgreSQL +2. 通过 `pgoutput` 插件实时捕获行级变更 +3. 将变更写入 {{{ .lake }}} 中的原始暂存表 +4. 使用主键定期将变更合并到目标表 +5. 保存检查点(LSN 位置)以便进行故障恢复 + +> **Note:** +> +> CDC 模式要求 PostgreSQL WAL 级别设置为 `logical`,并且必须指定主键(唯一列)。PostgreSQL 用户必须具有 `REPLICATION` 权限。 + +### Snapshot + CDC {#snapshot-cdc} + +该模式结合了两种方式:先对源表执行完整快照,然后无缝切换到 CDC 模式以持续捕获变更。对于大多数数据集成场景,这是推荐模式,因为它既能确保完整的初始数据加载,又能提供后续持续的实时同步。 + +## 高级配置 {#advanced-configuration} + +### 主键 {#primary-key} + +主键指定了 CDC 期间用于 MERGE 操作的唯一标识列。当捕获到变更事件时,{{{ .lake }}} 使用该键来判断是插入新行还是修改现有行。通常,这应当是源表的主键。 + +### 同步间隔 {#sync-interval} + +同步间隔(秒)控制将已捕获的变更合并到目标表的频率。较短的间隔可以提供更低的延时,但可能会增加资源使用量。默认值 3 秒适用于大多数工作负载。 + +### 批大小 {#batch-size} + +用于控制数据加载期间每批处理的行数。调整此值有助于优化大表场景下的吞吐。留空则使用系统默认值。 + +### 允许删除 {#allow-delete} + +启用后(CDC 模式下默认启用),从 PostgreSQL WAL 捕获到的 DELETE 操作会应用到 {{{ .lake }}} 中的目标表。禁用后,删除操作会被忽略,目标表将保留所有历史记录。这适用于希望保留完整审计轨迹的场景。 diff --git a/tidb-cloud-lake/guides/integration-tasks.md b/tidb-cloud-lake/guides/integration-tasks.md new file mode 100644 index 0000000000000..7555ec1e34849 --- /dev/null +++ b/tidb-cloud-lake/guides/integration-tasks.md @@ -0,0 +1,34 @@ +--- +title: 集成任务 +summary: 本页概述 {{{ .lake }}} 中的集成任务。集成任务定义了数据如何从外部源流入 {{{ .lake }}},包括源设置、目标表和运行时参数。 +--- + +# 集成任务 + +{{{ .lake }}} 中的集成任务定义了数据如何从源流入 {{{ .lake }}}。每个任务都会引用一个现有数据源,并指定源设置、目标位置或结果查看方法,以及特定于任务类型的运行时参数。 + +与数据源不同,集成任务是实际执行数据移动、同步或消息消费的可执行单元。数据源存储访问设置,而任务负责调度、摄取、同步、消费、下线、恢复和监控。 + +## 支持的任务类型 {#supported-task-types} + +| Task Type | Description | +|-----------|-------------| +| [Amazon S3](/tidb-cloud-lake/guides/integrate-with-amazon-s3.md) | 从 Amazon S3 导入 CSV、Parquet 或 NDJSON 文件,支持一次性或持续摄取。 | +| [Amazon SQS (S3) (Beta)](/tidb-cloud-lake/guides/integrate-with-amazon-sqs-s3.md) | 从 SQS 队列消费 S3 对象创建事件,并将相应的对象数据写入 {{{ .lake }}}。 | +| [MySQL](/tidb-cloud-lake/guides/integrate-with-mysql.md) | 使用 `Snapshot`、`CDC Only` 或 `Snapshot + CDC` 同步 MySQL 的表数据。 | +| [PostgreSQL](/tidb-cloud-lake/guides/integrate-with-postgresql.md) | 使用 `Snapshot`、`CDC Only` 或 `Snapshot + CDC` 同步 PostgreSQL 的表数据。 | +| [Kafka Consumer Integration Task (Beta)](/tidb-cloud-lake/guides/integrate-with-kafka.md) | 持续消费 Kafka topic 中的消息,并将消息内容保存到内部对象存储。 | + +## 阅读指南 {#reading-guide} + +建议按以下顺序阅读: + +1. 先阅读 [任务管理](/tidb-cloud-lake/guides/task-management.md),了解任务创建流程、启动 / 下线行为、状态和运行历史。 +2. 然后阅读与你要配置的源类型对应的任务专用指南。 + +## 任务类型差异 {#task-type-differences} + +- S3 任务适用于文件导入场景,主要关注文件路径模式、文件格式和摄取行为。 +- SQS (S3) 任务适用于由 S3 事件驱动的数据摄取场景,主要关注 SQS 队列、S3 事件过滤器、IAM Role 和目标表。 +- MySQL 和 PostgreSQL 任务适用于表同步场景,主要关注同步模式、主键、增量捕获和归档调度。 +- Kafka Consumer 任务适用于消息消费场景,主要关注 topic、起始位置、批大小、批等待间隔以及租户 Stage 查询。 \ No newline at end of file diff --git a/tidb-cloud-lake/guides/json-search.md b/tidb-cloud-lake/guides/json-search.md new file mode 100644 index 0000000000000..ccba372dbbdc1 --- /dev/null +++ b/tidb-cloud-lake/guides/json-search.md @@ -0,0 +1,138 @@ +--- +title: JSON & Search +summary: 在场景 CityDrive 中,每个提取出的帧都会附带一个元信息 JSON 负载。这些 JSON 数据由后台工具从视频关键帧中提取,包含场景识别、目标检测等丰富的非结构化信息。我们需要在 {{{ .lake }}} 中使用 Elasticsearch 风格的语法过滤这些 JSON,而无需将其复制到外部系统。JSON 无需从 {{{ .lake }}} 中导出。 +--- + +# JSON & Search + +> **场景:** CityDrive 为每个提取出的帧附加一个元信息 JSON 负载。这些 JSON 数据由后台工具从视频关键帧中提取,包含场景识别、目标检测等丰富的非结构化信息。我们需要在 {{{ .lake }}} 中使用 Elasticsearch 风格的语法过滤这些 JSON,而无需将其复制到外部系统。JSON 无需从 {{{ .lake }}} 中导出。 + +{{{ .lake }}} 将这些异构信号保存在同一个仓库中。倒排索引为 VARIANT 列提供 Elasticsearch 风格的搜索,位图表汇总标签覆盖情况,向量索引支持相似性查找,原生 GEOMETRY 列支持空间过滤。 + +## 1. 创建元信息表 {#1-create-the-metadata-table} + +为每一帧存储一个 JSON 负载,这样每次搜索都基于相同的结构执行。 + +```sql +CREATE DATABASE IF NOT EXISTS video_unified_demo; +USE video_unified_demo; + +CREATE OR REPLACE TABLE frame_metadata_catalog ( + doc_id STRING, + meta_json VARIANT, + captured_at TIMESTAMP, + INVERTED INDEX idx_meta_json (meta_json) +); + +-- Sample rows for the queries below. +INSERT INTO frame_metadata_catalog VALUES + ('FRAME-0101', PARSE_JSON('{"scene":{"weather_code":"rain","lighting":"day"},"camera":{"sensor_view":"roof"},"vehicle":{"speed_kmh":32.4},"detections":{"objects":[{"type":"vehicle","confidence":0.88},{"type":"brake_light","confidence":0.64}]},"media_meta":{"tagging":{"labels":["hard_brake","rain","downtown_loop"]}}}'), '2025-01-01 08:15:21'), + ('FRAME-0102', PARSE_JSON('{"scene":{"weather_code":"rain","lighting":"day"},"camera":{"sensor_view":"roof"},"vehicle":{"speed_kmh":24.8},"detections":{"objects":[{"type":"pedestrian","confidence":0.92},{"type":"bike","confidence":0.35}]},"media_meta":{"tagging":{"labels":["pedestrian","swerve","crosswalk"]}}}'), '2025-01-01 08:33:54'), + ('FRAME-0201', PARSE_JSON('{"scene":{"weather_code":"overcast","lighting":"day"},"camera":{"sensor_view":"front"},"vehicle":{"speed_kmh":48.1},"detections":{"objects":[{"type":"lane_merge","confidence":0.74},{"type":"vehicle","confidence":0.41}]},"media_meta":{"tagging":{"labels":["lane_merge","urban"]}}}'), '2025-01-01 11:12:02'), + ('FRAME-0301', PARSE_JSON('{"scene":{"weather_code":"clear","lighting":"day"},"camera":{"sensor_view":"front"},"vehicle":{"speed_kmh":52.6},"detections":{"objects":[{"type":"vehicle","confidence":0.82},{"type":"hard_brake","confidence":0.59}]},"media_meta":{"tagging":{"labels":["hard_brake","highway"]}}}'), '2025-01-02 09:44:18'), + ('FRAME-0401', PARSE_JSON('{"scene":{"weather_code":"lightfog","lighting":"night"},"camera":{"sensor_view":"rear"},"vehicle":{"speed_kmh":38.9},"detections":{"objects":[{"type":"traffic_light","confidence":0.78},{"type":"vehicle","confidence":0.36}]},"media_meta":{"tagging":{"labels":["night_lowlight","traffic_light"]}}}'), '2025-01-03 21:18:07'); +``` + +> 需要多模态数据(向量嵌入、GPS 轨迹、标签位图)?可以从 [向量](/tidb-cloud-lake/guides/vector-search-guide.md) 和 [地理空间](/tidb-cloud-lake/guides/geo-analytics.md) 指南中获取表结构,以便将它们与此处展示的搜索结果结合使用。 + +## 2. 使用 `QUERY()` 的搜索模式 {#2-search-patterns-with-query} + +### 数组匹配 {#array-match} + +```sql +SELECT doc_id, + captured_at, + meta_json['detections'] AS detections +FROM frame_metadata_catalog +WHERE QUERY('meta_json.detections.objects.type:pedestrian') +ORDER BY captured_at DESC +LIMIT 5; +``` + +示例输出: + +``` +doc_id | captured_at | detections +FRAME-0102 | 2025-01-01 08:33:54 | {"objects":[{"confidence":0.92,"type":"pedestrian"},{"confidence":0.35,"type":"bike"}]} +``` + +### 布尔 AND {#boolean-and} + +```sql +SELECT doc_id, captured_at +FROM frame_metadata_catalog +WHERE QUERY('meta_json.scene.weather_code:rain + AND meta_json.camera.sensor_view:roof') +ORDER BY captured_at; +``` + +示例输出: + +``` +doc_id | captured_at +FRAME-0101 | 2025-01-01 08:15:21 +FRAME-0102 | 2025-01-01 08:33:54 +``` + +### 布尔 OR / 列表 {#boolean-or-list} + +```sql +SELECT doc_id, + meta_json['media_meta']['tagging']['labels'] AS labels +FROM frame_metadata_catalog +WHERE QUERY('meta_json.media_meta.tagging.labels:(hard_brake OR swerve OR lane_merge)') +ORDER BY captured_at DESC +LIMIT 10; +``` + +示例输出: + +``` +doc_id | labels +FRAME-0301 | ["hard_brake","highway"] +FRAME-0201 | ["lane_merge","urban"] +FRAME-0102 | ["pedestrian","swerve","crosswalk"] +FRAME-0101 | ["hard_brake","rain","downtown_loop"] +``` + +### 数值范围 {#numeric-ranges} + +```sql +SELECT doc_id, + meta_json['vehicle']['speed_kmh']::DOUBLE AS speed +FROM frame_metadata_catalog +WHERE QUERY('meta_json.vehicle.speed_kmh:{30 TO 80}') +ORDER BY speed DESC +LIMIT 10; +``` + +示例输出: + +``` +doc_id | speed +FRAME-0301 | 52.6 +FRAME-0201 | 48.1 +FRAME-0401 | 38.9 +FRAME-0101 | 32.4 +``` + +### Boosting {#boosting} + +```sql +SELECT doc_id, + SCORE() AS relevance +FROM frame_metadata_catalog +WHERE QUERY('meta_json.scene.weather_code:rain AND (meta_json.media_meta.tagging.labels:hard_brake^2 OR meta_json.media_meta.tagging.labels:swerve)') +ORDER BY relevance DESC +LIMIT 8; +``` + +示例输出: + +``` +doc_id | relevance +FRAME-0101 | 7.0161 +FRAME-0102 | 3.6252 +``` + +`QUERY()` 遵循 Elasticsearch 语义(布尔逻辑、范围、boost、列表)。`SCORE()` 会暴露 Elasticsearch 的相关性分数,因此你可以在 SQL 内部对结果重新排序。完整的运算符列表,请参见[搜索函数](/tidb-cloud-lake/sql/full-text-search-functions.md)。 \ No newline at end of file diff --git a/tidb-cloud-lake/guides/jupyter-notebook.md b/tidb-cloud-lake/guides/jupyter-notebook.md new file mode 100644 index 0000000000000..da1e8abd84119 --- /dev/null +++ b/tidb-cloud-lake/guides/jupyter-notebook.md @@ -0,0 +1,134 @@ +--- +title: 使用 Jupyter Notebook 连接到 TiDB Cloud Lake +summary: 了解如何通过 SQLAlchemy 将 Jupyter Notebook 连接到 TiDB Cloud Lake,执行查询,并使用 pandas 可视化查询结果。 +--- + +# 使用 Jupyter Notebook 连接到 TiDB Cloud Lake + +[Jupyter Notebook](https://jupyter.org/) 是一个用于运行代码、查询数据和创建可视化内容的交互式环境。你可以通过 [TiDB Cloud Lake dialect for SQLAlchemy](https://github.com/tidbcloud/lake-sqlalchemy) 将 notebook 连接到 {{{ .lake }}}。 + +## 准备工作 {#prerequisites} + +开始之前,请确保你具备以下条件: + +- Python 3.8 或更高版本 +- 一个 {{{ .lake }}} 账户、数据库和计算集群 (Warehouse) +- 连接所需的 host、用户名、密码、数据库和计算集群名称 + +如需了解如何获取连接信息,请参见[连接到计算集群](/tidb-cloud-lake/guides/warehouse.md#connecting-to-a-warehouse)。 + +## 安装 Jupyter Notebook 和 SQLAlchemy 方言 {#install-jupyter-notebook-and-the-sqlalchemy-dialect} + +创建并激活虚拟环境: + +```shell +python3 -m venv .venv +source .venv/bin/activate +``` + +安装 Jupyter Notebook、SQLAlchemy 方言以及可视化所需的依赖: + +```shell +python3 -m pip install notebook tidbcloudlake-sqlalchemy pandas matplotlib +``` + +`tidbcloudlake-sqlalchemy` 包会安装 SQLAlchemy 以及所需的 {{{ .lake }}} Python 驱动。 + +启动 Jupyter Notebook: + +```shell +jupyter notebook +``` + +在 Jupyter 接口中,创建一个 Python notebook。 + +## 连接到 TiDB Cloud Lake {#connect-to-tidb-cloud-lake} + +SQLAlchemy 连接 URI 使用以下格式: + +```text +lake://:@:443/?warehouse= +``` + +为避免将凭证存储在 notebook 中,请在启动 Jupyter Notebook 之前,将连接 URI 设置到环境变量中: + +```shell +export LAKE_SQLALCHEMY_URI='lake://:@:443/?warehouse=' +``` + +在 notebook 中,创建一个 SQLAlchemy engine: + +```python +import os + +from sqlalchemy import create_engine, text + +engine = create_engine(os.environ["LAKE_SQLALCHEMY_URI"]) +``` + +## 查询并可视化数据 {#query-and-visualize-data} + +运行以下单元以创建示例表并对其进行查询: + +```python +with engine.connect() as connection: + connection.execute(text("DROP TABLE IF EXISTS jupyter_sales")) + connection.execute( + text( + """ + CREATE TABLE jupyter_sales ( + sale_date DATE, + quantity INT + ) + """ + ) + ) + connection.execute( + text( + """ + INSERT INTO jupyter_sales VALUES + ('2026-08-01', 5), + ('2026-08-01', 3), + ('2026-08-02', 4), + ('2026-08-03', 10) + """ + ) + ) + result = connection.execute( + text( + """ + SELECT sale_date, SUM(quantity) AS total_quantity + FROM jupyter_sales + GROUP BY sale_date + ORDER BY sale_date + """ + ) + ) + rows = result.fetchall() + columns = list(result.keys()) +``` + +将查询结果转换为 pandas DataFrame,并创建柱状图: + +```python +import matplotlib.pyplot as plt +import pandas as pd + +df = pd.DataFrame(rows, columns=columns) +df.plot.bar(x="sale_date", y="total_quantity", legend=False) +plt.ylabel("Quantity") +plt.tight_layout() +plt.show() +``` + +完成本教程后,删除示例表: + +```python +with engine.connect() as connection: + connection.execute(text("DROP TABLE IF EXISTS jupyter_sales")) +``` + +## 相关资源 {#related-resources} + +- [PyPI 上的 `tidbcloudlake-sqlalchemy`](https://pypi.org/project/tidbcloudlake-sqlalchemy/) +- [使用 Python 连接到 TiDB Cloud Lake](/tidb-cloud-lake/guides/connect-using-python.md) \ No newline at end of file diff --git a/tidb-cloud-lake/guides/kafka-credentials.md b/tidb-cloud-lake/guides/kafka-credentials.md new file mode 100644 index 0000000000000..a602d36988e83 --- /dev/null +++ b/tidb-cloud-lake/guides/kafka-credentials.md @@ -0,0 +1,43 @@ +--- +title: Kafka - Credentials(Beta) +summary: 创建一个 “Kafka - Credentials” 数据源,用于存储 Kafka 连接信息,以便在 Kafka Consumer 集成任务中复用。 +--- + +# Kafka - Credentials(Beta) + +本页介绍如何创建 `Kafka - Credentials` 数据源。该数据源用于存储访问 Kafka 集群所需的 broker 地址、认证方法和连接凭据。你可以在多个 Kafka Consumer 集成任务中复用这些设置。 + +`Kafka - Credentials` 仅存储 Kafka 连接信息。它本身不会消费消息。实际读取 Kafka topic 消息并将其写入内部对象存储的过程,由 [Kafka Consumer Integration Task (Beta)](/tidb-cloud-lake/guides/integrate-with-kafka.md) 执行。 + +## 使用场景 {#use-cases} + +- 集中管理 Kafka broker 地址和认证设置 +- 在多个 Kafka Consumer 任务之间复用相同的 Kafka 连接设置 +- 当多个任务引用同一配置时,可在一个位置统一修改 Kafka 地址、认证方法或账户信息 + +## 创建 Kafka - Credentials {#create-kafka-credentials} + +1. 进入 **Data** > **Data Sources**,然后点击 **Create Data Source**。 +2. 选择 **Kafka - Credentials** 作为服务类型,然后填写连接详情: + + | 字段 | 必填 | 描述 | + |-------|----------|-------------| + | **Name** | 是 | 数据源的描述性名称 | + | **Brokers** | 是 | Kafka broker 地址列表。多个地址之间使用逗号分隔,例如 `broker-1:9092,broker-2:9093,broker-3:9092` | + | **Authentication** | 是 | Kafka 认证方法。支持的选项为 **None** 和 **SASL/PLAIN** | + | **TLS encryption** | 否 | 是否启用 TLS 加密 | + | **Username** | 适用时必填 | Kafka 用户名。选择 **SASL/PLAIN** 时为必填项 | + | **Password** | 适用时必填 | Kafka 密码。选择 **SASL/PLAIN** 时为必填项 | + +3. 点击 **Test Connectivity** 以验证连接。如果测试成功,点击 **OK** 保存数据源。 + +## 配置建议 {#configuration-recommendations} + +- 建议为平台创建专用的 Kafka 用户,而不是共享应用账户。 +- 如果你的 Kafka 集群要求加密连接,请启用 **TLS encryption**。 +- 如果你选择 **SASL/PLAIN**,请确保 Kafka 用户具有读取下游任务将要消费的 topic 的权限。 +- 在保存数据源之前运行 **Test Connectivity**,以验证 broker 地址、网络访问和认证设置。 + +## 后续步骤 {#next-steps} + +创建数据源后,你可以使用它来创建 [Kafka Consumer Integration Task (Beta)](/tidb-cloud-lake/guides/integrate-with-kafka.md)。 diff --git a/tidb-cloud-lake/guides/lakehouse-etl.md b/tidb-cloud-lake/guides/lakehouse-etl.md new file mode 100644 index 0000000000000..692b51c931018 --- /dev/null +++ b/tidb-cloud-lake/guides/lakehouse-etl.md @@ -0,0 +1,238 @@ +--- +title: Lakehouse ETL +summary: 场景:CityDrive 的数据工程团队将每一批行车记录仪数据导出为 Parquet(视频、帧事件、元信息 JSON、嵌入向量、GPS 轨迹、红绿灯距离)。这些 Parquet 文件汇总了从原始视频流中提取的所有多模态信号,构成了计算集群的基础。他们希望通过单个 COPY pipeline 来修改 {{{ .lake }}} 中的共享表,以刷新 {{{ .lake }}} 中的共享表。 +--- + +# Lakehouse ETL + +> **场景:** CityDrive 的数据工程团队将每一批行车记录仪数据导出为 Parquet(视频、帧事件、元信息 JSON、嵌入向量、GPS 轨迹、红绿灯距离)。这些 Parquet 文件汇总了从原始视频流中提取的所有多模态信号,构成了计算集群的基础。他们希望通过单个 COPY pipeline 来修改 {{{ .lake }}} 中的共享表,以刷新 {{{ .lake }}} 中的共享表。 + +加载流程非常直接: + +``` +Object storage → STAGE → COPY INTO tables → (optional) STREAMS/TASKS +``` + +根据你的环境调整存储桶路径或格式,然后粘贴下面的命令。语法与数据加载指南保持一致。 + +--- + +## 1. Create a Stage {#1-create-a-stage} + +将一个可复用的 stage 指向存放 CityDrive 导出数据的存储桶。将凭证和 URL 替换为你自己的账户信息;这里使用 Parquet,但只要更改 `FILE_FORMAT`,也可以使用任何受支持的格式。 + +```sql +CREATE OR REPLACE CONNECTION citydrive_s3 + STORAGE_TYPE = 's3' + ACCESS_KEY_ID = '' + SECRET_ACCESS_KEY = ''; + +CREATE OR REPLACE STAGE citydrive_stage + URL = 's3://citydrive-lakehouse/raw/' + CONNECTION = (CONNECTION_NAME = 'citydrive_s3') + FILE_FORMAT = (TYPE = 'PARQUET'); +``` + +> [!IMPORTANT] +> 请将示例中的 AWS 密钥和存储桶 URL 占位符替换为你环境中的真实值。没有有效凭证时,`LIST`、`SELECT ... FROM @citydrive_stage` 和 `COPY INTO` 语句都会因 S3 返回的 `InvalidAccessKeyId`/403 错误而失败。 + +快速检查: + +```sql +LIST @citydrive_stage/videos/; +LIST @citydrive_stage/frame-events/; +LIST @citydrive_stage/manifests/; +LIST @citydrive_stage/frame-embeddings/; +LIST @citydrive_stage/frame-locations/; +LIST @citydrive_stage/traffic-lights/; +``` + +--- + +## 2. Peek at the Files {#2-peek-at-the-files} + +在加载之前,对 stage 执行 `SELECT`,以确认 schema 和示例行。 + +```sql +SELECT * +FROM @citydrive_stage/videos/capture_date=2025-01-01/videos.parquet +LIMIT 5; + +SELECT * +FROM @citydrive_stage/frame-events/batch_2025_01_01.parquet +LIMIT 5; +``` + +{{{ .lake }}} 会根据 stage 定义推导格式,因此这里不需要额外选项。 + +--- + +## 3. COPY INTO the Unified Tables {#3-copy-into-the-unified-tables} + +每份导出数据都映射到各指南中共用的一张共享表。内联类型转换可以在上游字段顺序发生变化时,仍保持 schema 一致。 + +### `citydrive_videos` {#citydrive-videos} + +```sql +COPY INTO citydrive_videos (video_id, vehicle_id, capture_date, route_name, weather, camera_source, duration_sec) +FROM ( + SELECT video_id::STRING, + vehicle_id::STRING, + capture_date::DATE, + route_name::STRING, + weather::STRING, + camera_source::STRING, + duration_sec::INT + FROM @citydrive_stage/videos/ +) +FILE_FORMAT = (TYPE = 'PARQUET'); +``` + +### `frame_events` {#frame-events} + +```sql +COPY INTO frame_events (frame_id, video_id, frame_index, collected_at, event_tag, risk_score, speed_kmh) +FROM ( + SELECT frame_id::STRING, + video_id::STRING, + frame_index::INT, + collected_at::TIMESTAMP, + event_tag::STRING, + risk_score::DOUBLE, + speed_kmh::DOUBLE + FROM @citydrive_stage/frame-events/ +) +FILE_FORMAT = (TYPE = 'PARQUET'); +``` + +### `frame_metadata_catalog` {#frame-metadata-catalog} + +```sql +COPY INTO frame_metadata_catalog (doc_id, meta_json, captured_at) +FROM ( + SELECT doc_id::STRING, + meta_json::VARIANT, + captured_at::TIMESTAMP + FROM @citydrive_stage/manifests/ +) +FILE_FORMAT = (TYPE = 'PARQUET'); +``` + +### `frame_embeddings` {#frame-embeddings} + +```sql +COPY INTO frame_embeddings (frame_id, video_id, sensor_view, embedding, encoder_build, created_at) +FROM ( + SELECT frame_id::STRING, + video_id::STRING, + sensor_view::STRING, + embedding::VECTOR(768), -- replace with your actual dimension + encoder_build::STRING, + created_at::TIMESTAMP + FROM @citydrive_stage/frame-embeddings/ +) +FILE_FORMAT = (TYPE = 'PARQUET'); +``` + +### `frame_geo_points` {#frame-geo-points} + +```sql +COPY INTO frame_geo_points (video_id, frame_id, position_wgs84, solution_grade, source_system, created_at) +FROM ( + SELECT video_id::STRING, + frame_id::STRING, + position_wgs84::GEOMETRY, + solution_grade::INT, + source_system::STRING, + created_at::TIMESTAMP + FROM @citydrive_stage/frame-locations/ +) +FILE_FORMAT = (TYPE = 'PARQUET'); +``` + +### `signal_contact_points` {#signal-contact-points} + +```sql +COPY INTO signal_contact_points (node_id, signal_position, video_id, frame_id, frame_position, distance_m, created_at) +FROM ( + SELECT node_id::STRING, + signal_position::GEOMETRY, + video_id::STRING, + frame_id::STRING, + frame_position::GEOMETRY, + distance_m::DOUBLE, + created_at::TIMESTAMP + FROM @citydrive_stage/traffic-lights/ +) +FILE_FORMAT = (TYPE = 'PARQUET'); +``` + +完成此步骤后,所有下游工作负载——SQL analytics、Elasticsearch `QUERY()`、向量相似度、地理空间过滤——都会读取完全相同的数据。 + +--- + +## 4. Streams for Incremental Reactions (Optional) {#4-streams-for-incremental-reactions-optional} + +如果你希望下游作业只消费自上一批次以来新增的行,请使用 stream。 + +```sql +CREATE OR REPLACE STREAM frame_events_stream ON TABLE frame_events; + +SELECT * FROM frame_events_stream; -- shows newly copied rows +-- …process rows… +SELECT * FROM frame_events_stream WITH CONSUME; -- advance the offset +``` + +`WITH CONSUME` 可确保在处理完这些行后,stream 游标继续向前推进。参考:[Streams](/tidb-cloud-lake/guides/track-and-transform-data-via-streams.md)。 + +--- + +## 5. Scheduled Loads 的任务(可选) {#5-tasks-for-scheduled-loads-optional} + +任务会按调度运行**一条 SQL 语句**。你可以按表创建轻量级任务;如果你更希望只有一个入口点,也可以将相关逻辑封装在存储过程中。 + +```sql +CREATE OR REPLACE TASK task_load_citydrive_videos + WAREHOUSE = 'default' + SCHEDULE = 10 MINUTE +AS + COPY INTO citydrive_videos (video_id, vehicle_id, capture_date, route_name, weather, camera_source, duration_sec) + FROM ( + SELECT video_id::STRING, + vehicle_id::STRING, + capture_date::DATE, + route_name::STRING, + weather::STRING, + camera_source::STRING, + duration_sec::INT + FROM @citydrive_stage/videos/ + ) + FILE_FORMAT = (TYPE = 'PARQUET'); + +ALTER TASK task_load_citydrive_videos RESUME; + +CREATE OR REPLACE TASK task_load_frame_events + WAREHOUSE = 'default' + SCHEDULE = 10 MINUTE + AS + COPY INTO frame_events (frame_id, video_id, frame_index, collected_at, event_tag, risk_score, speed_kmh) + FROM ( + SELECT frame_id::STRING, + video_id::STRING, + frame_index::INT, + collected_at::TIMESTAMP, + event_tag::STRING, + risk_score::DOUBLE, + speed_kmh::DOUBLE + FROM @citydrive_stage/frame-events/ + ) + FILE_FORMAT = (TYPE = 'PARQUET'); + +ALTER TASK task_load_frame_events RESUME; +``` + +你可以使用相同的模式为 `frame_metadata_catalog`、embeddings 或 GPS 数据添加更多任务。完整选项请参见:[任务](/tidb-cloud-lake/guides/automate-data-loading-with-tasks.md)。 + +--- + +这些作业运行后,Unified Workloads 系列中的每篇指南都会从同一组 CityDrive 表中读取数据——无需额外的 ETL 层,也无需重复存储。 \ No newline at end of file diff --git a/tidb-cloud-lake/guides/load-avro.md b/tidb-cloud-lake/guides/load-avro.md new file mode 100644 index 0000000000000..e013b88b2b080 --- /dev/null +++ b/tidb-cloud-lake/guides/load-avro.md @@ -0,0 +1,112 @@ +--- +title: 将 Avro 加载到 TiDB Cloud Lake +summary: Apache Avro™ 是记录数据的主流序列化格式,也是流式数据管道的首选格式。 +--- + +# 将 Avro 加载到 TiDB Cloud Lake + +## 什么是 Avro? {#what-is-avro} + +[Apache Avro™](https://avro.apache.org/) 是记录数据的主流序列化格式,也是流式数据管道的首选格式。 + +## 加载 Avro 文件 {#loading-avro-file} + +加载 AVRO 文件的通用语法如下: + +```sql +COPY INTO [.] + FROM { internalStage | externalStage | externalLocation } +[ PATTERN = '' ] +FILE_FORMAT = (TYPE = AVRO) +``` + +- 有关更多 Avro 文件格式选项,请参阅[Avro 文件格式选项](/tidb-cloud-lake/sql/input-output-file-formats.md#avro-options)。 +- 有关更多 COPY INTO table 选项,请参阅[COPY INTO table](/tidb-cloud-lake/sql/copy-into-table.md)。 + +## 教程:通过远程 HTTP URL 将 Avro 数据加载到 {{{ .lake }}} {#tutorial-loading-avro-data-into-lake-from-remote-http-url} + +在本教程中,你将基于 Avro schema 在 {{{ .lake }}} 中创建一张表,并通过 HTTPS 直接从 GitHub 托管的 `.avro` 文件加载 Avro 数据。 + +### 第 1 步:查看 Avro schema {#step-1-review-the-avro-schema} + +在 {{{ .lake }}} 中创建表之前,先快速了解一下我们要使用的 Avro schema:[userdata.avsc](https://github.com/Teradata/kylo/blob/master/samples/sample-data/avro/userdata.avsc)。该 schema 定义了一个名为 `User` 的 record,包含 13 个字段,大多为字符串类型,另外还有 `int` 和 `float` 类型。 + +```json +{ + "type": "record", + "name": "User", + "fields": [ + {"name": "registration_dttm", "type": "string"}, + {"name": "id", "type": "int"}, + {"name": "first_name", "type": "string"}, + {"name": "last_name", "type": "string"}, + {"name": "email", "type": "string"}, + {"name": "gender", "type": "string"}, + {"name": "ip_address", "type": "string"}, + {"name": "cc", "type": "string"}, + {"name": "country", "type": "string"}, + {"name": "birthdate", "type": "string"}, + {"name": "salary", "type": "float"}, + {"name": "title", "type": "string"}, + {"name": "comments", "type": "string"} + ] +} +``` + +### 第 2 步:在 {{{ .lake }}} 中创建表 {#step-2-create-a-table-in-lake} + +创建一张与该 schema 中定义的结构相匹配的表: + +```sql +CREATE TABLE userdata ( + registration_dttm STRING, + id INT, + first_name STRING, + last_name STRING, + email STRING, + gender STRING, + ip_address STRING, + cc VARIANT, + country STRING, + birthdate STRING, + salary FLOAT, + title STRING, + comments STRING +); +``` + +### 第 3 步:从远程 HTTPS URL 加载数据 {#step-3-load-data-from-a-remote-https-url} + +```sql +COPY INTO userdata +FROM 'https://raw.githubusercontent.com/Teradata/kylo/master/samples/sample-data/avro/userdata1.avro' +FILE_FORMAT = (type = avro); +``` + +```sql +┌────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ +│ File │ Rows_loaded │ Errors_seen │ First_error │ First_error_line │ +├──────────────────────────────────────────────────────────────┼─────────────┼─────────────┼──────────────────┼──────────────────┤ +│ Teradata/kylo/master/samples/sample-data/avro/userdata1.avro │ 1000 │ 0 │ NULL │ NULL │ +└────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ +``` + +### 第 4 步:查询数据 {#step-4-query-the-data} + +现在,你可以查看刚刚导入的数据: + +```sql +SELECT id, first_name, email, salary FROM userdata LIMIT 5; +``` + +```sql +┌───────────────────────────────────────────────────────────────────────────────────┐ +│ id │ first_name │ email │ salary │ +├─────────────────┼──────────────────┼──────────────────────────┼───────────────────┤ +│ 1 │ Amanda │ ajordan0@com.com │ 49756.53 │ +│ 2 │ Albert │ afreeman1@is.gd │ 150280.17 │ +│ 3 │ Evelyn │ emorgan2@altervista.org │ 144972.52 │ +│ 4 │ Denise │ driley3@gmpg.org │ 90263.05 │ +│ 5 │ Carlos │ cburns4@miitbeian.gov.cn │ NULL │ +└───────────────────────────────────────────────────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/guides/load-csv.md b/tidb-cloud-lake/guides/load-csv.md new file mode 100644 index 0000000000000..d4b12ae48371b --- /dev/null +++ b/tidb-cloud-lake/guides/load-csv.md @@ -0,0 +1,136 @@ +--- +title: 将 CSV 加载到 TiDB Cloud Lake +summary: CSV(Comma Separated Values,逗号分隔值)是一种用于存储表格数据的简单文件格式,例如电子表格或数据库中的数据。CSV 文件是纯文本文件,以表格形式包含数据,其中每一行表示一条新记录,各列之间通过分隔符分隔。 +--- + +# 将 CSV 加载到 TiDB Cloud Lake + +## 什么是 CSV? {#what-is-csv} + +CSV(Comma Separated Values,逗号分隔值)是一种用于存储表格数据的简单文件格式,例如电子表格或数据库中的数据。CSV 文件是纯文本文件,以表格形式包含数据,其中每一行表示一条新记录,各列之间通过分隔符分隔。 + +以下示例展示了一个包含两条记录的 CSV 文件: + +```text +Title_0,Author_0 +Title_1,Author_1 +``` + +## 加载 CSV 文件 {#loading-csv-file} + +加载 CSV 文件的常用语法如下: + +```sql +COPY INTO [.] +FROM { userStage | internalStage | externalStage | externalLocation } +[ PATTERN = '' ] +[ FILE_FORMAT = ( + TYPE = CSV, + RECORD_DELIMITER = '', + FIELD_DELIMITER = '', + SKIP_HEADER = , + COMPRESSION = AUTO +) ] +``` + +- 有关更多 CSV 文件格式选项,请参见 [CSV 文件格式选项](/tidb-cloud-lake/sql/input-output-file-formats.md#csv-options)。 +- 有关更多 COPY INTO table 选项,请参见 [COPY INTO table](/tidb-cloud-lake/sql/copy-into-table.md)。 + +## 教程:从 CSV 文件加载数据 {#tutorial-loading-data-from-csv-files} + +### 第 1 步:创建 Internal Stage {#step-1-create-an-internal-stage} + +创建一个 internal stage 来存储 CSV 文件。 + +```sql +CREATE STAGE my_csv_stage; +``` + +### 第 2 步:创建 CSV 文件 {#step-2-create-csv-files} + +使用以下 SQL 语句生成一个 CSV 文件: + +```sql +COPY INTO @my_csv_stage +FROM ( + SELECT + 'Title_' || CAST(number AS VARCHAR) AS title, + 'Author_' || CAST(number AS VARCHAR) AS author + FROM numbers(100000) +) + FILE_FORMAT = (TYPE = CSV, COMPRESSION = gzip) +; +``` + +验证 CSV 文件是否已创建: + +```sql +LIST @my_csv_stage; +``` + +结果: + +```text +┌─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ +│ name │ size │ md5 │ last_modified │ creator │ +├────────────────────────────────────────────────────────────────┼────────┼────────────────────────────────────┼───────────────────────────────┼──────────────────┤ +│ data_4bb7f864-f5f2-41e8-a442-68c2a709be5a_0000_00000000.csv.gz │ 483110 │ "0c8e28daed524468269e44ac13d2f463" │ 2023-12-26 11:37:21.000 +0000 │ NULL │ +└─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ +``` + +### 第 3 步:创建目标表 {#step-3-create-target-table} + +```sql +CREATE TABLE books +( + title VARCHAR, + author VARCHAR +); +``` + +### 第 4 步:直接从 CSV 复制 {#step-4-copying-directly-from-csv} + +要将 CSV 文件中的数据直接复制到表中,请使用以下 SQL 命令: + +```sql +COPY INTO books +FROM @my_csv_stage +PATTERN = '.*[.]csv.gz' +FILE_FORMAT = ( + TYPE = CSV, + FIELD_DELIMITER = ',', + RECORD_DELIMITER = '\n', + SKIP_HEADER = 0, -- Skip the first line if it is a header, here we don't have a header + COMPRESSION = AUTO +); +``` + +结果: + +```text +┌──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ +│ File │ Rows_loaded │ Errors_seen │ First_error │ First_error_line │ +├────────────────────────────────────────────────────────────────┼─────────────┼─────────────┼──────────────────┼──────────────────┤ +│ data_4bb7f864-f5f2-41e8-a442-68c2a709be5a_0000_00000000.csv.gz │ 100000 │ 0 │ NULL │ NULL │ +└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ +``` + +### 第 4 步(可选):使用 SELECT 复制数据 {#step-4-option-using-select-to-copy-data} + +如果你需要更精细的控制,例如在复制过程中转换数据,可以使用 SELECT 语句。更多信息请参见 [`SELECT from CSV`](/tidb-cloud-lake/guides/query-csv-files-in-stage.md)。 + +```sql +COPY INTO books (title, author) +FROM ( + SELECT $1, $2 + FROM @my_csv_stage +) +PATTERN = '.*[.]csv.gz' +FILE_FORMAT = ( + TYPE = 'CSV', + FIELD_DELIMITER = ',', + RECORD_DELIMITER = '\n', + SKIP_HEADER = 0, -- Skip the first line if it is a header, here we don't have a header + COMPRESSION = 'AUTO' +); +``` \ No newline at end of file diff --git a/tidb-cloud-lake/guides/load-from-bucket.md b/tidb-cloud-lake/guides/load-from-bucket.md new file mode 100644 index 0000000000000..4b8331154d98d --- /dev/null +++ b/tidb-cloud-lake/guides/load-from-bucket.md @@ -0,0 +1,75 @@ +--- +title: 从存储桶加载 +summary: 当数据文件存储在对象存储存储桶(例如 Amazon S3)中时,可以使用 COPY INTO 命令将其直接加载到 {{{ .lake }}} 中。请注意,文件必须采用 {{{ .lake }}} 支持的格式,否则无法导入数据。有关 {{{ .lake }}} 支持的文件格式的更多信息,请参见 Input & Output File Formats。 +--- + +# 从存储桶加载 + +当数据文件存储在对象存储存储桶(例如 Amazon S3)中时,可以使用 [COPY INTO](/tidb-cloud-lake/sql/copy-into-table.md) 命令将其直接加载到 {{{ .lake }}} 中。请注意,文件必须采用 {{{ .lake }}} 支持的格式,否则无法导入数据。有关 {{{ .lake }}} 支持的文件格式的更多信息,请参见 [输入与输出文件格式](/tidb-cloud-lake/sql/input-output-file-formats.md)。 + +![image](/media/tidb-cloud-lake/load-data-from-s3.jpeg) + +本教程以 Amazon S3 存储桶为例,提供详细的分步指南,帮助你顺利完成从存储桶中的文件加载数据的过程。 + +## 教程:从 Amazon S3 存储桶加载 {#tutorial-loading-from-amazon-s3-bucket} + +### 开始之前 {#before-you-begin} + +开始之前,请确保你已完成以下任务: + +1. 将示例文件 [books.parquet](https://lakesql-bin.tidbcloud.com/datasets/books.parquet) 下载并保存到本地文件夹中。该文件包含两条记录: + + ```text title='books.parquet' + Transaction Processing,Jim Gray,1992 + Readings in Database Systems,Michael Stonebraker,2004 + ``` + +2. 在 Amazon S3 中创建一个存储桶,并将示例文件上传到该存储桶。具体操作请参考以下链接: + +- 创建存储桶: +- 上传对象: + +在本教程中,将在区域 **US East (Ohio)**(ID:us-east-2)中创建一个名为 **lake-toronto** 的存储桶。 + +### 步骤 1:创建目标表 {#step-1-create-target-table} + +在 {{{ .lake }}} 中使用以下 SQL 语句创建表: + +```sql +USE default; +CREATE TABLE books +( + title VARCHAR, + author VARCHAR, + date VARCHAR +); +``` + +### 步骤 2:将数据复制到表中 {#step-2-copy-data-into-table} + +1. 使用 [COPY INTO](/tidb-cloud-lake/sql/copy-into-table.md) 命令将数据加载到目标表中: + + ```sql + COPY INTO books + FROM 's3://lake-toronto/' + CONNECTION = ( + ACCESS_KEY_ID = '', + SECRET_ACCESS_KEY = '' + ) + PATTERN = '.*[.]parquet' + FILE_FORMAT = ( + TYPE = 'PARQUET' + ); + ``` + +2. 检查已加载的数据: + +```sql +SELECT * FROM books; + +--- +title |author |date| +----------------------------+-------------------+----+ +Transaction Processing |Jim Gray |1992| +Readings in Database Systems|Michael Stonebraker|2004| +``` \ No newline at end of file diff --git a/tidb-cloud-lake/guides/load-from-files.md b/tidb-cloud-lake/guides/load-from-files.md new file mode 100644 index 0000000000000..cd62993690441 --- /dev/null +++ b/tidb-cloud-lake/guides/load-from-files.md @@ -0,0 +1,31 @@ +--- +title: 从文件加载 +summary: TiDB Cloud Lake 提供简单而强大的命令,可将数据文件加载到表中。大多数操作只需一条命令。 +--- + +# 从文件加载 + +{{{ .lake }}} 提供简单而强大的命令,可将数据文件加载到表中。大多数操作只需一条命令。你的数据必须采用[支持的格式](/tidb-cloud-lake/sql/input-output-file-formats.md)。 + +![Data Loading and Unloading Overview](/media/tidb-cloud-lake/load-unload.png) + +## 支持的文件格式 {#supported-file-formats} + +| 格式 | 类型 | 描述 | +|--------|------|-------------| +| [**CSV**](/tidb-cloud-lake/guides/load-csv.md), [**TSV**](/tidb-cloud-lake/guides/load-tsv.md) | 分隔符分隔 | 可自定义分隔符的文本文件 | +| [**NDJSON**](/tidb-cloud-lake/guides/load-ndjson.md) | 半结构化 | 每行一个 JSON 对象 | +| [**Parquet**](/tidb-cloud-lake/guides/load-parquet.md) | 半结构化 | 高效的列式存储格式 | +| [**ORC**](/tidb-cloud-lake/guides/load-orc.md) | 半结构化 | 高性能列式格式 | +| [**Avro**](/tidb-cloud-lake/guides/load-avro.md) | 半结构化 | 带 schema 的紧凑二进制格式 | + +## 按文件位置加载 {#loading-by-file-location} + +选择文件所在的位置,以查找推荐的加载方法: + +| 数据源 | 推荐工具 | 描述 | 文档 | +|-------------|-----------------|-------------|---------------| +| **暂存数据文件** | **COPY INTO** | 从内部/外部 stage 或用户 stage 快速高效地加载 | [从 stage 加载](/tidb-cloud-lake/guides/load-from-stage.md) | +| **云存储** | **COPY INTO** | 从 Amazon S3、Google Cloud Storage、Microsoft Azure 加载 | [从存储桶加载](/tidb-cloud-lake/guides/load-from-bucket.md) | +| **本地文件** | [**LakeSQL**](https://github.com/tidbcloud/lakesql) | {{{ .lake }}} 的原生 CLI 工具,用于加载本地文件 | [从本地文件加载](/tidb-cloud-lake/guides/load-from-local-file.md) | +| **远程文件** | **COPY INTO** | 从远程 HTTP/HTTPS 位置加载数据 | [从远程文件加载](/tidb-cloud-lake/guides/load-from-remote-file.md) | \ No newline at end of file diff --git a/tidb-cloud-lake/guides/load-from-local-file.md b/tidb-cloud-lake/guides/load-from-local-file.md new file mode 100644 index 0000000000000..1305889874a7f --- /dev/null +++ b/tidb-cloud-lake/guides/load-from-local-file.md @@ -0,0 +1,179 @@ +--- +title: 从本地文件加载 +summary: 在将本地数据文件加载到 {{{ .lake }}} 之前,先将其上传到 stage 或存储桶可能并非必要。相反,你可以使用 {{{ .lake }}} 原生 CLI 工具 LakeSQL 直接导入数据。这样可以简化工作流,并节省存储费用。 +--- + +# 从本地文件加载 + +在将本地数据文件加载到 {{{ .lake }}} 之前,先将其上传到 stage 或存储桶可能并非必要。相反,你可以使用 [LakeSQL](/tidb-cloud-lake/guides/connect-using-lakesql.md)({{{ .lake }}} 原生 CLI 工具)直接导入数据。这样可以简化工作流,并节省存储费用。 + +请注意,文件必须采用 {{{ .lake }}} 支持的格式,否则无法导入数据。有关 {{{ .lake }}} 支持的文件格式的更多信息,请参见 [输入与输出文件格式](/tidb-cloud-lake/sql/input-output-file-formats.md)。 + +你还可以使用 JDBC 或 Python 驱动,以编程方式将本地文件加载到表中。 + +## 加载方法 {#load-methods} + +从本地文件加载数据有两种方法: + +1. **Stage**:先将本地文件上传到内部 stage,然后将已暂存文件中的数据复制到表中。文件上传通过 lake-query 或 presigned URL 进行,具体取决于连接选项 `presigned_url_disabled`(默认值:`false`)。 +2. **Streaming**:在上传过程中将文件直接加载到表中。当文件过大,无法作为单个对象存储在对象存储中时,请使用此方法。 + +## 教程 1:从本地文件加载 {#tutorial-1-load-from-a-local-file} + +本教程以 CSV 文件为例,演示如何使用 [LakeSQL](/tidb-cloud-lake/guides/connect-using-lakesql.md) 从本地源将数据导入到 {{{ .lake }}}。 + +### 开始之前 {#before-you-begin} + +下载示例文件 [books.csv](https://lakesql-bin.tidbcloud.com/datasets/books.csv) 并将其保存到本地文件夹中。该文件包含两条记录: + +```text title='books.csv' +Transaction Processing,Jim Gray,1992 +Readings in Database Systems,Michael Stonebraker,2004 +``` + +### 步骤 1:创建数据库和表 {#step-1-create-database-and-table} + +```shell +❯ lakesql +root@localhost:8000/default> CREATE DATABASE book_db; + +root@localhost:8000/default> USE book_db; + +root@localhost:8000/book_db> CREATE TABLE books +( + title VARCHAR, + author VARCHAR, + date VARCHAR +); + +CREATE TABLE books ( + title VARCHAR, + author VARCHAR, + date VARCHAR +) +``` + +### 步骤 2:将数据加载到表中 {#step-2-load-data-into-table} + +使用以下命令发送加载数据请求: + +```shell +❯ lakesql --query='INSERT INTO book_db.books from @_databend_load file_format=(type=csv)' --data=@books.csv +``` + +- `@_databend_load` 是一个占位符,表示本地文件数据。 +- [file_format 子句](/tidb-cloud-lake/sql/input-output-file-formats.md) 使用与 COPY 命令相同的语法。 + +或者,使用 Python 脚本: + +```python +import tidbcloudlake_driver +dsn = "lake://root:@localhost:8000/?sslmode=disable" +client = tidbcloudlake_driver.BlockingLakeClient(dsn) +conn = client.get_conn() +query = "INSERT INTO book_db.books from @_databend_load file_format=(type=csv)" +progress = conn.load_file(query, "book.csv") +conn.close() +``` + +或者,使用 Java 代码: + +```java +import java.io.File; +import java.io.FileInputStream; +import java.sql.Connection; +import java.sql.DriverManager; + +import com.tidbcloud.jdbc.LakeConnection; + +String url = "jdbc:lake://localhost:8000"; +File file = new File("book.csv"); + +try (FileInputStream fileInputStream = new FileInputStream(file); + Connection connection = DriverManager.getConnection(url, "tidbcloud", "tidbcloud")) { + + LakeConnection lakeConnection = connection.unwrap(LakeConnection.class); + + String sql = + "INSERT INTO book_db.books FROM @_databend_load FILE_FORMAT=(TYPE=CSV)"; + + int nUpdate = lakeConnection.loadStreamToTable( + sql, + fileInputStream, + file.length(), + LakeConnection.LoadMethod.Stage + ); +} +``` + +> **Note:** +> +> 请确保你本地的 LakeSQL 可以直接连接到 {{{ .lake }}} 的后端对象存储。 +> 如果不能,则需要指定 `--set presigned_url_disabled=1` 选项以禁用 presigned url 功能。 + +### 步骤 3:验证已加载的数据 {#step-3-verify-loaded-data} + +```shell +root@localhost:8000/book_db> SELECT * FROM books; + +┌───────────────────────────────────────────────────────────────────────┐ +│ title │ author │ date │ +│ Nullable(String) │ Nullable(String) │ Nullable(String) │ +├──────────────────────────────┼─────────────────────┼──────────────────┤ +│ Transaction Processing │ Jim Gray │ 1992 │ +│ Readings in Database Systems │ Michael Stonebraker │ 2004 │ +└───────────────────────────────────────────────────────────────────────┘ +``` + +## 教程 2:加载到指定列 {#tutorial-2-load-into-specified-columns} + +在 [教程 1](#tutorial-1-load-from-a-local-file) 中,你创建了一个包含三列的表,这三列与示例文件中的数据完全对应。你也可以将数据加载到表中的指定列,因此表不需要与待加载数据具有完全相同的列,只要指定的列能够匹配即可。本教程将介绍如何实现这一点。 + +### 开始之前 {#before-you-begin} + +开始本教程之前,请确保你已完成 [教程 1](#tutorial-1-load-from-a-local-file)。 + +### 步骤 1:创建表 {#step-1-create-table} + +创建一个名为 "bookcomments" 的表,与 "books" 表相比,它额外包含一列 "comments": + +```shell +root@localhost:8000/book_db> CREATE TABLE bookcomments +( + title VARCHAR, + author VARCHAR, + comments VARCHAR, + date VARCHAR +); + +CREATE TABLE bookcomments ( + title VARCHAR, + author VARCHAR, + comments VARCHAR, + date VARCHAR +) +``` + +### 步骤 2:将数据加载到表中 {#step-2-load-data-into-table} + +使用以下命令发送加载数据请求: + +```shell +❯ lakesql --query='INSERT INTO book_db.bookcomments(title,author,date) file_format=(type=csv)' --data=@books.csv +``` + +请注意,上述 `query` 部分指定了列(title、author 和 date)以匹配加载的数据。 + +### 步骤 3:验证已加载的数据 {#step-3-verify-loaded-data} + +```shell +root@localhost:8000/book_db> SELECT * FROM bookcomments; + +┌──────────────────────────────────────────────────────────────────────────────────────────┐ +│ title │ author │ comments │ date │ +│ Nullable(String) │ Nullable(String) │ Nullable(String) │ Nullable(String) │ +├──────────────────────────────┼─────────────────────┼──────────────────┼──────────────────┤ +│ Transaction Processing │ Jim Gray │ NULL │ 1992 │ +│ Readings in Database Systems │ Michael Stonebraker │ NULL │ 2004 │ +└──────────────────────────────────────────────────────────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/guides/load-from-remote-file.md b/tidb-cloud-lake/guides/load-from-remote-file.md new file mode 100644 index 0000000000000..50d09ed462abe --- /dev/null +++ b/tidb-cloud-lake/guides/load-from-remote-file.md @@ -0,0 +1,78 @@ +--- +title: 从远程文件加载 +summary: 要将远程文件中的数据加载到 {{{ .lake }}} 中,可以使用 COPY INTO 命令。该命令允许你轻松地将来自多种来源(包括远程文件)的数据复制到 {{{ .lake }}} 中。使用 COPY INTO 时,你可以指定源文件位置、文件格式以及其他相关参数,以根据你的需求定制导入过程。请注意,文件必须采用 {{{ .lake }}} 支持的格式,否则无法导入数据。有关 {{{ .lake }}} 支持的文件格式的更多信息,请参见 Input & Output File Formats。 +--- + +# 从远程文件加载 + +要将远程文件中的数据加载到 {{{ .lake }}} 中,可以使用 [COPY INTO](/tidb-cloud-lake/sql/copy-into-table.md) 命令。该命令允许你轻松地将来自多种来源(包括远程文件)的数据复制到 {{{ .lake }}} 中。使用 COPY INTO 时,你可以指定源文件位置、文件格式以及其他相关参数,以根据你的需求定制导入过程。请注意,文件必须采用 {{{ .lake }}} 支持的格式,否则无法导入数据。有关 {{{ .lake }}} 支持的文件格式的更多信息,请参见 [输入与输出文件格式](/tidb-cloud-lake/sql/input-output-file-formats.md)。 + +## 使用 Glob 模式加载 {#loading-with-glob-patterns} + +{{{ .lake }}} 支持通过 glob 模式从远程文件加载数据。这些模式可用于高效且灵活地从遵循特定命名约定的多个文件中导入数据。{{{ .lake }}} 支持以下 glob 模式: + +### 集合模式 {#set-pattern} + +glob 表达式中的集合模式可用于匹配集合中的任意一个字符。例如,假设有名为 `data_file_a.csv`、`data_file_b.csv` 和 `data_file_c.csv` 的文件。你可以使用集合模式从这三个文件中加载数据: + +```sql +COPY INTO your_table +FROM 'https://your-remote-location/data_file_{a,b,c}.csv' ... +``` + +### 范围模式 {#range-pattern} + +当处理名为 `data_file_001.csv`、`data_file_002.csv` 和 `data_file_003.csv` 的文件时,范围模式会很有用。你可以像下面这样使用范围模式从这一系列文件中加载数据: + +```sql +COPY INTO your_table +FROM 'https://your-remote-location/data_file_[001-003].csv' ... +``` + +## 教程 - 从远程文件加载 {#tutorial-load-from-a-remote-file} + +本教程演示如何将远程 CSV 文件中的数据导入到 {{{ .lake }}} 中。示例文件 [books.csv](https://lakesql-bin.tidbcloud.com/datasets/books.csv) 包含两条记录: + +```text title='books.csv' +Transaction Processing,Jim Gray,1992 +Readings in Database Systems,Michael Stonebraker,2004 +``` + +### 步骤 1. 创建表 {#step-1-create-table} + +```sql +CREATE TABLE books +( + title VARCHAR, + author VARCHAR, + date VARCHAR +); +``` + +### 步骤 2. 将数据加载到表中 {#step-2-load-data-into-table} + +```sql +COPY INTO books +FROM 'https://lakesql-bin.tidbcloud.com/datasets/books.csv' +FILE_FORMAT = ( + TYPE = 'CSV', + FIELD_DELIMITER = ',', + RECORD_DELIMITER = '\n', + SKIP_HEADER = 0 +); +``` + +### 步骤 3. 验证已加载的数据 {#step-3-verify-loaded-data} + +```sql +SELECT * FROM books; +``` + +```text title='Result:' +┌──────────────────────────────────┬─────────────────────┬───────┐ +│ title │ author │ date │ +├──────────────────────────────────┼─────────────────────┼───────┤ +│ Transaction Processing │ Jim Gray │ 1992 │ +│ Readings in Database Systems │ Michael Stonebraker │ 2004 │ +└──────────────────────────────────┴─────────────────────┴───────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/guides/load-from-stage.md b/tidb-cloud-lake/guides/load-from-stage.md new file mode 100644 index 0000000000000..116b891448f67 --- /dev/null +++ b/tidb-cloud-lake/guides/load-from-stage.md @@ -0,0 +1,240 @@ +--- +title: 从 Stage 加载 +summary: "{{{ .lake }}} 使你能够轻松地从上传到用户 stage 或内部/外部 stage 的文件中导入数据。为此,你可以先使用 LakeSQL 将文件上传到 stage,然后使用 COPY INTO 命令从 stage 中的文件加载数据。请注意,文件必须采用 {{{ .lake }}} 支持的格式,否则无法导入数据。有关 {{{ .lake }}} 支持的文件格式的更多信息,请参见 Input & Output File Formats。" +--- + +# 从 Stage 加载 + +{{{ .lake }}} 使你能够轻松地从上传到用户 stage 或内部/外部 stage 的文件中导入数据。为此,你可以先使用 [LakeSQL](/tidb-cloud-lake/guides/connect-using-lakesql.md) 将文件上传到 stage,然后使用 [COPY INTO](/tidb-cloud-lake/sql/copy-into-table.md) 命令从 stage 中的文件加载数据。请注意,文件必须采用 {{{ .lake }}} 支持的格式,否则无法导入数据。有关 {{{ .lake }}} 支持的文件格式的更多信息,请参见 [输入与输出文件格式](/tidb-cloud-lake/sql/input-output-file-formats.md)。 + +![image](/media/tidb-cloud-lake/load-data-from-stage.png) + +以下教程提供了详细的分步指南,帮助你顺利完成从 stage 中的文件加载数据的过程。 + +## 开始之前 {#before-you-begin} + +开始之前,请确保你已完成以下任务: + +- 下载示例文件 [books.parquet](https://lakesql-bin.tidbcloud.com/datasets/books.parquet) 并将其保存到本地文件夹中。该文件包含两条记录: + +```text +Transaction Processing,Jim Gray,1992 +Readings in Database Systems,Michael Stonebraker,2004 +``` + +- 在 {{{ .lake }}} 中使用以下 SQL 语句创建表: + +```sql +USE default; +CREATE TABLE books +( + title VARCHAR, + author VARCHAR, + date VARCHAR +); +``` + +## 教程 1:从用户 stage 加载 {#tutorial-1-loading-from-user-stage} + +按照本教程将示例文件上传到用户 stage,并将 stage 中文件的数据加载到 {{{ .lake }}} 中。 + +### 步骤 1. 上传示例文件 {#step-1-upload-sample-file} + +1. 使用 [LakeSQL](/tidb-cloud-lake/guides/connect-using-lakesql.md) 上传示例文件: + + ```sql + root@localhost:8000/default> PUT fs:///Users/eric/Documents/books.parquet @~ + + ┌───────────────────────────────────────────────┐ + │ file │ status │ + │ String │ String │ + ├─────────────────────────────────────┼─────────┤ + │ /Users/eric/Documents/books.parquet │ SUCCESS │ + └───────────────────────────────────────────────┘ + ``` + +2. 验证 stage 中的文件: + +```sql +LIST @~; + +name |size|md5 |last_modified |creator| +-------------+----+----------------------------------+-----------------------------+-------+ +books.parquet| 998|"88432bf90aadb79073682988b39d461c"|2023-06-27 16:03:51.000 +0000| | +``` + +### 步骤 2. 将数据复制到表中 {#step-2-copy-data-into-table} + +1. 使用 [COPY INTO](/tidb-cloud-lake/sql/copy-into-table.md) 命令将数据加载到目标表中: + + ```sql + COPY INTO books FROM @~ files=('books.parquet') FILE_FORMAT = (TYPE = PARQUET); + ``` + +2. 验证已加载的数据: + +```sql +SELECT * FROM books; + +--- +title |author |date| +----------------------------+-------------------+----+ +Transaction Processing |Jim Gray |1992| +Readings in Database Systems|Michael Stonebraker|2004| +``` + +## 教程 2:从内部 stage 加载 {#tutorial-2-loading-from-internal-stage} + +按照本教程将示例文件上传到内部 stage,并将 stage 中文件的数据加载到 {{{ .lake }}} 中。 + +### 步骤 1. 创建内部 stage {#step-1-create-an-internal-stage} + +1. 使用 [CREATE STAGE](/tidb-cloud-lake/sql/create-stage.md) 命令创建内部 stage: + + ```sql + CREATE STAGE my_internal_stage; + ``` + +2. 验证已创建的 stage: + + ```sql + SHOW STAGES; + + ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ name │ stage_type │ storage_type │ url │ endpoint │ has_credentials │ has_encryption_key │ storage_params │ file_format_options │ creator │ created_on │ comment │ owner │ + │ String │ String │ Nullable(String) │ Nullable(String) │ Nullable(String) │ Boolean │ Boolean │ Nullable(Variant) │ Variant │ Nullable(String) │ Timestamp │ String │ Nullable(String) │ + ├───────────────────┼────────────┼──────────────────┼──────────────────┼──────────────────┼─────────────────┼───────────────────────┼───────────────────┼──────────────────────┼──────────────────┼─────────────┼─────────┼──────────────────┤ + │ my_internal_stage │ Internal │ NULL │ NULL │ NULL │ false │ false │ NULL │ {"compression":"Zst… │ 'root'@'%' │ 2026-06-16 │ │ account_admin │ + │ │ │ │ │ │ │ │ │ │ │ 22:21:19… │ │ │ + ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ + ``` + +### 步骤 2. 上传示例文件 {#step-2-upload-sample-file} + +1. 使用 [LakeSQL](/tidb-cloud-lake/guides/connect-using-lakesql.md) 上传示例文件: + + ```sql + root@localhost:8000/default> CREATE STAGE my_internal_stage; + + root@localhost:8000/default> PUT fs:///Users/eric/Documents/books.parquet @my_internal_stage + + ┌───────────────────────────────────────────────┐ + │ file │ status │ + │ String │ String │ + ├─────────────────────────────────────┼─────────┤ + │ /Users/eric/Documents/books.parquet │ SUCCESS │ + └───────────────────────────────────────────────┘ + ``` + +2. 验证 stage 中的文件: + +```sql +LIST @my_internal_stage; + +name |size |md5 |last_modified |creator| +-----------------------------------+------+----------------------------------+-----------------------------+-------+ +books.parquet | 998|"88432bf90aadb79073682988b39d461c"|2023-06-28 02:32:15.000 +0000| | +``` + +### 步骤 3. 将数据复制到表中 {#step-3-copy-data-into-table} + +1. 使用 [COPY INTO](/tidb-cloud-lake/sql/copy-into-table.md) 命令将数据加载到目标表中: + + ```sql + COPY INTO books + FROM @my_internal_stage + FILES = ('books.parquet') + FILE_FORMAT = ( + TYPE = 'PARQUET' + ); + ``` + +2. 验证已加载的数据: + +```sql +SELECT * FROM books; + +--- +title |author |date| +----------------------------+-------------------+----+ +Transaction Processing |Jim Gray |1992| +Readings in Database Systems|Michael Stonebraker|2004| +``` + +## 教程 3:从外部 stage 加载 {#tutorial-3-loading-from-external-stage} + +按照本教程将示例文件上传到外部 stage,并将 stage 中文件的数据加载到 {{{ .lake }}} 中。 + +### 步骤 1. 创建外部 stage {#step-1-create-an-external-stage} + +1. 使用 [CREATE STAGE](/tidb-cloud-lake/sql/create-stage.md) 命令创建外部 stage: + + ```sql + CREATE STAGE my_external_stage + URL = 's3://lake' + CONNECTION = ( + ENDPOINT_URL = 'http://127.0.0.1:9000', + ACCESS_KEY_ID = 'ROOTUSER', + SECRET_ACCESS_KEY = 'CHANGEME123' + ); + ``` + +2. 验证已创建的 stage: + + ```sql + SHOW STAGES; + + name |stage_type|creator |comment| + -----------------+----------+------------------+-------+ + my_external_stage|External |'root'@'%'| | + ``` + +### 第 2 步:上传示例文件 {#step-2-upload-sample-file} + +1. 使用 [LakeSQL](/tidb-cloud-lake/guides/connect-using-lakesql.md) 上传示例文件: + + ```sql + root@localhost:8000/default> PUT fs:///Users/eric/Documents/books.parquet @my_external_stage + + ┌───────────────────────────────────────────────┐ + │ file │ status │ + │ String │ String │ + ├─────────────────────────────────────┼─────────┤ + │ /Users/eric/Documents/books.parquet │ SUCCESS │ + └───────────────────────────────────────────────┘ + ``` + +2. 验证已暂存的文件: + + ```sql + LIST @my_external_stage; + + name |size|md5 |last_modified |creator| + -------------+----+----------------------------------+-----------------------------+-------+ + books.parquet| 998|"88432bf90aadb79073682988b39d461c"|2023-06-28 04:13:15.178 +0000| | + ``` + +### 第 3 步:将数据复制到表中 {#step-3-copy-data-into-table} + +1. 使用 [COPY INTO](/tidb-cloud-lake/sql/copy-into-table.md) 命令将数据加载到目标表中: + + ```sql + COPY INTO books + FROM @my_external_stage + FILES = ('books.parquet') + FILE_FORMAT = ( + TYPE = 'PARQUET' + ); + ``` + +2. 验证已加载的数据: + +```sql +SELECT * FROM books; + +--- +title |author |date| +----------------------------+-------------------+----+ +Transaction Processing |Jim Gray |1992| +Readings in Database Systems|Michael Stonebraker|2004| +``` \ No newline at end of file diff --git a/tidb-cloud-lake/guides/load-ndjson.md b/tidb-cloud-lake/guides/load-ndjson.md new file mode 100644 index 0000000000000..1096ad56e264e --- /dev/null +++ b/tidb-cloud-lake/guides/load-ndjson.md @@ -0,0 +1,125 @@ +--- +title: 将 NDJSON 加载到 TiDB Cloud Lake +summary: NDJSON 构建于 JSON 之上,并且是 JSON 的严格子集。每一行都必须包含一个独立且完整的有效 JSON 对象。 +--- + +# 将 NDJSON 加载到 TiDB Cloud Lake + +## 什么是 NDJSON? {#what-is-ndjson} + +NDJSON 构建于 JSON 之上,并且是 JSON 的严格子集。每一行都必须包含一个独立且完整的有效 JSON 对象。 + +以下示例展示了一个包含两个 JSON 对象的 NDJSON 文件: + +```text +{"title":"Title_0","author":"Author_0"} +{"title":"Title_1","author":"Author_1"} +``` + +## 加载 NDJSON 文件 {#loading-ndjson-file} + +加载 NDJSON 文件的通用语法如下: + +```sql +COPY INTO [.] +FROM { userStage | internalStage | externalStage | externalLocation } +[ PATTERN = '' ] +[ FILE_FORMAT = ( + TYPE = NDJSON, + COMPRESSION = AUTO +) ] +``` + +- 有关更多 NDJSON 文件格式选项,请参见 [NDJSON 文件格式选项](/tidb-cloud-lake/sql/input-output-file-formats.md#ndjson-options)。 +- 有关更多 COPY INTO table 选项,请参见 [COPY INTO table](/tidb-cloud-lake/sql/copy-into-table.md)。 + +## 教程:从 NDJSON 文件加载数据 {#tutorial-loading-data-from-ndjson-files} + +### 第 1 步:创建内部 stage {#step-1-create-an-internal-stage} + +创建一个内部 stage 来存储 NDJSON 文件。 + +```sql +CREATE STAGE my_ndjson_stage; +``` + +### 第 2 步:创建 NDJSON 文件 {#step-2-create-ndjson-files} + +使用以下 SQL 语句生成一个 NDJSON 文件: + +```sql +COPY INTO @my_ndjson_stage +FROM ( + SELECT + 'Title_' || CAST(number AS VARCHAR) AS title, + 'Author_' || CAST(number AS VARCHAR) AS author + FROM numbers(100000) +) + FILE_FORMAT = (TYPE = NDJSON) +; +``` + +验证 NDJSON 文件是否已创建: + +```sql +LIST @my_ndjson_stage; +``` + +结果: + +```text +┌──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ +│ name │ size │ md5 │ last_modified │ creator │ +├────────────────────────────────────────────────────────────────┼─────────┼────────────────────────────────────┼───────────────────────────────┼──────────────────┤ +│ data_b3d94fad-3052-42e4-b090-26409e88c7b9_0000_00000000.ndjson │ 4777780 │ "d1cc98fefc3e3aa0649cade880d754aa" │ 2023-12-26 12:15:59.000 +0000 │ NULL │ +└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ +``` + +### 第 3 步:创建目标表 {#step-3-create-target-table} + +```sql +CREATE TABLE books +( + title VARCHAR, + author VARCHAR +); +``` + +### 第 4 步:直接从 NDJSON 复制 {#step-4-copying-directly-from-ndjson} + +要将 NDJSON 文件中的数据直接复制到表中,请使用以下 SQL 命令: + +```sql +COPY INTO books +FROM @my_ndjson_stage +PATTERN = '.*[.]ndjson' +FILE_FORMAT = ( + TYPE = NDJSON +); +``` + +结果: + +```text +┌──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ +│ File │ Rows_loaded │ Errors_seen │ First_error │ First_error_line │ +├────────────────────────────────────────────────────────────────┼─────────────┼─────────────┼──────────────────┼──────────────────┤ +│ data_b3d94fad-3052-42e4-b090-26409e88c7b9_0000_00000000.ndjson │ 100000 │ 0 │ NULL │ NULL │ +└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ +``` + +### 第 4 步(可选):使用 SELECT 复制数据 {#step-4-option-using-select-to-copy-data} + +如果你需要更精细的控制,例如在复制过程中转换数据,请使用 SELECT 语句。更多信息,请参见 [`SELECT from NDJSON`](/tidb-cloud-lake/guides/query-ndjson-files-in-stage.md)。 + +```sql +COPY INTO books(title, author) +FROM ( + SELECT $1:title, $1:author + FROM @my_ndjson_stage +) +PATTERN = '.*[.]ndjson' +FILE_FORMAT = ( + TYPE = NDJSON +); +``` \ No newline at end of file diff --git a/tidb-cloud-lake/guides/load-orc.md b/tidb-cloud-lake/guides/load-orc.md new file mode 100644 index 0000000000000..fa428580a8fba --- /dev/null +++ b/tidb-cloud-lake/guides/load-orc.md @@ -0,0 +1,142 @@ +--- +title: 将 ORC 加载到 TiDB Cloud Lake +summary: ORC(Optimized Row Columnar)是一种在数据分析中常用的列式存储格式。 +--- + +# 将 ORC 加载到 TiDB Cloud Lake + +## 什么是 ORC? {#what-is-orc} + +ORC(Optimized Row Columnar)是一种在数据分析中常用的列式存储格式。 + +## 加载 ORC 文件 {#loading-orc-file} + +加载 ORC 文件的通用语法如下: + +```sql +COPY INTO [.] + FROM { internalStage | externalStage | externalLocation } +[ PATTERN = '' ] +FILE_FORMAT = (TYPE = ORC) +``` + +- 有关更多 ORC 文件格式选项,请参阅 [ORC 文件格式选项](/tidb-cloud-lake/sql/input-output-file-formats.md#orc-options)。 +- 有关更多 COPY INTO table 选项,请参阅 [COPY INTO table](/tidb-cloud-lake/sql/copy-into-table.md)。 + +## 教程:从 ORC 文件加载数据 {#tutorial-loading-data-from-orc-files} + +本教程演示如何将存储在 S3 存储桶中的 ORC 文件数据加载到 {{{ .lake }}} 表中。 + +### Step 1. 创建外部 stage {#step-1-create-an-external-stage} + +创建一个外部 stage,并将其指向 S3 存储桶中的 ORC 文件。 + +```sql +CREATE OR REPLACE CONNECTION aws_s3 + STORAGE_TYPE='s3' + ACCESS_KEY_ID='your-ak' + SECRET_ACCESS_KEY='your-sk'; + +CREATE OR REPLACE STAGE orc_data_stage + URL='s3://lakesql-binaries/datasets/sample-data/orc/' + CONNECTION=(CONNECTION_NAME='aws_s3'); +``` + +列出 stage 中的文件: + +```sql +LIST @orc_data_stage; +``` + +结果: + +```text + +┌────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ +│ name │ size │ md5 │ last_modified │ creator │ +├───────────────┼────────┼────────────────────────────────────┼───────────────────────────────┼──────────────────┤ +│ README.txt │ 494 │ "72529dd37b12faf08b090f941507a4f4" │ 2024-06-05 03:05:02.000 +0000 │ NULL │ +│ userdata1.orc │ 47448 │ "1595b4de335ac1825af2b846e82fbf48" │ 2024-06-05 03:05:36.000 +0000 │ NULL │ +│ userdata2.orc │ 46545 │ "8a8a1db8475a46365fcb3bcf773fa703" │ 2024-06-05 03:06:47.000 +0000 │ NULL │ +│ userdata3.orc │ 47159 │ "fb8a92554f90c9385388bd91eb1a25f1" │ 2024-06-05 03:12:52.000 +0000 │ NULL │ +│ userdata4.orc │ 47219 │ "222b1fbde459fd9233f5da5613dbcfa1" │ 2024-06-05 03:13:05.000 +0000 │ NULL │ +│ userdata5.orc │ 47206 │ "f12d768b5d210f488dcf55ed86ceaca6" │ 2024-06-05 03:13:16.000 +0000 │ NULL │ +└────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ +``` + +### Step 2: 查询 stage 文件 {#step-2-querying-the-stage-files} + +为 ORC 创建一个文件格式,并查询 stage 以查看数据和 schema。 + +```sql +-- Create a ORC file format +CREATE OR REPLACE FILE FORMAT orc_ff TYPE = 'ORC'; + +SELECT * +FROM @orc_data_stage ( + FILE_FORMAT => 'orc_ff', + PATTERN => '.*[.]orc' +) t +LIMIT 10; +``` + +结果: + +```text +┌───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ +│ _col0 │ _col1 │ _col2 │ _col3 │ _col4 │ _col5 │ _col6 │ _col7 │ _col8 │ _col9 │ _col10 │ _col11 │ _col12 │ +├─────────────────────┼─────────────────┼──────────────────┼──────────────────┼──────────────────────────┼──────────────────┼──────────────────┼──────────────────┼────────────────────────┼──────────────────┼───────────────────┼──────────────────────────┼──────────────────┤ +│ 2016-02-03 07:55:29 │ 1 │ Amanda │ Jordan │ ajordan0@com.com │ Female │ 1.197.201.2 │ 6759521864920116 │ Indonesia │ 3/8/1971 │ 49756.53 │ Internal Auditor │ 1E+02 │ +│ 2016-02-03 17:04:03 │ 2 │ Albert │ Freeman │ afreeman1@is.gd │ Male │ 218.111.175.34 │ │ Canada │ 1/16/1968 │ 150280.17 │ Accountant IV │ │ +│ 2016-02-03 01:09:31 │ 3 │ Evelyn │ Morgan │ emorgan2@altervista.org │ Female │ 7.161.136.94 │ 6767119071901597 │ Russia │ 2/1/1960 │ 144972.51 │ Structural Engineer │ │ +│ 2016-02-03 00:36:21 │ 4 │ Denise │ Riley │ driley3@gmpg.org │ Female │ 140.35.109.83 │ 3576031598965625 │ China │ 4/8/1997 │ 90263.05 │ Senior Cost Accountant │ │ +│ 2016-02-03 05:05:31 │ 5 │ Carlos │ Burns │ cburns4@miitbeian.gov.cn │ │ 169.113.235.40 │ 5602256255204850 │ South Africa │ │ NULL │ │ │ +│ 2016-02-03 07:22:34 │ 6 │ Kathryn │ White │ kwhite5@google.com │ Female │ 195.131.81.179 │ 3583136326049310 │ Indonesia │ 2/25/1983 │ 69227.11 │ Account Executive │ │ +│ 2016-02-03 08:33:08 │ 7 │ Samuel │ Holmes │ sholmes6@foxnews.com │ Male │ 232.234.81.197 │ 3582641366974690 │ Portugal │ 12/18/1987 │ 14247.62 │ Senior Financial Analyst │ │ +│ 2016-02-03 06:47:06 │ 8 │ Harry │ Howell │ hhowell7@eepurl.com │ Male │ 91.235.51.73 │ │ Bosnia and Herzegovina │ 3/1/1962 │ 186469.43 │ Web Developer IV │ │ +│ 2016-02-03 03:52:53 │ 9 │ Jose │ Foster │ jfoster8@yelp.com │ Male │ 132.31.53.61 │ │ South Korea │ 3/27/1992 │ 231067.84 │ Software Test Engineer I │ 1E+02 │ +│ 2016-02-03 18:29:47 │ 10 │ Emily │ Stewart │ estewart9@opensource.org │ Female │ 143.28.251.245 │ 3574254110301671 │ Nigeria │ 1/28/1997 │ 27234.28 │ Health Coach IV │ │ +└───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ +``` + +### Step 4: 创建目标表 {#step-4-create-target-table} + +在 {{{ .lake }}} 中创建一个目标表,用于存储来自 ORC 文件的数据。这里我们选择 ORC 文件中的部分列来创建该表。 + +```sql +CREATE OR REPLACE TABLE orc_test_table ( + firstname STRING, + lastname STRING, + email STRING, + gender STRING, + country STRING +); +``` + +### Step 5. 使用 SELECT 复制数据 {#step-5-using-select-to-copy-data} + +将外部 stage 中 ORC 文件的数据复制到目标表中。 + +```sql +COPY INTO orc_test_table +FROM ( + SELECT _col2, _col3, _col4, _col5, _col8 + FROM @orc_data_stage +) +PATTERN = '.*[.]orc' +FILE_FORMAT = (TYPE = ORC); +``` + +结果: + +```text +┌─────────────────────────────────────────────────────────────────────────────────┐ +│ File │ Rows_loaded │ Errors_seen │ First_error │ First_error_line │ +├───────────────┼─────────────┼─────────────┼──────────────────┼──────────────────┤ +│ userdata1.orc │ 1000 │ 0 │ NULL │ NULL │ +│ userdata2.orc │ 1000 │ 0 │ NULL │ NULL │ +│ userdata3.orc │ 1000 │ 0 │ NULL │ NULL │ +│ userdata4.orc │ 1000 │ 0 │ NULL │ NULL │ +│ userdata5.orc │ 1000 │ 0 │ NULL │ NULL │ +└─────────────────────────────────────────────────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/guides/load-parquet.md b/tidb-cloud-lake/guides/load-parquet.md new file mode 100644 index 0000000000000..c12498448c4d5 --- /dev/null +++ b/tidb-cloud-lake/guides/load-parquet.md @@ -0,0 +1,115 @@ +--- +title: 将 Parquet 加载到 TiDB Cloud Lake +summary: Parquet 是一种在数据分析中常用的列式存储格式。它旨在支持复杂的数据结构,并且能够高效处理大型数据集。 +--- + +# 将 Parquet 加载到 TiDB Cloud Lake + +## 什么是 Parquet? {#what-is-parquet} + +Parquet 是一种在数据分析中常用的列式存储格式。它旨在支持复杂的数据结构,并且能够高效处理大型数据集。 + +Parquet 文件对 {{{ .lake }}} 最友好。建议使用 Parquet 文件作为 {{{ .lake }}} 的数据源。 + +## 加载 Parquet 文件 {#loading-parquet-file} + +加载 Parquet 文件的常用语法如下: + +```sql +COPY INTO [.] + FROM { internalStage | externalStage | externalLocation } +[ PATTERN = '' ] +FILE_FORMAT = (TYPE = PARQUET) +``` + +- 有关更多 Parquet 文件格式选项,请参见 [Parquet 文件格式选项](/tidb-cloud-lake/sql/input-output-file-formats.md#parquet-options)。 +- 有关更多 COPY INTO table 选项,请参见 [COPY INTO table](/tidb-cloud-lake/sql/copy-into-table.md)。 + +## 教程:从 Parquet 文件加载数据 {#tutorial-loading-data-from-parquet-files} + +### 步骤 1. 创建内部 stage {#step-1-create-an-internal-stage} + +创建一个内部 stage 来存储 Parquet 文件。 + +```sql +CREATE STAGE my_parquet_stage; +``` + +### 步骤 2. 创建 Parquet 文件 {#step-2-create-parquet-files} + +使用以下 SQL 语句生成一个 Parquet 文件: + +```sql +COPY INTO @my_parquet_stage +FROM ( + SELECT + 'Title_' || CAST(number AS VARCHAR) AS title, + 'Author_' || CAST(number AS VARCHAR) AS author + FROM numbers(100000) +) + FILE_FORMAT = (TYPE = PARQUET); +``` + +验证 Parquet 文件是否已创建: + +```sql +LIST @my_parquet_stage; +``` + +结果: + +```text + +┌──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ +│ name │ size │ md5 │ last_modified │ creator │ +├─────────────────────────────────────────────────────────────────┼────────┼────────────────────────────────────┼───────────────────────────────┼──────────────────┤ +│ data_3890e0b1-0233-422c-b506-3a4501602f28_0000_00000000.parquet │ 65443 │ "ab4631846ca8a2beed6a48be75d2acac" │ 2023-12-26 10:28:18.000 +0000 │ NULL │ +└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ +``` + +有关将数据 unload 到 stage 的更多信息,请参见 [COPY INTO location](/tidb-cloud-lake/sql/copy-into-location.md)。 + +### 步骤 3. 创建目标表 {#step-3-create-target-table} + +```sql +CREATE TABLE books +( + title VARCHAR, + author VARCHAR +); +``` + +### 步骤 4. 直接从 Parquet 复制 {#step-4-copying-directly-from-parquet} + +要直接将 Parquet 文件中的数据复制到表中,请使用以下 SQL 命令: + +```sql +COPY INTO books + FROM @my_parquet_stage + PATTERN = '.*[.]parquet' + FILE_FORMAT = (TYPE = PARQUET); +``` + +结果: + +```text +┌───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ +│ File │ Rows_loaded │ Errors_seen │ First_error │ First_error_line │ +├─────────────────────────────────────────────────────────────────┼─────────────┼─────────────┼──────────────────┼──────────────────┤ +│ data_3890e0b1-0233-422c-b506-3a4501602f28_0000_00000000.parquet │ 100000 │ 0 │ NULL │ NULL │ +└───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ +``` + +### 步骤 5(可选). 使用 SELECT 复制数据 {#step-5-optional-using-select-to-copy-data} + +如果你需要更多控制,例如在复制过程中转换数据,可以使用 SELECT 语句。更多信息请参见 [`SELECT from Parquet`](/tidb-cloud-lake/guides/query-parquet-files-in-stage.md) + +```sql +COPY INTO books (title, author) +FROM ( + SELECT title, author + FROM @my_parquet_stage +) +PATTERN = '.*[.]parquet' +FILE_FORMAT = (TYPE = PARQUET); +``` \ No newline at end of file diff --git a/tidb-cloud-lake/guides/load-semi-structured-data.md b/tidb-cloud-lake/guides/load-semi-structured-data.md new file mode 100644 index 0000000000000..250940403f0c1 --- /dev/null +++ b/tidb-cloud-lake/guides/load-semi-structured-data.md @@ -0,0 +1,19 @@ +--- +title: 加载半结构化格式 +summary: 半结构化数据包含用于分隔语义元素的标签或标记,但不遵循严格的数据库结构。{{{ .lake }}} 使用 `COPY INTO` 命令高效加载这些格式,并可选择在加载过程中进行即时数据转换。 +--- + +# 加载半结构化数据 + +半结构化数据包含用于分隔语义元素的标签或标记,但不遵循严格的数据库结构。{{{ .lake }}} 使用 `COPY INTO` 命令高效加载这些格式,并可选择在加载过程中进行即时数据转换。 + +## 支持的文件格式 {#supported-file-formats} + +| 文件格式 | 描述 | 指南 | +| ----------- | ----------- | ----- | +| **Parquet** | 高效的列式存储格式 | [加载 Parquet](/tidb-cloud-lake/guides/load-parquet.md) | +| **CSV** | 逗号分隔值 | [加载 CSV](/tidb-cloud-lake/guides/load-csv.md) | +| **TSV** | 制表符分隔值 | [加载 TSV](/tidb-cloud-lake/guides/load-tsv.md) | +| **NDJSON** | 按换行符分隔的 JSON | [加载 NDJSON](/tidb-cloud-lake/guides/load-ndjson.md) | +| **ORC** | 优化的行列式格式 | [加载 ORC](/tidb-cloud-lake/guides/load-orc.md) | +| **Avro** | 带有模式定义的行式格式 | [加载 Avro](/tidb-cloud-lake/guides/load-avro.md) | \ No newline at end of file diff --git a/tidb-cloud-lake/guides/load-tsv.md b/tidb-cloud-lake/guides/load-tsv.md new file mode 100644 index 0000000000000..e5132f7553867 --- /dev/null +++ b/tidb-cloud-lake/guides/load-tsv.md @@ -0,0 +1,134 @@ +--- +title: 将 TSV 加载到 TiDB Cloud Lake +summary: TSV(Tab Separated Values)是一种用于存储表格数据的简单文件格式,例如电子表格或数据库。TSV 文件格式与 CSV 非常相似,记录之间以换行符分隔,每个字段之间以制表符分隔。以下示例展示了一个包含两条记录的 TSV 文件。 +--- + +# 将 TSV 加载到 TiDB Cloud Lake + +## 什么是 TSV? {#what-is-tsv} + +TSV(Tab Separated Values,在 {{{ .lake }}} `v1.2.890-nightly` 及更高版本中称为 `TEXT`)是一种用于存储表格数据的简单文件格式,例如电子表格或数据库。TSV 文件格式与 CSV 非常相似,记录之间以换行符分隔,每个字段之间以制表符分隔。 + +以下示例展示了一个包含两条记录的 TSV 文件: + +```text +Title_0 Author_0 +Title_1 Author_1 +``` + +## 加载 TSV 文件 {#loading-tsv-file} + +加载 TSV 文件的通用语法如下: + +```sql +COPY INTO [.] +FROM { userStage | internalStage | externalStage | externalLocation } +[ PATTERN = '' ] +[ FILE_FORMAT = ( + TYPE = TSV, + SKIP_HEADER = , + COMPRESSION = AUTO +) ] +``` + +> **注意:** +> +> 从 {{{ .lake }}} `v1.2.890-nightly` 开始,支持将 `TEXT` 作为 `TSV` 的别名。本指南在示例中仍使用 `TYPE = TSV`,以便它们在较旧的服务器版本上也能正常工作。如果你只面向 `v1.2.890-nightly` 或更高版本,也可以改用 `TYPE = TEXT`。 + +- 有关更多 TSV 文件格式选项,请参阅 [TSV 文件格式选项](/tidb-cloud-lake/sql/input-output-file-formats.md#tsv-options)。 +- 有关更多 COPY INTO table 选项,请参阅 [COPY INTO table](/tidb-cloud-lake/sql/copy-into-table.md)。 + +## 教程:从 TSV 文件加载数据 {#tutorial-loading-data-from-tsv-files} + +### 第 1 步:创建内部 stage {#step-1-create-an-internal-stage} + +创建一个内部 stage 来存储 TSV 文件。 + +```sql +CREATE STAGE my_tsv_stage; +``` + +### 第 2 步:创建 TSV 文件 {#step-2-create-tsv-files} + +使用以下 SQL 语句生成一个 TSV 文件: + +```sql +COPY INTO @my_tsv_stage +FROM ( + SELECT + 'Title_' || CAST(number AS VARCHAR) AS title, + 'Author_' || CAST(number AS VARCHAR) AS author + FROM numbers(100000) +) + FILE_FORMAT = (TYPE = TSV) +; +``` + +验证 TSV 文件是否已创建: + +```sql +LIST @my_tsv_stage; +``` + +结果: + +```text +┌───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ +│ name │ size │ md5 │ last_modified │ creator │ +├─────────────────────────────────────────────────────────────┼─────────┼────────────────────────────────────┼───────────────────────────────┼──────────────────┤ +│ data_7413d5d0-f992-4d92-b28e-0e501d66bdc1_0000_00000000.tsv │ 2477780 │ "a906769144de7aa6a0056a86ddae97d2" │ 2023-12-26 11:56:19.000 +0000 │ NULL │ +└───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ +``` + +### 第 3 步:创建目标表 {#step-3-create-target-table} + +```sql +CREATE TABLE books +( + title VARCHAR, + author VARCHAR +); +``` + +### 第 4 步:直接从 TSV 复制 {#step-4-copying-directly-from-tsv} + +要将 TSV 文件中的数据直接复制到表中,请使用以下 SQL 命令: + +```sql +COPY INTO books +FROM @my_tsv_stage +PATTERN = '.*[.]tsv' +FILE_FORMAT = ( + TYPE = TSV, + SKIP_HEADER = 0, -- Skip the first line if it is a header, here we don't have a header + COMPRESSION = AUTO +); +``` + +结果: + +```text +┌───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ +│ File │ Rows_loaded │ Errors_seen │ First_error │ First_error_line │ +├─────────────────────────────────────────────────────────────┼─────────────┼─────────────┼──────────────────┼──────────────────┤ +│ data_7413d5d0-f992-4d92-b28e-0e501d66bdc1_0000_00000000.tsv │ 100000 │ 0 │ NULL │ NULL │ +└───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ +``` + +### 第 4 步(可选):使用 SELECT 复制数据 {#step-4-option-using-select-to-copy-data} + +如果你需要更多控制,例如在复制时转换数据,可以使用 SELECT 语句。更多信息请参阅 [`SELECT from TSV`](/tidb-cloud-lake/guides/query-tsv-files-in-stage.md)。 + +```sql +COPY INTO books (title, author) +FROM ( + SELECT $1, $2 + FROM @my_tsv_stage +) +PATTERN = '.*[.]tsv' +FILE_FORMAT = ( + TYPE = 'TSV', + SKIP_HEADER = 0, -- Skip the first line if it is a header, here we don't have a header + COMPRESSION = 'AUTO' +); +``` \ No newline at end of file diff --git a/tidb-cloud-lake/guides/load-with-dbt.md b/tidb-cloud-lake/guides/load-with-dbt.md new file mode 100644 index 0000000000000..943e835d9fd0d --- /dev/null +++ b/tidb-cloud-lake/guides/load-with-dbt.md @@ -0,0 +1,56 @@ +--- +title: 使用 dbt 加载数据 +summary: dbt 是一种转换工作流,可帮助你在产出更高质量结果的同时完成更多工作。你可以使用 dbt 将分析代码模块化并集中管理,同时为数据团队提供软件工程工作流中常见的防护机制。在安全部署到生产环境之前,你可以协作构建数据模型、进行版本管理,并对查询进行测试和文档化,同时获得监控和可观测性。 +--- + +# 使用 dbt 加载数据 + +[dbt](https://www.getdbt.com/) 是一种转换工作流,可帮助你在产出更高质量结果的同时完成更多工作。你可以使用 dbt 将分析代码模块化并集中管理,同时为数据团队提供软件工程工作流中常见的防护机制。在安全部署到生产环境之前,你可以协作构建数据模型、进行版本管理,并对查询进行测试和文档化,同时获得监控和可观测性。 + +[tidbcloudlake-dbt](https://github.com/tidbcloud/lake-dbt) 是由 {{{ .lake }}} 开发的一个插件,主要目标是实现 dbt 与 {{{ .lake }}} 的平滑集成。借助该插件,你可以使用 dbt 无缝执行数据建模、转换和清洗任务,并方便地将输出加载到 {{{ .lake }}} 中。下表展示了 tidbcloudlake-dbt 插件对 dbt 常用功能的支持级别: + +| 功能 | 支持? | +|----------------------------- |----------- | +| 表物化 | 是 | +| 视图物化 | 是 | +| 增量物化 | 是 | +| 临时物化 | 否 | +| 数据填充 | 是 | +| 源 | 是 | +| 自定义数据测试 | 是 | +| 文档生成 | 是 | +| 快照 | 是 | +| 连接重试 | 是 | + +## 安装 tidbcloudlake-dbt {#install-tidbcloudlake-dbt} + +为了方便使用,tidbcloudlake-dbt 插件的安装流程已简化,因为它现在已将 dbt 作为必需依赖关系包含在内。要轻松完成 dbt 和 tidbcloudlake-dbt 插件的安装,请运行以下命令: + +```shell +pip3 install tidbcloudlake-dbt +``` + +不过,如果你希望单独安装 dbt,可以参考 dbt 官方安装指南获取详细说明。 + +## 教程:运行 dbt 项目 jaffle_shop {#tutorial-run-dbt-project-jaffle-shop} + +如果你刚开始接触 dbt,{{{ .lake }}} 建议你先完成官方 dbt 教程:。开始之前,请按照[安装 tidbcloudlake-dbt](#install-tidbcloudlake-dbt)中的说明安装 dbt 和 tidbcloudlake-dbt。 + +本教程提供了一个名为 “jaffle_shop” 的示例 dbt 项目,帮助你通过实践熟悉 dbt 工具。通过在默认的全局 profile(`~/.dbt/profiles.yml`)中配置连接到你的 {{{ .lake }}} 实例所需的信息,该项目会直接在你的 {{{ .lake }}} 数据库中生成 dbt models 中定义的表和视图。以下是一个连接到 {{{ .lake }}} 实例的 `profiles.yml` 文件示例: + +```yml title="~/.dbt/profiles.yml" +jaffle_shop_lake: + target: dev + outputs: + dev: + type: tidbcloudlake + host: tnxxxx.gw.aws-us-east-2.default.tidbcloud.com + port: 443 + schema: sjh_dbt + user: + pass: ******** + warehouse: default + secure: true +``` + +有关配置和使用该适配器的更多信息,请参见 [lake-dbt repository](https://github.com/tidbcloud/lake-dbt)。 \ No newline at end of file diff --git a/tidb-cloud-lake/guides/manage-costs.md b/tidb-cloud-lake/guides/manage-costs.md new file mode 100644 index 0000000000000..61a6b6c542e16 --- /dev/null +++ b/tidb-cloud-lake/guides/manage-costs.md @@ -0,0 +1,44 @@ +--- +title: 管理成本 +summary: 你可以在 **Manage** > **Billing** 下查看组织当月的消耗情况和账单历史。 +--- + +# 管理成本 + +你可以在 **Manage** > **Billing** 下查看组织当月的消耗情况和账单历史。 + +## 限制成本 {#limiting-your-costs} + +对于管理员用户,{{{ .lake }}} 提供了为其组织设置支出上限的选项。这样,管理员就可以控制在该平台上的最高支出金额。要进行设置,请前往首页并点击 **Activate Spending Limit**。在下一页中,你可以开启 **Enable Spending Limit** 按钮,并为你的组织指定允许的每月最高支出。 + +> **注意:** +> +> 你设置的支出上限将适用于每个自然月。例如,如果你在 8 月 10 日设置了上限,那么该上限将在整个 8 月生效,即从 1 日到 31 日。 + +设置支出上限时,你需要决定当达到上限后,{{{ .lake }}} 应采取什么操作。目前有两个选项: + +- **Suspend Service**:你的计算集群将无法运行,直到当月结束或你设置了更高的上限。 + +- **Send Notifications Only**:当支出接近上限时,你组织中的管理员将收到电子邮件通知。你的计算集群仍可继续正常运行。 + +对于 “Send Notifications Only” 选项,{{{ .lake }}} 将按照以下频率周期向管理员发送电子邮件通知: + +| 支出范围 | 通知频率 | +|---------------- |------------------------ | +| 80% - 90% | 每三天一次 | +| 90% - 100% | 每三天一次 | +| 100% 或以上 | 每三天一次 | + +## 向财务人员授予访问权限 {#granting-access-to-finance-personnel} + +为了在确保数据安全的同时方便财务团队开展工作,你可以在 {{{ .lake }}} 中创建一个名为 `billing` 的角色。该角色将专门用于仅提供对账单相关信息的访问权限。 + +```sql +CREATE ROLE billing; +``` + +在邀请财务人员加入你的组织时,为他们分配此 `billing` 角色。 + +![alt text](/media/tidb-cloud-lake/billing-role.png) + +当他们登录 {{{ .lake }}} 后,其访问权限将受到限制,只能访问账单页面,所有其他业务相关页面都会被隐藏。通过限制对 {{{ .lake }}} 环境中其他部分的不必要访问,这种方式有助于保护敏感数据。 \ No newline at end of file diff --git a/tidb-cloud-lake/guides/masking-policy.md b/tidb-cloud-lake/guides/masking-policy.md new file mode 100644 index 0000000000000..f852edd0c7dd6 --- /dev/null +++ b/tidb-cloud-lake/guides/masking-policy.md @@ -0,0 +1,201 @@ +--- +title: 脱敏策略 +summary: 脱敏策略通过在查询执行期间动态转换列值来保护敏感数据。它们支持基于角色访问机密信息——已授予权限的用户看到真实数据,其他用户看到脱敏后的值。 +--- + +# 脱敏策略 + +脱敏策略会在查询时转换列值。已授予权限的角色可以看到真实数据;其他角色看到的是脱敏后的值。存储的数据本身不会发生变化。 + +如果你想隐藏整行而不是对列进行脱敏,请使用[行访问策略](/tidb-cloud-lake/guides/row-access-policy.md)。 + +## 何时使用 {#when-to-use} + +- 客服支持 — 客服人员可以看到订单,但 ID 显示为 `3201**********1234` +- 分析场景 — email 显示为 `***@***.com`,同时不会影响聚合结果 +- VARIANT 日志 — 对非管理员隐藏 `secret_key` / `token` 等 JSON 键 +- 部分脱敏 — 为了验证,仅显示卡号后 4 位 + +## 快速开始 {#quick-start} + +```sql +CREATE TABLE user_info (id INT, email STRING NOT NULL); + +CREATE MASKING POLICY email_mask +AS (val STRING) +RETURNS STRING -> +CASE + WHEN is_role_in_session('managers') THEN val + ELSE '*********' +END; + +ALTER TABLE user_info MODIFY COLUMN email SET MASKING POLICY email_mask; + +INSERT INTO user_info VALUES (1, 'user@example.com'); +SELECT * FROM user_info; +``` + +``` +id | email +---|---------- + 1 | ********* +``` + +**工作原理** + +- 仅在查询时生效 — `SELECT` 会被脱敏;`INSERT` / `UPDATE` / `DELETE` 使用真实值 +- 列级作用域 — 每列只能绑定一个策略;同一个策略可在多张表中复用 +- 优先使用 `is_role_in_session()` 而不是 `current_role()`,这样用户无法通过 `SET ROLE` 绕过限制 + +## 示例 {#examples} + +### 条件脱敏(`USING`) {#conditional-masking-using} + +基于另一列进行脱敏: + +```sql +CREATE MASKING POLICY vip_mask +AS (val STRING, is_vip BOOLEAN) +RETURNS STRING -> +CASE + WHEN is_vip = true THEN val + ELSE '*********' +END; + +ALTER TABLE user_info +MODIFY COLUMN email SET MASKING POLICY vip_mask USING (email, is_vip); + +INSERT INTO user_info (id, email, is_vip) VALUES + (1, 'vip@example.com', true), + (2, 'normal@example.com', false); + +SELECT * FROM user_info; +``` + +``` +id | email | is_vip +---|-----------------|------- + 1 | vip@example.com | true + 2 | ********* | false +``` + +仅当策略体需要这些列时,才将列添加到 `USING` 中。 + +### VARIANT 子字段脱敏 {#variant-sub-field-masking} + +使用 `object_delete` 隐藏特定 JSON 键。所有访问路径都会遵循该脱敏规则(如下标、路径函数、类型转换、`json_object_keys`)。 + +```sql +CREATE TABLE events (id INT, data VARIANT); + +INSERT INTO events VALUES + (1, parse_json('{"name":"alice","content":"secret data","secret_key":"sk_123","age":30}')), + (2, parse_json('{"name":"bob","content":"private info","secret_key":"sk_456","age":25}')); + +CREATE ROLE data_admin; +CREATE ROLE data_reader; + +CREATE MASKING POLICY mask_variant_sensitive +AS (val VARIANT) RETURNS VARIANT -> +CASE + WHEN is_role_in_session('data_admin') OR is_role_in_session('account_admin') THEN val + ELSE object_delete(val, 'content', 'secret_key') +END; + +ALTER TABLE events MODIFY COLUMN data SET MASKING POLICY mask_variant_sensitive; + +GRANT SELECT ON default.events TO ROLE data_admin; +GRANT SELECT ON default.events TO ROLE data_reader; +``` + +| 作为 `data_admin` | 作为 `data_reader` | +|-----------------|------------------| +| 完整 JSON | 移除 `content` / `secret_key` | + +```sql +SET ROLE data_reader; + +SELECT data FROM events; +-- {"age":30,"name":"alice"} + +SELECT data['content'] FROM events; -- NULL +SELECT data['name'] FROM events; -- "alice" +SELECT json_path_query_first(data, '$.content'); -- NULL +SELECT data::STRING FROM events; -- {"age":30,"name":"alice"} +SELECT json_object_keys(data) FROM events; -- ["age","name"] +SELECT * FROM events WHERE data['content'] IS NOT NULL; +-- empty +``` + +嵌套键: + +```sql +ELSE delete_by_keypath(val, 'nested:secret') +``` + +## 读 / 写行为 {#read-write-behavior} + +| 操作 | 影响 | +|-----------|--------| +| `SELECT` | 脱敏后的值 | +| `INSERT` / `UPDATE` / `DELETE` | 真实值(写入不会被脱敏) | + +```sql +INSERT INTO user_info VALUES (2, 'admin@example.com'); -- stores real email +SELECT * FROM user_info WHERE id = 2; -- returns ********* +``` + +## 管理策略 {#manage-policies} + +```sql +DESCRIBE MASKING POLICY email_mask; + +ALTER TABLE user_info MODIFY COLUMN email UNSET MASKING POLICY; +DROP MASKING POLICY IF EXISTS email_mask; +``` + +在执行 `DROP MASKING POLICY` 之前,先解除每一列上的绑定。你可以使用 `POLICY_REFERENCES(POLICY_NAME => 'email_mask')` 查找绑定关系。 + +## 脱敏与行访问 {#masking-vs-row-access} + +| | 掩码策略 | 行访问策略 | +|---|---|---| +| 作用域 | 列值 | 整行 | +| 返回类型 | 必须与列类型匹配 | 始终为 BOOLEAN | +| 每表 | 每列一个 | 每表一个 | +| 影响 | `SELECT` | `SELECT`, `UPDATE`, `DELETE`, `MERGE` | + +同一列不能同时拥有这两种策略。如果行应当保留可见但列值需要隐藏,请使用脱敏;如果整行都应消失,请使用行访问策略。 + +## 限制 {#limits} + +- 每列只能有一个脱敏策略 +- 返回类型必须与列类型匹配 +- 在修改或删除列之前,必须先取消设置策略 +- 仍被任何表引用的策略不能被删除 +- 不支持 `CREATE OR REPLACE MASKING POLICY` — 需要先删除再重新创建 +- 临时表、视图和 stream 不支持 +- 脱敏策略和行访问策略的名称在全局范围内必须唯一 +- 策略参数名在创建时会被转换为小写 + +## 最佳实践 {#best-practices} + +1. 优先使用 `is_role_in_session()`,而不是 `current_role()`。 +2. 保持 `USING` 最小化 —— 只包含策略体所需的列。 +3. 如果应用会调用 `LENGTH` / `LIKE`,请返回与类型一致的占位值(例如 email 使用 `***@***.com`)。 +4. 对于 VARIANT,优先使用 `object_delete` / `delete_by_keypath`,而不是对整个值进行脱敏。 +5. 删除前先解除绑定;附加策略后,使用受限角色进行验证。 + +## 权限与参考 {#privileges-references} + +- 在 `*.*` 上具有 `CREATE MASKING POLICY` 权限以创建策略(创建者会获得 OWNERSHIP) +- 具有全局 `APPLY MASKING POLICY` 或 `APPLY ON MASKING POLICY ` 权限以进行附加/分离 +- 审计:`SHOW GRANTS ON MASKING POLICY ` + +另请参阅: + +- [用户与角色](/tidb-cloud-lake/sql/user-role.md) +- [CREATE MASKING POLICY](/tidb-cloud-lake/sql/create-masking-policy.md) +- [ALTER TABLE](/tidb-cloud-lake/sql/alter-table.md#column-operations) +- [脱敏策略命令](/tidb-cloud-lake/sql/masking-policy-sql.md) +- [行访问策略](/tidb-cloud-lake/guides/row-access-policy.md) \ No newline at end of file diff --git a/tidb-cloud-lake/guides/mcp-client-integration.md b/tidb-cloud-lake/guides/mcp-client-integration.md new file mode 100644 index 0000000000000..dddcd841c39ee --- /dev/null +++ b/tidb-cloud-lake/guides/mcp-client-integration.md @@ -0,0 +1,135 @@ +--- +title: 使用 MCP 将 AI 工具连接到 TiDB Cloud Lake +summary: 了解如何将兼容 MCP 的 AI 工具连接到 TiDB Cloud Lake,并使用会话沙箱保护来安全地探索数据。 +--- + +# 使用 MCP 将 AI 工具连接到 TiDB Cloud Lake + +[TiDB Cloud Lake MCP server](https://github.com/tidbcloud/lake-mcp) 通过 [Model Context Protocol (MCP)](https://modelcontextprotocol.io/) 将 AI 助手连接到 {{{ .lake }}}。借助兼容 MCP 的工具,你可以使用自然语言指令探索数据库对象、检查表结构,并运行 SQL。 + +## 前提条件 {#prerequisites} + +开始之前,请确保你具备以下条件: + +- Python 3.12 或更高版本 +- 已安装 [`uv`](https://docs.astral.sh/uv/getting-started/installation/) +- 一个兼容 MCP 的 AI 工具 +- 一个 {{{ .lake }}} 账户、数据库和计算集群 (Warehouse) + +## 获取连接字符串 {#get-a-connection-string} + +从你的 {{{ .lake }}} 计算集群中获取主机、用户名、密码、数据库和计算集群名称。更多信息,请参见[连接到计算集群](/tidb-cloud-lake/guides/warehouse.md#connecting-to-a-warehouse)。 + +使用以下格式构建 DSN: + +```text +lake://:@:443/?warehouse= +``` + +## 配置 MCP 客户端 {#configure-an-mcp-client} + +以下配置使用 `uv` 运行最新的 `tidbcloudlake-mcp` 包。每个示例中都显式启用了安全模式。 + + + +
+ +```shell +codex mcp add lake-mcp \ + --env LAKE_DSN='lake://:@:443/?warehouse=' \ + --env LAKE_MCP_SAFE_MODE=true \ + -- uv tool run --from tidbcloudlake-mcp@latest lake-mcp +``` + +
+ +
+ +```shell +claude mcp add lake-mcp \ + --env LAKE_DSN='lake://:@:443/?warehouse=' \ + --env LAKE_MCP_SAFE_MODE=true \ + -- uv tool run --from tidbcloudlake-mcp@latest lake-mcp +``` + +
+ +
+ +将以下服务器添加到你的 Cursor MCP 配置中: + +```json +{ + "mcpServers": { + "lake-mcp": { + "command": "uv", + "args": ["tool", "run", "--from", "tidbcloudlake-mcp@latest", "lake-mcp"], + "env": { + "LAKE_DSN": "lake://:@:443/?warehouse=", + "LAKE_MCP_SAFE_MODE": "true" + } + } + } +} +``` + +
+ +
+ +将以下服务器添加到你的 Gemini CLI `settings.json` 文件中的 `mcpServers` 对象: + +```json +{ + "mcpServers": { + "lake-mcp": { + "command": "uv", + "args": ["tool", "run", "--from", "tidbcloudlake-mcp@latest", "lake-mcp"], + "env": { + "LAKE_DSN": "lake://:@:443/?warehouse=", + "LAKE_MCP_SAFE_MODE": "true" + } + } + } +} +``` + +
+ +
+ +对于接受标准 JSON 配置的 MCP 客户端,添加以下服务器: + +```json +{ + "mcpServers": { + "lake-mcp": { + "command": "uv", + "args": ["tool", "run", "--from", "tidbcloudlake-mcp@latest", "lake-mcp"], + "env": { + "LAKE_DSN": "lake://:@:443/?warehouse=", + "LAKE_MCP_SAFE_MODE": "true" + } + } + } +} +``` + +
+ +
+ +保存 MCP 配置后,重启 AI 工具。然后,你就可以让该工具列出数据库、检查表,或运行查询。 + +## 会话沙箱保护 {#session-sandbox-protection} + +`LAKE_MCP_SAFE_MODE` 用于控制服务器是否根据会话专属的沙箱来校验写操作。 + +| 值 | 行为 | +| --- | --- | +| `true` | 对 AI 工具而言,生产对象是只读的。写操作仅限于名称以当前 `mcp_sandbox_{session_id}_*` 前缀开头的对象。这是默认且推荐的设置。 | +| `false` | 服务器允许已配置的 {{{ .lake }}} 用户所具备权限允许的任何 SQL 操作。仅在使用受信任的工具和最小权限账户时使用此设置。 | + +MCP 工具 `get_session_sandbox_prefix` 会返回当前会话的前缀。 + +有关服务器传输方式、配置变量以及可用的 MCP 工具,请参见 [TiDB Cloud Lake MCP Server](/tidb-cloud-lake/guides/mcp-server.md)。 \ No newline at end of file diff --git a/tidb-cloud-lake/guides/mcp-server.md b/tidb-cloud-lake/guides/mcp-server.md new file mode 100644 index 0000000000000..a7cfcc57bfbdb --- /dev/null +++ b/tidb-cloud-lake/guides/mcp-server.md @@ -0,0 +1,126 @@ +--- +title: TiDB Cloud Lake MCP Server +summary: 了解如何安装、运行和配置 TiDB Cloud Lake MCP server,包括传输方式、安全控制和可用工具。 +--- + +# TiDB Cloud Lake MCP Server + +[TiDB Cloud Lake MCP server](https://github.com/tidbcloud/lake-mcp) 向支持 Model Context Protocol (MCP) 的客户端暴露 {{{ .lake }}} 操作。`tidbcloudlake-mcp` 包支持标准输入/输出、HTTP 和 server-sent events (SSE) 传输方式。 + +## 前提条件 {#prerequisites} + +开始之前,请确保你具备以下条件: + +- Python 3.12 或更高版本 +- 一个 {{{ .lake }}} 账户、数据库和计算集群 (Warehouse) +- 一个符合以下格式的 {{{ .lake }}} DSN: + + ```text + lake://:@:443/?warehouse= + ``` + +有关如何获取连接信息,请参见[连接到计算集群](/tidb-cloud-lake/guides/warehouse.md#connecting-to-a-warehouse)。 + +## 安装 MCP server {#install-the-mcp-server} + +创建并激活虚拟环境: + +```shell +python3.12 -m venv .venv +source .venv/bin/activate +``` + +从 PyPI 安装 server: + +```shell +python -m pip install tidbcloudlake-mcp +``` + +## 运行 MCP server {#run-the-mcp-server} + +设置 {{{ .lake }}} DSN: + +```shell +export LAKE_DSN='lake://:@:443/?warehouse=' +``` + +使用默认的 `stdio` 传输方式运行 server: + +```shell +lake-mcp +``` + +你也可以在不将该包安装到当前激活环境中的情况下运行它: + +```shell +uv tool run --from tidbcloudlake-mcp@latest lake-mcp +``` + +## 配置传输方式 {#configure-the-transport} + +将 `LAKE_MCP_SERVER_TRANSPORT` 设置为以下值之一: + +| 值 | 描述 | +| --- | --- | +| `stdio` | 通过标准输入和输出与本地 MCP 客户端通信。这是默认值。 | +| `http` | 启动一个 HTTP 服务器。 | +| `sse` | 启动一个使用服务器发送事件的服务器。 | + +例如,要在默认的 loopback 地址和端口上运行一个 HTTP server: + +```shell +export LAKE_MCP_SERVER_TRANSPORT=http +export LAKE_MCP_BIND_HOST=127.0.0.1 +export LAKE_MCP_BIND_PORT=8001 +lake-mcp +``` + +> **Warning:** +> +> 请将绑定地址限制在受信任的网络内。MCP server 可以使用已配置 {{{ .lake }}} 用户的权限访问数据。 + +## 配置 {#configuration} + +| 环境变量 | 默认值 | 描述 | +| --- | --- | --- | +| `LAKE_DSN` | {{{ .lake }}} 必需 | 数据库和计算集群的连接字符串。 | +| `LAKE_MCP_SAFE_MODE` | `true` | 启用会话沙箱校验。 | +| `LAKE_QUERY_TIMEOUT` | `300` | 查询超时时间,单位为秒。 | +| `LAKE_MCP_SERVER_TRANSPORT` | `stdio` | 服务器传输方式:`stdio`、`http` 或 `sse`。 | +| `LAKE_MCP_BIND_HOST` | `127.0.0.1` | `http` 和 `sse` 传输方式的绑定地址。 | +| `LAKE_MCP_BIND_PORT` | `8001` | `http` 和 `sse` 传输方式的绑定端口。 | + +## 可用工具 {#available-tools} + +| 工具 | 描述 | +| --- | --- | +| `execute_sql` | 执行带有沙箱校验的 SQL。 | +| `execute_multi_sql` | 执行多条 SQL 语句。 | +| `show_databases` | 列出数据库。 | +| `show_tables` | 列出数据库中的表。 | +| `describe_table` | 返回表的 schema。 | +| `get_session_sandbox_prefix` | 返回当前会话的沙箱前缀。 | +| `list_session_sandbox_databases` | 列出当前会话的沙箱数据库。 | +| `create_session_sandbox_database` | 为当前会话创建一个沙箱数据库。 | +| `show_stages` | 列出 stage。 | +| `list_stage_files` | 列出 stage 中的文件。 | +| `create_stage` | 创建一个 stage,并受沙箱校验约束。 | +| `show_connections` | 列出连接。 | + +## 安全模式 {#safe-mode} + +默认启用安全模式。在安全模式下: + +- `SELECT`、`SHOW`、`DESCRIBE`、`EXPLAIN` 和 `LIST` 等读操作可以访问已配置 {{{ .lake }}} 用户被允许访问的对象。 +- 写操作仅限于名称以当前 `mcp_sandbox_{session_id}_*` 前缀开头的对象。 +- 数据操作语句只能修改沙箱表。 +- 权限变更只能针对沙箱对象和 principals。 + +仅当 MCP 客户端可信,且已配置 {{{ .lake }}} 用户具有所需的最小权限时,才将 `LAKE_MCP_SAFE_MODE=false`。 + +有关特定客户端的配置示例,请参见[使用 MCP 将 AI 工具连接到 TiDB Cloud Lake](/tidb-cloud-lake/guides/mcp-client-integration.md)。 + +## 相关资源 {#related-resources} + +- [PyPI 上的 `tidbcloudlake-mcp`](https://pypi.org/project/tidbcloudlake-mcp/) +- [Model Context Protocol 文档](https://modelcontextprotocol.io/) diff --git a/tidb-cloud-lake/guides/monitor-usage.md b/tidb-cloud-lake/guides/monitor-usage.md new file mode 100644 index 0000000000000..277443887e829 --- /dev/null +++ b/tidb-cloud-lake/guides/monitor-usage.md @@ -0,0 +1,41 @@ +--- +title: 监控使用情况 +summary: TiDB Cloud Lake 提供监控功能,帮助你全面了解你自己以及组织成员在平台上的使用情况。要访问 Monitor 页面,请在首页的侧边栏菜单中点击 Monitor。该页面包含以下标签页。 +--- + +# 监控使用情况 + +{{{ .lake }}} 提供监控功能,帮助你全面了解你自己以及组织成员在平台上的使用情况。要访问 **Monitor** 页面,请在首页的侧边栏菜单中点击 **Monitor**。该页面包含以下标签页: + +- [Metrics](#metrics) +- [SQL History](#sql-history) +- [Task History](#task-history) +- [Audit](#audit):仅对 `account_admin` 用户可见。 + +## Metrics {#metrics} + +**Metrics** 标签页通过图表直观展示以下指标的使用统计信息,涵盖过去一小时、一天或一周的数据: + +- 存储大小 +- SQL 查询次数 +- 会话连接数 +- 扫描 / 写入的数据量 +- 计算集群状态 +- 扫描 / 写入的行数 + +## SQL History {#sql-history} + +**SQL History** 标签页显示组织内所有用户已执行的 SQL 语句列表。点击列表顶部的 **Filter**,你可以按多个维度筛选记录。 + +在 **SQL History** 页面点击某条记录后,可以查看 {{{ .lake }}} 如何执行该 SQL 语句的详细信息,并访问以下标签页: + +- **Query Details**:包括 Query State(成功或失败)、Rows Scanned、计算集群 (Warehouse)、Bytes Scanned、Start Time、End Time 和 Handler Type。 +- **Query Profile**:展示该 SQL 语句的执行方式。 + +## Task History {#task-history} + +**Task History** 标签页提供组织内所有已执行任务的完整日志,便于用户查看任务设置并监控其状态。 + +## Audit {#audit} + +**Audit** 标签页记录所有组织成员的操作日志,包括操作类型、操作时间、IP 地址以及操作人的账户。点击列表顶部的 **Filter**,你可以按多个维度筛选记录。 \ No newline at end of file diff --git a/tidb-cloud-lake/guides/multimodal-data-analytics.md b/tidb-cloud-lake/guides/multimodal-data-analytics.md new file mode 100644 index 0000000000000..872fea4cb8988 --- /dev/null +++ b/tidb-cloud-lake/guides/multimodal-data-analytics.md @@ -0,0 +1,20 @@ +--- +title: 多模态数据分析 +summary: CityDrive Intelligence 记录每一次驾驶的视频。后台处理工具将视频流切分为关键帧图像,从每张图像中提取丰富的多模态信息,并按 `video_id` 存储。这些信号包括关系型元信息、JSON 清单、行为标签、向量嵌入和 GPS 轨迹。 +--- + +# 多模态数据分析 + +CityDrive Intelligence 记录每一次驾驶的视频。后台处理工具将视频流切分为关键帧图像,从每张图像中提取丰富的多模态信息,并按 `video_id` 存储。这些信号包括关系型元信息、JSON 清单、行为标签、向量嵌入和 GPS 轨迹。 + +本指南系列展示了 {{{ .lake }}} 如何将所有这些工作负载保留在同一个计算集群中——无需复制作业,也无需额外的搜索集群。 + +| 指南 | 涵盖内容 | +|-------|----------------| +| [SQL 分析](/tidb-cloud-lake/guides/sql-analytics.md) | 基础表、过滤、连接、窗口、聚合索引 | +| [JSON & Search](/tidb-cloud-lake/guides/json-search.md) | 加载 `frame_metadata_catalog`,运行 Elasticsearch `QUERY()`,关联位图标签 | +| [向量搜索](/tidb-cloud-lake/guides/vector-search-guide.md) | 持久化嵌入,运行余弦搜索,连接风险指标 | +| [地理空间分析](/tidb-cloud-lake/guides/geo-analytics.md) | 使用 `GEOMETRY`、距离/多边形过滤、交通灯连接 | +| [Lakehouse ETL](/tidb-cloud-lake/guides/lakehouse-etl.md) | 一次 stage,使用 `COPY INTO` 导入共享表,添加 streams/tasks | + +按顺序阅读这些指南,可以了解相同的标识符如何从经典 SQL 流转到文本搜索、向量、地理空间和 ETL——所有内容都基于同一个 CityDrive 场景。 \ No newline at end of file diff --git a/tidb-cloud-lake/guides/mysql-credentials.md b/tidb-cloud-lake/guides/mysql-credentials.md new file mode 100644 index 0000000000000..1e7e2d8913429 --- /dev/null +++ b/tidb-cloud-lake/guides/mysql-credentials.md @@ -0,0 +1,42 @@ +--- +title: MySQL - Credentials +summary: 本页面介绍如何创建 `MySQL - Credentials` 数据源。该数据源存储访问 MySQL 所需的连接信息,并可在多个 MySQL 集成任务中复用。 +--- + +# MySQL - Credentials + +本页面介绍如何创建 `MySQL - Credentials` 数据源。该数据源存储访问 MySQL 所需的连接信息,并可在多个 MySQL 集成任务中复用。 + +## 使用场景 {#use-cases} + +- 为多个 MySQL 同步任务集中管理主机、端口和账户信息 +- 避免在每个任务中重复输入相同的数据库连接设置 +- 当数据库端点或账户发生变化时,可在一个位置统一修改所有依赖任务 + +## 创建 MySQL - Credentials {#create-mysql-credentials} + +1. 进入 **Data** > **Data Sources**,然后点击 **Create Data Source**。 +2. 选择 **MySQL - Credentials** 作为服务类型,然后填写连接详情: + + | 字段 | 必填 | 说明 | + |-------|----------|-------------| + | **Name** | 是 | 此数据源的描述性名称 | + | **Hostname** | 是 | MySQL 服务器主机名或 IP 地址 | + | **Port Number** | 是 | MySQL 服务器端口(默认值:`3306`) | + | **DB Username** | 是 | 用于访问 MySQL 的用户名 | + | **DB Password** | 是 | MySQL 用户的密码 | + | **Database Name** | 是 | 源数据库名称 | + | **DB Charset** | 否 | 字符集(默认值:`utf8mb4`) | + | **Server ID** | 否 | 唯一的 binlog 复制标识符。如果未提供,则自动生成 | + +3. 点击 **Test Connectivity** 以验证连接。如果测试成功,点击 **OK** 保存数据源。 + +## 使用建议 {#usage-recommendations} + +- 使用专用的 MySQL 账户,而不是与应用负载共享同一个账户 +- 如果你计划创建 `CDC Only` 或 `Snapshot + CDC` 任务,请确保该账户具有与复制相关的权限 +- 在创建下游任务之前,先验证网络访问、binlog 配置和权限 + +## 后续步骤 {#next-steps} + +创建此数据源后,你可以使用它来创建 [MySQL Integration Task](/tidb-cloud-lake/guides/integrate-with-mysql.md)。 diff --git a/tidb-cloud-lake/guides/network-policy.md b/tidb-cloud-lake/guides/network-policy.md new file mode 100644 index 0000000000000..6d9e90908c6d1 --- /dev/null +++ b/tidb-cloud-lake/guides/network-policy.md @@ -0,0 +1,94 @@ +--- +title: 网络策略 +summary: 网络策略根据客户端 IP 控制谁可以登录 {{{ .lake }}}。即使凭据正确,如果连接请求的 IP 不满足策略,也会被拒绝,从而在用户名和密码之外为你提供额外的一层安全保护。 +--- + +# 网络策略 + +网络策略根据客户端 IP 控制谁可以登录 {{{ .lake }}}。即使凭据正确,如果连接请求的 IP 不满足策略,也会被拒绝,从而在用户名和密码之外为你提供额外的一层安全保护。 + +## 工作原理 {#how-it-works} + +- `ALLOWED_IP_LIST` 接受单个 IPv4 地址或 CIDR 网段(例如 `10.0.0.0/24`)。只有列表中的地址才允许登录。 +- `BLOCKED_IP_LIST`(可选)允许你从已允许的范围中进一步明确指定拒绝规则。{{{ .lake }}} 会先检查阻止列表,因此同时存在于两个列表中的 IP 仍会被拒绝。 +- 一个用户在同一时间最多只能引用一个网络策略,但同一个策略可以被多个用户共享,以便于管理。 +- 如果服务器无法确定客户端 IP,或者该 IP 与允许列表不匹配,{{{ .lake }}} 会立即返回 `AuthenticateFailure`。 + +## 端到端示例 {#end-to-end-example} + +以下演练涵盖了典型的生命周期:创建策略、将其绑定到用户、确认其状态、集中修改策略,最后解绑并删除策略。 + +### 1. 创建并查看策略 {#1-create-and-inspect-a-policy} + +```sql +CREATE NETWORK POLICY corp_vpn_policy + ALLOWED_IP_LIST=('10.1.0.0/16', '172.16.8.12/32') + BLOCKED_IP_LIST=('10.1.10.25') + COMMENT='Only VPN ranges'; + +SHOW NETWORK POLICIES; + +Name |Allowed Ip List |Blocked Ip List|Comment | +----------------+--------------------------+---------------+-----------------+ +corp_vpn_policy |10.1.0.0/16,172.16.8.12/32|10.1.10.25 |Only VPN ranges | +``` + +### 2. 将策略绑定到用户 {#2-attach-the-policy-to-users} + +```sql +CREATE USER alice IDENTIFIED BY 'Str0ngPass!' WITH SET NETWORK POLICY='corp_vpn_policy'; +CREATE USER bob IDENTIFIED BY 'An0therPass!'; + +-- Apply the policy to an existing user +ALTER USER bob WITH SET NETWORK POLICY='corp_vpn_policy'; +``` + +### 3. 验证策略是否生效 {#3-verify-enforcement} + +```sql +DESC USER alice; + +┌──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ +│ name │ hostname │ auth_type │ default_role │ roles │ disabled │ network_policy │ password_policy │ must_change_password │ +├────────┼──────────┼──────────────────────┼──────────────┼───────┼──────────┼───────────────────┼─────────────────┼──────────────────────┤ +│ alice │ % │ double_sha1_password │ │ │ false │ corp_vpn_policy │ │ NULL │ +└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ + +DESC NETWORK POLICY corp_vpn_policy; + +Name |Allowed Ip List |Blocked Ip List|Comment | +----------------+--------------------------+---------------+----------------+ +corp_vpn_policy |10.1.0.0/16,172.16.8.12/32|10.1.10.25 |Only VPN ranges | +``` + +### 4. 修改并复用策略 {#4-update-and-reuse-the-policy} + +使用 [ALTER NETWORK POLICY](/tidb-cloud-lake/sql/network-policy-sql.md) 可以调整允许或阻止的 IP,而无需逐个修改用户: + +```sql +ALTER NETWORK POLICY corp_vpn_policy + SET ALLOWED_IP_LIST=('10.1.0.0/16', '10.2.0.0/16') + BLOCKED_IP_LIST=('10.1.10.25', '10.2.5.5') + COMMENT='VPN + DR site'; + +DESC NETWORK POLICY corp_vpn_policy; + +Name |Allowed Ip List |Blocked Ip List |Comment | +----------------+----------------------------+-------------------------+-----------------+ +corp_vpn_policy |10.1.0.0/16,10.2.0.0/16 |10.1.10.25,10.2.5.5 |VPN + DR site | +``` + +所有引用该策略的用户都会自动获取新的 IP 范围。 + +### 5. 解绑并清理 {#5-detach-and-clean-up} + +```sql +ALTER USER bob WITH UNSET NETWORK POLICY; +DROP NETWORK POLICY corp_vpn_policy; +``` + +删除策略前,请确认没有用户依赖该策略;否则,这些用户将无法登录。 + +--- + +有关完整的语法详情,请参见 [网络策略 SQL 参考](/tidb-cloud-lake/sql/network-policy-sql.md),其中涵盖了 `CREATE`、`ALTER`、`SHOW`、`DESC` 和 `DROP`。 \ No newline at end of file diff --git a/tidb-cloud-lake/guides/ngram-index.md b/tidb-cloud-lake/guides/ngram-index.md new file mode 100644 index 0000000000000..93bc206cd429b --- /dev/null +++ b/tidb-cloud-lake/guides/ngram-index.md @@ -0,0 +1,194 @@ +--- +title: Ngram 索引 +summary: Ngram 索引通过使用带有通配符(`%`)的 `LIKE` 运算符来加速模式匹配查询,从而无需全表扫描即可实现快速子字符串搜索。 +--- + +# Ngram 索引 + +Ngram 索引通过使用带有通配符(`%`)的 `LIKE` 运算符来加速模式匹配查询,从而无需全表扫描即可实现快速子字符串搜索。 + +## 它解决了什么问题? {#what-problem-does-it-solve} + +在大规模数据集上,使用 `LIKE` 进行模式匹配查询会面临显著的性能挑战: + +| 问题 | 影响 | Ngram Index 解决方案 | +|---------|--------|---------------------| +| **缓慢的通配符搜索** | `WHERE content LIKE '%keyword%'` 扫描整个表 | 使用 n-gram 片段预过滤数据块 | +| **全表扫描** | 每次模式搜索都会读取所有行 | 仅读取包含模式的相关数据块 | +| **搜索性能差** | 用户需要长时间等待子字符串搜索结果 | 亚秒级模式匹配响应时间 | +| **传统索引无效** | B-tree 索引无法优化中间通配符 | 字符级索引可处理任意通配符位置 | + +**示例**:在 1000 万条日志记录中搜索 `'%error log%'`。如果没有 ngram 索引,需要扫描全部 1000 万行;而使用 ngram 索引时,可以立即将范围预过滤到约 1000 个相关数据块。 + +## Ngram 与全文索引:何时使用哪一种? {#ngram-vs-full-text-index-when-to-use-which} + +| 功能 | Ngram 索引 | 全文索引 | +|---------|-------------|-----------------| +| **主要使用场景** | 使用 `LIKE '%pattern%'` 进行模式匹配 | 使用 `MATCH()` 进行语义文本搜索 | +| **搜索类型** | 精确子字符串匹配 | 基于词的相关性搜索 | +| **查询语法** | `WHERE column LIKE '%text%'` | `WHERE MATCH(column, 'text')` | +| **高级功能** | 不区分大小写的匹配 | 模糊搜索、相关性评分、布尔运算符 | +| **性能侧重点** | 加速现有的 LIKE 查询 | 用高级搜索函数替换 LIKE | +| **最适合** | 日志分析、代码搜索、精确模式匹配 | 文档搜索、内容发现、搜索引擎 | + +**在以下场景中选择 Ngram 索引:** + +- 你已有 `LIKE '%pattern%'` 查询需要优化 +- 需要精确的子字符串匹配(不区分大小写) +- 处理的是日志、代码或 ID 等结构化数据 +- 希望在不修改查询语法的情况下提升性能 + +**在以下场景中选择全文索引:** + +- 为文档或内容构建搜索功能 +- 需要模糊搜索、相关性评分或复杂查询 +- 处理自然语言文本 +- 希望获得超出简单模式匹配的高级搜索能力 + +## Ngram 索引的工作原理 {#how-ngram-index-works} + +Ngram 索引会将文本拆分为重叠的字符子串(n-gram),以便快速查找模式: + +**`gram_size = 3` 示例:** + +```text +Input: "The quick brown" +N-grams: "The", "he ", "e q", " qu", "qui", "uic", "ick", "ck ", "k b", " br", "bro", "row", "own" +``` + +**查询处理过程:** + +```sql +SELECT * FROM t WHERE content LIKE '%quick br%' +``` + +1. 将模式 `'quick br'` 分词为 n-gram:"qui"、"uic"、"ick"、"ck "、"k b"、" br" +2. 索引过滤出包含这些 n-gram 的数据块 +3. 仅对预过滤后的数据块应用完整的 `LIKE` 过滤 + +> **注意:** +> +> - 模式长度必须至少为 `gram_size` 个字符(例如,当 `gram_size=3` 时,像 `'%yo%'` 这样的短模式不会使用索引) +> - 匹配不区分大小写("FOO" 可匹配 "foo"、"Foo"、"fOo") +> - 仅适用于 `LIKE` 运算符,不适用于其他模式匹配函数 + +## 快速开始 {#quick-setup} + +```sql +-- Create table with text content +CREATE TABLE logs(id INT, message STRING); + +-- Create ngram index with 3-character segments +CREATE NGRAM INDEX logs_message_idx ON logs(message) gram_size = 3; + +-- Insert data (automatically indexed) +INSERT INTO logs VALUES (1, 'Application error occurred'); + +-- Search using LIKE - automatically optimized +SELECT * FROM logs WHERE message LIKE '%error%'; +``` + +## 完整示例 {#complete-example} + +以下示例演示了如何为日志分析创建 ngram 索引,并验证其带来的性能收益: + +```sql +-- Create table for application logs +CREATE TABLE t_articles ( + id INT, + content STRING +); + +-- Create ngram index with 3-character segments +CREATE NGRAM INDEX ngram_idx_content +ON t_articles(content) +gram_size = 3; + +-- Verify index creation +SHOW INDEXES; +``` + +```sql +┌─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ +│ name │ type │ original │ definition │ created_on │ updated_on │ +├───────────────────┼────────┼──────────┼──────────────────────────────────┼────────────────────────────┼─────────────────────┤ +│ ngram_idx_content │ NGRAM │ │ t_articles(content)gram_size='3' │ 2025-05-13 01:02:58.598409 │ NULL │ +└─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ +``` + +```sql +-- Insert test data: 995 irrelevant rows + 5 target rows +INSERT INTO t_articles +SELECT number, CONCAT('Random text number ', number) +FROM numbers(995); + +INSERT INTO t_articles VALUES + (1001, 'The silence was deep and complete'), + (1002, 'They walked in silence through the woods'), + (1003, 'Silence fell over the room'), + (1004, 'A moment of silence was observed'), + (1005, 'In silence, they understood each other'); + +-- Search with pattern matching +SELECT id, content FROM t_articles WHERE content LIKE '%silence%'; + +-- Verify index usage +EXPLAIN SELECT id, content FROM t_articles WHERE content LIKE '%silence%'; +``` + +**性能结果:** + +```sql +-[ EXPLAIN ]----------------------------------- +TableScan +├── table: default.default.t_articles +├── output columns: [id (#0), content (#1)] +├── read rows: 5 +├── read size: < 1 KiB +├── partitions total: 2 +├── partitions scanned: 1 +├── pruning stats: [segments: , blocks: ] +├── push downs: [filters: [is_true(like(t_articles.content (#1), '%silence%'))], limit: NONE] +└── estimated rows: 15.62 +``` + +**关键性能指标:** `bloom pruning: 2 to 1` 表明 ngram 索引在扫描前成功过滤掉了 50% 的数据块。 + +## 最佳实践 {#best-practices} + +| 实践 | 收益 | +|----------|---------| +| **选择合适的 gram_size** | `gram_size=3` 适用于大多数情况;对于更长的模式使用更大的值 | +| **为经常搜索的列建立索引** | 重点关注用于 `LIKE '%pattern%'` 查询的列 | +| **监控索引使用情况** | 使用 `EXPLAIN` 验证 `bloom pruning` 统计信息 | +| **考虑模式长度** | 确保搜索模式的长度至少为 `gram_size` 个字符 | + +## 常用命令 {#essential-commands} + +完整命令参考请参见 [Ngram 索引](/tidb-cloud-lake/sql/ngram-index-sql.md)。 + +| 命令 | 用途 | +|----------------------------------------------------------|----------------------------------------------| +| `CREATE NGRAM INDEX name ON table(column) gram_size = N` | 创建具有 N 字符分段的 ngram 索引 | +| `SHOW INDEXES` | 列出所有索引,包括 ngram 索引 | +| `REFRESH NGRAM INDEX name ON table` | 刷新 ngram 索引 | +| `DROP NGRAM INDEX name ON table` | 删除 ngram 索引 | + +**何时使用 Ngram 索引** + +**适用场景:** + +- 日志分析和监控系统 +- 代码搜索和模式匹配 +- 商品目录搜索 +- 任何频繁使用 `LIKE '%pattern%'` 查询的应用 + +**不推荐的场景:** + +- 短模式搜索(少于 `gram_size` 个字符) +- 精确字符串匹配(应改用等值比较) +- 复杂文本搜索需求(应改用全文索引) + +--- + +*Ngram 索引对于需要在大型文本数据集上使用 `LIKE` 查询进行快速模式匹配的应用来说至关重要。* diff --git a/tidb-cloud-lake/guides/ownership.md b/tidb-cloud-lake/guides/ownership.md new file mode 100644 index 0000000000000..8ed3b072b1240 --- /dev/null +++ b/tidb-cloud-lake/guides/ownership.md @@ -0,0 +1,70 @@ +--- +title: 所有权 +summary: 所有权是一种特殊的权限,表示某个角色在 {{{ .lake }}} 中对特定数据对象(当前包括数据库、表、UDF 和 stage)所拥有的专属权利和责任。 +--- + +# 所有权 + +所有权是一种特殊的权限,表示某个角色在 {{{ .lake }}} 中对特定数据对象(当前包括数据库、表、UDF 和 stage)所拥有的专属权利和责任。 + +## 授予所有权 {#granting-ownership} + +对象的所有权会自动授予创建该对象的用户所属角色,并且可以使用 [GRANT](/tidb-cloud-lake/sql/grant.md) 命令在角色之间转移: + +- 将对象的所有权授予新角色时,会把完整所有权转移给新角色,并从原角色中移除该所有权。例如,如果角色 A 最初拥有某个表,而你将所有权授予角色 B,则角色 B 会成为新的所有者,角色 A 将不再拥有该表的所有权。 +- 出于安全原因,不建议将所有权授予内置角色 `public`。如果用户在创建对象时属于 `public` 角色,那么所有用户都将拥有该对象的所有权,因为每个用户默认都具有 `public` 角色。{{{ .lake }}} 建议创建并为用户分配自定义角色,而不是使用 `public` 角色,以便更清晰地管理所有权。有关内置角色的信息,请参见[内置角色](/tidb-cloud-lake/guides/roles.md)。 +- `default` 数据库中的表不能授予所有权,因为它由内置角色 `account_admin` 拥有。 + +## 不允许撤销所有权 {#revoking-ownership-not-allowed} + +不支持撤销所有权,因为每个对象都必须有一个所有者。 + +- 如果对象被删除,它不会保留原角色的所有权。如果该对象被恢复(如果可能),所有权也不会自动重新分配,此时需要由 `account_admin` 手动将所有权重新分配给某个角色。 +- 如果拥有某个对象的角色被删除,`account_admin` 可以将该对象的所有权转移给另一个角色。 + +## 示例 {#examples} + +要将所有权授予某个角色,请使用 [GRANT](/tidb-cloud-lake/sql/grant.md) 命令。以下示例演示了如何将不同数据库对象的所有权授予角色 'data_owner': + +```sql +-- Grant ownership of all tables in the 'finance_data' database to the role 'data_owner' +GRANT OWNERSHIP ON finance_data.* TO ROLE 'data_owner'; + +-- Grant ownership of the table 'transactions' in the 'finance_data' schema to the role 'data_owner' +GRANT OWNERSHIP ON finance_data.transactions TO ROLE 'data_owner'; + +-- Grant ownership of the stage 'ingestion_stage' to the role 'data_owner' +GRANT OWNERSHIP ON STAGE ingestion_stage TO ROLE 'data_owner'; + +-- Grant ownership of the user-defined function 'calculate_profit' to the role 'data_owner' +GRANT OWNERSHIP ON UDF calculate_profit TO ROLE 'data_owner'; +``` + +以下示例演示了如何在 {{{ .lake }}} 中建立基于角色的所有权。管理员创建角色 'role1' 并将其分配给用户 'u1'。随后,将在 'db' schema 中创建表的权限授予 'role1'。因此,当 'u1' 登录后,他们将拥有 'role1' 的权限,从而可以在 'db' 下创建并拥有表。但是,对不属于 'role1' 所有的表的访问会受到限制,这一点可以从对 'db.t_old_exists' 的查询失败中看出。 + +```sql +-- Admin creates roles and assigns roles to corresponding users +CREATE ROLE role1; +CREATE USER u1 IDENTIFIED BY '123' WITH DEFAULT ROLE 'role1'; +GRANT CREATE ON db.* TO ROLE role1; +GRANT ROLE role1 TO u1; + +-- After u1 logs into {{{ .lake }}}, role1 has been granted to u1, so u1 can create and own tables under db: +u1> CREATE TABLE db.t(id INT); +u1> INSERT INTO db.t VALUES(1); +u1> SELECT * FROM db.t; +u1> SELECT * FROM db.t_old_exists; -- Failed because the owner of this table is not role1 +``` + +以下示例展示了如何让用户创建仅由其角色拥有的数据库,这样其他用户除非被显式授予访问权限,否则无法看到这些数据库: + +```sql +CREATE ROLE part1_role; +GRANT CREATE DATABASE ON *.* TO ROLE part1_role; +CREATE USER user1 IDENTIFIED BY 'abc123' WITH DEFAULT ROLE 'part1_role'; +GRANT ROLE part1_role TO user1; + +-- When user1 creates a database, ownership is assigned to part1_role. +-- Other users will not be able to see or access that database unless +-- privileges or ownership are granted to their roles. +``` \ No newline at end of file diff --git a/tidb-cloud-lake/guides/password-policy.md b/tidb-cloud-lake/guides/password-policy.md new file mode 100644 index 0000000000000..416f7fc1da612 --- /dev/null +++ b/tidb-cloud-lake/guides/password-policy.md @@ -0,0 +1,114 @@ +--- +title: 密码策略 +summary: 密码策略定义了 {{{ .lake }}} 密码必须有多强(长度、字符、历史记录、重试限制等)以及密码可以多久修改一次。它们为每次 `CREATE USER` 和密码修改提供了可预测的约束。有关完整属性列表,请参见 Password Policy Attributes。 +--- + +# 密码策略 + +密码策略定义了 {{{ .lake }}} 密码必须有多强(长度、字符、历史记录、重试限制等)以及密码可以多久修改一次。它们为每次 `CREATE USER` 和密码修改提供了可预测的约束。有关完整属性列表,请参见[密码策略属性](/tidb-cloud-lake/sql/create-password-policy.md#password-policy-attributes)。 + +## 工作原理 {#how-it-works} + +- SQL 用户默认没有密码策略。你可以在创建用户时通过 `CREATE USER ... WITH SET PASSWORD POLICY` 指定策略,也可以稍后通过 [ALTER USER](/tidb-cloud-lake/sql/alter-user.md) 指定。 +- 每当受管理的用户设置或修改密码时,{{{ .lake }}} 都会验证复杂度规则(长度和字符组合);对于密码修改,还会强制执行最短使用期限和密码历史记录限制。 +- 登录时,{{{ .lake }}} 还会根据 `PASSWORD_MAX_RETRIES`/`PASSWORD_LOCKOUT_TIME_MINS` 跟踪失败尝试次数和锁定状态,并在超过 `PASSWORD_MAX_AGE_DAYS` 后将密码标记为过期。密码已过期的用户只能登录来修改自己的密码。 + +> **Note:** +> +> 用户通常不能修改自己的密码,除非他们具有内置的 `account-admin` 角色。`account-admin` 可以运行 `ALTER USER ... IDENTIFIED BY ...` 为任何用户轮转密码。 + +## 端到端示例 {#end-to-end-example} + +本示例将为管理员和分析师分别创建专用策略,将其绑定到用户,并展示后续如何修改或移除这些策略。 + +### 1. 创建策略并查看它们 {#1-create-policies-and-inspect-them} + +```sql +CREATE PASSWORD POLICY dba_policy + PASSWORD_MIN_LENGTH = 12 + PASSWORD_MAX_LENGTH = 18 + PASSWORD_MIN_UPPER_CASE_CHARS = 2 + PASSWORD_MIN_LOWER_CASE_CHARS = 2 + PASSWORD_MIN_NUMERIC_CHARS = 2 + PASSWORD_MIN_SPECIAL_CHARS = 1 + PASSWORD_MIN_AGE_DAYS = 1 + PASSWORD_MAX_AGE_DAYS = 45 + PASSWORD_MAX_RETRIES = 3 + PASSWORD_LOCKOUT_TIME_MINS = 30 + PASSWORD_HISTORY = 5 + COMMENT='Strict controls for DBAs'; + +CREATE PASSWORD POLICY analyst_policy + COMMENT='Defaults for analysts'; + +SHOW PASSWORD POLICIES; + +┌─────────────────┬───────────────────────────────┬─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ +│ name │ comment │ options │ +├─────────────────┼───────────────────────────────┼─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤ +│ analyst_policy │ Defaults for analysts │ MIN_LENGTH=8, MAX_LENGTH=256, MIN_UPPER_CASE_CHARS=1, MIN_LOWER_CASE_CHARS=1, MIN_NUMERIC_CHARS=1, MIN_SPECIAL_CHARS=0, ... HISTORY=0 │ +│ dba_policy │ Strict controls for DBAs │ MIN_LENGTH=12, MAX_LENGTH=18, MIN_UPPER_CASE_CHARS=2, MIN_LOWER_CASE_CHARS=2, MIN_NUMERIC_CHARS=2, MIN_SPECIAL_CHARS=1, ... HISTORY=5 │ +└─────────────────┴───────────────────────────────┴─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ +``` + +### 2. 将策略绑定到用户 {#2-attach-the-policy-to-users} + +```sql +CREATE USER dba_jane IDENTIFIED BY 'Str0ngPass123!' WITH SET PASSWORD POLICY='dba_policy'; + +CREATE USER analyst_mike IDENTIFIED BY 'Abc12345' + WITH SET PASSWORD POLICY='analyst_policy'; + +CREATE USER analyst_zoe IDENTIFIED BY 'Byt3Crush!'; +ALTER USER analyst_zoe WITH SET PASSWORD POLICY='analyst_policy'; +``` + +### 3. 验证绑定结果 {#3-verify-the-assignments} + +```sql +DESC USER dba_jane; + +┌──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ +│ name │ hostname │ auth_type │ default_role │ roles │ disabled │ network_policy │ password_policy │ must_change_password │ +├─────────┼──────────┼──────────────────────┼──────────────┼───────┼──────────┼────────────────┼─────────────────┼──────────────────────┤ +│ dba_jane│ % │ double_sha1_password │ │ │ false │ │ dba_policy │ NULL │ +└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ + +DESC PASSWORD POLICY dba_policy; + +Name |Comment |Options +-----------+----------------------------+---------------------------------------------------------------------------------------------------------------------------------+ +dba_policy |Strict controls for DBAs |MIN_LENGTH=12,MAX_LENGTH=18,MIN_UPPER_CASE_CHARS=2,MIN_LOWER_CASE_CHARS=2,MIN_NUMERIC_CHARS=2,MIN_SPECIAL_CHARS=1,...,HISTORY=5 | +``` + +### 4. 集中修改策略 {#4-update-a-policy-centrally} + +使用 [ALTER PASSWORD POLICY](/tidb-cloud-lake/sql/alter-password-policy.md) 可以在不逐个修改用户的情况下收紧规则: + +```sql +ALTER PASSWORD POLICY analyst_policy SET + PASSWORD_MIN_SPECIAL_CHARS = 1 + PASSWORD_MAX_AGE_DAYS = 60 + COMMENT='Analysts need specials now'; + +DESC PASSWORD POLICY analyst_policy; + +Name |Comment |Options +---------------+-----------------------------+------------------------------------------------------------------------------------------------------------------------+ +analyst_policy |Analysts need specials now |MIN_LENGTH=8,MAX_LENGTH=256,MIN_UPPER_CASE_CHARS=1,MIN_LOWER_CASE_CHARS=1,MIN_NUMERIC_CHARS=1,MIN_SPECIAL_CHARS=1,... | +``` + +现在,所有引用 `analyst_policy` 的用户都会自动继承更严格的密码字符组合要求和过期时间窗口。 + +### 5. 解绑并清理 {#5-detach-and-clean-up} + +```sql +ALTER USER analyst_zoe WITH UNSET PASSWORD POLICY; +DROP PASSWORD POLICY analyst_policy; +``` + +{{{ .lake }}} 会阻止你删除仍在使用中的策略;在运行 `DROP PASSWORD POLICY` 之前,请先从所有用户上取消该策略。 + +--- + +有关完整语法,请参见[密码策略 SQL 参考](/tidb-cloud-lake/sql/password-policy-sql.md),其中涵盖了 `CREATE`、`ALTER`、`SHOW`、`DESC` 和 `DROP`。 \ No newline at end of file diff --git a/tidb-cloud-lake/guides/performance-optimization.md b/tidb-cloud-lake/guides/performance-optimization.md new file mode 100644 index 0000000000000..d00ae262bd7f0 --- /dev/null +++ b/tidb-cloud-lake/guides/performance-optimization.md @@ -0,0 +1,30 @@ +--- +title: 性能优化 +summary: "{{{ .lake }}} 主要通过**多种索引技术**来加速查询性能,包括数据聚簇、结果缓存和专用索引,帮助你显著提升查询响应时间。" +--- + +# 性能优化 + +{{{ .lake }}} 主要通过**多种索引技术**来加速查询性能,包括数据聚簇、结果缓存和专用索引,帮助你显著提升查询响应时间。 + +## 优化功能 {#optimization-features} + +| 功能 | 用途 | 适用场景 | +|---------|---------|------------| +| [**Cluster Key**](/tidb-cloud-lake/sql/cluster-key.md) | 自动以物理方式组织数据,以获得最佳查询性能 | 当你拥有大型表,并且经常基于特定列进行过滤时,尤其适用于时序数据或分类数据 | +| [**查询结果缓存**](/tidb-cloud-lake/guides/query-result-cache.md) | 自动存储并复用相同查询的结果 | 当你的应用会重复运行相同的分析查询时,例如在仪表板或定时报告中 | +| [**虚拟列**](/tidb-cloud-lake/guides/virtual-column.md) | 自动加速对 JSON/VARIANT 数据内部字段的访问 | 当你经常查询半结构化数据中的特定路径,并且需要亚秒级响应时间时 | +| [**聚合索引**](/tidb-cloud-lake/guides/aggregating-index.md) | 预计算并存储常见聚合结果 | 当你的分析负载经常在大型数据集上运行 SUM、COUNT、AVG 查询时 | +| [**全文索引**](/tidb-cloud-lake/guides/full-text-index.md) | 提供极快的语义文本搜索能力 | 当你需要高级文本搜索功能(如相关性评分和模糊匹配)时 | +| [**Ngram 索引**](/tidb-cloud-lake/guides/ngram-index.md) | 加速带有通配符的模式匹配 | 当你的查询在大型文本列上使用带通配符的 LIKE 运算符时(尤其是 '%keyword%') | + +## 功能可用性 {#feature-availability} + +| 功能 | 社区版 | 企业版 | 云版 | +|---------|-----------|------------|-------| +| cluster key | ✅ | ✅ | ✅ | +| 查询结果缓存 | ✅ | ✅ | ✅ | +| 虚拟列 | ❌ | ✅ | ✅ | +| 聚合索引 | ✅ | ✅ | ✅ | +| 全文索引 | ✅ | ✅ | ✅ | +| Ngram 索引 | ✅ | ✅ | ✅ | \ No newline at end of file diff --git a/tidb-cloud-lake/guides/platforms-regions.md b/tidb-cloud-lake/guides/platforms-regions.md new file mode 100644 index 0000000000000..ff9ad1db87178 --- /dev/null +++ b/tidb-cloud-lake/guides/platforms-regions.md @@ -0,0 +1,24 @@ +--- +title: 平台与 Region +summary: 了解 TiDB Cloud Lake 支持的云平台和 Region。 +--- + +# 平台与 Region + +{{{ .lake }}} 是一种云原生解决方案,目前支持以下云服务提供商和 Region: + +| Cloud Provider | Region Name | Region ID | +|----------------|--------------------------|----------------| +| AWS | US West (Oregon) | us-west-2 | +| AWS | Asia Pacific (Tokyo) | ap-northeast-1 | +| AWS | US East (N. Virginia) | us-east-1 | +| AWS | Asia Pacific (Singapore) | ap-southeast-1 | +| AWS | Asia Pacific (Mumbai) | ap-south-1 | +| Alibaba Cloud | Japan (Tokyo) | ap-northeast-1 | + +> **注意:** +> +> 为确保高效且稳定的数据同步与导入,我们强烈建议你选择与当前正在使用的云服务提供商和 Region 相匹配的云服务。这样可以有效避免跨网络数据传输可能带来的网络延迟和数据丢失风险,保障数据传输过程的安全与顺畅,同时显著提升数据同步与导入的效率和稳定性。 +> {{{ .lake }}} 计划扩展对更多云服务提供商和 Region 的支持。如果你当前使用的云服务提供商或 Region 尚未受支持,请点击 [Contact Sales](https://www.pingcap.com/contact-us/) 与 {{{ .lake }}} 团队联系。 + +当你注册 {{{ .lake }}} 账户时,需要选择一个云平台和 Region。账户创建成功后,所选的云平台和 Region 将无法更改。 \ No newline at end of file diff --git a/tidb-cloud-lake/guides/postgresql-credentials.md b/tidb-cloud-lake/guides/postgresql-credentials.md new file mode 100644 index 0000000000000..aa35cd98e2648 --- /dev/null +++ b/tidb-cloud-lake/guides/postgresql-credentials.md @@ -0,0 +1,41 @@ +--- +title: PostgreSQL - Credentials +summary: 本页介绍如何创建 `PostgreSQL - Credentials` 数据源。该数据源存储访问 PostgreSQL 所需的连接信息,并可在多个 PostgreSQL 集成任务中复用。 +--- + +# PostgreSQL - Credentials + +本页介绍如何创建 `PostgreSQL - Credentials` 数据源。该数据源存储访问 PostgreSQL 所需的连接信息,并可在多个 PostgreSQL 集成任务中复用。 + +## 使用场景 {#use-cases} + +- 为多个 PostgreSQL 同步任务集中管理主机、端口和账户信息 +- 避免在每个任务中重复输入相同的数据库连接设置 +- 当数据库端点或账户发生变化时,可在一个位置统一修改所有依赖任务 + +## 创建 PostgreSQL - Credentials {#create-postgresql-credentials} + +1. 进入 **Data** > **Data Sources**,然后点击 **Create Data Source**。 +2. 选择 **PostgreSQL - Credentials** 作为服务类型,然后填写连接详情: + + | 字段 | 必填 | 说明 | + |-------|----------|-------------| + | **Name** | 是 | 此数据源的描述性名称 | + | **Hostname** | 是 | PostgreSQL 服务器主机名或 IP 地址 | + | **Port Number** | 是 | PostgreSQL 服务器端口(默认值:`5432`) | + | **DB Username** | 是 | 用于访问 PostgreSQL 的用户名 | + | **DB Password** | 是 | PostgreSQL 用户的密码 | + | **Database Name** | 是 | 源数据库名称 | + | **SSL Mode** | 否 | SSL 连接模式:`disable`、`require`、`verify-ca` 或 `verify-full`(默认值:`disable`) | + +3. 点击 **Test Connectivity** 以验证连接。如果测试成功,点击 **OK** 保存数据源。 + +## 使用建议 {#usage-recommendations} + +- 使用专用的 PostgreSQL 账户,而不是与应用负载共用同一个账户 +- 如果你计划创建 `CDC Only` 或 `Snapshot + CDC` 任务,请确保该账户具有与复制相关的权限 +- 在创建下游任务之前,先验证网络访问、WAL 配置和权限 + +## 后续步骤 {#next-steps} + +创建此数据源后,你可以使用它来创建 [PostgreSQL 集成任务](/tidb-cloud-lake/guides/integrate-with-postgresql.md)。 diff --git a/tidb-cloud-lake/guides/pricing-billing.md b/tidb-cloud-lake/guides/pricing-billing.md new file mode 100644 index 0000000000000..a420a5ee50675 --- /dev/null +++ b/tidb-cloud-lake/guides/pricing-billing.md @@ -0,0 +1,94 @@ +--- +title: TiDB Cloud Lake 价格与计费 +summary: 了解 TiDB Cloud Lake 的定价模型和计费详情。 +--- + +# TiDB Cloud Lake 价格与计费 + +你在 {{{ .lake }}} 上的费用由以下部分组成:计算集群、存储、云服务和服务托管费用。本页介绍各个组成部分的定价信息以及计费方式。 + +## {{{ .lake }}} 定价 {#lake-pricing} + +本节提供有关计算集群、存储、云服务和服务托管的定价信息。 + +### 计算集群 (Warehouse) 定价 {#warehouse-pricing} + +你的计算集群在运行时(具体来说,处于 Running 状态时)会产生费用。费用取决于计算集群的大小和运行时长。**计费按秒计算**。例如,如果你的计算集群运行了三秒钟,则会按这三秒的实际时长收费。 + +计算集群的大小表示其可处理的最大并发查询数,价格会根据可选的不同大小以及你使用的 {{{ .lake }}} 版本而有所不同。 + +| 大小 | 每小时成本(个人) | 每小时成本(企业) | +|---------|-----------------------------------|-----------------------------------| +| XSmall | $1.6 | $2.4 | +| Small | $3.2 | $4.8 | +| Medium | $6.4 | $9.6 | +| Large | $12.8 | $19.2 | +| XLarge | $25.6 | $38.4 | +| 2XLarge | $51.2 | $76.8 | +| 3XLarge | $102.4 | $153.6 | +| 4XLarge | $204.8 | $307.2 | +| 5XLarge | $409.6 | $614.4 | +| 6XLarge | $819.2 | $1228.8 | + +已暂停的计算集群不会消耗任何资源。默认情况下,{{{ .lake }}} 会在计算集群空闲五分钟后自动将其暂停,以节省资源和成本。你可以根据需要调整或禁用此自动暂停功能。 + +### 存储定价 {#storage-pricing} + +你在 {{{ .lake }}} 中的数据实际存储在 Amazon S3 中。{{{ .lake }}} 中的存储费用基于 Amazon S3 的定价。目前,Personal Edition 和 Business Edition 的价格均为每 TB 每月 $23.00。 + +| 版本 | 每 TB 每月价格 | +| ---------------- | ---------------------- | +| 个人版 | $23.00 | +| 商业版 | $23.00 | + +### 云服务定价 {#cloud-service-pricing} + +云服务费用目前包括 API 请求费用。每次你使用 {{{ .lake }}} 运行 SQL 查询时,都会通过 {{{ .lake }}} HTTP 句柄向 `lake-query` 发送一个 REST API 请求。在 Personal Edition 中,每 10,000 次 API 请求收费 $1;在 Business Edition 中,每 10,000 次 API 请求收费 $2。 + +| 版本 | 每 10,000 次 API 请求的费用 | +| ---------------- | ---------------------------- | +| 个人版 | $1.00 | +| 商业版 | $2.00 | + +### 服务托管定价 {#service-hosting-pricing} + +服务托管费用适用于数据集成服务。与计算集群不同,数据集成服务通常会持续运行(24/7),直到你将其下线。其计费方式与计算集群相同:根据实际运行时长按秒计费,价格取决于服务大小以及你使用的 {{{ .lake }}} 版本。 + +服务大小基于 XSmall 计算集群大小推导而来。下表中的月度费用是基于每月连续 24/7 运行 720 小时(30 天)的估算值,仅供参考。 + +| 大小 | 每小时费用(个人) | 每小时费用(企业) | 每月费用(个人,24/7) | 每月费用(企业,24/7) | +|---------|------------------------|------------------------|--------------------------------|--------------------------------| +| 4XSmall | $0.20 | $0.30 | $144 | $216 | +| 3XSmall | $0.40 | $0.60 | $288 | $432 | +| 2XSmall | $0.80 | $1.20 | $576 | $864 | + +## 示例 1 {#example-1} + +**使用场景:** 用户正在使用一个 XSmall 计算集群(Business),并偶尔查询数据。某次特定查询耗时 5 分 20 秒,数据存储大小为 100GB。 + +| 成本 | 公式 | 金额 | +|------|---------|--------| +| 计算集群 (Warehouse) | $2.4 ÷ 3600 × (5×60+20) | $0.21 | +| 存储 | $23 ÷ 1024 ÷ 30 × 100 | $0.07 | +| **每日总计** | | **$0.28** | +| **每月总计** | | **$8.40** | + +## 示例 2 {#example-2} + +**使用场景:** 用户正在使用一个 XSmall 计算集群(Business)持续向 {{{ .lake }}} 导入数据。该计算集群每天运行 24 小时,存储为 1TB,并使用 Task 服务按分钟加载数据。预计 API 调用次数为 50,000。 + +| 成本 | 公式 | 金额 | +|------|---------|--------| +| 计算集群 (Warehouse) | $2.40 × 24h | $57.60/天 | +| 存储 | $23 ÷ 30 | $0.77/天 | +| 云服务 | $2 × 5 | $10.00/天 | +| **每日总计** | | **$68.37** | +| **每月总计** | | **$2,051.10** | + +## {{{ .lake }}} 计费 {#lake-billing} + +计费周期按自然月设置,从每月 1 日开始,到当月最后一天结束。对于你的首个计费月,计费周期将从你的组织创建当天开始。 + +如需查看计费详情,请前往 **Manage**,然后点击 **Billing**。在该页面中,你可以查看账单并绑定信用卡进行支付。 + +在向用户计费时,{{{ .lake }}} 会优先使用代金券。如果有多张代金券可用,系统会优先从最早到期的代金券中扣减。请确保在代金券到期前使用。 \ No newline at end of file diff --git a/tidb-cloud-lake/guides/privileges.md b/tidb-cloud-lake/guides/privileges.md new file mode 100644 index 0000000000000..62d7e8eb23e0f --- /dev/null +++ b/tidb-cloud-lake/guides/privileges.md @@ -0,0 +1,257 @@ +--- +title: 权限 +summary: 权限是执行某项操作的许可。用户必须具有特定权限,才能在 {{{ .lake }}} 中执行特定操作。例如,查询表时,用户需要具有该表的 `SELECT` 权限。类似地,要读取 stage 中的数据集,用户必须具有 `READ` 权限。 +--- + +# 权限 + +权限是执行某项操作的许可。用户必须具有特定权限,才能在 {{{ .lake }}} 中执行特定操作。例如,查询表时,用户需要具有该表的 `SELECT` 权限。类似地,要读取 stage 中的数据集,用户必须具有 `READ` 权限。 + +在 {{{ .lake }}} 中,权限授予给角色。用户通过分配给他们的角色获得权限。 + +![Alt text](/media/tidb-cloud-lake/access-control-2.png) + +## 管理权限 {#managing-privileges} + +要管理角色的权限,请使用以下命令: + +- [GRANT](/tidb-cloud-lake/sql/grant.md) +- [REVOKE](/tidb-cloud-lake/sql/revoke.md) +- [SHOW GRANTS](/tidb-cloud-lake/sql/show-grants.md) + +### 向角色授予权限 {#granting-privileges-to-roles} + +要授予权限,请先创建一个角色,将权限授予该角色,然后再将该角色授予需要该权限的用户。在以下示例中,首先创建了一个名为 'writer' 的新角色,并向其授予 'default' schema 中对象的所有权限。随后,创建新用户 'david',密码为 'abc123',并将 'writer' 角色授予 'david'。最后,显示 'writer' 已被授予的权限。 + +```sql title='Example:' +-- Create a new role named 'writer' +CREATE ROLE writer; + +-- Grant all privileges on all objects in the 'default' schema to the role 'writer' +GRANT ALL ON default.* TO ROLE writer; + +-- Create a new user named 'david' with the password 'abc123' and set the default role +CREATE USER david IDENTIFIED BY 'abc123' WITH DEFAULT_ROLE = 'writer'; + +-- Grant the role 'writer' to the user 'david' +GRANT ROLE writer TO david; + +-- Show the granted privileges for the role 'writer' +SHOW GRANTS FOR ROLE writer; + +┌───────────────────────────────────────────────────────┐ +│ Grants │ +├───────────────────────────────────────────────────────┤ +│ GRANT ALL ON 'default'.'default'.* TO ROLE 'writer' │ +└───────────────────────────────────────────────────────┘ +``` + +### 从角色中回收权限 {#revoking-privileges-from-roles} + +在访问控制的上下文中,权限是从角色中回收的。在以下示例中,我们从角色 'writer' 中回收其在 'default' schema 中所有对象上的全部权限,然后显示角色 'writer' 已被授予的权限: + +```sql title='Example (Continued):' +-- Revoke all privileges on all objects in the 'default' schema from role 'writer' +REVOKE ALL ON default.* FROM ROLE writer; + +-- Show the granted privileges for the role 'writer' +SHOW GRANTS FOR ROLE writer; +``` + +## 访问控制权限 {#access-control-privileges} + +{{{ .lake }}} 提供了一系列权限,使你能够对数据库对象进行细粒度控制。{{{ .lake }}} 权限可分为以下类型: + +- 全局权限:这组权限适用于整个数据库管理系统,而不是系统中的特定对象。全局权限授予会影响数据库整体功能和管理的操作,例如创建或删除数据库、管理用户和角色,以及修改系统级设置。有关包含哪些权限,请参见[全局权限](#global-privileges)。 + +- 对象特定权限:对象特定权限包含不同的权限集,每一种都适用于特定的数据库对象。其中包括: + - [表权限](#table-privileges) + - [视图权限](#view-privileges) + - [数据库权限](#database-privileges) + - [会话策略权限](#session-policy-privileges) + - [Stage 权限](#stage-privileges) + - [UDF 权限](#udf-privileges) + - [序列权限](#sequence-privileges) + - [连接权限](#connection-privileges) + - [存储过程权限](#procedure-privileges) + - [Catalog 权限](#catalog-privileges) + - [Share 权限](#share-privileges) + +### 所有权限 {#all-privileges} + +| 权限 | 对象类型 | 描述 | +|:------------------|:------------------------------|:---------------------------------------------------------------------------------------------------------------------------------------------------| +| ALL | 所有 | 授予指定对象类型的所有权限。 | +| APPLY MASKING POLICY | 全局, Masking Policy | 附加、分离、描述或删除 masking policy。当在 *.* 上授予时,被授权者可以管理任何 masking policy。 | +| APPLY ROW ACCESS POLICY | 全局, Row Access Policy | 向表添加或移除行访问策略,并允许对任何策略执行 DESCRIBE/DROP 操作。当在 *.* 上授予时,被授权者可以管理所有行访问策略。 | +| ALTER | 全局, 数据库, 表, 视图 | 修改数据库、表、用户或 UDF。 | +| CREATE | 全局, 表 | 创建表或 UDF。 | +| CREATE DATABASE | 全局 | 创建数据库或 UDF。 | +| CREATE WAREHOUSE | 全局 | 创建计算集群。 | +| CREATE CONNECTION | 全局 | 创建连接。 | +| CREATE SEQUENCE | 全局 | 创建序列。 | +| CREATE PROCEDURE | PROCEDURE | 创建存储过程。 | +| CREATE MASKING POLICY | 全局 | 创建 masking policy。 | +| CREATE ROW ACCESS POLICY | 全局 | 创建行访问策略。 | +| DELETE | 表 | 删除表中的行或截断表中的行。 | +| DROP | 全局, 数据库, 表, 视图 | 删除数据库、表、视图或 UDF。撤销删除表。 | +| INSERT | 表 | 向表中插入行。 | +| SELECT | 数据库, 表 | 从表中选择行。显示或使用数据库。 | +| UPDATE | 表 | 修改表中的行。 | +| GRANT | 全局 | 向角色授予 / 从角色回收权限。 | +| SUPER | 全局, 表 | 终止查询。设置全局配置。优化表。分析表。操作 stage(列出 stages、创建 stage、删除 stage)、catalog 或 share。 | +| USAGE | 全局 | “无权限”的同义词。 | +| CREATE ROLE | 全局 | 创建角色。 | +| DROP ROLE | 全局 | 删除角色。 | +| CREATE USER | 全局 | 创建 SQL 用户。 | +| DROP USER | 全局 | 删除 SQL 用户。 | +| WRITE | Stage | 向 stage 写入。 | +| READ | Stage | 读取 stage。 | +| USAGE | UDF | 使用 udf。 | +| ACCESS CONNECTION | CONNECTION | 访问连接。 | +| ACCESS SEQUENCE | SEQUENCE | 访问序列。 | +| ACCESS PROCEDURE | PROCEDURE | 访问存储过程。 | + +### 全局权限 {#global-privileges} + +| 权限 | 描述 | +|:------------------|:------------------------------------------------------------------------------------------------------------------| +| ALL | 授予指定对象类型的所有权限。 | +| ALTER | 添加或删除表列。修改 cluster key。对表重新执行 cluster。 | +| CREATEROLE | 创建角色。 | +| CREAT DATABASE | 创建 DATABASE。 | +| CREATE WAREHOUSE | 创建 WAREHOUSE。 | +| CREATE CONNECTION | 创建 CONNECTION。 | +| DROPUSER | 删除用户。 | +| CREATEUSER | 创建用户。 | +| DROPROLE | 删除角色。 | +| SUPER | 终止查询。设置或取消设置某项设置。操作 stage、catalog 或 share。调用函数。将 COPY INTO 到 stage。 | +| USAGE | 仅连接到 {{{ .lake }}} 查询。 | +| CREATE | 创建 UDF。 | +| DROP | 删除 UDF。 | +| ALTER | 修改 UDF。修改 SQL 用户。 | + +### 表权限 {#table-privileges} + +| 权限 | 描述 | +|:----------|:-----------------------------------------------------------------------------------------------------------------| +| ALL | 授予指定对象类型的所有权限。 | +| ALTER | 添加或删除表列。修改 cluster key。对表重新执行 cluster。 | +| CREATE | 创建表。 | +| DELETE | 删除表中的行。截断表。 | +| DROP | 删除或撤销删除表。恢复最近删除版本的表。 | +| INSERT | 向表中插入行。COPY INTO 到表。 | +| SELECT | 从表中选择行。SHOW CREATE 表。DESCRIBE 表。 | +| UPDATE | 修改表中的行。 | +| SUPER | 优化或分析表。 | +| OWNERSHIP | 授予对数据库的完全控制权。任一时刻,特定对象上的此权限只能由单个角色持有。 | + +### 视图权限 {#view-privileges} + +| 权限 | 描述 | +|:----------|:-----------------------------------------------------------------------| +| ALL | 授予指定对象类型的所有权限 | +| ALTER | 创建或删除视图。使用另一个 QUERY 修改现有视图。 | +| DROP | 删除视图。 | + +### 数据库权限 {#database-privileges} + +请注意,一旦你对数据库具有以下任一权限,或对该数据库中的某个表具有任意权限,就可以使用 [USE DATABASE](/tidb-cloud-lake/sql/use-database.md) 命令来指定数据库。 + +| 权限 | 描述 | +|:----------|:-----------------------------------------------------------------------------------------------------------------| +| ALTER | 重命名数据库。 | +| DROP | 删除或撤销删除数据库。恢复最近删除版本的数据库。 | +| SELECT | SHOW CREATE 数据库。 | +| OWNERSHIP | 授予对数据库的完全控制权。任一时刻,特定对象上的此权限只能由单个角色持有。 | +| USAGE | 允许使用 `USE ` 进入数据库,而不授予对其中任何对象的访问权限。 | + +> Note: +> +> 1. 如果某个角色拥有数据库,则该角色可以访问该数据库中的所有表。 + +### 会话策略权限 {#session-policy-privileges} + +| Privilege | Description | +| :-- | :-- | +| SUPER | 终止查询。设置或取消设置某项设置。 | +| ALL | 授予指定对象类型的所有权限。 | + +### Stage 权限 {#stage-privileges} + +| 权限 | 描述 | +|:----------|:--------------------------------------------------------------------------------------------------------------| +| WRITE | 向 stage 写入。例如,copy into 到 stage、presign upload 或删除 stage | +| READ | 读取 stage。例如,列出 stage、查询 stage、从 stage copy into 到表、presign download | +| ALL | 授予指定对象类型的 READ、WRITE 权限。 | +| OWNERSHIP | 授予对 stage 的完全控制权。任一时刻,特定对象上的此权限只能由单个角色持有。 | + +> Note: +> +> 1. 不检查 external location auth。 + +### UDF 权限 {#udf-privileges} + +| 权限 | 描述 | +|:----------|:------------------------------------------------------------------------------------------------------------| +| USAGE | 可以使用 UDF。例如,copy into 一个 stage、presign upload | +| ALL | 为指定对象类型授予 READ、WRITE 权限。 | +| OWNERSHIP | 授予对 UDF 的完全控制权。在任意时刻,特定对象上的此权限只能由单个角色持有。 | + +> 注意: +> +> 1. 如果 udf 已经被 constant fold,则不检查其 auth。 +> 2. 如果 udf 是 insert 中的一个值,则不检查其 auth。 + +### Catalog 权限 {#catalog-privileges} + +| 权限 | 描述 | +|:----------|:---------------------------------------------------------| +| SUPER | SHOW CREATE catalog。创建或删除 catalog。 | +| ALL | 为指定对象类型授予所有权限。 | + +### Share 权限 {#share-privileges} + +可以使用相同的 SQL 权限模型(`GRANT`/`REVOKE`)对 share 对象授予和(权限)回收 share 权限。 + +### Connection 权限 {#connection-privileges} + +| 权限 | 描述 | +|:------------------|:-------------------------------------------------------------------------------------------------------------------| +| Access Connection | 可以访问 Connection。 | +| ALL | 为指定对象类型授予访问 Connection 权限。 | +| OWNERSHIP | 授予对 Connection 的完全控制权。在任意时刻,特定对象上的此权限只能由单个角色持有。 | + +### Sequence 权限 {#sequence-privileges} + +| 权限 | 描述 | +|:----------------|:-----------------------------------------------------------------------------------------------------------------| +| Access Sequence | 可以访问 Sequence。(例如:Drop、Desc) | +| ALL | 为指定对象类型授予访问 Sequence 权限。 | +| OWNERSHIP | 授予对 Sequence 的完全控制权。在任意时刻,特定对象上的此权限只能由单个角色持有。 | + +### Procedure 权限 {#procedure-privileges} + +| 权限 | 描述 | +|:-----------------|:------------------------------------------------------------------------------------------------------------------| +| Access Procedure | 可以访问 Procedure。(例如:Drop、Call、Desc) | +| ALL | 为指定对象类型授予访问 Procedure 权限。 | +| OWNERSHIP | 授予对 Procedure 的完全控制权。在任意时刻,特定对象上的此权限只能由单个角色持有。 | + +### Masking Policy 权限 {#masking-policy-privileges} + +除了全局 `CREATE MASKING POLICY` 和 `APPLY MASKING POLICY` 权限外,还可以为单个 masking policy 授予访问权限: + +| 权限 | 描述 | +|:----------|:--------------------------------------------------------------------------------------------------------------------------------------| +| APPLY | 将 masking policy 附加到列或从列中分离,并允许对该 policy 执行 DESC/DROP 操作。 | +| OWNERSHIP | 授予对 masking policy 的完全控制权。{{{ .lake }}} 会将 OWNERSHIP 授予创建该 policy 的角色,并在 policy 被删除时自动(权限)回收该权限。 | + +### Row Access Policy 权限 {#row-access-policy-privileges} + +Row access policy 采用相同的治理模型。除了全局 `CREATE ROW ACCESS POLICY` 和 `APPLY ROW ACCESS POLICY` 权限外,还可以在需要时按 policy 授予访问权限: + +| 权限 | 描述 | +|:----------|:---------------------------------------------------------------------------------------------------------------------------------------------------| +| APPLY | 将 row access policy 添加到表中或从表中移除,并允许对该 policy 执行 DESC/DROP 操作。 | +| OWNERSHIP | 授予对 row access policy 的完全控制权。{{{ .lake }}} 会将 OWNERSHIP 授予创建者角色,并在 policy 被删除时自动(权限)回收该权限。 | diff --git a/tidb-cloud-lake/guides/query-avro-files-in-stage.md b/tidb-cloud-lake/guides/query-avro-files-in-stage.md new file mode 100644 index 0000000000000..97b753cfc1f5f --- /dev/null +++ b/tidb-cloud-lake/guides/query-avro-files-in-stage.md @@ -0,0 +1,99 @@ +--- +title: 在 Stage 中查询 Avro 文件 +summary: "{{{ .lake }}} 提供了对直接从 stage 查询 Avro 文件的全面支持。这使你无需先将数据加载到表中,即可灵活地进行数据探索和转换。" +--- + +# 在 Stage 中查询 Avro 文件 + +## 语法 {#syntax} + +- [将行作为 Variant 查询](/tidb-cloud-lake/guides/query-stage.md#query-rows-as-variants) +- [查询元信息](/tidb-cloud-lake/guides/query-stage.md#query-metadata) + +## Avro 查询功能概览 {#avro-querying-features-overview} + +{{{ .lake }}} 提供了对直接从 stage 查询 Avro 文件的全面支持。这使你无需先将数据加载到表中,即可灵活地进行数据探索和转换。 + +* **Variant 表示**:Avro 文件中的每一行都会被视为一个 variant,并通过 `$1` 引用。这使你能够灵活访问 Avro 数据中的嵌套结构。 +* **类型映射**:每种 Avro 类型都会映射为 {{{ .lake }}} 中对应的 variant 类型。 +* **元信息访问**:你可以访问 `METADATA$FILENAME` 和 `METADATA$FILE_ROW_NUMBER` 等元信息列,以获取有关源文件和行的更多上下文信息。 + +## 教程 {#tutorial} + +本教程演示如何查询存储在 stage 中的 Avro 文件。 + +### 第 1 步:准备一个 Avro 文件 {#step-1-prepare-an-avro-file} + +假设有一个名为 `user` 的 Avro 文件,其 schema 如下: + +```json +{ + "type": "record", + "name": "user", + "fields": [ + { + "name": "id", + "type": "long" + }, + { + "name": "name", + "type": "string" + } + ] +} +``` + +### 第 2 步:创建一个外部 Stage {#step-2-create-an-external-stage} + +使用你自己的 S3 存储桶和凭证创建一个外部 stage,其中存储了你的 Avro 文件。 + +```sql +CREATE STAGE avro_query_stage +URL = 's3://load/avro/' +CONNECTION = ( + ACCESS_KEY_ID = '' + SECRET_ACCESS_KEY = '' +); +``` + +### 第 3 步:查询 Avro 文件 {#step-3-query-avro-files} + +#### 基本查询 {#basic-query} + +直接从 stage 查询 Avro 文件: + +```sql +SELECT + CAST($1:id AS INT) AS id, + $1:name AS name +FROM @avro_query_stage +( + FILE_FORMAT => 'AVRO', + PATTERN => '.*[.]avro' +); +``` + +### 带元信息的查询 {#query-with-metadata} + +直接从 stage 查询 Avro 文件,并包含 `METADATA$FILENAME` 和 `METADATA$FILE_ROW_NUMBER` 等元信息列: + +```sql +SELECT + METADATA$FILENAME, + METADATA$FILE_ROW_NUMBER, + CAST($1:id AS INT) AS id, + $1:name AS name +FROM @avro_query_stage +( + FILE_FORMAT => 'AVRO', + PATTERN => '.*[.]avro' +); +``` + +## 到 Variant 的类型映射 {#type-mapping-to-variant} + +{{{ .lake }}} 中的 variant 以 JSONB 形式存储。虽然大多数 Avro 类型都可以直接映射,但仍有一些特殊情况需要注意: + +* **时间类型**:`TimeMillis` 和 `TimeMicros` 会映射为 `INT64`,因为 JSONB 没有原生的 Time 类型。用户在处理这些值时应注意其原始类型。 +* **Decimal 类型**:Decimal 会被加载为 `DECIMAL128` 或 `DECIMAL256`。如果精度超出支持的限制,可能会报错。 +* **Enum 类型**:Avro `ENUM` 类型会映射为 {{{ .lake }}} 中的 `STRING` 值。 \ No newline at end of file diff --git a/tidb-cloud-lake/guides/query-csv-files-in-stage.md b/tidb-cloud-lake/guides/query-csv-files-in-stage.md new file mode 100644 index 0000000000000..47b6d85a35996 --- /dev/null +++ b/tidb-cloud-lake/guides/query-csv-files-in-stage.md @@ -0,0 +1,77 @@ +--- +title: 在 Stage 中查询 CSV 文件 +summary: 使用你自己的 S3 存储桶和凭证创建一个外部 stage,用于存储你的 CSV 文件。 +--- + +# 在 Stage 中查询 CSV 文件 + +## 语法 {#syntax} + +- [按位置查询列](/tidb-cloud-lake/guides/query-stage.md#query-columns-by-position) +- [查询元信息](/tidb-cloud-lake/guides/query-stage.md#query-metadata) + +## 教程 {#tutorial} + +### 第 1 步:创建外部 Stage {#step-1-create-an-external-stage} + +使用你自己的 S3 存储桶和凭证创建一个外部 stage,用于存储你的 CSV 文件。 + +```sql +CREATE STAGE csv_query_stage +URL = 's3://load/csv/' +CONNECTION = ( + ACCESS_KEY_ID = '' + SECRET_ACCESS_KEY = '' +); +``` + +### 第 2 步:创建自定义 CSV 文件格式 {#step-2-create-custom-csv-file-format} + +```sql +CREATE FILE FORMAT csv_query_format + TYPE = CSV, + RECORD_DELIMITER = '\n', + FIELD_DELIMITER = ',', + COMPRESSION = AUTO, + SKIP_HEADER = 1; -- Skip first line when querying if the CSV file has header +``` + +- 更多 CSV 文件格式选项,请参见 [CSV 文件格式选项](/tidb-cloud-lake/sql/input-output-file-formats.md#csv-options) + +### 第 3 步:查询 CSV 文件 {#step-3-query-csv-files} + +```sql +SELECT $1, $2, $3 +FROM @csv_query_stage +( + FILE_FORMAT => 'csv_query_format', + PATTERN => '.*[.]csv' +); +``` + +如果 CSV 文件使用 gzip 压缩,可以使用以下查询: + +```sql +SELECT $1, $2, $3 +FROM @csv_query_stage +( + FILE_FORMAT => 'csv_query_format', + PATTERN => '.*[.]csv[.]gz' +); +``` + +### 使用元信息进行查询 {#query-with-metadata} + +直接从 stage 查询 CSV 文件,包括 `METADATA$FILENAME` 和 `METADATA$FILE_ROW_NUMBER` 等元信息列: + +```sql +SELECT + METADATA$FILENAME, + METADATA$FILE_ROW_NUMBER, + $1, $2, $3 +FROM @csv_query_stage +( + FILE_FORMAT => 'csv_query_format', + PATTERN => '.*[.]csv' +); +``` \ No newline at end of file diff --git a/tidb-cloud-lake/guides/query-ndjson-files-in-stage.md b/tidb-cloud-lake/guides/query-ndjson-files-in-stage.md new file mode 100644 index 0000000000000..3a47eac0c3624 --- /dev/null +++ b/tidb-cloud-lake/guides/query-ndjson-files-in-stage.md @@ -0,0 +1,97 @@ +--- +title: 在 Stage 中查询 NDJSON 文件 +summary: 在 {{{ .lake }}} 中,你可以直接查询存储在 stage 中的 NDJSON 文件,而无需先将数据加载到表中。这种方式特别适用于数据探索、ETL 处理和临时分析场景。 +--- + +# 在 Stage 中查询 NDJSON 文件 + +在 {{{ .lake }}} 中,你可以直接查询存储在 stage 中的 NDJSON 文件,而无需先将数据加载到表中。这种方式特别适用于数据探索、ETL 处理和临时分析场景。 + +## 什么是 NDJSON? {#what-is-ndjson} + +NDJSON(Newline Delimited JSON)是一种基于 JSON 的文件格式,其中每一行都包含一个完整且有效的 JSON 对象。这种格式特别适合流式数据处理和大数据分析。 + +**NDJSON 文件内容示例:** + +```json +{"id": 1, "title": "Database Fundamentals", "author": "John Doe", "price": 45.50, "category": "Technology"} +{"id": 2, "title": "Machine Learning in Practice", "author": "Jane Smith", "price": 68.00, "category": "AI"} +{"id": 3, "title": "Web Development Guide", "author": "Mike Johnson", "price": 52.30, "category": "Frontend"} +``` + +**NDJSON 的优势:** + +- **适合流式处理**:可以逐行解析,而无需将整个文件加载到内存中 +- **兼容大数据**:广泛用于日志文件、数据导出和 ETL 管道 +- **易于处理**:每一行都是一个独立的 JSON 对象,便于并行处理 + +## 语法 {#syntax} + +- [将行查询为 Variants](/tidb-cloud-lake/guides/query-stage.md#query-rows-as-variants) +- [查询元信息](/tidb-cloud-lake/guides/query-stage.md#query-metadata) + +## 教程 {#tutorial} + +### 第 1 步:创建外部 Stage {#step-1-create-an-external-stage} + +使用你自己的 S3 存储桶和凭证创建一个外部 stage,用于存储 NDJSON 文件。 + +```sql +CREATE STAGE ndjson_query_stage +URL = 's3://load/ndjson/' +CONNECTION = ( + ACCESS_KEY_ID = '' + SECRET_ACCESS_KEY = '' +); +``` + +### 第 2 步:创建自定义 NDJSON 文件格式 {#step-2-create-custom-ndjson-file-format} + +```sql +CREATE FILE FORMAT ndjson_query_format + TYPE = NDJSON, + COMPRESSION = AUTO; +``` + +- 更多 NDJSON 文件格式选项,请参见 [NDJSON 文件格式选项](/tidb-cloud-lake/sql/input-output-file-formats.md#ndjson-options) + +### 第 3 步:查询 NDJSON 文件 {#step-3-query-ndjson-files} + +现在,你可以直接从 stage 中查询 NDJSON 文件。以下示例从每个 JSON 对象中提取 `title` 和 `author` 字段: + +```sql +SELECT $1:title, $1:author +FROM @ndjson_query_stage +( + FILE_FORMAT => 'ndjson_query_format', + PATTERN => '.*[.]ndjson' +); +``` + +**说明:** + +- `$1:title` 和 `$1:author`:从 JSON 对象中提取特定字段。`$1` 表示整个 JSON 对象(作为 variant),而 `:field_name` 用于访问各个字段 +- `@ndjson_query_stage`:引用在第 1 步中创建的外部 stage +- `FILE_FORMAT => 'ndjson_query_format'`:使用在第 2 步中定义的自定义文件格式 +- `PATTERN => '.*[.]ndjson'`:匹配所有以 `.ndjson` 结尾文件的正则表达式模式 + +### 查询压缩文件 {#querying-compressed-files} + +如果 NDJSON 文件使用 gzip 压缩,请修改模式以匹配压缩文件: + +```sql +SELECT $1:title, $1:author +FROM @ndjson_query_stage +( + FILE_FORMAT => 'ndjson_query_format', + PATTERN => '.*[.]ndjson[.]gz' +); +``` + +**关键区别:** 模式 `.*[.]ndjson[.]gz` 匹配所有以 `.ndjson.gz` 结尾的文件。由于文件格式中设置了 `COMPRESSION = AUTO`,{{{ .lake }}} 会在查询执行期间自动解压缩 gzip 文件。 + +## 相关文档 {#related-documentation} + +- [加载 NDJSON 文件](/tidb-cloud-lake/guides/load-ndjson.md) - 如何将 NDJSON 数据加载到表中 +- [NDJSON 文件格式选项](/tidb-cloud-lake/sql/input-output-file-formats.md#ndjson-options) - 完整的 NDJSON 格式配置 +- [CREATE STAGE](/tidb-cloud-lake/sql/create-stage.md) - 管理外部和内部 stage \ No newline at end of file diff --git a/tidb-cloud-lake/guides/query-parquet-files-in-stage.md b/tidb-cloud-lake/guides/query-parquet-files-in-stage.md new file mode 100644 index 0000000000000..c80200d476115 --- /dev/null +++ b/tidb-cloud-lake/guides/query-parquet-files-in-stage.md @@ -0,0 +1,75 @@ +--- +title: 在 Stage 中查询 Parquet 文件 +summary: 使用你自己的 S3 存储桶和凭证创建一个外部 stage,用于存储你的 Parquet 文件。 +--- + +# 在 Stage 中查询 Parquet 文件 + +## 语法 {#syntax} + +- [将行查询为 Variant](/tidb-cloud-lake/guides/query-stage.md#query-rows-as-variants) +- [按名称查询列](/tidb-cloud-lake/guides/query-stage.md#query-columns-by-name) +- [查询元信息](/tidb-cloud-lake/guides/query-stage.md#query-metadata) + +## 教程 {#tutorial} + +### 第 1 步:创建外部 Stage {#step-1-create-an-external-stage} + +使用你自己的 S3 存储桶和凭证创建一个外部 stage,用于存储你的 Parquet 文件。 + +```sql +CREATE STAGE parquet_query_stage +URL = 's3://load/parquet/' +CONNECTION = ( + ACCESS_KEY_ID = '' + SECRET_ACCESS_KEY = '' +); +``` + +### 第 2 步:创建自定义 Parquet 文件格式 {#step-2-create-custom-parquet-file-format} + +```sql +CREATE FILE FORMAT parquet_query_format TYPE = PARQUET; +``` + +- 更多 Parquet 文件格式选项,请参见 [Parquet 文件格式选项](/tidb-cloud-lake/sql/input-output-file-formats.md#parquet-options) + +### 第 3 步:查询 Parquet 文件 {#step-3-query-parquet-files} + +使用列名进行查询: + +```sql +SELECT * +FROM @parquet_query_stage +( + FILE_FORMAT => 'parquet_query_format', + PATTERN => '.*[.]parquet' +); +``` + +使用路径表达式进行查询: + +```sql +SELECT $1 +FROM @parquet_query_stage +( + FILE_FORMAT => 'parquet_query_format', + PATTERN => '.*[.]parquet' +); +``` + +### 使用元信息进行查询 {#query-with-metadata} + +直接从 stage 查询 Parquet 文件,包括 `METADATA$FILENAME` 和 `METADATA$FILE_ROW_NUMBER` 等元信息列: + +```sql +SELECT + METADATA$FILENAME, + METADATA$FILE_ROW_NUMBER, + * +FROM @parquet_query_stage +( + FILE_FORMAT => 'parquet_query_format', + PATTERN => '.*[.]parquet' +); +``` \ No newline at end of file diff --git a/tidb-cloud-lake/guides/query-result-cache.md b/tidb-cloud-lake/guides/query-result-cache.md new file mode 100644 index 0000000000000..3e9f6a9794d8d --- /dev/null +++ b/tidb-cloud-lake/guides/query-result-cache.md @@ -0,0 +1,121 @@ +--- +title: 查询结果缓存 +summary: "{{{ .lake }}} 在启用后会缓存并持久化每个已执行查询的结果。这可以显著缩短获得查询结果所需的时间。" +--- + +# 查询结果缓存 + +{{{ .lake }}} 在启用后会缓存并持久化每个已执行查询的结果。这可以显著缩短获得查询结果所需的时间。 + +## 缓存使用条件 {#cache-usage-conditions} + +只有在**所有**条件都满足时,查询结果才会从缓存中复用: + +| 条件 | 要求 | +|-----------|-------------| +| **启用缓存** | 当前会话中 `enable_query_result_cache = 1` | +| **相同查询** | 查询文本必须完全一致(大小写敏感) | +| **执行时间** | 原始查询运行时 ≥ `query_result_cache_min_execute_secs` | +| **结果大小** | 缓存结果 ≤ `query_result_cache_max_bytes` | +| **TTL 有效** | 缓存存活时间 < `query_result_cache_ttl_secs` | +| **数据一致性** | 自缓存以来表数据未发生变化(除非 `query_result_cache_allow_inconsistent = 1`) | +| **会话作用域** | 缓存仅限当前会话 | + +> **注意:** +> +> 默认情况下(`query_result_cache_allow_inconsistent = 0`),当底层表数据发生变化时,缓存结果会被自动失效。这可以确保数据一致性,但在频繁修改的表上可能会降低缓存效果。 + +## 快速开始 {#quick-start} + +在你的会话中启用查询结果缓存: + +```sql +-- Enable query result cache +SET enable_query_result_cache = 1; + +-- Optional: Cache all queries (including fast ones) +SET query_result_cache_min_execute_secs = 0; +``` + +## 配置项 {#configuration-settings} + +| 设置 | 默认值 | 描述 | +|---------|---------|-------------| +| `enable_query_result_cache` | 0 | 启用/禁用查询结果缓存 | +| `query_result_cache_allow_inconsistent` | 0 | 即使底层数据已变化,也允许使用缓存结果 | +| `query_result_cache_max_bytes` | 1048576 | 单个缓存结果的最大大小(字节) | +| `query_result_cache_min_execute_secs` | 1 | 开始缓存前所需的最小执行时间 | +| `query_result_cache_ttl_secs` | 300 | 缓存过期时间(5 分钟) | + +## 性能示例 {#performance-example} + +本示例演示如何缓存一个 TPC-H Q1 查询: + +### 1. 启用缓存 {#1-enable-caching} + +```sql +SET enable_query_result_cache = 1; +SET query_result_cache_min_execute_secs = 0; +``` + +### 2. 第一次执行(无缓存) {#2-first-execution-no-cache} + +```sql +SELECT + l_returnflag, + l_linestatus, + sum(l_quantity) as sum_qty, + sum(l_extendedprice) as sum_base_price, + sum(l_extendedprice * (1 - l_discount)) as sum_disc_price, + sum(l_extendedprice * (1 - l_discount) * (1 + l_tax)) as sum_charge, + avg(l_quantity) as avg_qty, + avg(l_extendedprice) as avg_price, + avg(l_discount) as avg_disc, + count(*) as count_order +FROM lineitem +WHERE l_shipdate <= add_days(to_date('1998-12-01'), -90) +GROUP BY l_returnflag, l_linestatus +ORDER BY l_returnflag, l_linestatus; +``` + +**结果**:4 行,耗时 **21.492 秒**(处理了 6 亿行) + +### 3. 验证缓存条目 {#3-verify-cache-entry} + +```sql +SELECT sql, query_id, result_size, num_rows FROM system.query_cache; +``` + +### 4. 第二次执行(来自缓存) {#4-second-execution-from-cache} + +再次运行相同的查询。 + +**结果**:4 行,耗时 **0.164 秒**(处理了 0 行) + +## 缓存管理 {#cache-management} + +### 监控缓存使用情况 {#monitor-cache-usage} + +```sql +SELECT * FROM system.query_cache; +``` + +### 访问缓存结果 {#access-cached-results} + +```sql +SELECT * FROM RESULT_SCAN(LAST_QUERY_ID()); +``` + +### 缓存生命周期 {#cache-lifecycle} + +在以下情况下,缓存结果会被自动移除: + +- **TTL 过期**(默认:5 分钟) +- **结果大小超过限制**(默认:1MB) +- **会话结束**(缓存的作用域为会话) +- **底层数据发生变化**(为保证一致性会自动失效) +- **表结构发生变化**(schema 修改会使缓存失效) + +> **注意:** +> +> 查询结果缓存的作用域为会话。每个会话都会维护自己的缓存,并在会话结束时自动清理。 \ No newline at end of file diff --git a/tidb-cloud-lake/guides/query-stage.md b/tidb-cloud-lake/guides/query-stage.md new file mode 100644 index 0000000000000..85846e0f13587 --- /dev/null +++ b/tidb-cloud-lake/guides/query-stage.md @@ -0,0 +1,161 @@ +--- +title: 查询与转换 +summary: "{{{ .lake }}} 支持直接查询已暂存的文件,而无需先将数据加载到表中。你可以查询任意 stage 类型(user、internal、external)中的文件,也可以直接查询对象存储和 HTTPS URL 中的文件。它非常适合在加载前后进行数据检查、验证和转换。" +--- + +# 查询与转换 + +{{{ .lake }}} 支持直接查询已暂存的文件,而无需先将数据加载到表中。你可以查询任意 stage 类型(user、internal、external)中的文件,也可以直接查询对象存储和 HTTPS URL 中的文件。它非常适合在加载前后进行数据检查、验证和转换。 + +## 语法 {#syntax} + +仅查询 + +```sql +SELECT { + [.] [, [.] ...] -- Query columns by name + | [.]$ [, [.]$ ...] -- Query columns by position + | [.]$1[:] [, [.]$1[:] ...] -- Query rows as Variants +} +FROM {@[/] | ''} -- stage table function + [( -- stage table function parameters + [], + [ PATTERN => ''], + [ FILE_FORMAT => 'CSV | TSV | NDJSON | PARQUET | ORC | Avro | '], + [ FILES => ( '' [ , '' ... ])], + [ CASE_SENSITIVE => true | false ] + )] + [] +``` + +带转换的复制 + +```sql +COPY INTO [.] [ ( [ , ... ] ) ] + FROM ( + SELECT { + [.] [, [.] ...] -- Query columns by name + | [.]$ [, [.]$ ...] -- Query columns by position + | [.]$1[:] [, [.]$1[:] ...] -- Query rows as Variants + } ] + FROM {@[/] | ''} + ) +[ FILES = ( '' [ , '' ] [ , ... ] ) ] +[ PATTERN = '' ] +[ FILE_FORMAT = ( + FORMAT_NAME = '' + | TYPE = { CSV | TSV | NDJSON | PARQUET | ORC | AVRO } [ formatTypeOptions ] + ) ] +[ copyOptions ] +``` + +> **注意:** +> +> 对比这两种语法: +> +> - `Select List` 相同 +> - `FROM {@[/] | ''}` 相同 +> - 参数不同: +> - 查询使用 `table function parameters`,即 `( => , ...)` +> - 转换使用位于末尾的选项,参见 [Copy into table](/tidb-cloud-lake/sql/copy-into-table.md) + +## FROM 子句 {#from-clause} + +`FROM` 子句使用与 `Table Function` 类似的语法。与普通表一样,在与其他表进行 join 时也可以使用表 `alias`。 + +table function 参数: + +| 参数 | 描述 | +|-------------------------|---------------------------------------------------------| +| `FILE_FORMAT` | 文件格式类型(CSV、TSV、NDJSON、PARQUET、ORC、Avro) | +| `PATTERN` | 用于过滤文件的正则表达式模式 | +| `FILES` | 要查询的文件显式列表 | +| `CASE_SENSITIVE` | 列名是否区分大小写(仅 Parquet) | +| `connection_parameters` | 外部存储连接详情 | + +## 查询文件数据 {#query-file-data} + +select 列表支持三种语法;一次只能使用其中一种,不能混用。 + +### 将行作为 Variants 查询 {#query-rows-as-variants} + +- 支持的文件格式:NDJSON、AVRO、Parquet、ORC + +> **注意:** +> +> 当前对于 Parquet 和 ORC,`Query rows as Variants` 比 `Query columns by name` 更慢,并且这两种方法不能混用。 + +语法: + +```sql +SELECT [.]$1[:] [, [.]$1[:] ...] +``` + +- 示例:`SELECT $1:id, $1:name FROM ...` +- 表结构:($1: Variant)。即只有一列,类型为 Variant Object,每个 Variant 表示完整的一行 +- 说明: + - 像 `$1:column` 这样的路径表达式的类型也是 Variant,在表达式中使用或加载到目标表列时可以自动转换为原生类型。有时你可能希望在执行特定类型操作前手动进行类型转换(例如 `CAST($1:id AS INT)`),以使语义更加明确。 + +### 按名称查询列 {#query-columns-by-name} + +- 支持的文件格式:NDJSON、AVRO、Parquet、ORC + +```sql +SELECT [.] [, [.] ...] +``` + +- 示例:`SELECT id, name FROM ...` +- 表结构:从 Parquet 或 ORC 文件 schema 映射得到的列 +- 说明: + - 所有文件都必须具有相同的 Parquet/ORC schema;否则会返回错误 + +### 按位置查询列 {#query-columns-by-position} + +- 支持的文件格式:CSV、TSV + +```sql +SELECT [.]$[, [.]$, ...] +``` + +- 示例:`SELECT $1, $2 FROM ...` +- 表结构:类型为 `VARCHAR NULL` 的列 +- 说明 + - `` 从 1 开始 + +## 查询元信息 {#query-metadata} + +你还可以在查询中包含文件元信息,这对于跟踪数据血缘和调试非常有用: + +```sql +SELECT METADATA$FILENAME, METADATA$FILE_ROW_NUMBER, $1, +( + FILE_FORMAT => 'ndjson_query_format', + PATTERN => '.*[.]ndjson' +); +``` + +以下是支持的文件格式可用的文件级元信息字段: + +| 文件元信息 | 类型 | 描述 | +| -------------------------- | ------- |--------------------------------------------------| +| `METADATA$FILENAME` | VARCHAR | 读取该行所在文件的路径 | +| `METADATA$FILE_ROW_NUMBER` | INT | 该行在文件中的行号(从 0 开始) | + +**使用场景:** + +- **数据血缘**:跟踪每条记录来自哪个源文件 +- **调试**:通过文件和行号定位有问题的记录 +- **增量处理**:仅处理特定文件或文件中的特定范围 + +## 按文件格式分类的教程 {#tutorials-by-file-formats} + +- [在 Stage 中查询 Parquet 文件](/tidb-cloud-lake/guides/query-parquet-files-in-stage.md) +- [在 Stage 中查询 ORC 文件](/tidb-cloud-lake/guides/query-staged-orc-files-in-stage.md) +- [在 Stage 中查询 NDJSON 文件](/tidb-cloud-lake/guides/query-ndjson-files-in-stage.md) +- [在 Stage 中查询 Avro 文件](/tidb-cloud-lake/guides/query-avro-files-in-stage.md) +- [在 Stage 中查询 CSV 文件](/tidb-cloud-lake/guides/query-csv-files-in-stage.md) +- [在 Stage 中查询 TSV 文件](/tidb-cloud-lake/guides/query-tsv-files-in-stage.md) + +## Schema Evolution {#schema-evolution} + +- [Schema Evolution](/tidb-cloud-lake/guides/schema-evolution.md):在加载表结构持续演进的 Parquet 文件时,自动向表中添加新列。 \ No newline at end of file diff --git a/tidb-cloud-lake/guides/query-staged-orc-files-in-stage.md b/tidb-cloud-lake/guides/query-staged-orc-files-in-stage.md new file mode 100644 index 0000000000000..6fb9ee16ee629 --- /dev/null +++ b/tidb-cloud-lake/guides/query-staged-orc-files-in-stage.md @@ -0,0 +1,93 @@ +--- +title: 在 Stage 中查询暂存的 ORC 文件 +summary: 在本教程中,我们将带你完成以下过程:下载 ORC 格式的 Iris 数据集,将其上传到 Amazon S3 存储桶,创建外部 stage,并直接从 ORC 文件中查询数据。 +--- + +# 在 Stage 中查询暂存的 ORC 文件 + +## 语法 {#syntax} + +- [将行作为 Variant 查询](/tidb-cloud-lake/guides/query-stage.md#query-rows-as-variants) +- [按列名查询列](/tidb-cloud-lake/guides/query-stage.md#query-columns-by-name) +- [查询元信息](/tidb-cloud-lake/guides/query-stage.md#query-metadata) + +## 教程 {#tutorial} + +在本教程中,我们将带你完成以下过程:下载 ORC 格式的 Iris 数据集,将其上传到 Amazon S3 存储桶,创建外部 stage,并直接从 ORC 文件中查询数据。 + +## 第 1 步:下载 Iris 数据集 {#step-1-download-iris-dataset} + +从 下载 iris 数据集,然后将其上传到你的 Amazon S3 存储桶。 + +iris 数据集包含 3 个类,每个类有 50 个实例,其中每个类对应一种鸢尾花类型。它包含 4 个属性:(1) 萼片长度,(2) 萼片宽度,(3) 花瓣长度,(4) 花瓣宽度,最后一列包含类标签。 + +## 第 2 步:创建外部 stage {#step-2-create-external-stage} + +使用存放 iris 数据集文件的 Amazon S3 存储桶创建一个外部 stage。 + +```sql +CREATE STAGE orc_query_stage + URL = 's3://lake-doc' + CONNECTION = ( + ACCESS_KEY_ID = '', + SECRET_ACCESS_KEY = '' + ); +``` + +## 第 3 步:查询 ORC 文件 {#step-3-query-orc-file} + +按列查询 + +```sql +SELECT * +FROM @orc_query_stage +( + FILE_FORMAT => 'orc', + PATTERN => '.*[.]orc' +); + +┌──────────────────────────────────────────────────────────────────────────────────────────────────┐ +│ sepal_length │ sepal_width │ petal_length │ petal_width │ species │ +├───────────────────┼───────────────────┼───────────────────┼───────────────────┼──────────────────┤ +│ 5.1 │ 3.5 │ 1.4 │ 0.2 │ setosa │ +│ · │ · │ · │ · │ · │ +│ 5.9 │ 3 │ 5.1 │ 1.8 │ virginica │ +└──────────────────────────────────────────────────────────────────────────────────────────────────┘ +``` + +使用路径表达式查询: + +```sql +SELECT $1 +FROM @orc_query_stage +( + FILE_FORMAT => 'orc', + PATTERN => '.*[.]orc' + +); +``` + +你也可以直接查询远程 ORC 文件: + +```sql +SELECT + * +FROM + 'https://github.com/tensorflow/io/raw/master/tests/test_orc/iris.orc' (file_format => 'orc'); +``` + +## 第 4 步:结合元信息查询 {#step-4-query-with-metadata} + +直接从 stage 查询 ORC 文件,包括 `METADATA$FILENAME` 和 `METADATA$FILE_ROW_NUMBER` 等元信息列: + +```sql +SELECT + METADATA$FILENAME, + METADATA$FILE_ROW_NUMBER, + * +FROM @orc_query_stage +( + FILE_FORMAT => 'orc', + PATTERN => '.*[.]orc' +); +``` \ No newline at end of file diff --git a/tidb-cloud-lake/guides/query-tsv-files-in-stage.md b/tidb-cloud-lake/guides/query-tsv-files-in-stage.md new file mode 100644 index 0000000000000..d34672c51eb2b --- /dev/null +++ b/tidb-cloud-lake/guides/query-tsv-files-in-stage.md @@ -0,0 +1,78 @@ +--- +title: 在 Stage 中查询 TSV 文件 +summary: 创建一个外部 stage,使用你自己的 S3 存储桶和凭证来存放 TSV 文件。 +--- + +# 在 Stage 中查询 TSV 文件 + +本指南介绍如何从 stage 中查询 TSV 文件(在 {{{ .lake }}} `v1.2.890-nightly` 及更高版本中称为 `TEXT`)。为兼容旧版本服务器,示例中仍使用 `TSV`。 + +## 语法 {#syntax} + +- [按位置查询列](/tidb-cloud-lake/guides/query-stage.md#query-columns-by-position) +- [查询元信息](/tidb-cloud-lake/guides/query-stage.md#query-metadata) + +## 教程 {#tutorial} + +### 第 1 步:创建外部 Stage {#step-1-create-an-external-stage} + +创建一个外部 stage,使用你自己的 S3 存储桶和凭证来存放 TSV 文件。 + +```sql +CREATE STAGE tsv_query_stage +URL = 's3://load/tsv/' +CONNECTION = ( + ACCESS_KEY_ID = '' + SECRET_ACCESS_KEY = '' +); +``` + +### 第 2 步:创建自定义 TSV 文件格式 {#step-2-create-custom-tsv-file-format} + +```sql +CREATE FILE FORMAT tsv_query_format + TYPE = TSV, + RECORD_DELIMITER = '\n', + FIELD_DELIMITER = ',', + COMPRESSION = AUTO; +``` + +- 更多 TSV 文件格式选项,请参见 [TSV 文件格式选项](/tidb-cloud-lake/sql/input-output-file-formats.md#tsv-options) + +### 第 3 步:查询 TSV 文件 {#step-3-query-tsv-files} + +```sql +SELECT $1, $2, $3 +FROM @tsv_query_stage +( + FILE_FORMAT => 'tsv_query_format', + PATTERN => '.*[.]tsv' +); +``` + +如果 TSV 文件使用 gzip 压缩,可以使用以下查询: + +```sql +SELECT $1, $2, $3 +FROM @tsv_query_stage +( + FILE_FORMAT => 'tsv_query_format', + PATTERN => '.*[.]tsv[.]gz' +); +``` + +### 查询时包含元信息 {#query-with-metadata} + +直接从 stage 查询 TSV 文件,并包含 `METADATA$FILENAME` 和 `METADATA$FILE_ROW_NUMBER` 等元信息列: + +```sql +SELECT + METADATA$FILENAME, + METADATA$FILE_ROW_NUMBER, + $1, $2, $3 +FROM @tsv_query_stage +( + FILE_FORMAT => 'tsv_query_format', + PATTERN => '.*[.]tsv' +); +``` \ No newline at end of file diff --git a/tidb-cloud-lake/guides/recovery-from-operational-errors.md b/tidb-cloud-lake/guides/recovery-from-operational-errors.md new file mode 100644 index 0000000000000..06ea668620822 --- /dev/null +++ b/tidb-cloud-lake/guides/recovery-from-operational-errors.md @@ -0,0 +1,210 @@ +--- +title: 从操作错误中恢复 +summary: 本指南提供了在 {{{ .lake }}} 中从常见操作错误中恢复的分步说明。 +--- + +# 从操作错误中恢复 + +本指南提供了在 {{{ .lake }}} 中从常见操作错误中恢复的分步说明。 + +## 简介 {#introduction} + +{{{ .lake }}} 可以帮助你从以下常见操作错误中恢复: + +- **意外删除数据库** +- **意外删除表** +- **错误的数据修改(UPDATE/DELETE 操作)** +- **意外截断表** +- **数据加载错误** +- **Schema Evolution 回滚**(还原表结构变更) +- **已删除的列或约束** + +这些恢复能力由 {{{ .lake }}} 的 FUSE 引擎提供支持。该引擎采用类似 Git 的存储设计,可维护数据在不同时间点的快照。 + +## 恢复场景与解决方案 {#recovery-scenarios-and-solutions} + +### 场景:意外删除数据库 {#scenario-accidentally-dropped-database} + +如果你意外删除了数据库,可以使用 `UNDROP DATABASE` 命令将其恢复: + +1. 确认已删除的数据库: + + ```sql + SHOW DROP DATABASES LIKE '%sales_data%'; + ``` + +2. 恢复已删除的数据库: + + ```sql + UNDROP DATABASE sales_data; + ``` + +3. 验证数据库是否已恢复: + + ```sql + SHOW DATABASES; + ``` + +4. 恢复所有权(如有需要): + + ```sql + GRANT OWNERSHIP on sales_data.* to ROLE ; + ``` + +> **重要:** +> +> 只能在保留时间内恢复已删除的数据库(默认值为 24 小时)。 + +更多详情,请参见 [UNDROP DATABASE](/tidb-cloud-lake/sql/undrop-database.md) 和 [SHOW DROP DATABASES](/tidb-cloud-lake/sql/show-drop-databases.md)。 + +### 场景:意外删除表 {#scenario-accidentally-dropped-table} + +如果你意外删除了表,可以使用 `UNDROP TABLE` 命令将其恢复: + +1. 确认已删除的表: + + ```sql + SHOW DROP TABLES LIKE '%order%'; + ``` + +2. 恢复已删除的表: + + ```sql + UNDROP TABLE sales_data.orders; + ``` + +3. 验证表是否已恢复: + + ```sql + SHOW TABLES FROM sales_data; + ``` + +4. 恢复所有权(如有需要): + + ```sql + GRANT OWNERSHIP on sales_data.orders to ROLE ; + ``` + +> **重要:** +> +> 只能在保留时间内恢复已删除的表(默认值为 24 小时)。 + +更多详情,请参见 [UNDROP TABLE](/tidb-cloud-lake/sql/undrop-table.md) 和 [SHOW DROP TABLES](/tidb-cloud-lake/sql/show-drop-tables.md)。 + +### 场景:错误的数据修改或删除 {#scenario-incorrect-data-updates-or-deletions} + +如果你意外修改或删除了表中的数据,可以使用 `FLASHBACK TABLE` 命令将其恢复到之前的状态: + +1. 找出错误操作发生前的快照 ID 或时间戳: + + ```sql + SELECT * FROM fuse_snapshot('sales_data', 'orders'); + ``` + + ```text + snapshot_id: c5c538d6b8bc42f483eefbddd000af7d + snapshot_location: 29356/44446/_ss/c5c538d6b8bc42f483eefbddd000af7d_v2.json + format_version: 2 + previous_snapshot_id: NULL + [... ...] + timestamp: 2023-04-19 04:20:25.062854 + ``` + +2. 将表恢复到之前的状态: + + ```sql + -- Using snapshot ID + ALTER TABLE sales_data.orders FLASHBACK TO (SNAPSHOT => 'c5c538d6b8bc42f483eefbddd000af7d'); + + -- Or using timestamp + ALTER TABLE sales_data.orders FLASHBACK TO (TIMESTAMP => '2023-04-19 04:20:25.062854'::TIMESTAMP); + ``` + +3. 验证数据是否已恢复: + + ```sql + SELECT * FROM sales_data.orders LIMIT 3; + ``` + +> **重要:** +> +> 仅可对现有表执行 Flashback 操作,且必须在保留时间内进行。 + +更多详情,请参见 [FLASHBACK TABLE](/tidb-cloud-lake/sql/flashback-table.md)。 + +### 场景:Schema Evolution 回滚 {#scenario-schema-evolution-rollbacks} + +如果你对表结构进行了不需要的更改,可以回退到之前的 schema: + +1. 创建表并添加一些数据: + + ```sql + CREATE OR REPLACE TABLE customers (id INT, name VARCHAR, email VARCHAR); + INSERT INTO customers VALUES (1, 'John', 'john@example.com'); + ``` + +2. 进行 schema 更改: + + ```sql + ALTER TABLE customers ADD COLUMN phone VARCHAR; + DESC customers; + ``` + + 输出: + + ```text + ┌─────────┬─────────┬──────┬─────────┬─────────┐ + │ Field │ Type │ Null │ Default │ Extra │ + ├─────────┼─────────┼──────┼─────────┼─────────┤ + │ id │ INT │ YES │ NULL │ │ + │ name │ VARCHAR │ YES │ NULL │ │ + │ email │ VARCHAR │ YES │ NULL │ │ + │ phone │ VARCHAR │ YES │ NULL │ │ + └─────────┴─────────┴──────┴─────────┴─────────┘ + ``` + +3. 查找 schema 更改之前的 snapshot ID: + + ```sql + SELECT * FROM fuse_snapshot('default', 'customers'); + ``` + + 输出: + + ```text + snapshot_id: 01963cefafbb785ea393501d2e84a425 timestamp: 2025-04-16 04:51:03.227000 previous_snapshot_id: 01963ce9cc29735b87886a08d3ca7e2f + snapshot_id: 01963ce9cc29735b87886a08d3ca7e2f timestamp: 2025-04-16 04:44:37.289000 previous_snapshot_id: NULL + ``` + +4. 回退到之前的 schema(使用较早的 snapshot): + + ```sql + ALTER TABLE customers FLASHBACK TO (SNAPSHOT => '01963ce9cc29735b87886a08d3ca7e2f'); + ``` + +5. 验证 schema 已恢复: + + ```sql + DESC customers; + ``` + + 输出: + + ```text + ┌─────────┬─────────┬──────┬─────────┬─────────┐ + │ Field │ Type │ Null │ Default │ Extra │ + ├─────────┼─────────┼──────┼─────────┼─────────┤ + │ id │ INT │ YES │ NULL │ │ + │ name │ VARCHAR │ YES │ NULL │ │ + │ email │ VARCHAR │ YES │ NULL │ │ + └─────────┴─────────┴──────┴─────────┴─────────┘ + ``` + +## 重要注意事项和限制 {#important-considerations-and-limitations} + +- **时间限制**:恢复仅在保留时间内有效(默认:24 小时)。 +- **名称冲突**:如果已存在同名对象,则无法执行 undrop——请先[重命名数据库](/tidb-cloud-lake/sql/alter-database.md)或[重命名表](/tidb-cloud-lake/sql/rename-table.md)。 +- **所有权**:所有权不会自动恢复,需要在恢复后手动授予。 +- **临时表**:Flashback 不适用于 transient tables(不会存储快照)。 + +**紧急情况**:遇到严重数据丢失?请立即联系 {{{ .lake }}} Support 寻求帮助。 \ No newline at end of file diff --git a/tidb-cloud-lake/guides/roles.md b/tidb-cloud-lake/guides/roles.md new file mode 100644 index 0000000000000..d4c5df11a5038 --- /dev/null +++ b/tidb-cloud-lake/guides/roles.md @@ -0,0 +1,377 @@ +--- +title: 角色 +summary: {{{ .lake }}} 中的角色在简化权限管理方面发挥着关键作用。当多个用户需要相同的一组权限时,逐个授予权限会很繁琐。角色通过将一组权限分配给某个角色来提供解决方案,然后可以轻松地将该角色分配给多个用户。 +--- + +# 角色 + +{{{ .lake }}} 中的角色在简化权限管理方面发挥着关键作用。当多个用户需要相同的一组权限时,逐个授予权限会很繁琐。角色通过将一组权限分配给某个角色来提供解决方案,然后可以轻松地将该角色分配给多个用户。 + +![Alt text](/media/tidb-cloud-lake/access-control-3.png) + +## 继承角色并建立层级关系 {#inheriting-roles-establishing-hierarchy} + +角色授予允许一个角色继承另一个角色的权限和职责。这有助于创建一种灵活的层级结构,类似于组织架构,其中存在两个[内置角色](#built-in-roles):最高的是 `account-admin`,最低的是 `public`。 + +假设创建了三个角色:*manager*、*engineer* 和 *intern*。在这个示例中,*intern* 角色被授予给 *engineer* 角色。因此,*engineer* 不仅拥有自身的一组权限,还会继承与 *intern* 角色相关的权限。进一步扩展这一层级关系,如果将 *engineer* 角色授予给 *manager*,那么 *manager* 现在将同时获得 *engineer* 和 *intern* 角色所固有的权限。 + +![Alt text](/media/tidb-cloud-lake/access-control-4.png) + +## 内置角色 {#built-in-roles} + +{{{ .lake }}} 提供以下内置角色: + +| 内置角色 | 描述 | +|---------------|----------------------------------------------------------------------------------------------------------------------------------------| +| account-admin | 拥有所有权限,作为所有其他角色的父角色,并支持在租户内无缝切换到任意角色。 | +| public | 不继承任何权限,将所有角色视为其父角色,并允许任何角色切换到 public 角色。 | + +要在 {{{ .lake }}} 中将 `account-admin` 角色分配给用户,请在邀请用户时选择该角色。你也可以在用户加入后再将该角色分配给他们。如果你使用的是 {{{ .lake }}} Community Edition 或 Enterprise Edition,请先在部署期间配置一个 `account-admin` 用户,然后根据需要将该角色分配给其他用户。 + +## 设置默认角色 {#setting-default-role} + +当一个用户被授予多个角色时,你可以使用 [CREATE USER](/tidb-cloud-lake/sql/create-user.md) 或 [ALTER USER](/tidb-cloud-lake/sql/alter-user.md) 命令为该用户设置默认角色。默认角色决定了在会话开始时自动分配给用户的角色: + +```sql title='Example:' +-- Show existing roles in the system +SHOW ROLES; + +┌───────────────────────────────────────────────────────────┐ +│ name │ inherited_roles │ is_current │ is_default │ +├───────────────┼─────────────────┼────────────┼────────────┤ +│ account_admin │ 0 │ true │ true │ +│ public │ 0 │ false │ false │ +│ writer │ 0 │ false │ false │ +└───────────────────────────────────────────────────────────┘ + +-- Create a user 'eric' with the password 'abc123' and set 'writer' as the default role +CREATE USER eric IDENTIFIED BY 'abc123' WITH DEFAULT_ROLE = 'writer'; + +-- Grant the 'account_admin' role to the user 'eric' +GRANT ROLE account_admin TO eric; + +-- Set 'account_admin' as the default role for user 'eric' +ALTER USER eric WITH DEFAULT_ROLE = 'account_admin'; +``` + +- 用户可以在会话中使用 [SET ROLE](/tidb-cloud-lake/sql/set-role.md) 命令灵活切换到其他角色。 +- 用户可以使用 [SHOW ROLES](/tidb-cloud-lake/sql/show-roles.md) 命令查看当前角色以及授予给自己的所有角色。 +- 如果你没有为用户显式设置默认角色,{{{ .lake }}} 会默认使用内置角色 `public` 作为默认角色。 + +## 活动角色和次要角色 {#active-role-secondary-roles} + +在 {{{ .lake }}} 中,一个用户可以被授予多个角色。这些角色分为活动角色和次要角色: + +- 活动角色是用户在当前会话中处于活动状态的主要角色,可以使用 [SET ROLE](/tidb-cloud-lake/sql/set-role.md) 命令进行设置。 + +- 次要角色是提供额外权限的附加角色,默认处于激活状态。用户可以使用 [SET SECONDARY ROLES](/tidb-cloud-lake/sql/set-secondary-roles.md) 命令启用或停用次要角色,以临时调整其权限作用域。 + +## 计费角色 {#billing-role} + +除了标准内置角色之外,你还可以在 {{{ .lake }}} 中创建一个名为 `billing` 的自定义角色,以专门满足财务人员的需求。`billing` 角色仅提供对计费相关信息的访问,确保财务人员能够查看必要的财务数据,而不会接触到其他业务相关页面。 + +要设置并使用 `billing` 角色,可以使用以下命令创建它: + +```sql +CREATE ROLE billing; +``` + +角色名称不区分大小写,因此 `billing` 和 `Billing` 被视为相同。有关设置和分配 `billing` 角色的详细步骤,请参见[向财务人员授予访问权限](/tidb-cloud-lake/guides/manage-costs.md#granting-access-to-finance-personnel)。 + +## 使用示例(基础) {#usage-examples-basic} + +本示例展示了基于角色的权限管理。首先,创建一个 `writer` 角色并授予其权限。随后,将这些权限分配给用户 `eric`,使其继承这些权限。最后,从该角色回收这些权限,以展示其对用户权限的影响。 + +```sql title='Example:' +-- Create a new role named 'writer' +CREATE ROLE writer; + +-- Grant all privileges on all objects in the 'default' schema to the role 'writer' +GRANT ALL ON default.* TO ROLE writer; + +-- Create a new user named 'eric' with the password 'abc123' and set the default role +CREATE USER eric IDENTIFIED BY 'abc123' WITH DEFAULT_ROLE = 'writer'; + +-- Grant the role 'writer' to the user 'eric' +GRANT ROLE writer TO eric; + +-- Show the granted privileges for the role 'writer' +SHOW GRANTS FOR ROLE writer; + +┌───────────────────────────────────────────────────────┐ +│ Grants │ +├───────────────────────────────────────────────────────┤ +│ GRANT ALL ON 'default'.'default'.* TO ROLE 'writer' │ +└───────────────────────────────────────────────────────┘ + +-- Revoke all privileges on all objects in the 'default' schema from role 'writer' +REVOKE ALL ON default.* FROM ROLE writer; + +-- Show the granted privileges for the role 'writer' +-- No privileges are displayed as they have been revoked from the role +SHOW GRANTS FOR ROLE writer; +``` + +## 与业务对齐的角色模型 {#business-aligned-role-model} + +将角色与业务系统对齐,使每个领域只能访问自己的数据,而跨领域访问则通过协作角色来授予。 + +### 参考架构 {#reference-architecture} + +```text + ┌──────────────┐ + │ identity │ + │ account │ + └──────┬───────┘ + │ users/permissions + v +┌──────────────┐ products ┌──────────────┐ settlement ┌──────────────┐ +│ marketing │─────────────>│ commerce │─────────────>│ payment │ +│ growth │ │ orders │ │ settlement │ +└──────┬───────┘ └──────┬───────┘ └──────┬───────┘ + │ │ fulfillment │ accounting + │ v v + │ ┌──────────────┐ ┌──────────────┐ + │ │ fulfillment │ │ finance │ + │ │ logistics │ │ accounting │ + │ └──────────────┘ └──────────────┘ + │ + │ support/feedback + v +┌──────────────┐ +│ support │ +│ tickets │ +└──────────────┘ + + ^ risk monitoring/policies + │ +┌──────────────┐ +│ risk │ +│ fraud │ +└──────────────┘ +``` + +### 角色命名约定 {#role-conventions} + +- `_owner`:拥有该领域中的所有对象 +- `_rw`:供 pipeline 和工程师使用的写访问权限 +- `_ro`:供分析师使用的只读访问权限 +- Databases:`_raw`、`_mart` +- Stages:`stage__ingest` + +### 所有权行为 {#ownership-behavior} + +对象归创建它们时处于活动状态的角色所有。请确保在创建对象之前执行 `SET ROLE _owner`。详情请参见 [所有权](/tidb-cloud-lake/guides/ownership.md)。 + +### 使用示例(业务领域) {#usage-examples-business-domains} + +```sql title='示例:' +-- 1) 业务系统角色 +CREATE ROLE identity_owner; +CREATE ROLE identity_rw; +CREATE ROLE identity_ro; + +CREATE ROLE commerce_owner; +CREATE ROLE commerce_rw; +CREATE ROLE commerce_ro; + +CREATE ROLE payment_owner; +CREATE ROLE payment_rw; +CREATE ROLE payment_ro; + +CREATE ROLE fulfillment_owner; +CREATE ROLE fulfillment_rw; +CREATE ROLE fulfillment_ro; + +CREATE ROLE marketing_owner; +CREATE ROLE marketing_rw; +CREATE ROLE marketing_ro; + +CREATE ROLE finance_owner; +CREATE ROLE finance_rw; +CREATE ROLE finance_ro; + +CREATE ROLE support_owner; +CREATE ROLE support_rw; +CREATE ROLE support_ro; + +CREATE ROLE risk_owner; +CREATE ROLE risk_rw; +CREATE ROLE risk_ro; + +-- 2) 业务系统资源 +CREATE DATABASE identity_raw; +CREATE DATABASE identity_mart; +CREATE STAGE stage_identity_ingest; + +CREATE DATABASE commerce_raw; +CREATE DATABASE commerce_mart; +CREATE STAGE stage_commerce_ingest; + +CREATE DATABASE payment_raw; +CREATE DATABASE payment_mart; +CREATE STAGE stage_payment_ingest; + +CREATE DATABASE fulfillment_raw; +CREATE DATABASE fulfillment_mart; +CREATE STAGE stage_fulfillment_ingest; + +CREATE DATABASE marketing_raw; +CREATE DATABASE marketing_mart; +CREATE STAGE stage_marketing_ingest; + +CREATE DATABASE finance_raw; +CREATE DATABASE finance_mart; +CREATE STAGE stage_finance_ingest; + +CREATE DATABASE support_raw; +CREATE DATABASE support_mart; +CREATE STAGE stage_support_ingest; + +CREATE DATABASE risk_raw; +CREATE DATABASE risk_mart; +CREATE STAGE stage_risk_ingest; + +-- 3) 将所有权分配给 owner 角色 +GRANT OWNERSHIP ON identity_raw.* TO ROLE identity_owner; +GRANT OWNERSHIP ON identity_mart.* TO ROLE identity_owner; +GRANT OWNERSHIP ON STAGE stage_identity_ingest TO ROLE identity_owner; + +GRANT OWNERSHIP ON commerce_raw.* TO ROLE commerce_owner; +GRANT OWNERSHIP ON commerce_mart.* TO ROLE commerce_owner; +GRANT OWNERSHIP ON STAGE stage_commerce_ingest TO ROLE commerce_owner; + +GRANT OWNERSHIP ON payment_raw.* TO ROLE payment_owner; +GRANT OWNERSHIP ON payment_mart.* TO ROLE payment_owner; +GRANT OWNERSHIP ON STAGE stage_payment_ingest TO ROLE payment_owner; + +GRANT OWNERSHIP ON fulfillment_raw.* TO ROLE fulfillment_owner; +GRANT OWNERSHIP ON fulfillment_mart.* TO ROLE fulfillment_owner; +GRANT OWNERSHIP ON STAGE stage_fulfillment_ingest TO ROLE fulfillment_owner; + +GRANT OWNERSHIP ON marketing_raw.* TO ROLE marketing_owner; +GRANT OWNERSHIP ON marketing_mart.* TO ROLE marketing_owner; +GRANT OWNERSHIP ON STAGE stage_marketing_ingest TO ROLE marketing_owner; + +GRANT OWNERSHIP ON finance_raw.* TO ROLE finance_owner; +GRANT OWNERSHIP ON finance_mart.* TO ROLE finance_owner; +GRANT OWNERSHIP ON STAGE stage_finance_ingest TO ROLE finance_owner; + +GRANT OWNERSHIP ON support_raw.* TO ROLE support_owner; +GRANT OWNERSHIP ON support_mart.* TO ROLE support_owner; +GRANT OWNERSHIP ON STAGE stage_support_ingest TO ROLE support_owner; + +GRANT OWNERSHIP ON risk_raw.* TO ROLE risk_owner; +GRANT OWNERSHIP ON risk_mart.* TO ROLE risk_owner; +GRANT OWNERSHIP ON STAGE stage_risk_ingest TO ROLE risk_owner; + +-- 4) 每个域内的读写分离 +GRANT USAGE ON identity_raw.* TO ROLE identity_rw; +GRANT SELECT ON identity_raw.* TO ROLE identity_rw; +GRANT CREATE, INSERT, UPDATE, DELETE, ALTER, DROP ON identity_mart.* TO ROLE identity_rw; +GRANT USAGE ON identity_mart.* TO ROLE identity_ro; +GRANT SELECT ON identity_mart.* TO ROLE identity_ro; +GRANT READ, WRITE ON STAGE stage_identity_ingest TO ROLE identity_rw; + +GRANT USAGE ON commerce_raw.* TO ROLE commerce_rw; +GRANT SELECT ON commerce_raw.* TO ROLE commerce_rw; +GRANT CREATE, INSERT, UPDATE, DELETE, ALTER, DROP ON commerce_mart.* TO ROLE commerce_rw; +GRANT USAGE ON commerce_mart.* TO ROLE commerce_ro; +GRANT SELECT ON commerce_mart.* TO ROLE commerce_ro; +GRANT READ, WRITE ON STAGE stage_commerce_ingest TO ROLE commerce_rw; + +GRANT USAGE ON payment_raw.* TO ROLE payment_rw; +GRANT SELECT ON payment_raw.* TO ROLE payment_rw; +GRANT CREATE, INSERT, UPDATE, DELETE, ALTER, DROP ON payment_mart.* TO ROLE payment_rw; +GRANT USAGE ON payment_mart.* TO ROLE payment_ro; +GRANT SELECT ON payment_mart.* TO ROLE payment_ro; +GRANT READ, WRITE ON STAGE stage_payment_ingest TO ROLE payment_rw; + +GRANT USAGE ON fulfillment_raw.* TO ROLE fulfillment_rw; +GRANT SELECT ON fulfillment_raw.* TO ROLE fulfillment_rw; +GRANT CREATE, INSERT, UPDATE, DELETE, ALTER, DROP ON fulfillment_mart.* TO ROLE fulfillment_rw; +GRANT USAGE ON fulfillment_mart.* TO ROLE fulfillment_ro; +GRANT SELECT ON fulfillment_mart.* TO ROLE fulfillment_ro; +GRANT READ, WRITE ON STAGE stage_fulfillment_ingest TO ROLE fulfillment_rw; + +GRANT USAGE ON marketing_raw.* TO ROLE marketing_rw; +GRANT SELECT ON marketing_raw.* TO ROLE marketing_rw; +GRANT CREATE, INSERT, UPDATE, DELETE, ALTER, DROP ON marketing_mart.* TO ROLE marketing_rw; +GRANT USAGE ON marketing_mart.* TO ROLE marketing_ro; +GRANT SELECT ON marketing_mart.* TO ROLE marketing_ro; +GRANT READ, WRITE ON STAGE stage_marketing_ingest TO ROLE marketing_rw; + +GRANT USAGE ON finance_raw.* TO ROLE finance_rw; +GRANT SELECT ON finance_raw.* TO ROLE finance_rw; +GRANT CREATE, INSERT, UPDATE, DELETE, ALTER, DROP ON finance_mart.* TO ROLE finance_rw; +GRANT USAGE ON finance_mart.* TO ROLE finance_ro; +GRANT SELECT ON finance_mart.* TO ROLE finance_ro; +GRANT READ, WRITE ON STAGE stage_finance_ingest TO ROLE finance_rw; + +GRANT USAGE ON support_raw.* TO ROLE support_rw; +GRANT SELECT ON support_raw.* TO ROLE support_rw; +GRANT CREATE, INSERT, UPDATE, DELETE, ALTER, DROP ON support_mart.* TO ROLE support_rw; +GRANT USAGE ON support_mart.* TO ROLE support_ro; +GRANT SELECT ON support_mart.* TO ROLE support_ro; +GRANT READ, WRITE ON STAGE stage_support_ingest TO ROLE support_rw; + +GRANT USAGE ON risk_raw.* TO ROLE risk_rw; +GRANT SELECT ON risk_raw.* TO ROLE risk_rw; +GRANT CREATE, INSERT, UPDATE, DELETE, ALTER, DROP ON risk_mart.* TO ROLE risk_rw; +GRANT USAGE ON risk_mart.* TO ROLE risk_ro; +GRANT SELECT ON risk_mart.* TO ROLE risk_ro; +GRANT READ, WRITE ON STAGE stage_risk_ingest TO ROLE risk_rw; + +-- 5) 在创建时分配所有权 +SET ROLE commerce_owner; +CREATE TABLE commerce_mart.orders ( + order_id STRING, + user_id STRING, + order_ts TIMESTAMP, + amount DECIMAL(18, 2) +); + +SET ROLE payment_owner; +CREATE TABLE payment_mart.transactions ( + transaction_id STRING, + order_id STRING, + user_id STRING, + transaction_ts TIMESTAMP, + amount DECIMAL(18, 2) +); + +SET ROLE identity_owner; +CREATE TABLE identity_mart.users ( + user_id STRING, + email STRING, + created_at TIMESTAMP +); + +-- 6) 与架构对齐的协作角色 +CREATE ROLE collab_marketing_commerce; +GRANT SELECT ON commerce_mart.orders TO ROLE collab_marketing_commerce; +GRANT ROLE collab_marketing_commerce TO ROLE marketing_ro; + +CREATE ROLE collab_fulfillment_commerce; +GRANT SELECT ON commerce_mart.orders TO ROLE collab_fulfillment_commerce; +GRANT ROLE collab_fulfillment_commerce TO ROLE fulfillment_ro; + +CREATE ROLE collab_payment_commerce; +GRANT SELECT ON commerce_mart.orders TO ROLE collab_payment_commerce; +GRANT ROLE collab_payment_commerce TO ROLE payment_ro; + +CREATE ROLE collab_finance_payment; +GRANT SELECT ON payment_mart.transactions TO ROLE collab_finance_payment; +GRANT ROLE collab_finance_payment TO ROLE finance_ro; + +CREATE ROLE collab_support_core; +GRANT SELECT ON commerce_mart.orders TO ROLE collab_support_core; +GRANT SELECT ON payment_mart.transactions TO ROLE collab_support_core; +GRANT ROLE collab_support_core TO ROLE support_ro; + +CREATE ROLE collab_risk_core; +GRANT SELECT ON identity_mart.users TO ROLE collab_risk_core; +GRANT SELECT ON commerce_mart.orders TO ROLE collab_risk_core; +GRANT SELECT ON payment_mart.transactions TO ROLE collab_risk_core; +GRANT ROLE collab_risk_core TO ROLE risk_ro; +``` \ No newline at end of file diff --git a/tidb-cloud-lake/guides/row-access-policy.md b/tidb-cloud-lake/guides/row-access-policy.md new file mode 100644 index 0000000000000..ee62fef15cd4a --- /dev/null +++ b/tidb-cloud-lake/guides/row-access-policy.md @@ -0,0 +1,304 @@ +--- +title: 行访问策略 +summary: 行访问策略通过在查询时过滤表中的行来保护数据。你可以集中定义一次行级谓词,将其附加到表上,并确保用户只能看到满足策略的行。 +--- + +# 行访问策略 + +行访问策略会在查询时过滤表中的行。只需定义一次布尔谓词并将其附加到表上,用户就只能看到通过该策略的行。 + +如果你希望进行列级脱敏,而不是隐藏整行,请使用[脱敏策略](/tidb-cloud-lake/guides/masking-policy.md)。 + +> **Note:** +> +> 这是一个**实验性**功能。可通过 `SET enable_experimental_row_access_policy = 1`(会话)或 `SET GLOBAL enable_experimental_row_access_policy = 1`(账户)启用。 + +## 何时使用 {#when-to-use} + +- 多租户隔离 —— 每个租户只能看到自己的行 +- 区域 / 部门隔离 —— 销售只能看到其所属区域的数据 +- 时间窗口控制 —— 告警可扫描 1 天数据;离线分析可扫描 7 天数据 +- 向量 / RAG 搜索 —— 共享知识库,基于角色控制文档可见性 +- 合规 —— 审计人员只能看到已批准的时间范围或子集 + +## 快速开始 {#quick-start} + +```sql +SET enable_experimental_row_access_policy = 1; + +CREATE TABLE employees ( + id INT, + name STRING, + department STRING +); + +INSERT INTO employees VALUES + (1, 'Alice', 'Engineering'), + (2, 'Bob', 'Sales'), + (3, 'Charlie', 'Engineering'); + +CREATE ROW ACCESS POLICY rap_engineering +AS (dept STRING) +RETURNS BOOLEAN -> +CASE + WHEN IS_ROLE_IN_SESSION('admin') THEN true + WHEN dept = 'Engineering' THEN true + ELSE false +END; + +-- ON (column) maps to the policy argument by position +ALTER TABLE employees ADD ROW ACCESS POLICY rap_engineering ON (department); + +SELECT id, name, department FROM employees ORDER BY id; +``` + +``` +id | name | department +---|---------|------------- + 1 | Alice | Engineering + 3 | Charlie | Engineering +``` + +**工作原理** + +- 仅在查询时生效 —— 存储的数据不会改变 +- 每张表只能有一个策略;参数会按位置映射到 `ON (...)` 中的列 +- 优先使用 `IS_ROLE_IN_SESSION()` 而不是 `current_role()`,这样用户无法通过 `SET ROLE` 绕过策略 + +多列策略: + +```sql +CREATE ROW ACCESS POLICY rap_region_dept +AS (region STRING, dept STRING) +RETURNS BOOLEAN -> + region = 'APAC' AND dept = 'Engineering'; + +ALTER TABLE employees +ADD ROW ACCESS POLICY rap_region_dept ON (office_region, department); +``` + +## 示例 {#examples} + +### 向量 / RAG 文档可见性 {#vector-rag-document-visibility} + +共享知识库表 + 向量搜索。只需配置一次可见性;搜索 SQL 无需携带文档 ID 过滤条件。参见[向量搜索](/tidb-cloud-lake/guides/vector-search-guide.md)。 + +| 角色 | 可见内容 | +|------|------| +| `admin` | 所有行 | +| `sales` | `dept = 'sales'` + 公开 | +| `finance` | `dept = 'finance'` + 公开 | + +```sql +SET enable_experimental_row_access_policy = 1; + +CREATE ROLE IF NOT EXISTS admin; +CREATE ROLE IF NOT EXISTS sales; +CREATE ROLE IF NOT EXISTS finance; + +CREATE TABLE knowledge_docs ( + doc_id BIGINT, + title STRING, + dept STRING, + is_public BOOLEAN, + embedding VECTOR(4), + VECTOR INDEX idx_emb(embedding) distance='cosine' +); + +INSERT INTO knowledge_docs VALUES + (1, 'Sales contract template', 'sales', false, [0.90, 0.10, 0.05, 0.05]), + (2, 'Q2 financial draft', 'finance', false, [0.10, 0.90, 0.05, 0.05]), + (3, 'Public company handbook', 'hr', true, [0.20, 0.20, 0.90, 0.10]), + (4, 'Competitor pricing notes', 'sales', false, [0.85, 0.15, 0.10, 0.05]), + (5, 'Internal audit checklist', 'finance', false, [0.15, 0.85, 0.10, 0.05]); + +CREATE ROW ACCESS POLICY rap_knowledge_docs +AS (dept STRING, is_public BOOLEAN) +RETURNS BOOLEAN -> +CASE + WHEN IS_ROLE_IN_SESSION('admin') THEN true + WHEN is_public THEN true + WHEN IS_ROLE_IN_SESSION('sales') AND dept = 'sales' THEN true + WHEN IS_ROLE_IN_SESSION('finance') AND dept = 'finance' THEN true + ELSE false +END; + +ALTER TABLE knowledge_docs +ADD ROW ACCESS POLICY rap_knowledge_docs ON (dept, is_public); + +GRANT SELECT ON knowledge_docs TO ROLE sales; +GRANT SELECT ON knowledge_docs TO ROLE finance; + +-- Activate one role for the session, then run the same search SQL +SET ROLE sales; +SET SECONDARY ROLES NONE; + +SELECT doc_id, title, + round(cosine_distance(embedding, [0.88, 0.12, 0.08, 0.05]::VECTOR(4)), 4) AS dist +FROM knowledge_docs +ORDER BY dist +LIMIT 10; +``` + +| 作为 `sales` | 作为 `finance` (`SET ROLE finance`) | +|------------|-------------------------------------| +| 1 销售合同模板 `0.0009` | 3 上市公司手册 `0.6731` | +| 4 竞争对手定价说明 `0.0011` | 5 内部审计检查清单 `0.6855` | +| 3 上市公司手册 `0.6731` | 2 Q2 财务草案 `0.7504` | + +### 按角色进行时间范围访问 {#time-range-access-by-role} + +不同的服务账户可能只能扫描不同的历史时间窗口。 + +| 账户 | 角色 | 窗口 | +|---------|-------|--------| +| `svc_realtime_alert` | `rap_role_1_day` | 最近 1 天 | +| `svc_offline_analysis` | `rap_role_1_day`, `rap_role_7_day` | 最多 7 天 | + +```sql +SET enable_experimental_row_access_policy = 1; + +CREATE ROLE rap_role_7_day; +CREATE ROLE rap_role_1_day; + +-- CASE is top-down: put the wider window first +CREATE ROW ACCESS POLICY rap_time_range +AS (start_time TIMESTAMP) +RETURNS BOOLEAN -> +CASE + WHEN IS_ROLE_IN_SESSION('rap_role_7_day') THEN + start_time >= now() - INTERVAL 7 DAY + WHEN IS_ROLE_IN_SESSION('rap_role_1_day') THEN + start_time >= now() - INTERVAL 1 DAY + ELSE false +END; + +CREATE TABLE metrics(id INT, start_time TIMESTAMP); +INSERT INTO metrics VALUES + (1, now() - INTERVAL 15 DAY), + (2, now() - INTERVAL 5 DAY), + (3, now() - INTERVAL 12 HOUR), + (4, now() - INTERVAL 1 HOUR), + (5, now() - INTERVAL 8 DAY); + +ALTER TABLE metrics ADD ROW ACCESS POLICY rap_time_range ON (start_time); + +GRANT ROLE rap_role_1_day TO USER svc_realtime_alert; +GRANT ROLE rap_role_1_day TO USER svc_offline_analysis; +GRANT ROLE rap_role_7_day TO USER svc_offline_analysis; + +SELECT id, start_time FROM metrics ORDER BY id; +``` + +登录后,{{{ .lake }}} 会激活所有已授予的角色(`SECONDARY ROLES ALL`)。 + +| 会话 | 可见行 | +|---------|--------------| +| `svc_realtime_alert`(仅 1 天) | 最近 1 天 | +| `svc_offline_analysis`(两个角色) | 默认最近 7 天 | + +将离线账户收窄为 1 天: + +```sql +SET ROLE rap_role_1_day; +SET SECONDARY ROLES NONE; +SELECT id, start_time FROM metrics ORDER BY id; +``` + +再次放宽: + +```sql +SET ROLE rap_role_7_day; +SELECT id, start_time FROM metrics ORDER BY id; +``` + +一个账户只能激活已授予给它的角色。`svc_realtime_alert` 不能执行 `SET ROLE rap_role_7_day`。 + +## 读写行为 {#read-and-write-behavior} + +| 操作 | 影响 | +|-----------|--------| +| `SELECT` | 仅返回策略可见的行 | +| `UPDATE` / `DELETE` / `MERGE` | 仅匹配/修改可见的目标行 | +| `INSERT` | 不会被过滤——即使当前不可见,行也会被存储 | + +要检查所有已存储的行,请使用一个能够通过该策略的角色,或临时将策略解绑。 + +```sql +SET enable_experimental_row_access_policy = 1; + +CREATE ROW ACCESS POLICY rap_sales_only +AS (dept STRING) RETURNS BOOLEAN -> dept = 'sales'; + +CREATE TABLE orders(id INT, dept STRING, amount INT); +ALTER TABLE orders ADD ROW ACCESS POLICY rap_sales_only ON (dept); + +INSERT INTO orders VALUES (1, 'sales', 100), (2, 'eng', 200), (3, 'sales', 300); + +SELECT * FROM orders ORDER BY id; +-- 1 sales 100 +-- 3 sales 300 + +UPDATE orders SET amount = amount + 10; +DELETE FROM orders WHERE dept = 'eng'; -- no-op: eng rows are invisible +DELETE FROM orders WHERE id = 1; -- deletes visible row 1 + +-- MERGE only matches visible targets +CREATE TABLE src(id INT, new_amount INT); +INSERT INTO src VALUES (2, 777), (3, 888); + +MERGE INTO orders AS t +USING src AS s +ON t.id = s.id +WHEN MATCHED THEN UPDATE SET t.amount = s.new_amount; + +-- Detach to inspect storage +ALTER TABLE orders DROP ROW ACCESS POLICY rap_sales_only; +SELECT * FROM orders ORDER BY id; +-- 2 eng 200 (never updated) +-- 3 sales 888 (merged) +``` + +## 管理策略 {#manage-policies} + +```sql +DESC ROW ACCESS POLICY rap_engineering; + +ALTER TABLE employees DROP ROW ACCESS POLICY rap_engineering; +DROP ROW ACCESS POLICY rap_engineering; + +ALTER TABLE employees DROP ALL ROW ACCESS POLICIES; +``` + +在执行 `DROP ROW ACCESS POLICY` 之前,请先解绑。修改受保护列之前,也需要先删除或解绑策略。 + +## 限制 {#limits} + +- 每个表只能有一个行访问策略 +- 仅支持普通表——不支持视图、流、临时表或 ICE 数据库 +- 每列只能有一个安全策略(脱敏 **or** 行访问,不能同时使用) +- 不支持 `CREATE OR REPLACE` / `ALTER` policy——需要删除后重建 +- 策略名称在脱敏策略和行访问策略之间是全局唯一的 +- 创建时,策略参数名称会被转换为小写 + +## 最佳实践 {#best-practices} + +1. 优先使用 `IS_ROLE_IN_SESSION()`,而不是 `current_role()`。 +2. 按“最宽 → 最窄”的顺序排列 `CASE` 分支(管理员优先)。 +3. 如果策略引用了查找表,请将其与受保护表放在同一个数据库中。 +4. 在绑定后使用多个角色进行验证——管理员、受限角色和无匹配角色都要验证。 +5. 对于全量数据检查,优先使用有权限的角色,而不是反复解绑/绑定。 + +## 权限与参考 {#privileges-references} + +- 在 `*.*` 上具有 `CREATE ROW ACCESS POLICY` 权限以创建策略(创建者获得 OWNERSHIP) +- 具有表上的 `ALTER` 权限,以及 `APPLY ROW ACCESS POLICY`(全局)或 `APPLY ON ROW ACCESS POLICY ` 权限以进行绑定/解绑 +- 审计:`SHOW GRANTS ON ROW ACCESS POLICY ` +- 用法:[`POLICY_REFERENCES`](/tidb-cloud-lake/sql/policy-references.md) + +另请参阅: + +- [用户与角色](/tidb-cloud-lake/sql/user-role.md) +- [CREATE ROW ACCESS POLICY](/tidb-cloud-lake/sql/create-row-access-policy.md) +- [ALTER TABLE](/tidb-cloud-lake/sql/alter-table.md#row-access-policy-operations) +- [行访问策略命令](/tidb-cloud-lake/sql/row-access-policy-overview.md) \ No newline at end of file diff --git a/tidb-cloud-lake/guides/schema-evolution.md b/tidb-cloud-lake/guides/schema-evolution.md new file mode 100644 index 0000000000000..25aa964c90f1c --- /dev/null +++ b/tidb-cloud-lake/guides/schema-evolution.md @@ -0,0 +1,255 @@ +--- +title: Schema Evolution +summary: 使用 COPY INTO 加载数据时自动演进表结构。 +--- + +# Schema Evolution + +Schema Evolution 允许 {{{ .lake }}} 在执行 `COPY INTO` 时,自动将源文件中存在但目标表中缺失的列添加到目标表。目前它支持 **Parquet** 和 **NDJSON** 文件。 + +## 工作原理 {#how-it-works} + +启用后,{{{ .lake }}} 会在加载前推导源文件的表结构,并将新列追加到表末尾。新列均为可空列,缺失的值会填充为 `NULL`。 + +不同文件格式的工作流程略有不同: + +- **Parquet**:启用表选项后,`COPY INTO` 会直接从 Parquet 文件的表结构中推导新列。 +- **NDJSON**:启用表选项后,`COPY INTO` 会使用 `AUTO` 采样值进行表结构推导。你也可以选择添加 `SCHEMA_EVOLUTION = (...)` 来覆盖文件和记录的采样限制。 + +## 启用 Schema Evolution {#enabling-schema-evolution} + +将表选项 `ENABLE_SCHEMA_EVOLUTION` 设置为 `true`: + +```sql +-- On an existing table +ALTER TABLE my_table SET OPTIONS(ENABLE_SCHEMA_EVOLUTION = true); + +-- Or when creating a new table +CREATE TABLE my_table(id INT) ENABLE_SCHEMA_EVOLUTION = true; +``` + +如需禁用 Schema Evolution,请将其重新设置为 `false`: + +```sql +ALTER TABLE my_table SET OPTIONS(ENABLE_SCHEMA_EVOLUTION = false); +``` + +## 权限 {#privileges} + +当 `COPY INTO
` 从 stage 或外部位置加载文件并执行 Schema Evolution 推导时,执行加载的角色必须同时拥有目标表的 `INSERT` 和 `ALTER` 权限。之所以需要 `ALTER`,是因为 {{{ .lake }}} 可能会在加载前追加新列。 + +基于查询的 COPY 不受影响。例如,`COPY INTO
FROM (SELECT ... FROM @stage)` 仍保持现有的权限要求。 + +## Parquet 示例 {#parquet-example} + +以下示例加载具有不同表结构的 Parquet 文件,并自动添加缺失列。 + +### 第 1 步:创建表和 stage {#step-1-create-a-table-and-stage} + +```sql +CREATE OR REPLACE TABLE invoices(order_id INT); +CREATE OR REPLACE STAGE my_stage; +``` + +### 第 2 步:生成具有不同表结构的 Parquet 文件 {#step-2-generate-parquet-files-with-different-schemas} + +```sql +-- File with columns: order_id, amount, currency +COPY INTO @my_stage FROM ( + SELECT 1 AS order_id, 100.50::DOUBLE AS amount, 'USD' AS currency + UNION ALL + SELECT 2, 250.50::DOUBLE, 'EUR' +) FILE_FORMAT = (TYPE = parquet); + +-- File with columns: order_id, amount (no currency) +COPY INTO @my_stage FROM ( + SELECT 3 AS order_id, 75.50::DOUBLE AS amount +) FILE_FORMAT = (TYPE = parquet); +``` + +### 第 3 步:启用 Schema Evolution 并加载数据 {#step-3-enable-schema-evolution-and-load} + +```sql +ALTER TABLE invoices SET OPTIONS(ENABLE_SCHEMA_EVOLUTION = true); + +COPY INTO invoices +FROM @my_stage/ +FILE_FORMAT = (TYPE = parquet MISSING_FIELD_AS = FIELD_DEFAULT); +``` + +### 第 4 步:验证结果 {#step-4-verify-results} + +该表现在有三列。`amount` 和 `currency` 已被自动添加: + +```sql +DESC invoices; +``` + +```text +┌─────────────────────────────────────────────────────────────┐ +│ Field │ Type │ Null │ Default │ Extra │ +├──────────┼────────────────┼────────┼─────────┼──────────────┤ +│ order_id │ INT │ YES │ NULL │ │ +│ amount │ DOUBLE │ YES │ NULL │ │ +│ currency │ VARCHAR │ YES │ NULL │ │ +└─────────────────────────────────────────────────────────────┘ +``` + +```sql +SELECT * FROM invoices ORDER BY order_id; +``` + +```text +┌──────────────────────────────────────────────────┐ +│ order_id │ amount │ currency │ +├──────────┼──────────┼─────────────────────────────┤ +│ 1 │ 100.50 │ USD │ +│ 2 │ 250.50 │ EUR │ +│ 3 │ 75.50 │ NULL │ +└──────────────────────────────────────────────────┘ +``` + +第 3 行的 `currency = NULL`,因为其源文件中不包含该列。 + +## NDJSON 示例 {#ndjson-example} + +{{{ .lake }}} 使用 `TYPE = ndjson` 加载 NDJSON 文件。NDJSON 文件不像 Parquet 文件那样内嵌列式表结构,因此 {{{ .lake }}} 会对文件内容进行采样,推导目标表中缺失的字段,并将它们追加为可空列。 + +### 第 1 步:创建表和 stage {#step-1-create-a-table-and-stage} + +```sql +CREATE OR REPLACE TABLE events(id INT); +CREATE OR REPLACE STAGE events_stage; +``` + +### 第 2 步:生成具有不同字段的 NDJSON 文件 {#step-2-generate-ndjson-files-with-different-fields} + +```sql +-- File with fields: id, city, score +COPY INTO @events_stage FROM ( + SELECT 1 AS id, 'SF' AS city, 9 AS score + UNION ALL + SELECT 2, 'NYC', 8 +) FILE_FORMAT = (TYPE = ndjson); + +-- File with fields: id, score (no city) +COPY INTO @events_stage FROM ( + SELECT 3 AS id, 7 AS score +) FILE_FORMAT = (TYPE = ndjson); +``` + +### 第 3 步:启用 Schema Evolution 并加载数据 {#step-3-enable-schema-evolution-and-load} + +```sql +ALTER TABLE events SET OPTIONS(ENABLE_SCHEMA_EVOLUTION = true); + +COPY INTO events +FROM @events_stage/ +FILE_FORMAT = (TYPE = ndjson MISSING_FIELD_AS = FIELD_DEFAULT) +SCHEMA_EVOLUTION = ( + SAMPLE_FILES = AUTO, + SAMPLE_RECORDS_PER_FILE = AUTO, + SAMPLE_TOTAL_RECORDS = AUTO +); +``` + +这三个 `SCHEMA_EVOLUTION` 采样选项都接受 `AUTO` 或正整数: + +| 选项 | 描述 | +|------|------| +| `SAMPLE_FILES` | 采样的文件数量。 | +| `SAMPLE_RECORDS_PER_FILE` | 从每个选中文件中采样的最大记录数。 | +| `SAMPLE_TOTAL_RECORDS` | 在所有选中文件中采样的最大记录总数。 | + +如果省略 `SCHEMA_EVOLUTION`,{{{ .lake }}} 会对这三个采样选项全部使用 `AUTO`。当前 `AUTO` 的行为是最多采样 64 个文件、每个文件 1,000 条记录,以及总计 10,000 条记录。这些内部默认值可能会在未来版本中发生变化。如果你的加载任务对采样策略较为敏感,请显式设置 `SAMPLE_FILES`、`SAMPLE_RECORDS_PER_FILE` 和 `SAMPLE_TOTAL_RECORDS`。 + +#### NDJSON 推导规则 {#ndjson-inference-rules} + +在对 NDJSON 运行 Schema Evolution 时,{{{ .lake }}} 会按照以下规则推导新列: + +- Schema 仅根据采样到的 NDJSON 记录进行推导。未被采样覆盖的字段不会提前添加到目标表中。 +- 每一行都必须是一个 JSON 对象。{{{ .lake }}} 使用顶层对象的字段名作为候选列名。 +- 目标表中已存在的列不会重复添加。只会追加目标表中缺失的字段。 +- 新字段的类型根据采样到的 JSON 值进行推导,例如整数型、float、字符串和布尔值。 +- Schema Evolution 对 NDJSON 使用浅层推导:如果顶层字段值是对象或数组,则会将其作为 `VARIANT` 列追加,而不是递归展开。 +- `NULL` 样本只会将该字段标记为可为空。它们不会强制后续的非空值变为 `VARCHAR` 或 `VARIANT`。 +- 跨文件或记录的同名字段会被合并:整数型与 float 的冲突会变为 `DOUBLE`;其他标量冲突会变为 `VARCHAR`;任何涉及对象、数组或 `VARIANT` 的冲突都会变为 `VARIANT`。 +- 如果在加载时遇到采样推导期间未推导出的额外字段,则加载会失败并报告这些字段名。请增大 `SAMPLE_FILES`、`SAMPLE_RECORDS_PER_FILE` 或 `SAMPLE_TOTAL_RECORDS` 后重试。 + +> **Note:** +> +> 默认情况下,`INFER_SCHEMA` 表函数不会限制 NDJSON 的嵌套深度。这里的规则描述的是 `COPY INTO` Schema Evolution 使用的浅层推导。 + +例如,以下 NDJSON 记录会推导出六个新列:`name`、`age`、`active`、`score`、`profile` 和 `tags`: + +```json +{"id":1,"name":"Alice","age":30,"active":true,"score":1,"profile":{"city":"SF"},"tags":["new"]} +{"id":2,"name":"Bob","age":null,"active":false,"score":1.5,"profile":{"city":"NYC"},"tags":["vip"]} +``` + +如果目标表只有 `id INT`,{{{ .lake }}} 会追加: + +```text +name VARCHAR NULL +age BIGINT NULL +active BOOLEAN NULL +score DOUBLE NULL +profile VARIANT NULL +tags VARIANT NULL +``` + +第二行中 `age = NULL`,这不会改变根据第一行推导出的 `BIGINT` 类型。`score` 同时包含整数型和 float,因此会变为 `DOUBLE`。`profile` 和 `tags` 分别是对象和数组,因此 Schema Evolution 会将它们作为 `VARIANT` 列追加。 + +### 第 4 步:验证结果 {#step-4-verify-results} + +该表现在有三列。`city` 和 `score` 已自动添加: + +```sql +DESC events; +``` + +```text +┌─────────────────────────────────────────────────────────┐ +│ Field │ Type │ Null │ Default │ Extra │ +├───────┼──────────────┼────────┼─────────┼──────────────┤ +│ id │ INT │ YES │ NULL │ │ +│ city │ VARCHAR │ YES │ NULL │ │ +│ score │ BIGINT │ YES │ NULL │ │ +└─────────────────────────────────────────────────────────┘ +``` + +```sql +SELECT * FROM events ORDER BY id; +``` + +```text +┌────────────────────────────┐ +│ id │ city │ score │ +├────┼──────┼────────────────┤ +│ 1 │ SF │ 9 │ +│ 2 │ NYC │ 8 │ +│ 3 │ NULL │ 7 │ +└────────────────────────────┘ +``` + +如果采样未覆盖后续数据中出现的某个字段,加载会失败并返回该额外字段名。请增大 `SAMPLE_FILES`、`SAMPLE_RECORDS_PER_FILE` 或 `SAMPLE_TOTAL_RECORDS` 后重试。 + +## 列匹配模式 {#column-match-mode} + +默认情况下,列名匹配不区分大小写。使用 `COLUMN_MATCH_MODE` 可进行大小写敏感匹配: + +```sql +COPY INTO invoices +FROM @my_stage/ +FILE_FORMAT = (TYPE = parquet MISSING_FIELD_AS = FIELD_DEFAULT) +COLUMN_MATCH_MODE = CASE_SENSITIVE; +``` + +## 限制 {#limitations} + +- 当前支持 **Parquet** 和 **NDJSON** 文件。 +- 新列会追加到表末尾,并且始终可为空。 +- 如果同一列名在多个文件中出现且**数据类型不同**,加载会失败。 +- 不支持自动类型提升,例如从 `INT` 到 `BIGINT`。 +- 不支持通过 schema evolution 删除列或重命名列。 +- NDJSON 依赖采样来推导 schema。如果采样未覆盖所有字段,请增大 `SCHEMA_EVOLUTION` 的采样选项。 \ No newline at end of file diff --git a/tidb-cloud-lake/guides/security-reliability.md b/tidb-cloud-lake/guides/security-reliability.md new file mode 100644 index 0000000000000..73e270b4f3765 --- /dev/null +++ b/tidb-cloud-lake/guides/security-reliability.md @@ -0,0 +1,20 @@ +--- +title: 安全性与可靠性 +summary: "{{{ .lake }}} 提供企业级的安全性与可靠性功能,在数据的整个生命周期内为其保驾护航。从控制谁可以访问您的数据,到防御网络威胁,再到从操作错误中恢复,{{{ .lake }}} 的多层安全方法可帮助您维护数据完整性、合规性和业务可持续性。" +--- + +# 安全性与可靠性 + +{{{ .lake }}} 提供**企业级的安全性与可靠性功能**,在数据的整个生命周期内为其保驾护航。从控制谁可以访问您的数据,到防御网络威胁,再到从操作错误中恢复,{{{ .lake }}} 的**多层安全方法**可帮助您维护数据完整性、合规性和业务可持续性。 + +| 安全功能 | 用途 | 何时使用 | +|-----------------|---------|------------| +| [**访问控制**](/tidb-cloud-lake/guides/access-control.md) | 管理用户权限 | 当您需要通过基于角色的安全机制和对象所有权来控制数据访问时 | +| [**数据保护策略**](/tidb-cloud-lake/guides/data-protection-policies.md) | 在行级和列级保护敏感数据 | 当您需要行级过滤、列级脱敏或同时需要两者时 | +| [**审计追踪**](/tidb-cloud-lake/guides/audit-trail.md) | 跟踪数据库活动 | 当您需要全面的审计跟踪以进行安全监控、合规和性能分析时 | +| [**网络策略**](/tidb-cloud-lake/guides/network-policy.md) | 限制网络访问 | 当您希望即使在凭证有效的情况下,也仅允许来自特定 IP 范围的连接时 | +| [**密码策略**](/tidb-cloud-lake/guides/password-policy.md) | 设置密码要求 | 当您需要强制执行密码复杂度、轮换和账户锁定规则时 | +| [**使用 AWS IAM Role 进行认证**](/tidb-cloud-lake/guides/authenticate-with-aws-iam-role.md) | 使用 AWS IAM 角色进行身份验证 | 当您希望利用 AWS IAM 安全访问 {{{ .lake }}} 时 | +| [**合规与安全**](/tidb-cloud-lake/guides/compliance-security.md) | 确保监管合规 | 当您需要遵循行业标准和法规时 | +| [**Fail-Safe**](/tidb-cloud-lake/guides/fail-safe.md) | 防止数据丢失 | 当您需要从兼容 S3 的存储中恢复被意外删除的数据时 | +| [**从操作错误中恢复**](/tidb-cloud-lake/guides/recovery-from-operational-errors.md) | 修复操作失误 | 当您需要从已删除的数据库/表或错误的数据修改中恢复时 | \ No newline at end of file diff --git a/tidb-cloud-lake/guides/sql-analytics.md b/tidb-cloud-lake/guides/sql-analytics.md new file mode 100644 index 0000000000000..632e70926a961 --- /dev/null +++ b/tidb-cloud-lake/guides/sql-analytics.md @@ -0,0 +1,405 @@ +--- +title: SQL 分析 +summary: 场景:CityDrive 将所有行车记录仪记录 stage 到共享关系型表中。这些关系型数据(例如视频元信息、事件标签)由后台处理流水线从原始行车记录仪视频的关键帧中提取而来。 +--- + +# SQL 分析 + +> **场景:** CityDrive 将所有行车记录仪记录 stage 到共享关系型表中。这些关系型数据(例如视频元信息、事件标签)由后台处理流水线从原始行车记录仪视频的关键帧中提取而来。随后,分析人员可以基于所有下游工作负载共用的同一组 `video_id` / `frame_id` 对进行过滤、JOIN 和聚合。 + +本演练对该目录中关系型数据的一侧进行建模,并重点介绍实用的 SQL 构建模块。这里的示例 ID 也会在 JSON、向量、地理空间和 ETL 指南中再次出现。 + +## 1. 创建基础表 {#1-create-the-base-tables} + +`citydrive_videos` 用于存储片段元信息,而 `frame_events` 用于记录从每个片段中提取出的关键帧事件。 + +```sql +CREATE OR REPLACE TABLE citydrive_videos ( + video_id STRING, + vehicle_id STRING, + capture_date DATE, + route_name STRING, + weather STRING, + camera_source STRING, + duration_sec INT +); + +CREATE OR REPLACE TABLE frame_events ( + frame_id STRING, + video_id STRING, + frame_index INT, + collected_at TIMESTAMP, + event_tag STRING, + risk_score DOUBLE, + speed_kmh DOUBLE +); + +INSERT INTO citydrive_videos VALUES + ('VID-20250101-001', 'VEH-21', '2025-01-01', 'Downtown Loop', 'Rain', 'roof_cam', 3580), + ('VID-20250101-002', 'VEH-05', '2025-01-01', 'Port Perimeter', 'Overcast', 'front_cam',4020), + ('VID-20250102-001', 'VEH-21', '2025-01-02', 'Airport Connector', 'Clear', 'front_cam',3655), + ('VID-20250103-001', 'VEH-11', '2025-01-03', 'CBD Night Sweep', 'LightFog', 'rear_cam', 3310); + +INSERT INTO frame_events VALUES + ('FRAME-0101', 'VID-20250101-001', 125, '2025-01-01 08:15:21', 'hard_brake', 0.81, 32.4), + ('FRAME-0102', 'VID-20250101-001', 416, '2025-01-01 08:33:54', 'pedestrian', 0.67, 24.8), + ('FRAME-0201', 'VID-20250101-002', 298, '2025-01-01 11:12:02', 'lane_merge', 0.74, 48.1), + ('FRAME-0301', 'VID-20250102-001', 188, '2025-01-02 09:44:18', 'hard_brake', 0.59, 52.6), + ('FRAME-0401', 'VID-20250103-001', 522, '2025-01-03 21:18:07', 'night_lowlight', 0.63, 38.9), + -- Deliberate orphan to illustrate NOT EXISTS + ('FRAME-0501', 'VID-MISSING-001', 10, '2025-01-04 10:00:00', 'sensor_fault', 0.25, 15.0); + +-- Needed for the JOIN patterns below; same schema as the JSON & Search guide. +CREATE OR REPLACE TABLE frame_metadata_catalog ( + doc_id STRING, + meta_json VARIANT, + captured_at TIMESTAMP, + INVERTED INDEX idx_meta_json (meta_json) +); + +INSERT INTO frame_metadata_catalog VALUES + ('FRAME-0101', PARSE_JSON('{"scene":{"weather_code":"rain","lighting":"day"},"camera":{"sensor_view":"roof"},"vehicle":{"speed_kmh":32.4},"detections":{"objects":[{"type":"vehicle","confidence":0.88},{"type":"brake_light","confidence":0.64}]},"media_meta":{"tagging":{"labels":["hard_brake","rain","downtown_loop"]}}}'), '2025-01-01 08:15:21'), + ('FRAME-0102', PARSE_JSON('{"scene":{"weather_code":"rain","lighting":"day"},"camera":{"sensor_view":"roof"},"vehicle":{"speed_kmh":24.8},"detections":{"objects":[{"type":"pedestrian","confidence":0.92},{"type":"bike","confidence":0.35}]},"media_meta":{"tagging":{"labels":["pedestrian","swerve","crosswalk"]}}}'), '2025-01-01 08:33:54'), + ('FRAME-0201', PARSE_JSON('{"scene":{"weather_code":"overcast","lighting":"day"},"camera":{"sensor_view":"front"},"vehicle":{"speed_kmh":48.1},"detections":{"objects":[{"type":"lane_merge","confidence":0.74},{"type":"vehicle","confidence":0.41}]},"media_meta":{"tagging":{"labels":["lane_merge","urban"]}}}'), '2025-01-01 11:12:02'), + ('FRAME-0301', PARSE_JSON('{"scene":{"weather_code":"clear","lighting":"day"},"camera":{"sensor_view":"front"},"vehicle":{"speed_kmh":52.6},"detections":{"objects":[{"type":"vehicle","confidence":0.82},{"type":"hard_brake","confidence":0.59}]},"media_meta":{"tagging":{"labels":["hard_brake","highway"]}}}'), '2025-01-02 09:44:18'), + ('FRAME-0401', PARSE_JSON('{"scene":{"weather_code":"lightfog","lighting":"night"},"camera":{"sensor_view":"rear"},"vehicle":{"speed_kmh":38.9},"detections":{"objects":[{"type":"traffic_light","confidence":0.78},{"type":"vehicle","confidence":0.36}]},"media_meta":{"tagging":{"labels":["night_lowlight","traffic_light"]}}}'), '2025-01-03 21:18:07'); +``` + +文档: [CREATE TABLE](/tidb-cloud-lake/sql/create-table.md)、[INSERT](/tidb-cloud-lake/sql/insert.md)。 + +--- + +## 2. 过滤工作集 {#2-filter-the-working-set} + +将分析范围限定在数据填充数据中的 1 月 1 日至 3 日快照上,以确保演示始终会返回结果行。 + +```sql +WITH recent_videos AS ( + SELECT * + FROM citydrive_videos + WHERE capture_date >= '2025-01-01' + AND capture_date < '2025-01-04' +) +SELECT v.video_id, + v.route_name, + v.weather, + COUNT(f.frame_id) AS flagged_frames +FROM recent_videos v +LEFT JOIN frame_events f USING (video_id) +GROUP BY v.video_id, v.route_name, v.weather +ORDER BY flagged_frames DESC; +``` + +文档: [DATEADD](/tidb-cloud-lake/sql/date-add.md)、[GROUP BY](/tidb-cloud-lake/sql/select.md#group-by-clause)。 + +示例输出: + +``` +video_id | route_name | weather | flagged_frames +VID-20250101-001| Downtown Loop | Rain | 2 +VID-20250101-002| Port Perimeter | Overcast | 1 +VID-20250102-001| Airport Connector | Clear | 1 +VID-20250103-001| CBD Night Sweep | LightFog | 1 +``` + +--- + +## 3. JOIN 模式 {#3-join-patterns} + +### 用于帧上下文的 INNER JOIN {#inner-join-for-frame-context} + +```sql +SELECT f.frame_id, + f.event_tag, + f.risk_score, + v.route_name, + v.camera_source +FROM frame_events AS f +JOIN citydrive_videos AS v USING (video_id) +ORDER BY f.collected_at; +``` + +示例输出: + +``` +frame_id | event_tag | risk_score | route_name | camera_source +FRAME-0101| hard_brake | 0.81 | Downtown Loop | roof_cam +FRAME-0102| pedestrian | 0.67 | Downtown Loop | roof_cam +FRAME-0201| lane_merge | 0.74 | Port Perimeter | front_cam +FRAME-0301| hard_brake | 0.59 | Airport Connector | front_cam +FRAME-0401| night_lowlight | 0.63 | CBD Night Sweep | rear_cam +``` + +### 用于 QA 的反连接 {#anti-join-qa} + +```sql +SELECT frame_id +FROM frame_events f +WHERE NOT EXISTS ( + SELECT 1 + FROM citydrive_videos v + WHERE v.video_id = f.video_id +); +``` + +示例输出: + +``` +frame_id +FRAME-0501 +``` + +### 用于嵌套检测结果的 LATERAL FLATTEN {#lateral-flatten-for-nested-detections} + +```sql +SELECT f.frame_id, + obj.value['type']::STRING AS detected_type, + obj.value['confidence']::DOUBLE AS confidence +FROM frame_events AS f +JOIN frame_metadata_catalog AS meta ON meta.doc_id = f.frame_id, + LATERAL FLATTEN(input => meta.meta_json['detections']['objects']) AS obj +WHERE f.event_tag = 'pedestrian' +ORDER BY confidence DESC; +``` + +示例输出: + +``` +frame_id | detected_type | confidence +FRAME-0102| pedestrian | 0.92 +FRAME-0102| bike | 0.35 +``` + +文档: [JOIN](/tidb-cloud-lake/sql/join.md)、[FLATTEN](/tidb-cloud-lake/sql/flatten.md)。 + +--- + +## 4. 用于车队 KPI 的聚合 {#4-aggregations-for-fleet-kpis} + +### 按路线的行为 {#behaviour-by-route} + +```sql +SELECT v.route_name, + f.event_tag, + COUNT(*) AS occurrences, + AVG(f.risk_score) AS avg_risk +FROM frame_events f +JOIN citydrive_videos v USING (video_id) +GROUP BY v.route_name, f.event_tag +ORDER BY avg_risk DESC, occurrences DESC; +``` + +示例输出: + +``` +route_name | event_tag | occurrences | avg_risk +Downtown Loop | hard_brake | 1 | 0.81 +Port Perimeter | lane_merge | 1 | 0.74 +Downtown Loop | pedestrian | 1 | 0.67 +CBD Night Sweep | night_lowlight | 1 | 0.63 +Airport Connector | hard_brake | 1 | 0.59 +``` + +### ROLLUP 总计 {#rollup-totals} + +```sql +SELECT v.route_name, + f.event_tag, + COUNT(*) AS occurrences +FROM frame_events f +JOIN citydrive_videos v USING (video_id) +GROUP BY ROLLUP(v.route_name, f.event_tag) +ORDER BY v.route_name NULLS LAST, f.event_tag; +``` + +示例输出(前 6 行): + +``` +route_name | event_tag | occurrences +Airport Connector | hard_brake | 1 +Airport Connector | NULL | 1 +CBD Night Sweep | night_lowlight | 1 +CBD Night Sweep | NULL | 1 +Downtown Loop | hard_brake | 1 +Downtown Loop | pedestrian | 1 +... (total rows: 10) +``` + +### 用于路线 × 天气覆盖情况的 CUBE {#cube-for-route-weather-coverage} + +```sql +SELECT v.route_name, + v.weather, + COUNT(DISTINCT v.video_id) AS videos +FROM citydrive_videos v +GROUP BY CUBE(v.route_name, v.weather) +ORDER BY v.route_name NULLS LAST, v.weather NULLS LAST; +``` + +示例输出(前 6 行): + +``` +route_name | weather | videos +Airport Connector | Clear | 1 +Airport Connector | NULL | 1 +CBD Night Sweep | LightFog | 1 +CBD Night Sweep | NULL | 1 +Downtown Loop | Rain | 1 +Downtown Loop | NULL | 1 +... (total rows: 13) +``` + +--- + +## 5. 窗口函数 {#5-window-functions} + +### 每个视频的累计风险 {#running-risk-per-video} + +```sql +WITH ordered_events AS ( + SELECT video_id, collected_at, risk_score + FROM frame_events +) +SELECT video_id, + collected_at, + risk_score, + SUM(risk_score) OVER ( + PARTITION BY video_id + ORDER BY collected_at + ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW + ) AS cumulative_risk +FROM ordered_events +ORDER BY video_id, collected_at; +``` + +示例输出(前 6 行): + +``` +video_id | collected_at | risk_score | cumulative_risk +VID-20250101-001| 2025-01-01 08:15:21 | 0.81 | 0.81 +VID-20250101-001| 2025-01-01 08:33:54 | 0.67 | 1.48 +VID-20250101-002| 2025-01-01 11:12:02 | 0.74 | 0.74 +VID-20250102-001| 2025-01-02 09:44:18 | 0.59 | 0.59 +VID-20250103-001| 2025-01-03 21:18:07 | 0.63 | 0.63 +VID-MISSING-001 | 2025-01-04 10:00:00 | 0.25 | 0.25 +``` + +### 最近帧的滚动平均值 {#rolling-average-over-recent-frames} + +```sql +SELECT video_id, + frame_id, + frame_index, + risk_score, + AVG(risk_score) OVER ( + PARTITION BY video_id + ORDER BY frame_index + ROWS BETWEEN 3 PRECEDING AND CURRENT ROW + ) AS rolling_avg_risk +FROM frame_events +ORDER BY video_id, frame_index; +``` + +示例输出(前 6 行): + +``` +video_id | frame_id | frame_index | risk_score | rolling_avg_risk +VID-20250101-001| FRAME-0101 | 125 | 0.81 | 0.81 +VID-20250101-001| FRAME-0102 | 416 | 0.67 | 0.74 +VID-20250101-002| FRAME-0201 | 298 | 0.74 | 0.74 +VID-20250102-001| FRAME-0301 | 188 | 0.59 | 0.59 +VID-20250103-001| FRAME-0401 | 522 | 0.63 | 0.63 +VID-MISSING-001 | FRAME-0501 | 10 | 0.25 | 0.25 +``` + +文档:[窗口函数](/tidb-cloud-lake/sql/window-functions-overview.md)。 + +--- + +## 6. 聚合索引加速 {#6-aggregating-index-boost} + +将仪表板中经常使用的汇总结果持久化。 + +```sql +CREATE OR REPLACE AGGREGATING INDEX idx_video_event_summary +AS +SELECT video_id, + event_tag, + COUNT(*) AS event_count, + AVG(risk_score) AS avg_risk +FROM frame_events +GROUP BY video_id, event_tag; +``` + +当分析师重新运行熟悉的 KPI 时,优化器会直接从该索引提供结果: + +```sql +SELECT v.route_name, + e.event_tag, + COUNT(*) AS event_count, + AVG(e.risk_score) AS avg_risk +FROM frame_events e +JOIN citydrive_videos v USING (video_id) +WHERE v.capture_date >= '2025-01-01' +GROUP BY v.route_name, e.event_tag +ORDER BY avg_risk DESC; +``` + +示例输出: + +``` +route_name | event_tag | event_count | avg_risk +Downtown Loop | hard_brake | 1 | 0.81 +Port Perimeter | lane_merge | 1 | 0.74 +Downtown Loop | pedestrian | 1 | 0.67 +CBD Night Sweep | night_lowlight | 1 | 0.63 +Airport Connector | hard_brake | 1 | 0.59 +``` + +文档:[聚合索引](/tidb-cloud-lake/guides/aggregating-index.md) 和 [EXPLAIN](/tidb-cloud-lake/sql/explain.md)。 + +--- + +## 7. 存储过程自动化 {#7-stored-procedure-automation} + +对相关逻辑进行封装,使调度任务始终生成相同的报表。 + +```sql +CREATE OR REPLACE PROCEDURE citydrive_route_report(days_back UINT8) +RETURNS TABLE(route_name STRING, event_tag STRING, event_count BIGINT, avg_risk DOUBLE) +LANGUAGE SQL +AS +$$ +BEGIN + RETURN TABLE ( + SELECT v.route_name, + e.event_tag, + COUNT(*) AS event_count, + AVG(e.risk_score) AS avg_risk + FROM frame_events e + JOIN citydrive_videos v USING (video_id) + WHERE v.capture_date >= DATEADD('day', -:days_back, DATE '2025-01-04') + GROUP BY v.route_name, e.event_tag + ); +END; +$$; + +CALL PROCEDURE citydrive_route_report(30); +``` + +示例输出: + +``` +route_name | event_tag | event_count | avg_risk +Downtown Loop | hard_brake | 1 | 0.81 +CBD Night Sweep | night_lowlight | 1 | 0.63 +Downtown Loop | pedestrian | 1 | 0.67 +Airport Connector | hard_brake | 1 | 0.59 +Port Perimeter | lane_merge | 1 | 0.74 +``` + +存储过程既可以手动触发,也可以通过 [TASKS](/tidb-cloud-lake/sql/task.md) 或编排工具触发。 + +--- + +有了这些表和模式后,CityDrive 其余指南就可以引用完全相同的 `video_id` 键:使用 `frame_metadata_catalog` 进行 JSON 搜索,使用帧向量嵌入进行相似度检索,使用 GPS 位置进行地理查询,并通过统一的 ETL 路径保持它们同步。 \ No newline at end of file diff --git a/tidb-cloud-lake/guides/stage-overview.md b/tidb-cloud-lake/guides/stage-overview.md new file mode 100644 index 0000000000000..2173380eac7ef --- /dev/null +++ b/tidb-cloud-lake/guides/stage-overview.md @@ -0,0 +1,109 @@ +--- +title: Stage 概述 +summary: stage 是一个用于存放数据文件的虚拟位置。stage 中的文件可以直接查询,也可以加载到表中。或者,你也可以将表中的数据以文件形式卸载到 stage 中。 +--- + +# Stage 概述 + +在 {{{ .lake }}} 中,stage 是一个用于存放数据文件的虚拟位置。stage 中的文件可以直接查询,也可以加载到表中。或者,你也可以将表中的数据以文件形式卸载到 stage 中。使用 stage 的优势在于,你可以像访问计算机上的文件夹一样方便地对其进行数据加载和卸载。就像把文件放进文件夹时,你不一定需要知道它在硬盘上的确切位置一样,访问 stage 中的文件时,你只需要指定 stage 名称和文件名,例如 `@mystage/mydatafile.csv`,而不需要指定它在对象存储 bucket 中的具体位置。与计算机上的文件夹类似,你可以在 {{{ .lake }}} 中根据需要创建任意数量的 stage。不过需要注意的是,一个 stage 不能包含另一个 stage。每个 stage 都是独立运行的,不会包含其他 stage。 + +使用 stage 进行数据加载还可以提升数据文件上传、管理和筛选的效率。借助 [LakeSQL](/tidb-cloud-lake/guides/connect-using-lakesql.md),你可以通过一条命令轻松地将文件上传到 stage,或从 stage 下载文件。将数据加载到 {{{ .lake }}} 时,你可以在 COPY INTO 命令中直接指定 stage,使该命令能够从该 stage 中读取数据文件,甚至对其进行筛选。同样地,从 {{{ .lake }}} 导出数据时,你也可以将数据文件转储到 stage 中。 + +## stage 类型 {#stage-types} + +根据实际存储位置和可访问性,stage 可分为以下几种类型:Internal Stage、External Stage 和 User Stage。下表总结了 {{{ .lake }}} 中不同 stage 类型的特征,包括其存储位置、可访问性以及推荐使用场景: + +| | 用户 Stage | 内部 Stage | 外部 Stage | +|----------------------|------------------------------------|--------------------------------------------------|---------------------------------------------------------------------------------------------------------------| +| **存储位置** | 内部对象存储 ({{{ .lake }}}) | 内部对象存储 ({{{ .lake }}}) | 外部对象存储(例如 S3、Azure) | +| **创建方法** | 自动创建 | 通过以下方式手动创建:`CREATE STAGE stage_name;` | 通过以下方式手动创建:`CREATE STAGE stage_name` `'s3://bucket/prefix/'` `CONNECTION=(endpoint_url='x', ...);` | +| **访问控制** | 仅用户本人可访问 | 可与其他用户或角色共享 | 可与其他用户或角色共享 | +| **删除 Stage** | 不允许 | 删除 stage 并清空其中的文件 | 仅删除 stage;外部位置中的文件会被保留 | +| **文件上传** | 必须将文件上传到 {{{ .lake }}} | 必须将文件上传到 {{{ .lake }}} | 无需上传;用于从外部存储读取数据或将数据卸载到外部存储 | +| **使用场景** | 个人/私有数据 | 团队/共享数据 | 外部数据集成或数据卸载 | +| **路径格式** | `@~/` | `@stage_name/` | `@stage_name/` | + +### Internal Stage {#internal-stage} + +Internal Stage 中的文件实际上存储在 {{{ .lake }}} 所在的对象存储中。Internal Stage 可供你所在组织内的所有用户访问,因此每个用户都可以将该 stage 用于数据加载或导出任务。与创建文件夹类似,创建 stage 时需要指定名称。下面是使用 [CREATE STAGE](/tidb-cloud-lake/sql/create-stage.md) 命令创建 Internal Stage 的示例: + +```sql +-- Create an internal stage named my_internal_stage +CREATE STAGE my_internal_stage; +``` + +### External Stage {#external-stage} + +External Stage 允许你指定一个位于 {{{ .lake }}} 所在位置之外的对象存储位置。例如,如果你的数据集位于 Google Cloud Storage 容器中,你可以基于该容器创建一个 External Stage。创建 External Stage 时,你必须提供连接信息,以便 {{{ .lake }}} 连接到该外部位置。 + +下面是创建 External Stage 的示例。假设你的数据集位于名为 `lake-doc` 的 Amazon S3 bucket 中。 + +你可以使用 [CREATE STAGE](/tidb-cloud-lake/sql/create-stage.md) 命令创建一个 External Stage,将 {{{ .lake }}} 连接到该 bucket: + +```sql +-- Create an external stage named my_external_stage +CREATE STAGE my_external_stage + URL = 's3://lake-doc' + CONNECTION = ( + ACCESS_KEY_ID = '', + SECRET_ACCESS_KEY = '' + ); +``` + +创建 External Stage 后,你就可以从 {{{ .lake }}} 访问这些数据集。例如,列出文件: + +```sql +LIST @my_external_stage; + +┌────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ +│ name │ size │ md5 │ last_modified │ creator │ +├───────────────┼────────┼────────────────────────────────────┼───────────────────────────────┼──────────────────┤ +│ Inventory.csv │ 57585 │ "0cd02fb636a22ba9f4ae4d24555a7d68" │ 2024-03-17 21:22:38.000 +0000 │ NULL │ +│ Products.csv │ 42987 │ "570e5cbf6a4b6e7e9a258094192f4784" │ 2024-03-17 21:22:38.000 +0000 │ NULL │ +└────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ +``` + +请注意,外部存储必须是 {{{ .lake }}} 支持的对象存储解决方案之一。[CREATE STAGE](/tidb-cloud-lake/sql/create-stage.md) 命令页面提供了如何为常用对象存储解决方案指定连接信息的示例。 + +### User Stage {#user-stage} + +User Stage 可以视为一种特殊类型的 Internal Stage:User Stage 中的文件存储在 {{{ .lake }}} 所在的对象存储中,但其他用户无法访问。每个用户开箱即有自己的 User Stage,使用前无需创建或命名。此外,你也不能删除自己的 User Stage。 + +对于不需要与他人共享的数据文件,User Stage 可以作为一个方便的仓库。要访问你的 User Stage,请使用 `@~`。例如,列出你的 stage 中的所有文件: + +```sql +LIST @~; +``` + +## 使用 PATTERN 过滤 stage 中的文件 {#filtering-staged-files-with-pattern} + +读取、列出、删除或检查 stage 中文件的命令和函数都可以使用 `PATTERN` 通过正则表达式筛选文件。对于 stage 位置,`PATTERN` 匹配的是 `@[/]` 之后的文件路径部分,而不是完整的 stage URI。 + +> **Note:** +> +> 文件路径中的 Glob 模式(例如 `ontime_200{6,7,8}.csv` 或 `ontime_200[6-8].csv`)仅支持基于 HTTP 的外部位置。S3 和其他对象存储位置不支持文件路径中的 glob 展开——请改用带正则表达式的 `PATTERN`。 + +例如,对于 `@sales_stage/raw/`,stage 文件 `@sales_stage/raw/year=2025/month=01/sales_20250101.parquet` 会按 `year=2025/month=01/sales_20250101.parquet` 进行匹配: + +```sql +LIST @sales_stage/raw/ PATTERN = 'year=2025/month=01/.*[.]parquet'; +``` + +要匹配某个 stage 路径下所有的 `.log` 文件,可以使用如下正则表达式: + +```sql +LIST @my_stage PATTERN = '.*[.]log'; +``` + +## 管理 stage {#managing-stages} + +{{{ .lake }}} 提供了多种命令,帮助你管理 stage 及其中暂存的文件: + +| 命令 | 描述 | 适用于 User Stage | 适用于 Internal Stage | 适用于 External Stage | +| ------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | --------------------- | ------------------------- | ------------------------- | +| [CREATE STAGE](/tidb-cloud-lake/sql/create-stage.md) | 创建 Internal Stage 或 External Stage。 | 否 | 是 | 是 | +| [DROP STAGE](/tidb-cloud-lake/sql/drop-stage.md) | 删除 Internal Stage 或 External Stage。 | 否 | 是 | 是 | +| [DESC STAGE](/tidb-cloud-lake/sql/desc-stage.md) | 显示 Internal Stage 或 External Stage 的属性。 | 否 | 是 | 是 | +| [LIST](/tidb-cloud-lake/sql/list-stage-files.md) | 返回 stage 中暂存文件的列表。或者,表函数 [LIST_STAGE](/tidb-cloud-lake/sql/list-stage.md) 提供了类似功能,并具有更高的灵活性,可用于获取特定文件信息 | 是 | 是 | 是 | +| [REMOVE](/tidb-cloud-lake/sql/remove-stage-files.md) | 从 stage 中删除暂存文件。 | 是 | 是 | 是 | +| [SHOW STAGES](/tidb-cloud-lake/sql/show-stages.md) | 返回已创建的 Internal Stage 和 External Stage 列表。 | 否 | 是 | 是 | \ No newline at end of file diff --git a/tidb-cloud-lake/guides/superset.md b/tidb-cloud-lake/guides/superset.md new file mode 100644 index 0000000000000..15b87ac67c824 --- /dev/null +++ b/tidb-cloud-lake/guides/superset.md @@ -0,0 +1,96 @@ +--- +title: 使用 Apache Superset 连接到 TiDB Cloud Lake +summary: 了解如何在 Apache Superset 中安装 TiDB Cloud Lake 的 SQLAlchemy 方言,并将 Superset 连接到 TiDB Cloud Lake 计算集群。 +--- + +# 使用 Apache Superset 连接到 TiDB Cloud Lake + +[Apache Superset](https://superset.apache.org/) 是一个开源的数据探索和可视化平台。Superset 通过 [TiDB Cloud Lake dialect for SQLAlchemy](https://github.com/tidbcloud/lake-sqlalchemy) 连接到 {{{ .lake }}}。 + +## 前提条件 {#prerequisites} + +开始之前,请确保你已具备以下条件: + +- Docker +- 一个 {{{ .lake }}} 账户、数据库和计算集群 +- 用于连接的主机、用户名、密码、数据库名称和计算集群名称 + +如需了解如何获取连接信息,请参见[连接到计算集群](/tidb-cloud-lake/guides/warehouse.md#connecting-to-a-warehouse)。 + +## 构建 Superset 镜像 {#build-a-superset-image} + +官方 Superset 镜像不包含 {{{ .lake }}} SQLAlchemy 方言。请创建一个名为 `Dockerfile` 的文件,并写入以下内容: + +```dockerfile +FROM apache/superset + +USER root +RUN pip install --no-cache-dir tidbcloudlake-sqlalchemy +USER superset +``` + +`tidbcloudlake-sqlalchemy` 包会安装所需的 {{{ .lake }}} Python 驱动作为依赖关系。 + +构建镜像: + +```shell +docker build -t superset-lake . +``` + +基于该镜像启动一个容器: + +```shell +docker run -d \ + -p 8080:8088 \ + -e "SUPERSET_SECRET_KEY=" \ + --name superset \ + superset-lake +``` + +## 初始化 Superset {#initialize-superset} + +创建管理员账户: + +```shell +docker exec -it superset superset fab create-admin \ + --username admin \ + --firstname Superset \ + --lastname Admin \ + --email admin@example.com \ + --password +``` + +应用数据库迁移: + +```shell +docker exec -it superset superset db upgrade +``` + +初始化 Superset: + +```shell +docker exec -it superset superset init +``` + +打开 `http://localhost:8080`,并使用管理员账户登录。 + +## 将 Superset 连接到 TiDB Cloud Lake {#connect-superset-to-tidb-cloud-lake} + +1. 在 Superset 中,选择 **Settings** > **Data** > **Connect Database**。 +2. 选择 **Other** 作为数据库类型。 +3. 输入一个显示名称,例如 `TiDB Cloud Lake`。 +4. 按以下格式输入 SQLAlchemy URI: + + ```text + lake://:@:443/?warehouse= + ``` + +5. 点击 **Test Connection**。 +6. 连接测试成功后,点击 **Connect**。 + +现在,你可以在 Superset 中基于 {{{ .lake }}} 表创建数据集,并将其用于图表和仪表板。 + +## 相关资源 {#related-resources} + +- [PyPI 上的 `tidbcloudlake-sqlalchemy`](https://pypi.org/project/tidbcloudlake-sqlalchemy/) +- [Apache Superset 文档](https://superset.apache.org/docs/intro) \ No newline at end of file diff --git a/tidb-cloud-lake/guides/support-services.md b/tidb-cloud-lake/guides/support-services.md new file mode 100644 index 0000000000000..0b4c2db27c248 --- /dev/null +++ b/tidb-cloud-lake/guides/support-services.md @@ -0,0 +1,52 @@ +--- +title: 支持服务 +summary: "{{{ .lake }}} 为我们的 {{{ .lake }}} 用户和客户提供全面的支持服务。我们的目标是提供卓越的支持,体现 {{{ .lake }}} 产品的核心价值——高性能、易用性以及快速、高质量的结果。" +--- + +# 支持服务 + +{{{ .lake }}} 为我们的 {{{ .lake }}} 用户和客户提供全面的支持服务。我们的目标是提供卓越的支持,体现 {{{ .lake }}} 产品的核心价值——高性能、易用性以及快速、高质量的结果。 + +如需了解不同版本的支持服务级别的详细信息,请参见 [支持服务级别](#support-service-levels)。如需更多信息,请联系我们的[销售团队](https://www.pingcap.com/contact-us/)。 + +## 获取支持 {#getting-support} + +你可以通过多种渠道获取支持: + +- **Cloud Console**:登录 {{{ .lake }}} 控制台,并从菜单中选择 **Support → Create New Ticket**,以创建新的支持工单并查看已提交工单的状态。 +- **Status Page**:订阅我们的 [status page](https://status.tidbcloud.com/),以便在平台受到任何事件影响时快速收到通知。 +- **Documentation**:浏览我们全面的[文档](https://docs.pingcap.com/tidbcloudlake/),获取指南、教程和参考资料。 + +## 支持服务级别 {#support-service-levels} + +{{{ .lake }}} 根据你的订阅层级提供不同级别的支持: + +| 功能 | Personal | Business | Dedicated | +| ------------------------------------------------------ | -------- | -------- | --------- | +| 记录和跟踪支持工单 | ✓ | ✓ | ✓ | +| Severity 1 问题的每周 4 天、每天 7 小时覆盖和响应窗口 | 24 小时 | 8 小时 | 4 小时 | +| 非 Severity 1 问题的响应时间 | 48 小时 | 24 小时 | 8 小时 | + +### 严重级别 {#severity-levels} + +- **Severity 1**:严重问题导致业务运营中断,且没有可行的临时解决方法 +- **Severity 2**:主要功能受到影响,并伴随显著的性能下降 +- **Severity 3**:部分功能丢失,对业务影响较小 +- **Severity 4**:一般性问题、建议或功能请求 + +> **注意:** +> +> 请注意,只有 Business 和 Dedicated 客户在支持事件上享有服务级别协议(SLA)。如果你使用的是 Personal 版本,虽然我们会尽快回答你的问题,但也建议你同时查看我们的社区资源: +> +> - [{{{ .lake }}} Community Slack Channel](https://slack.tidb.io/invite?team=tidb-community&channel=everyone&ref=tidbcloud) + +## 企业支持 {#enterprise-support} + +对于具有关键任务部署需求的客户,我们的 Dedicated 版本提供增强型支持选项,包括: + +- 所有严重级别问题的优先响应时间 +- 专属支持工程师 +- 主动监控和问题解决 +- 定期健康检查和优化建议 + +联系[销售团队](https://www.pingcap.com/contact-us/)以了解有关企业支持服务的更多信息。 \ No newline at end of file diff --git a/tidb-cloud-lake/guides/tableau.md b/tidb-cloud-lake/guides/tableau.md new file mode 100644 index 0000000000000..4dc31672a2b25 --- /dev/null +++ b/tidb-cloud-lake/guides/tableau.md @@ -0,0 +1,52 @@ +--- +title: 使用 Tableau 连接到 TiDB Cloud Lake +summary: Tableau 是一个可视化分析平台,正在改变我们使用数据解决问题的方式。你可以通过 Tableau 的 **Other Databases (JDBC)** 接口,使用 lake-jdbc driver 连接到 TiDB Cloud Lake。 +--- + +# 使用 Tableau 连接到 TiDB Cloud Lake + +[Tableau](https://www.tableau.com/) 是一个可视化分析平台,正在改变我们使用数据解决问题的方式。你可以通过 Tableau 的 **Other Databases (JDBC)** 接口,使用 [lake-jdbc driver](https://github.com/tidbcloud/lake-jdbc) 连接到 {{{ .lake }}}。 + +为获得最佳兼容性,建议使用 Tableau 2022.3 或更高版本。 + +## 教程:集成 {{{ .lake }}} {#tutorial-integrating-with-lake} + +本教程将指导你使用 `lake-jdbc` 将 Tableau Desktop 连接到 {{{ .lake }}}。 + +### 步骤 1. 获取连接信息 {#step-1-obtain-connection-information} + +获取你的 {{{ .lake }}} 计算集群连接信息。更多详情,请参见[连接到计算集群](/tidb-cloud-lake/guides/warehouse.md#connecting-to-a-warehouse)。 + +### 步骤 2. 安装 lake-jdbc {#step-2-install-lake-jdbc} + +1. 从以下任一位置下载 `0.4.6` 或更高版本的 `lake-jdbc`: + + - [lake-jdbc GitHub repository](https://github.com/tidbcloud/lake-jdbc) + - [lake-jdbc on Maven Central](https://repo1.maven.org/maven2/com/tidbcloud/lake-jdbc/) + +2. 将驱动 JAR 文件(例如 `lake-jdbc-0.4.6.jar`)移动到 Tableau 的驱动目录中。 + + | 操作系统 | Tableau 的驱动程序文件夹 | + | ---------------- | -------------------------------- | + | MacOS | ~/Library/Tableau/Drivers | + | Windows | C:\Program Files\Tableau\Drivers | + | Linux | /opt/tableau/tableau_driver/jdbc | + +### 步骤 3. 连接到 {{{ .lake }}} {#step-3-connect-to-lake} + +1. 启动 Tableau Desktop,并在侧边栏中选择 **Other Databases (JDBC)**。 + + ![Other Databases (JDBC)](/media/tidb-cloud-lake/bi-tableau-1.png) + +2. 在窗口中填写你的 {{{ .lake }}} 连接信息,然后点击 **Sign In**。 + + | 参数 | 描述 | 本教程 | + | --------- | ----------------------------------------- | ------------------------------------------------------------------- | + | URL | 格式:`jdbc:lake://{user}:{password}@{host}:{port}/{database}` | `jdbc:lake://cloudapp:@:443/default` | + | Dialect | SQL 方言选择 "MySQL"。 | MySQL | + | Username | 用于连接到 {{{ .lake }}} 的 SQL 用户 | cloudapp | + | Password | SQL 用户密码 | 你的密码 | + +3. 当 Tableau 工作簿打开后,选择你要查询的数据库、schema 和表。对于本教程,**Database** 和 **Schema** 都选择 _default_。 + +至此,配置已完成!现在你可以将表拖到工作区中,开始进行查询和进一步分析。 diff --git a/tidb-cloud-lake/guides/task-flow.md b/tidb-cloud-lake/guides/task-flow.md new file mode 100644 index 0000000000000..1c95dc7bd799a --- /dev/null +++ b/tidb-cloud-lake/guides/task-flow.md @@ -0,0 +1,214 @@ +--- +title: 任务流 (Task Flow) +summary: "任务流 (Task Flow) 是 {{{ .lake }}} 内置的工作流编排功能。它允许你将基于 SQL 的数据流水线定义、调度和监控为有向无环图 (DAG)。" +--- + +# 任务流 (Task Flow) + +任务流 (Task Flow) 是 {{{ .lake }}} 内置的工作流编排功能。它允许你将基于 SQL 的数据流水线定义、调度和监控为有向无环图 (DAG)。图中的每个节点都是一个 **Task**——一条具有自身调度、依赖关系和执行设置的 SQL 语句。**Flow** 将多个任务组合在一起,并自动管理它们的执行顺序。 + +## 概述 {#overview} + +Task Flow 用更强大的模型替代了旧版的 Task List: + +| 功能 | 旧版任务列表 | 任务流 (Task Flow) | +| --------------------- | ---------------- | --------- | +| 单个 SQL 任务 | ✅ | ✅ | +| 多任务 DAG | ❌ | ✅ | +| 可视化图形编辑器 | ❌ | ✅ | +| 版本历史 | ❌ | ✅ | +| 基于流的触发器 | ❌ | ✅ | +| 批量操作 | ❌ | ✅ | + +## 核心概念 {#key-concepts} + +### Task {#task} + +Task 是最小的工作单元。它包含: + +- 一条要执行的 SQL 语句 +- 调度方式(手动、间隔或 cron) +- 对其他任务或 stream 的可选依赖关系 +- 高级设置(失败阈值、查询结果缓存、最小执行间隔) + +### Flow {#flow} + +Flow 是一组具有依赖关系的命名任务集合。{{{ .lake }}} 会根据 DAG 结构自动确定执行顺序。一个 flow 包含: + +- 名称和分配的计算集群 (Warehouse) +- 一个或多个已定义依赖关系的任务 +- 生命周期:Created → Started → Suspended → Resumed → Dropped + +### DAG (Directed Acyclic Graph) {#dag-directed-acyclic-graph} + +任务之间的依赖图。如果 Task B 依赖于 Task A,{{{ .lake }}} 会先运行 Task A,并且只有在 Task A 成功后才会触发 Task B。不允许存在循环依赖。 + +## 快速开始 {#getting-started} + +### 创建任务流 {#creating-a-task-flow} + +1. 在左侧边栏中,导航到 **Data** > **Task & Flows**。 +2. 点击右上角的 **Create**。 +3. 在 flow 弹窗中: + - 输入 **Flow Name**。 + - 选择用于运行任务的 **Warehouse**。 +4. 点击 **Add Task to Flow** 添加第一个任务。 + +### 配置任务 {#configuring-a-task} + +在任务表单中,填写以下内容: + +**Basic Settings** + +| 字段 | 描述 | +| --------- | ------------------------------------------------------------------------ | +| Task Name | flow 内的唯一名称 | +| Schedule | 运行时间:Manual、Interval(例如每 5 分钟)或 Cron 表达式 | +| Timezone | 用于 cron 调度计算的时区 | +| SQL | 要执行的 SQL 语句 | +| Comment | 可选描述 | + +**Dependencies** + +| 字段 | 描述 | +| -------------- | ------------------------------------------------------------------- | +| Require Tasks | 在此任务运行前必须完成的其他任务 | +| Require Stream | 在触发此任务前必须有新数据的数据库 stream | + +**Advanced Options** + +| 字段 | 描述 | +| ------------------------------- | ----------------------------------------------------------------------- | +| Suspend Task After Num Failures | 连续失败 N 次后自动暂停该任务(0 = 从不) | +| Enable Query Result Cache | 缓存查询结果以避免重复计算 | +| Min Execute Seconds | 两次执行之间的最小间隔(5s / 10s / 15s / 30s) | + +1. 点击 **Save** 将任务添加到 flow 中。 +2. 重复上述步骤以添加更多任务。使用 **Require Tasks** 定义它们之间的依赖关系。 +3. 点击 **Publish** 创建 flow。 + +> **Note:** +> +> 只有 `account_admin` 或 flow 创建者可以编辑或删除 flow。 + +## 可视化 Flow {#visualizing-the-flow} + +创建 flow 后,点击其名称以打开详情页。**Latest Run** 标签页会显示 DAG 可视化图。 + +每个节点会显示: + +- 任务名称 +- 最近一次执行状态(用颜色区分) +- 执行时间范围 +- 错误信息(如果失败) + +**状态颜色:** + +| 颜色 | 状态 | +| ----------------- | ------------------- | +| 蓝色边框 | Scheduled | +| 绿色边框 | Succeeded | +| 红色边框 | Failed | +| 浅蓝色边框 | Executing | +| 灰色边框 | Cancelled / Waiting | + +## 管理 Flows {#managing-flows} + +### Flow 操作 {#flow-actions} + +在 **Task & Flows** 列表中,每一行都有一个操作菜单,包含: + +| 操作 | 描述 | +| --------------------- | ------------------------------------- | +| Edit | 修改 flow 名称、计算集群或任务 | +| Suspend | 暂停所有已调度的执行 | +| Resume | 重新启用已调度的执行 | +| Execute Once | 立即触发一次性运行 | +| View Runs History | 查看所有历史执行 | +| View Versions History | 浏览并比较历史版本 | +| Delete | 永久删除该 flow | + +### 批量操作 {#bulk-operations} + +使用复选框选择多个 flow,然后使用批量操作菜单来: + +- 暂停所有选中的 flow +- 恢复所有选中的 flow +- 删除所有选中的 flow + +## 监控执行情况 {#monitoring-executions} + +### 运行历史 {#runs-history} + +在详情页点击 **Runs History** 以查看所有历史执行: + +| 列 | 描述 | +| -------------- | ------------------------------------------------------ | +| Task Name | 运行的是哪个任务 | +| Warehouse | 使用的 Warehouse | +| State | Scheduled / Executing / Succeeded / Failed / Cancelled | +| SQL | 已执行的 SQL(带 Query ID 链接) | +| Scheduled Time | 运行被触发的时间 | +| Completed Time | 运行完成的时间 | +| Comment | 任务备注 | + +失败或已取消的运行会显示错误提示。你可以点击错误查看详情或创建支持工单。 + +### 全局任务历史 {#global-task-history} + +导航到 **Data** → **Task History**,查看组织中所有 flow 的执行情况。你可以按以下条件筛选: + +- 任务名称(多选) +- 时间范围(最近 2 天、最近 3 天) + +## 版本控制 {#version-control} + +每次你发布对 flow 的更改时,{{{ .lake }}} 都会保存一个新版本。要访问版本历史: + +1. 打开 flow 详情页。 +2. 点击 **Versions History** 标签页。 + +### 比较版本 {#comparing-versions} + +1. 使用复选框选择两个版本。 +2. 点击 **Compare**。 +3. 系统会打开一个并排的 SQL diff 抽屉,显示这两个版本之间的变更内容。 + +### 回退到先前版本 {#reverting-to-a-previous-version} + +1. 从列表中选择一个版本。 +2. 点击 **Revert**。 +3. 在对话框中确认该操作。 + +flow 会恢复到所选版本,并创建一个新的版本记录。 + +## 调度参考 {#scheduling-reference} + +### 调度类型 {#schedule-types} + +**Manual**:任务仅在通过 **Execute Once** 触发时运行。不会自动调度。 + +**Interval**:每 N 分钟/小时运行一次。示例:`EVERY 5 MINUTE`。 + +**Cron**:带时区支持的标准 cron 表达式。示例:`0 9 * * 1-5`(工作日上午 9 点)。 + +### 基于 Stream 的触发器 {#stream-based-triggers} + +如果任务具有 **Require Stream** 依赖关系,则只有在指定 stream 存在未消费数据时才会执行。这对于构建响应表变更(CDC)的事件驱动型流水线非常有用。 + +## 最佳实践 {#best-practices} + +- **从简单开始**:先创建一个单任务流,以便在添加依赖关系之前验证 SQL。 +- **对 CDC 管道使用 stream**:将 stream 触发器与 `MERGE INTO` 语句结合使用,以构建增量数据管道。 +- **设置失败阈值**:使用 **Suspend Task After Num Failures**,防止失控重试消耗计算集群额度。 +- **启用结果缓存**:对于重复查询相同数据的任务,启用 **Query Result Cache** 以降低计算成本。 +- **使用版本历史**:在进行重大更改之前,记下当前版本号,以便在需要时回退。 +- **按工作负载分离计算集群**:将较重的转换任务分配到更大的计算集群,将轻量任务分配到较小的计算集群。 + +## 权限 {#permissions} + +| 角色 | 创建 | 编辑 | 删除 | 查看 | +| ------------- | ------ | -------- | -------- | ---- | +| account_admin | ✅ | ✅(任意) | ✅(任意) | ✅ | +| 创建者 | ✅ | ✅(自己的) | ✅(自己的) | ✅ | +| 其他用户 | ❌ | ❌ | ❌ | ✅ | diff --git a/tidb-cloud-lake/guides/task-management.md b/tidb-cloud-lake/guides/task-management.md new file mode 100644 index 0000000000000..956548f985961 --- /dev/null +++ b/tidb-cloud-lake/guides/task-management.md @@ -0,0 +1,59 @@ +--- +title: 任务管理 +summary: 本页介绍数据集成任务的常见操作,包括任务创建流程、启动和下线行为、任务状态以及运行历史。有关特定数据源的配置,请参阅详细的任务指南。 +--- + +# 任务管理 + +本页介绍数据集成任务的常见操作,包括任务创建流程、启动和下线行为、任务状态以及运行历史。有关特定数据源的配置,请参阅详细的任务指南。 + +## 通用任务创建流程 {#general-task-creation-flow} + +1. 导航到 **Data** > **Data Integration**,然后点击 **Create Task**。 +2. 选择一个现有的数据源。 +3. 根据任务类型填写源端参数,例如文件路径、源表、同步模式、topic 或过滤条件。 +4. 预览源数据并验证 schema、字段类型或消息内容。 +5. 根据任务类型,选择目标计算集群和目标数据库 / 表,或配置结果查看方式。 +6. 创建任务,并在需要时启动任务。 + +## 启动和下线任务 {#starting-and-stopping-tasks} + +任务创建后,其初始状态为 **Stopped**。要开始同步、导入或消费,请在任务上点击 **Start**。 + +要下线正在运行的任务,请点击 **Stop**。任务将优雅地下线并保存当前进度。 + +## 任务状态 {#task-status} + +数据集成页面会显示所有任务及其当前状态: + +| 状态 | 描述 | +|--------|-------------| +| Running | 任务正在主动同步、导入或消费数据 | +| Stopped | 任务当前未运行 | +| Failed | 任务在执行期间遇到错误 | + +## 查看运行历史 {#viewing-run-history} + +点击某个任务可查看其执行历史。运行历史包括: + +- 执行开始或结束时间 +- 已导入或同步的行数,或已写入的消息对象数量 +- 错误详情(如有) + +## 按任务类型划分的运行时行为 {#runtime-behavior-by-task-type} + +- S3 任务可以运行一次,也可以持续轮询新文件。 +- MySQL `Snapshot` 任务通常会在全量负载完成后自动下线。 +- MySQL `CDC Only` 和 `Snapshot + CDC` 任务会持续运行,直到手动下线。 +- PostgreSQL `Snapshot` 任务通常会在全量负载完成后自动下线。 +- PostgreSQL `CDC Only` 和 `Snapshot + CDC` 任务会持续运行,直到手动下线。 +- SQS (S3) 任务会持续轮询 SQS 队列,消费 S3 对象创建事件,并将数据写入目标表,直到手动下线。 +- Kafka Consumer 任务会持续消费 Kafka topic,并将消息内容保存到内部对象存储中,直到手动下线。 + +有关字段级配置和详细行为,请继续阅读相应的任务指南: + +- [Amazon S3 集成任务](/tidb-cloud-lake/guides/integrate-with-amazon-s3.md) +- [Amazon SQS (S3) 集成任务(Beta)](/tidb-cloud-lake/guides/integrate-with-amazon-sqs-s3.md) +- [MySQL Integration Task](/tidb-cloud-lake/guides/integrate-with-mysql.md) +- [PostgreSQL 集成任务](/tidb-cloud-lake/guides/integrate-with-postgresql.md) +- [Kafka Consumer Integration Task (Beta)](/tidb-cloud-lake/guides/integrate-with-kafka.md) diff --git a/tidb-cloud-lake/guides/tidb-cloud-lake-architecture.md b/tidb-cloud-lake/guides/tidb-cloud-lake-architecture.md new file mode 100644 index 0000000000000..368a6417339fa --- /dev/null +++ b/tidb-cloud-lake/guides/tidb-cloud-lake-architecture.md @@ -0,0 +1,49 @@ +--- +title: TiDB Cloud Lake Architecture +summary: TiDB Cloud Lake 架构。 +--- + +# TiDB Cloud Lake 架构 + +本文介绍 TiDB Cloud Lake 的架构。 + +![TiDB Cloud Lake Architecture](/media/tidb-cloud-lake/architecture.png) + + + +
+ +元信息服务是一个多租户服务,它将 {{{ .lake }}} 中每个租户的元信息存储在一个高可用的 Raft 集群中。这些元信息包括: + +- 表结构:包括每张表的字段结构和存储位置信息,为查询规划提供优化信息,并为存储层写入提供事务原子性保证; +- 集群管理:当每个租户的集群启动时,集群内的多个实例会注册为元信息,并为这些实例提供健康检查,以确保集群整体健康; +- 安全管理:保存用户、角色和权限授予信息,以确保数据访问认证和授权过程的安全性与可靠性。 + +
+ +
+ +存储与计算完全分离的架构赋予了 {{{ .lake }}} 独特的计算弹性。 + +{{{ .lake }}} 中的每个租户都可以拥有多个计算集群 (Warehouse),每个计算集群都具有独占的计算资源,并且在空闲超过 1 分钟后可以自动释放,以降低使用成本。 + +在计算集群中,查询通过高性能的 {{{ .lake }}} 引擎执行。每个查询都会经过多个不同的子模块: + +- Planner:在解析 SQL 语句后,它会根据不同的查询类型,将不同的运算符(如 Projection、Filter、Limit 等)组合成查询计划。 +- Optimizer:{{{ .lake }}} 引擎提供了一个基于规则和基于成本的优化器框架,实现了一系列优化机制,例如谓词下推、Join 重排序和扫描裁剪,从而大幅加速查询。 +- Processors:{{{ .lake }}} 实现了一个推拉结合的流水线执行引擎。它在 Processor 中将查询的物理执行组织为一系列流水线,并可根据查询任务的运行时信息动态调整流水线配置,结合向量化表达式计算框架,最大化 CPU 的计算能力。 + +此外,{{{ .lake }}} 还可以随着查询负载的变化动态增加或减少集群中的节点,使计算更快且更具成本效益。 + +
+ +
+ +{{{ .lake }}} 的存储层基于 FuseEngine,后者专为低成本对象存储而设计和优化。FuseEngine 根据对象存储的特性高效组织数据,从而实现高吞吐的数据写入和读取。 + +FuseEngine 以列式格式压缩数据并将其存储在对象存储中,这显著减少了数据量和存储成本。 + +除了存储数据文件外,FuseEngine 还会生成索引信息,包括 MinMax index、Bloomfilter index 等。这些索引可在查询执行期间减少 IO 和 CPU 消耗,从而大幅提升查询性能。 + +
+
\ No newline at end of file diff --git a/tidb-cloud-lake/guides/track-and-transform-data-via-streams.md b/tidb-cloud-lake/guides/track-and-transform-data-via-streams.md new file mode 100644 index 0000000000000..3386b4285385d --- /dev/null +++ b/tidb-cloud-lake/guides/track-and-transform-data-via-streams.md @@ -0,0 +1,243 @@ +--- +title: 通过 Streams 跟踪和转换数据 +summary: {{{ .lake }}} 中的 stream 是一种始终开启的变更表:每个已提交的 INSERT、UPDATE 或 DELETE 都会被捕获,直到你将其消费。本页保持简洁——先快速概览,再通过一个包含真实输出的实验帮助你直观了解 stream 的实际效果。 +--- + +# 通过 Streams 跟踪和转换数据 + +{{{ .lake }}} 中的 stream 是一种始终开启的变更表:每个已提交的 INSERT、UPDATE 或 DELETE 都会被捕获,直到你将其消费。本页保持简洁——先快速概览,再通过一个包含真实输出的实验帮助你直观了解 stream 的实际效果。 + +## Stream 概览 {#stream-overview} + +- Stream 不会复制表存储;在你消费之前,它会为每个受影响的行列出最新的变更。 +- 消费(task、INSERT ... SELECT、`WITH CONSUME` 等)会清空 stream,同时保持其可继续接收新数据。 +- `APPEND_ONLY` 默认为 `true`;仅当你必须捕获 UPDATE/DELETE 事件时,才将 `APPEND_ONLY = false`。 + +| 模式 | 捕获内容 | 典型用途 | +| --- | --- | --- | +| Standard (`APPEND_ONLY = false`) | INSERT + UPDATE + DELETE,并按每行折叠为最新状态。 | 缓慢变化维度、合规审计。 | +| Append-Only (`APPEND_ONLY = true`, default) | 仅 INSERT。 | 仅追加的事实/事件摄取。 | + +## 示例 1:Append-Only Stream {#example-1-append-only-stream} + +在任意 {{{ .lake }}} 部署(Cloud 工作区 (Worksheet) 或本地)中运行以下语句,查看默认 append-only 模式如何捕获并消费插入数据。 + +### 1. 创建表和 stream {#1-create-table-and-stream} + +```sql +CREATE OR REPLACE TABLE sensor_readings ( + sensor_id INT, + temperature DOUBLE +); + +-- APPEND_ONLY defaults to true, so no extra clause is required. +CREATE OR REPLACE STREAM sensor_readings_stream + ON TABLE sensor_readings; +``` + +### 2. 插入行并预览 {#2-insert-rows-and-preview} + +```sql +INSERT INTO sensor_readings VALUES (1, 21.5), (2, 19.7); + +SELECT sensor_id, temperature, change$action, change$is_update +FROM sensor_readings_stream; +``` + +输出: + +``` +┌────────────┬───────────────┬───────────────┬──────────────────┐ +│ sensor_id │ temperature │ change$action │ change$is_update │ +├────────────┼───────────────┼───────────────┼──────────────────┤ +│ 1 │ 21.5 │ INSERT │ false │ +│ 2 │ 19.7 │ INSERT │ false │ +└────────────┴───────────────┴───────────────┴──────────────────┘ +``` + +### 3. 消费(可选) {#3-consume-optional} + +```sql +SELECT sensor_id, temperature +FROM sensor_readings_stream WITH CONSUME; + +SELECT * FROM sensor_readings_stream; -- now empty +``` + +`WITH CONSUME` 会读取一次 stream 并清空增量,以便下一轮能够捕获新的 INSERT。 + +## 示例 2:Standard Stream(Updates 和 Deletes) {#example-2-standard-stream-updates-deletes} + +当你必须对每个变异作出响应(包括 UPDATE 或 DELETE)时,请切换到 Standard 模式。 + +### 1. 创建 Standard stream {#1-create-a-standard-stream} + +```sql +CREATE OR REPLACE STREAM sensor_readings_stream_std + ON TABLE sensor_readings + APPEND_ONLY = false; +``` + +### 2. 变异行并进行对比 {#2-mutate-rows-and-compare} + +```sql +DELETE FROM sensor_readings WHERE sensor_id = 1; -- remove old reading +INSERT INTO sensor_readings VALUES (1, 22); -- same sensor, new value +DELETE FROM sensor_readings WHERE sensor_id = 2; -- pure deletion +INSERT INTO sensor_readings VALUES (3, 18.5); -- brand-new sensor + +SELECT * FROM sensor_readings_stream; -- still empty (Append-Only ignores non-inserts) + +SELECT sensor_id, temperature, change$action, change$is_update +FROM sensor_readings_stream_std +ORDER BY change$row_id; +``` + +输出: + +``` +┌────────────┬───────────────┬───────────────┬──────────────────┐ +│ sensor_id │ temperature │ change$action │ change$is_update │ +├────────────┼───────────────┼───────────────┼──────────────────┤ +│ 1 │ 21.5 │ DELETE │ true │ +│ 1 │ 22 │ INSERT │ true │ +│ 2 │ 19.7 │ DELETE │ false │ +│ 3 │ 18.5 │ INSERT │ false │ +└────────────┴───────────────┴───────────────┴──────────────────┘ +``` + +Standard stream 会结合上下文捕获每次变更:修改会在同一个 `sensor_id` 上显示为 DELETE+INSERT,而独立的删除/插入则会分别单独显示。Append-Only stream 会保持为空,因为它只跟踪插入。 + +## 示例 3:增量 Stream Join {#example-3-incremental-stream-join} + +将多个 append-only stream 进行 join,以生成增量 KPI。由于 {{{ .lake }}} stream 会在数据被消费前一直保留新行,因此你可以在每次负载后运行同一个查询。每次执行都只会通过 [`WITH CONSUME`](/tidb-cloud-lake/sql/with-consume.md) 提取新的行,因此即使修改在不同时间到达,也仍会在下一次迭代中完成匹配。 + +### 1. 创建表和 stream {#1-create-tables-and-streams} + +```sql +CREATE OR REPLACE TABLE customers ( + customer_id INT, + segment VARCHAR, + city VARCHAR +); + +CREATE OR REPLACE TABLE orders ( + order_id INT, + customer_id INT, + amount DOUBLE +); + +CREATE OR REPLACE STREAM customers_stream ON TABLE customers; +CREATE OR REPLACE STREAM orders_stream ON TABLE orders; +``` + +### 2. 加载第一批数据 {#2-load-the-first-batch} + +```sql +INSERT INTO customers VALUES + (101, 'VIP', 'Seattle'), + (102, 'Standard', 'Austin'), + (103, 'VIP', 'Austin'); + +INSERT INTO orders VALUES + (5001, 101, 199.0), + (5002, 101, 59.0), + (5003, 102, 89.0); +``` + +### 3. 运行第一次增量查询 {#3-run-the-first-incremental-query} + +```sql +WITH + orders_delta AS ( + SELECT customer_id, amount + FROM orders_stream WITH CONSUME + ), + customers_delta AS ( + SELECT customer_id, segment + FROM customers_stream WITH CONSUME + ) +SELECT + o.customer_id, + c.segment, + SUM(o.amount) AS incremental_sales +FROM orders_delta AS o +JOIN customers_delta AS c + ON o.customer_id = c.customer_id +GROUP BY o.customer_id, c.segment +ORDER BY o.customer_id; +``` + +``` +┌──────────────┬───────────┬────────────────────┐ +│ customer_id │ segment │ incremental_sales │ +├──────────────┼───────────┼────────────────────┤ +│ 101 │ VIP │ 258.0 │ +│ 102 │ Standard │ 89.0 │ +└──────────────┴───────────┴────────────────────┘ +``` + +这些 stream 现在已为空。当有更多行到达时,同一个查询将只捕获新数据。 + +### 4. 在下一批数据到达后再次运行 {#4-run-again-after-the-next-batch} + +```sql +-- New data arrives later +INSERT INTO customers VALUES (104, 'Standard', 'Denver'); +INSERT INTO orders VALUES + (5004, 101, 40.0), + (5005, 104, 120.0); + +-- Same incremental query as before +WITH + orders_delta AS ( + SELECT customer_id, amount + FROM orders_stream WITH CONSUME + ), + customers_delta AS ( + SELECT customer_id, segment + FROM customers_stream WITH CONSUME + ) +SELECT + o.customer_id, + c.segment, + SUM(o.amount) AS incremental_sales +FROM orders_delta AS o +JOIN customers_delta AS c + ON o.customer_id = c.customer_id +GROUP BY o.customer_id, c.segment +ORDER BY o.customer_id; +``` + +``` +┌──────────────┬───────────┬────────────────────┐ +│ customer_id │ segment │ incremental_sales │ +├──────────────┼───────────┼────────────────────┤ +│ 101 │ VIP │ 40.0 │ +│ 104 │ Standard │ 120.0 │ +└──────────────┴───────────┴────────────────────┘ +``` + +每个 stream 中的行会一直保留,直到运行 `WITH CONSUME`,因此即使插入在不同时间到达,也仍然会在下一次运行时被匹配到。当你预计还会有更多相关行到达时,可以先不消费这些 stream,然后重新运行查询以获取增量 delta。 + +## Stream 工作流说明 {#stream-workflow-notes} + +**消费** + +- Stream 会在事务内部被清空:`INSERT INTO target SELECT ... FROM stream` 只有在语句提交时才会清空 stream。 +- 同一时间只能有一个消费者成功;其他并发语句会回滚。 + +**模式** + +- Append-Only stream 仅捕获 INSERT,适合以追加为主的负载。 +- Standard stream 会在你消费它们期间输出 update 和 delete;延迟到达的 update 会保留到下一次运行。 + +**隐藏列** + +- Stream 会暴露 `change$action`、`change$is_update` 和 `change$row_id`;你可以使用它们来了解 {{{ .lake }}} 如何记录每一行。 +- 基表会增加 `_origin_version`、`_origin_block_id`、`_origin_block_row_num`,用于调试行来源。 + +**集成** + +- 将 stream 与 task 结合使用,并通过 `task_history('', )` 实现按调度执行的增量 load。 +- 当你只想清空最新的增量 delta 时,使用 [`WITH CONSUME`](/tidb-cloud-lake/sql/task.md)。 diff --git a/tidb-cloud-lake/guides/transform-data-on-load.md b/tidb-cloud-lake/guides/transform-data-on-load.md new file mode 100644 index 0000000000000..069f81be7bd82 --- /dev/null +++ b/tidb-cloud-lake/guides/transform-data-on-load.md @@ -0,0 +1,257 @@ +--- +title: 加载时转换数据 +summary: "{{{ .lake }}} 的 `COPY INTO` 命令支持在加载过程中进行数据转换。通过集成基础转换能力,它可以简化你的 ETL 流水线,并免去使用临时表的需求。" +--- + +# 加载时转换数据 + +{{{ .lake }}} 的 `COPY INTO` 命令支持在加载过程中进行数据转换。通过集成基础转换能力,它可以简化你的 ETL 流水线,并免去使用临时表的需求。 + +语法请参见 [查询与转换]( /tidb-cloud-lake/guides/query-stage.md)。 + +你可以执行的关键转换包括: + +- **加载部分数据列**:有选择地导入特定列。 +- **重排列顺序**:在加载过程中调整列顺序。 +- **转换数据类型**:确保一致性和兼容性。 +- **执行算术运算**:生成新的派生数据。 +- **将数据加载到包含额外列的表中**:将数据映射并插入到现有结构中。 + +## 教程 {#tutorials} + +以下教程演示了如何在加载过程中进行数据转换。每个示例都展示了如何从 staged file 加载数据。 + +### 开始之前 {#before-you-begin} + +创建一个 stage 并生成一个示例 Parquet 文件: + +```sql +CREATE STAGE my_parquet_stage; +COPY INTO @my_parquet_stage +FROM ( + SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS id, + 'Name_' || CAST(number AS VARCHAR) AS name, + 20 + MOD(number, 23) AS age, + DATE_ADD('day', MOD(number, 60), '2022-01-01') AS onboarded + FROM numbers(10) +) +FILE_FORMAT = (TYPE = PARQUET); +``` + +查询 stage 中的示例文件: + +```sql +SELECT * FROM @my_parquet_stage; +``` + +结果: + +``` +┌───────────────────────────────────────┐ +│ id │ name │ age │ onboarded │ +├────────┼────────┼────────┼────────────┤ +│ 1 │ Name_0 │ 20 │ 2022-01-01 │ +│ 2 │ Name_5 │ 25 │ 2022-01-06 │ +│ 3 │ Name_1 │ 21 │ 2022-01-02 │ +│ 4 │ Name_6 │ 26 │ 2022-01-07 │ +│ 5 │ Name_7 │ 27 │ 2022-01-08 │ +│ 6 │ Name_2 │ 22 │ 2022-01-03 │ +│ 7 │ Name_8 │ 28 │ 2022-01-09 │ +│ 8 │ Name_3 │ 23 │ 2022-01-04 │ +│ 9 │ Name_4 │ 24 │ 2022-01-05 │ +│ 10 │ Name_9 │ 29 │ 2022-01-10 │ +└───────────────────────────────────────┘ +``` + +### 教程 1 - 加载部分数据列 {#tutorial-1-loading-a-subset-of-data-columns} + +将数据加载到一个列数少于源文件的表中(例如,不包含 `age` 列)。 + +```sql +CREATE TABLE employees_no_age ( + id INT, + name VARCHAR, + onboarded timestamp +); + +COPY INTO employees_no_age +FROM ( + SELECT t.id, + t.name, + t.onboarded + FROM @my_parquet_stage t +) +FILE_FORMAT = (TYPE = PARQUET) +PATTERN = '.*parquet'; + +SELECT * FROM employees_no_age; +``` + +结果(前 3 行): + +``` +┌──────────────────────────────────────────────────────────┐ +│ id │ name │ onboarded │ +├─────────────────┼──────────────────┼─────────────────────┤ +│ 1 │ Name_0 │ 2022-01-01 00:00:00 │ +│ 2 │ Name_5 │ 2022-01-06 00:00:00 │ +│ 3 │ Name_1 │ 2022-01-02 00:00:00 │ +└──────────────────────────────────────────────────────────┘ +``` + +### 教程 2 - 加载时重排列顺序 {#tutorial-2-reordering-columns-during-load} + +将数据加载到一个列顺序与源文件不同的表中(例如,将 `age` 放在 `name` 前面)。 + +```sql +CREATE TABLE employees_new_order ( + id INT, + age INT, + name VARCHAR, + onboarded timestamp +); + +COPY INTO employees_new_order +FROM ( + SELECT + t.id, + t.age, + t.name, + t.onboarded + FROM @my_parquet_stage t +) +FILE_FORMAT = (TYPE = PARQUET) +PATTERN = '.*parquet'; + +SELECT * FROM employees_new_order; +``` + +结果(前 3 行): + +``` +┌────────────────────────────────────────────────────────────────────────────┐ +│ id │ age │ name │ onboarded │ +├─────────────────┼─────────────────┼──────────────────┼─────────────────────┤ +│ 1 │ 20 │ Name_0 │ 2022-01-01 00:00:00 │ +│ 2 │ 25 │ Name_5 │ 2022-01-06 00:00:00 │ +│ 3 │ 21 │ Name_1 │ 2022-01-02 00:00:00 │ +└────────────────────────────────────────────────────────────────────────────┘ +``` + +### 教程 3 - 加载时转换数据类型 {#tutorial-3-converting-datatypes-during-load} + +加载数据时转换某一列的数据类型(例如,将 `onboarded` 转换为 `DATE`)。 + +```sql +CREATE TABLE employees_date ( + id INT, + name VARCHAR, + age INT, + onboarded date +); + +COPY INTO employees_date +FROM ( + SELECT + t.id, + t.name, + t.age, + to_date(t.onboarded) + FROM @my_parquet_stage t +) +FILE_FORMAT = (TYPE = PARQUET) +PATTERN = '.*parquet'; + +SELECT * FROM employees_date; +``` + +结果(前 3 行): + +``` +┌───────────────────────────────────────────────────────────────────────┐ +│ id │ name │ age │ onboarded │ +├─────────────────┼──────────────────┼─────────────────┼────────────────┤ +│ 1 │ Name_0 │ 20 │ 2022-01-01 │ +│ 2 │ Name_5 │ 25 │ 2022-01-06 │ +│ 3 │ Name_1 │ 21 │ 2022-01-02 │ +└───────────────────────────────────────────────────────────────────────┘ +``` + +### 教程 4 - 在加载期间执行算术运算 {#tutorial-4-performing-arithmetic-operations-during-load} + +加载数据并执行算术运算(例如,将 `age` 加 1)。 + +```sql +CREATE TABLE employees_new_age ( + id INT, + name VARCHAR, + age INT, + onboarded timestamp +); + +COPY INTO employees_new_age +FROM ( + SELECT + t.id, + t.name, + t.age + 1, + t.onboarded + FROM @my_parquet_stage t +) +FILE_FORMAT = (TYPE = PARQUET) +PATTERN = '.*parquet'; + +SELECT * FROM employees_new_age; +``` + +结果(前 3 行): + +``` +┌────────────────────────────────────────────────────────────────────────────┐ +│ id │ name │ age │ onboarded │ +├─────────────────┼──────────────────┼─────────────────┼─────────────────────┤ +│ 1 │ Name_0 │ 21 │ 2022-01-01 00:00:00 │ +│ 2 │ Name_5 │ 26 │ 2022-01-06 00:00:00 │ +│ 3 │ Name_1 │ 22 │ 2022-01-02 00:00:00 │ +└────────────────────────────────────────────────────────────────────────────┘ +``` + +### 教程 5 - 加载到包含附加列的表中 {#tutorial-5-loading-to-a-table-with-additional-columns} + +将数据加载到一个列数多于源文件的表中。 + +```sql +CREATE TABLE employees_plus ( + id INT, + name VARCHAR, + age INT, + onboarded timestamp, + lastday timestamp +); + +COPY INTO employees_plus (id, name, age, onboarded) +FROM ( + SELECT + t.id, + t.name, + t.age, + t.onboarded + FROM @my_parquet_stage t +) +FILE_FORMAT = (TYPE = PARQUET) +PATTERN = '.*parquet'; + +SELECT * FROM employees_plus; +``` + +结果(前 3 行): + +``` +┌──────────────────────────────────────────────────────────────────────────────────────────────────┐ +│ id │ name │ age │ onboarded │ lastday │ +├─────────────────┼──────────────────┼─────────────────┼─────────────────────┼─────────────────────┤ +│ 1 │ Name_0 │ 20 │ 2022-01-01 00:00:00 │ NULL │ +│ 2 │ Name_5 │ 25 │ 2022-01-06 00:00:00 │ NULL │ +│ 3 │ Name_1 │ 21 │ 2022-01-02 00:00:00 │ NULL │ +└──────────────────────────────────────────────────────────────────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/guides/troubleshooting.md b/tidb-cloud-lake/guides/troubleshooting.md new file mode 100644 index 0000000000000..fa73c46cc5980 --- /dev/null +++ b/tidb-cloud-lake/guides/troubleshooting.md @@ -0,0 +1,167 @@ +--- +title: 故障排查 +summary: 本页介绍如何对 TiDB Cloud Lake 中的常见问题进行故障排查。 +--- + +# 故障排查 + +使用 `system_history` 表诊断慢查询、错误、资源使用情况和登录问题。使用 `profile_history` 进行按操作符的执行分析(CPU 时间、I/O、spill、输出行数)。所有表都按租户隔离。 + +## 表 {#tables} + +### system_history.query_history {#system-history-query-history} + +完整的 SQL 执行审计轨迹。每个查询都会生成包含开始/结束状态的记录。 + +| 字段 | 类型 | 描述 | +|-------|------|-------------| +| log_type | TINYINT | 查询状态:1=Start,2=Finish,3=Error,4=Aborted,5=Closed | +| log_type_name | VARCHAR | 字符串名称:"Start"、"Finish"、"Error"、"Aborted"、"Closed" | +| handler_type | VARCHAR | 使用的协议(例如 `HTTPQuery`、`MySQL`) | +| tenant_id | VARCHAR | 租户标识符 | +| cluster_id | VARCHAR | 集群标识符 | +| node_id | VARCHAR | 节点标识符 | +| sql_user | VARCHAR | 执行查询的用户 | +| sql_user_quota | VARCHAR | 用户配额信息 | +| sql_user_privileges | VARCHAR | 用户权限 | +| query_id | VARCHAR | 唯一查询标识符 | +| query_kind | VARCHAR | 查询类型(例如 `Query`、`Insert`、`CopyIntoTable`) | +| query_text | VARCHAR | 查询的 SQL 文本 | +| query_hash | VARCHAR | 查询文本的哈希值 | +| query_parameterized_hash | VARCHAR | 忽略字面量值后的哈希值 | +| event_date | DATE | 事件日期 | +| event_time | TIMESTAMP | 事件时间戳 | +| query_start_time | TIMESTAMP | 查询开始时间戳 | +| query_duration_ms | BIGINT | 总耗时(毫秒,包含排队和执行) | +| query_queued_duration_ms | BIGINT | 排队耗时(毫秒) | +| current_database | VARCHAR | 当前使用的数据库 | +| written_rows | BIGINT UNSIGNED | 写入的行数 | +| written_bytes | BIGINT UNSIGNED | 写入的字节数 | +| join_spilled_rows | BIGINT UNSIGNED | Join 期间 spill 的行数 | +| join_spilled_bytes | BIGINT UNSIGNED | Join 期间 spill 的字节数 | +| agg_spilled_rows | BIGINT UNSIGNED | 聚合期间 spill 的行数 | +| agg_spilled_bytes | BIGINT UNSIGNED | 聚合期间 spill 的字节数 | +| group_by_spilled_rows | BIGINT UNSIGNED | Group By 期间 spill 的行数 | +| group_by_spilled_bytes | BIGINT UNSIGNED | Group By 期间 spill 的字节数 | +| written_io_bytes | BIGINT UNSIGNED | 写入到 IO 的字节数 | +| written_io_bytes_cost_ms | BIGINT UNSIGNED | IO 写入耗时(毫秒) | +| scan_rows | BIGINT UNSIGNED | 扫描的行数 | +| scan_bytes | BIGINT UNSIGNED | 扫描的字节数 | +| scan_io_bytes | BIGINT UNSIGNED | 扫描期间读取的 IO 字节数 | +| scan_io_bytes_cost_ms | BIGINT UNSIGNED | IO 扫描耗时(毫秒) | +| scan_partitions | BIGINT UNSIGNED | 扫描的分区数 | +| total_partitions | BIGINT UNSIGNED | 涉及的分区总数 | +| result_rows | BIGINT UNSIGNED | 结果中的行数 | +| result_bytes | BIGINT UNSIGNED | 结果中的字节数 | +| bytes_from_remote_disk | BIGINT UNSIGNED | 从远程磁盘读取的字节数 | +| bytes_from_local_disk | BIGINT UNSIGNED | 从本地磁盘读取的字节数 | +| bytes_from_memory | BIGINT UNSIGNED | 从内存读取的字节数 | +| client_address | VARCHAR | 客户端地址 | +| user_agent | VARCHAR | 客户端 user agent | +| exception_code | INT | 异常代码(0 = 成功) | +| exception_text | VARCHAR | 异常消息 | +| server_version | VARCHAR | 服务器版本 | +| query_tag | VARCHAR | 查询标签 | +| has_profile | BOOLEAN | 查询是否具有执行 profile | +| peek_memory_usage | VARIANT | 峰值内存使用量(JSON) | +| session_id | VARCHAR | 会话标识符 | +| session_settings | VARCHAR | 会话设置 | + +### system_history.profile_history {#system-history-profile-history} + +每个查询的详细执行 profile。使用 `jq()` 提取按操作符统计的信息。 + +| 字段 | 类型 | 描述 | +|-------|------|-------------| +| timestamp | TIMESTAMP | 记录 profile 的时间 | +| query_id | VARCHAR | 查询 ID | +| profiles | VARIANT | 操作符的 JSON 数组,每个元素包含 `id`、`name`、`statistics[]` | +| statistics_desc | VARIANT | 描述统计信息格式的 JSON | + +统计数组索引:`[0]`=OutputRows,`[1]`=OutputBytes,`[2]`=InputRows,`[3]`=InputBytes,`[4]`=CpuTime(ns)。 + +### system_history.log_history {#system-history-log-history} + +来自所有 {{{ .lake }}} 节点和组件的原始日志条目。 + +| 字段 | 类型 | 描述 | +|-------|------|-------------| +| timestamp | TIMESTAMP | 日志条目的时间戳 | +| path | VARCHAR | 源文件路径和行号 | +| target | VARCHAR | 目标模块或组件 | +| log_level | VARCHAR | 日志等级(`INFO`、`ERROR`、`WARN` 等) | +| cluster_id | VARCHAR | 集群标识符 | +| node_id | VARCHAR | 节点标识符 | +| warehouse_id | VARCHAR | 计算集群 (Warehouse) 标识符 | +| query_id | VARCHAR | 关联的查询 ID | +| message | VARCHAR | 日志消息(纯文本) | +| fields | VARIANT | 附加字段(JSON) | +| batch_number | BIGINT | 内部使用 | + +### system_history.access_history {#system-history-access-history} + +数据血缘和访问控制审计。跟踪所有被访问或修改的对象。 + +| 字段 | 类型 | 描述 | +|-------|------|-------------| +| query_id | VARCHAR | 查询 ID | +| query_start | TIMESTAMP | 查询开始时间 | +| user_name | VARCHAR | 执行查询的用户 | +| base_objects_accessed | VARIANT | 被访问的对象(JSON 数组) | +| direct_objects_accessed | VARIANT | 预留供未来使用 | +| objects_modified | VARIANT | 被 DML 修改的对象(JSON 数组) | +| object_modified_by_ddl | VARIANT | 被 DDL 修改的对象(JSON 数组) | + +JSON 对象字段:`object_domain`(Database/Table/Stage)、`object_name`、`columns[]`、`stage_type`、`operation_type`(Create/Alter/Drop/Undrop)、`properties`。 + +### system_history.login_history {#system-history-login-history} + +所有登录尝试的身份验证审计轨迹。 + +| 字段 | 类型 | 描述 | +|-------|------|-------------| +| event_time | TIMESTAMP | 登录事件时间戳 | +| handler | VARCHAR | 协议(例如 `HTTP`、`MySQL`) | +| event_type | VARCHAR | `LoginSuccess` 或 `LoginFailed` | +| connection_uri | VARCHAR | 连接 URI | +| auth_type | VARCHAR | 身份验证方法(例如 Password) | +| user_name | VARCHAR | 尝试登录的用户 | +| client_ip | VARCHAR | 客户端 IP 地址 | +| user_agent | VARCHAR | 客户端用户代理 | +| session_id | VARCHAR | 会话 ID | +| node_id | VARCHAR | 节点 ID | +| error_message | VARCHAR | 失败时的错误消息 | + +## 快速示例 {#quick-examples} + +查找最近一小时内的慢查询(>5s): + +```sql +SELECT query_id, sql_user, query_duration_ms, query_text +FROM system_history.query_history +WHERE query_duration_ms > 5000 + AND event_time > now() - INTERVAL 1 HOUR + AND log_type = 2 +ORDER BY query_duration_ms DESC +LIMIT 20; +``` + +查找失败的查询: + +```sql +SELECT query_id, sql_user, exception_code, exception_text, query_text +FROM system_history.query_history +WHERE exception_code != 0 + AND event_time > now() - INTERVAL 1 HOUR +ORDER BY event_time DESC; +``` + +检查登录失败: + +```sql +SELECT event_time, user_name, client_ip, error_message +FROM system_history.login_history +WHERE event_type = 'LoginFailed' + AND event_time > now() - INTERVAL 24 HOUR +ORDER BY event_time DESC; +``` diff --git a/tidb-cloud-lake/guides/unload-csv-file.md b/tidb-cloud-lake/guides/unload-csv-file.md new file mode 100644 index 0000000000000..500435a9ea6ac --- /dev/null +++ b/tidb-cloud-lake/guides/unload-csv-file.md @@ -0,0 +1,96 @@ +--- +title: 卸载 CSV 文件 +summary: 了解如何卸载 CSV 文件。 +--- + +# 卸载 CSV 文件 + +本页介绍如何使用 `COPY INTO` 命令卸载 CSV 文件。 + +## 语法 {#syntax} + +```sql +COPY INTO { internalStage | externalStage | externalLocation } +FROM { [.] | ( ) } +FILE_FORMAT = ( + TYPE = CSV, + RECORD_DELIMITER = '', + FIELD_DELIMITER = '', + COMPRESSION = gzip, + OUTPUT_HEADER = true -- Unload with header +) +[MAX_FILE_SIZE = ] +[DETAILED_OUTPUT = true | false] +``` + +- 更多 CSV 选项,请参见 [CSV 文件格式选项](/tidb-cloud-lake/sql/input-output-file-formats.md#csv-options) +- 卸载到多个文件时,请使用 [`MAX_FILE_SIZE` Copy 选项](/tidb-cloud-lake/sql/copy-into-location.md#copyoptions) +- 有关该语法的更多详细信息,请参见 [COPY INTO location](/tidb-cloud-lake/sql/copy-into-location.md) + +## 教程 {#tutorial} + +### 步骤 1:创建 External Stage {#step-1-create-an-external-stage} + +```sql +CREATE STAGE csv_unload_stage +URL = 's3://unload/csv/' +CONNECTION = ( + ACCESS_KEY_ID = '' + SECRET_ACCESS_KEY = '' +); +``` + +### 步骤 2:创建自定义 CSV 文件格式 {#step-2-create-custom-csv-file-format} + +```sql +CREATE FILE FORMAT csv_unload_format + TYPE = CSV, + RECORD_DELIMITER = '\n', + FIELD_DELIMITER = ',', + COMPRESSION = gzip, -- Unload with gzip compression + OUTPUT_HEADER = true, -- Unload with header + SKIP_HEADER = 1; -- Only for loading, skip first line when querying if the CSV file has header +``` + +### 步骤 3:卸载到 CSV 文件 {#step-3-unload-into-csv-file} + +```sql +COPY INTO @csv_unload_stage +FROM ( + SELECT * + FROM generate_series(1, 100) +) +FILE_FORMAT = (FORMAT_NAME = 'csv_unload_format') +DETAILED_OUTPUT = true; +``` + +结果: + +```text +┌──────────────────────────────────────────────────────────────────────────────────────────┐ +│ file_name │ file_size │ row_count │ +├──────────────────────────────────────────────────────────────────┼───────────┼───────────┤ +│ data_c8382216-0a04-4920-9eca-7b5debe3eed6_0000_00000000.csv.gz │ 187 │ 100 │ +└──────────────────────────────────────────────────────────────────────────────────────────┘ +``` + +### 步骤 4:验证已卸载的 CSV 文件 {#step-4-verify-the-unloaded-csv-files} + +```sql +SELECT COUNT($1) +FROM @csv_unload_stage +( + FILE_FORMAT => 'csv_unload_format', + PATTERN => '.*[.]csv[.]gz' +); +``` + +结果: + +```text +┌───────────┐ +│ count($1) │ +├───────────┤ +│ 100 │ +└───────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/guides/unload-data.md b/tidb-cloud-lake/guides/unload-data.md new file mode 100644 index 0000000000000..a43cbe5b806ff --- /dev/null +++ b/tidb-cloud-lake/guides/unload-data.md @@ -0,0 +1,25 @@ +--- +title: 从 TiDB Cloud Lake 卸载数据 +summary: 了解如何使用 `COPY INTO` 命令将 TiDB Cloud Lake 中的数据卸载为多种文件格式,并导出到不同的存储目标。 +--- + +# 从 TiDB Cloud Lake 卸载数据 + +{{{ .lake }}} 的 `COPY INTO` 命令支持将数据导出为多种文件格式,并写入不同的存储位置,同时提供灵活的格式化选项。 + +## 支持的文件格式 {#supported-file-formats} + +| 格式 | 示例语法 | 主要使用场景 | +|--------|---------------|------------------| +| [**卸载 Parquet 文件**](/tidb-cloud-lake/guides/unload-parquet-file.md) | `FILE_FORMAT = (TYPE = PARQUET)` | 分析型工作负载,高效存储 | +| [**卸载 CSV 文件**](/tidb-cloud-lake/guides/unload-csv-file.md) | `FILE_FORMAT = (TYPE = CSV)` | 数据交换,通用兼容性 | +| [**卸载 TSV 文件**](/tidb-cloud-lake/guides/unload-tsv-file.md) | `FILE_FORMAT = (TYPE = TSV)` | 带逗号值的表格数据 | +| [**卸载 NDJSON 文件**](/tidb-cloud-lake/guides/unload-ndjson-file.md) | `FILE_FORMAT = (TYPE = NDJSON)` | 半结构化数据,灵活 schema | +| [**卸载 Lance 数据集**](/tidb-cloud-lake/guides/unload-lance-dataset.md) | `FILE_FORMAT = (TYPE = LANCE)` | 机器学习和向量工作负载,Arrow/Lance 使用方 | + +## 存储目标 {#storage-destinations} + +| 目标 | 示例 | 适用场景 | +|-------------|---------|-------------| +| **命名 stage** | `COPY INTO my_stage FROM my_table` | 适用于重复导出到同一位置的场景 | +| **S3 兼容存储** | `COPY INTO 's3://bucket/path/' FROM my_table` | 使用 Amazon S3 的云对象存储 | \ No newline at end of file diff --git a/tidb-cloud-lake/guides/unload-lance-dataset.md b/tidb-cloud-lake/guides/unload-lance-dataset.md new file mode 100644 index 0000000000000..c30a86f1287fc --- /dev/null +++ b/tidb-cloud-lake/guides/unload-lance-dataset.md @@ -0,0 +1,180 @@ +--- +title: 卸载 Lance Dataset +summary: 了解如何卸载 Lance dataset。 +--- + +## 卸载 Lance Dataset {#unloading-lance-dataset} + +Lance 导出面向以 dataset 为中心的使用者,例如机器学习和向量工作流。与 CSV、TSV、NDJSON 或 Parquet 卸载不同,{{{ .lake }}} 会写入一个 Lance **dataset directory**,其中包含 `.lance` 数据文件以及诸如 `_versions/` 之类的元信息。 + +语法: + +```sql +COPY INTO { internalStage | externalStage | externalLocation } +FROM { [.] | ( ) } +FILE_FORMAT = (TYPE = LANCE) +[MAX_FILE_SIZE = ] +[USE_RAW_PATH = true | false] +[OVERWRITE = true | false] +[DETAILED_OUTPUT = true | false] +``` + +- Lance 仅支持用于 `COPY INTO `。 +- Lance 不支持 `SINGLE` 和 `PARTITION BY`。 +- 当 `USE_RAW_PATH = false`(默认值)时,{{{ .lake }}} 会将查询 ID 追加到目标路径,因此每次导出都会获得各自独立的 dataset 根目录。 +- 如果你希望为下游读者(例如 Python `lance`)提供稳定的 dataset URI,请设置 `USE_RAW_PATH = true`。 +- 有关语法的更多详细信息,请参见 [COPY INTO location](/tidb-cloud-lake/sql/copy-into-location.md)。 +- 更多 Lance 行为说明列在 [输入与输出文件格式](/tidb-cloud-lake/sql/input-output-file-formats.md#lance-options) 中。 + +## 教程 {#tutorial} + +本示例将构建一个小型文档分类 dataset。原始文本文件存储在一个 stage 中,`READ_FILE` 会在查询执行期间将它们转换为 `BINARY` 值,而 {{{ .lake }}} 会以 Lance 格式导出最终的 dataset,供 Python 使用者使用。 + +### 前提条件 {#prerequisites} + +准备一个 S3-compatible 存储桶,并确保 {{{ .lake }}} 和你的 Python 环境都可以访问它。 + +### 第 1 步:创建 External Stage {#step-1-create-an-external-stage} + +```sql +CREATE OR REPLACE STAGE ml_assets +URL = 's3://your-bucket/lance-demo/' +CONNECTION = ( + ENDPOINT_URL = '', + ACCESS_KEY_ID = '', + SECRET_ACCESS_KEY = '', + REGION = '' +); +``` + +### 第 2 步:创建示例源文件 {#step-2-create-sample-source-files} + +在该 stage 中创建三个原始文本文件: + +```sql +COPY INTO @ml_assets/raw/ticket_001.txt +FROM (SELECT 'customer asked for a refund after the package arrived damaged') +FILE_FORMAT = (TYPE = CSV FIELD_DELIMITER = '|' RECORD_DELIMITER = '\n') +SINGLE = TRUE +USE_RAW_PATH = TRUE +OVERWRITE = TRUE; + +COPY INTO @ml_assets/raw/ticket_002.txt +FROM (SELECT 'customer praised the fast response and confirmed the issue was resolved') +FILE_FORMAT = (TYPE = CSV FIELD_DELIMITER = '|' RECORD_DELIMITER = '\n') +SINGLE = TRUE +USE_RAW_PATH = TRUE +OVERWRITE = TRUE; + +COPY INTO @ml_assets/raw/ticket_003.txt +FROM (SELECT 'customer requested escalation because the replacement order was delayed') +FILE_FORMAT = (TYPE = CSV FIELD_DELIMITER = '|' RECORD_DELIMITER = '\n') +SINGLE = TRUE +USE_RAW_PATH = TRUE +OVERWRITE = TRUE; +``` + +### 第 3 步:创建清单表 {#step-3-create-a-manifest-table} + +```sql +CREATE OR REPLACE TABLE support_ticket_manifest ( + ticket_id INT, + label STRING, + file_path STRING +); + +INSERT INTO support_ticket_manifest VALUES + (1, 'refund', 'raw/ticket_001.txt'), + (2, 'resolved', 'raw/ticket_002.txt'), + (3, 'escalation', 'raw/ticket_003.txt'); +``` + +### 第 4 步:将 dataset 导出为 Lance {#step-4-export-the-dataset-to-lance} + +`READ_FILE` 会将 stage 中的文本文件读取为原始字节。然后,`COPY INTO` 会将这些行写入 Lance dataset: + +```sql +COPY INTO @ml_assets/datasets/support-ticket-train +FROM ( + SELECT + ticket_id, + label, + file_path, + READ_FILE('@ml_assets', file_path) AS content + FROM support_ticket_manifest + ORDER BY ticket_id +) +FILE_FORMAT = (TYPE = LANCE) +USE_RAW_PATH = TRUE +OVERWRITE = TRUE +DETAILED_OUTPUT = TRUE; +``` + +结果: + +```text +┌───────────────────────────────────────────────────────────────┐ +│ file_name │ file_size │ row_count │ +├────────────────────────────────────┼───────────┼─────────────┤ +│ datasets/support-ticket-train │ ... │ 3 │ +└───────────────────────────────────────────────────────────────┘ +``` + +### 第 5 步:检查导出的 dataset 布局 {#step-5-inspect-the-exported-dataset-layout} + +```sql +LIST @ml_assets/datasets/support-ticket-train; +``` + +你将看到一个 dataset 目录,其中包含类似以下的路径: + +```text +datasets/support-ticket-train/_versions/... +datasets/support-ticket-train/data/... .lance +datasets/support-ticket-train/*.manifest +``` + +### 第 6 步:使用 Python `lance` 验证 {#step-6-verify-with-python-lance} + +安装 Python 包: + +```bash +pip install pylance +``` + +从同一个对象存储位置读取导出的 dataset: + +```python +import os +import lance + +storage_options = { + "aws_access_key_id": os.environ["AWS_ACCESS_KEY_ID"], + "aws_secret_access_key": os.environ["AWS_SECRET_ACCESS_KEY"], + "region": os.environ.get("AWS_REGION", "us-east-1"), +} + +if endpoint := os.environ.get("AWS_ENDPOINT_URL"): + storage_options["aws_endpoint"] = endpoint + storage_options["aws_allow_http"] = "true" if endpoint.startswith("http://") else "false" + +dataset = lance.dataset( + "s3://your-bucket/lance-demo/datasets/support-ticket-train", + storage_options=storage_options, +) + +table = dataset.to_table() +print(table.num_rows) +print(table["label"].to_pylist()) +print(table["content"].to_pylist()[0].decode("utf-8").strip()) +``` + +预期输出: + +```text +3 +['refund', 'resolved', 'escalation'] +customer asked for a refund after the package arrived damaged +``` + +至此,你已经拥有一个完整的 Lance dataset,它将标签、原始路径和原始文件字节保存在一起,便于下游 ML 处理。 \ No newline at end of file diff --git a/tidb-cloud-lake/guides/unload-ndjson-file.md b/tidb-cloud-lake/guides/unload-ndjson-file.md new file mode 100644 index 0000000000000..dc8f0857dd087 --- /dev/null +++ b/tidb-cloud-lake/guides/unload-ndjson-file.md @@ -0,0 +1,90 @@ +--- +title: 卸载 NDJSON 文件 +summary: 了解如何卸载 NDJSON 文件。 +--- + +# 卸载 NDJSON 文件 + +## 卸载 TSV 文件 {#unloading-tsv-file} + +语法: + +```sql +COPY INTO { internalStage | externalStage | externalLocation } +FROM { [.] | ( ) } +FILE_FORMAT = ( + TYPE = NDJSON, + COMPRESSION = gzip, + OUTPUT_HEADER = true +) +[MAX_FILE_SIZE = ] +[DETAILED_OUTPUT = true | false] +``` + +- 更多 NDJSON 选项,请参见 [NDJSON 文件格式选项](/tidb-cloud-lake/sql/input-output-file-formats.md#ndjson-options) +- 使用 [`MAX_FILE_SIZE` Copy 选项](/tidb-cloud-lake/sql/copy-into-location.md#copyoptions) 可将数据卸载到多个文件中 +- 有关该语法的更多详细信息,请参见 [COPY INTO location](/tidb-cloud-lake/sql/copy-into-location.md) + +## 教程 {#tutorial} + +### 第 1 步:创建 External Stage {#step-1-create-an-external-stage} + +```sql +CREATE STAGE ndjson_unload_stage +URL = 's3://unload/ndjson/' +CONNECTION = ( + ACCESS_KEY_ID = '' + SECRET_ACCESS_KEY = '' +); +``` + +### 第 2 步:创建自定义 NDJSON 文件格式 {#step-2-create-custom-ndjson-file-format} + +``` +CREATE FILE FORMAT ndjson_unload_format + TYPE = NDJSON, + COMPRESSION = gzip; -- Unload with gzip compression +``` + +### 第 3 步:卸载到 NDJSON 文件 {#step-3-unload-into-ndjson-file} + +```sql +COPY INTO @ndjson_unload_stage +FROM ( + SELECT * + FROM generate_series(1, 100) +) +FILE_FORMAT = (FORMAT_NAME = 'ndjson_unload_format') +DETAILED_OUTPUT = true; +``` + +结果: + +```text +┌─────────────────────────────────────────────────────────────────────────────────────────────┐ +│ file_name │ file_size │ row_count │ +├─────────────────────────────────────────────────────────────────────┼───────────┼───────────┤ +│ data_068976e5-2072-4ad8-9887-16fb9129ed80_0000_00000000.ndjson.gz │ 263 │ 100 │ +└─────────────────────────────────────────────────────────────────────────────────────────────┘ +``` + +### 第 4 步:验证已卸载的 NDJSON 文件 {#step-4-verify-the-unloaded-ndjson-files} + +```sql +SELECT COUNT($1) +FROM @ndjson_unload_stage +( + FILE_FORMAT => 'ndjson_unload_format', + PATTERN => '.*[.]ndjson[.]gz' +); +``` + +结果: + +```text +┌───────────┐ +│ count($1) │ +├───────────┤ +│ 100 │ +└───────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/guides/unload-parquet-file.md b/tidb-cloud-lake/guides/unload-parquet-file.md new file mode 100644 index 0000000000000..235e9e72b612f --- /dev/null +++ b/tidb-cloud-lake/guides/unload-parquet-file.md @@ -0,0 +1,87 @@ +--- +title: 导出 Parquet 文件 +summary: 了解如何导出 Parquet 文件。 +--- + +# 导出 Parquet 文件 + +## 导出 Parquet 文件 {#unloading-parquet-file} + +语法: + +```sql +COPY INTO {internalStage | externalStage | externalLocation} +FROM { [.] | ( ) } +FILE_FORMAT = (TYPE = PARQUET) +[MAX_FILE_SIZE = ] +[DETAILED_OUTPUT = true | false] +``` + +- 更多 Parquet 选项,请参见 [Parquet 文件格式选项](/tidb-cloud-lake/sql/input-output-file-formats.md#parquet-options) +- 如需导出到多个文件,请使用 [`MAX_FILE_SIZE` Copy 选项](/tidb-cloud-lake/sql/copy-into-location.md#copyoptions) +- 有关该语法的更多详细信息,请参见 [COPY INTO location](/tidb-cloud-lake/sql/copy-into-location.md) + +## 教程 {#tutorial} + +### 步骤 1. 创建 External Stage {#step-1-create-an-external-stage} + +```sql +CREATE STAGE parquet_unload_stage +URL = 's3://unload/parquet/' +CONNECTION = ( + ACCESS_KEY_ID = '' + SECRET_ACCESS_KEY = '' +); +``` + +### 步骤 2. 创建自定义 Parquet 文件格式 {#step-2-create-custom-parquet-file-format} + +```sql +CREATE FILE FORMAT parquet_unload_format + TYPE = PARQUET + ; +``` + +### 步骤 3. 导出为 Parquet 文件 {#step-3-unload-into-parquet-file} + +```sql +COPY INTO @parquet_unload_stage +FROM ( + SELECT * + FROM generate_series(1, 100) +) +FILE_FORMAT = (FORMAT_NAME = 'parquet_unload_format') +DETAILED_OUTPUT = true; +``` + +结果: + +```text +┌───────────────────────────────────────────────────────────────────────────────────────────┐ +│ file_name │ file_size │ row_count │ +│ String │ UInt64 │ UInt64 │ +├───────────────────────────────────────────────────────────────────┼───────────┼───────────┤ +│ data_a3760513-78a8-4a89-8f92-b1a17e0a61b6_0000_00000000.parquet │ 445 │ 100 │ +└───────────────────────────────────────────────────────────────────────────────────────────┘ +``` + +### 步骤 4. 验证已导出的 Parquet 文件 {#step-4-verify-the-unloaded-parquet-files} + +```sql +SELECT COUNT($1) +FROM @parquet_unload_stage +( + FILE_FORMAT => 'parquet_unload_format', + PATTERN => '.*[.]parquet' +); +``` + +结果: + +```text +┌───────────┐ +│ count($1) │ +├───────────┤ +│ 100 │ +└───────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/guides/unload-tsv-file.md b/tidb-cloud-lake/guides/unload-tsv-file.md new file mode 100644 index 0000000000000..026da125d524f --- /dev/null +++ b/tidb-cloud-lake/guides/unload-tsv-file.md @@ -0,0 +1,92 @@ +--- +title: 卸载 TSV 文件 +summary: 了解如何卸载 TSV 文件。 +--- + +# 卸载 TSV 文件 + +## 卸载 TSV 文件 {#unloading-tsv-file} + +语法: + +```sql +COPY INTO { internalStage | externalStage | externalLocation } +FROM { [.] | ( ) } +FILE_FORMAT = ( + TYPE = TSV, + RECORD_DELIMITER = '', + FIELD_DELIMITER = '', + COMPRESSION = gzip, + OUTPUT_HEADER = true -- Unload with header +) +[MAX_FILE_SIZE = ] +[DETAILED_OUTPUT = true | false] +``` + +- 更多 TSV 选项,请参见 [TSV 文件格式选项](/tidb-cloud-lake/sql/input-output-file-formats.md#tsv-options) +- 卸载到多个文件时,使用 [`MAX_FILE_SIZE` Copy 选项](/tidb-cloud-lake/sql/copy-into-location.md#copyoptions) +- 有关该语法的更多详细信息,请参见 [COPY INTO location](/tidb-cloud-lake/sql/copy-into-location.md) + +## 教程 {#tutorial} + +### 第 1 步:创建 External Stage {#step-1-create-an-external-stage} + +```sql +CREATE STAGE tsv_unload_stage +URL = 's3://unload/tsv/' +CONNECTION = ( + ACCESS_KEY_ID = '' + SECRET_ACCESS_KEY = '' +); +``` + +### 第 2 步:创建自定义 TSV 文件格式 {#step-2-create-custom-tsv-file-format} + +```sql +CREATE FILE FORMAT tsv_unload_format + TYPE = TSV, + COMPRESSION = gzip; -- Unload with gzip compression +``` + +### 第 3 步:卸载到 TSV 文件 {#step-3-unload-into-tsv-file} + +```sql +COPY INTO @tsv_unload_stage +FROM ( + SELECT * + FROM generate_series(1, 100) +) +FILE_FORMAT = (FORMAT_NAME = 'tsv_unload_format') +DETAILED_OUTPUT = true; +``` + +结果: + +```text +┌──────────────────────────────────────────────────────────────────────────────────────────┐ +│ file_name │ file_size │ row_count │ +├──────────────────────────────────────────────────────────────────┼───────────┼───────────┤ +│ data_99e8f5c8-79d6-43d8-80d7-13e3f4c91dd5_0002_00000000.tsv.gz │ 160 │ 100 │ +└──────────────────────────────────────────────────────────────────────────────────────────┘ +``` + +### 第 4 步:验证已卸载的 TSV 文件 {#step-4-verify-the-unloaded-tsv-files} + +``` +SELECT COUNT($1) +FROM @tsv_unload_stage +( + FILE_FORMAT => 'tsv_unload_format', + PATTERN => '.*[.]tsv[.]gz' +); +``` + +结果: + +```text +┌───────────┐ +│ count($1) │ +├───────────┤ +│ 100 │ +└───────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/guides/upload-to-stage.md b/tidb-cloud-lake/guides/upload-to-stage.md new file mode 100644 index 0000000000000..d84c6c77c3ade --- /dev/null +++ b/tidb-cloud-lake/guides/upload-to-stage.md @@ -0,0 +1,406 @@ +--- +title: 上传到 Stage +summary: "{{{ .lake }}} 推荐对 stage 使用两种文件上传方法:PRESIGN 和 PUT/GET 命令。这些方法支持客户端与你的存储之间直接传输数据,无需中间环节,并通过减少 {{{ .lake }}} 与你的存储之间的流量来节省成本。" +--- + +# 上传到 Stage + +{{{ .lake }}} 推荐对 stage 使用两种文件上传方法:[PRESIGN](/tidb-cloud-lake/sql/presign.md) 和 PUT/GET 命令。这些方法支持客户端与你的存储之间直接传输数据,无需中间环节,并通过减少 {{{ .lake }}} 与你的存储之间的流量来节省成本。 + +![Uploading to Stage](/media/tidb-cloud-lake/staging-file.png) + +PRESIGN 方法会生成一个带签名且有时间限制的 URL,客户端可以使用该 URL 安全地发起文件上传。此 URL 会授予对指定 stage 的临时访问权限,使客户端能够直接传输数据,而无需在整个过程中依赖 {{{ .lake }}} 服务器,从而同时提升安全性和效率。 + +如果你使用 [LakeSQL](/tidb-cloud-lake/guides/connect-using-lakesql.md) 管理 stage 中的文件,可以使用 PUT 命令上传文件,使用 GET 命令下载文件。 + +- GET 命令当前只能下载 stage 中的所有文件,不能下载单个文件。 +- 这些命令仅适用于 LakeSQL;当 {{{ .lake }}} 使用文件系统作为存储后端时,GET 命令将无法工作。 + +## 使用预签名 URL 上传 {#uploading-with-presigned-url} + +以下示例演示如何使用预签名 URL 将示例文件 ([books.parquet](https://lakesql-bin.tidbcloud.com/datasets/books.parquet)) 上传到用户 stage、内部 stage 和外部 stage。 + + + +
+ +```sql +PRESIGN UPLOAD @~/books.parquet; +``` + +结果: + +``` +┌────────┬────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ +│ Name │ Value │ +├────────┼────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤ +│ method │ PUT │ +│ headers│ {"host":"s3.us-east-2.amazonaws.com"} │ +│ url │ https://s3.us-east-2.amazonaws.com/lake-toronto/stage/user/root/books.parquet?X-Amz-Algorithm... │ +└────────┴────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ +``` + +```shell +curl -X PUT -T books.parquet "https://s3.us-east-2.amazonaws.com/lake-toronto/stage/user/root/books.parquet?X-Amz-Algorithm=... ... +``` + +检查已暂存的文件: + +```sql +LIST @~; +``` + +结果: + +``` +┌───────────────┬──────┬──────────────────────────────────────┬─────────────────────────────────┬─────────┐ +│ name │ size │ md5 │ last_modified │ creator │ +├───────────────┼──────┼──────────────────────────────────────┼─────────────────────────────────┼─────────┤ +│ books.parquet │ 998 │ 88432bf90aadb79073682988b39d461c │ 2023-06-27 16:03:51.000 +0000 │ │ +└───────────────┴──────┴──────────────────────────────────────┴─────────────────────────────────┴─────────┘ +``` + +
+ +
+ +```sql +CREATE STAGE my_internal_stage; +``` + +```sql +PRESIGN UPLOAD @my_internal_stage/books.parquet; +``` + +结果: + +``` +┌─────────┬─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ +│ Name │ Value │ +├─────────┼─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤ +│ method │ PUT │ +│ headers │ {"host":"s3.us-east-2.amazonaws.com"} │ +│ url │ https://s3.us-east-2.amazonaws.com/lake-toronto/stage/internal/my_internal_stage/books.parquet?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=%2F20230628%2Fus-east-2%2Fs3%2Faws4_request&X-Amz-Date=20230628T022951Z&X-Amz-Expires=3600&X-Amz-SignedHeaders=host&X-Amz-Signature=9cfcdf3b3554280211f88629d60358c6d6e6a5e49cd83146f1daea7dfe37f5c1 │ +└─────────┴─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ +``` + +```shell +curl -X PUT -T books.parquet "https://s3.us-east-2.amazonaws.com/lake-toronto/stage/internal/my_internal_stage/books.parquet?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=%2F20230628%2Fus-east-2%2Fs3%2Faws4_request&X-Amz-Date=20230628T022951Z&X-Amz-Expires=3600&X-Amz-SignedHeaders=host&X-Amz-Signature=9cfcdf3b3554280211f88629d60358c6d6e6a5e49cd83146f1daea7dfe37f5c1" +``` + +检查已暂存的文件: + +```sql +LIST @my_internal_stage; +``` + +结果: + +``` +┌──────────────────────────────────┬───────┬──────────────────────────────────────┬─────────────────────────────────┬─────────┐ +│ name │ size │ md5 │ last_modified │ creator │ +├──────────────────────────────────┼───────┼──────────────────────────────────────┼─────────────────────────────────┼─────────┤ +│ books.parquet │ 998 │ "88432bf90aadb79073682988b39d461c" │ 2023-06-28 02:32:15.000 +0000 │ │ +└──────────────────────────────────┴───────┴──────────────────────────────────────┴─────────────────────────────────┴─────────┘ +``` + +
+ +
+ +```sql +CREATE STAGE my_external_stage +URL = 's3://lake' +CONNECTION = ( + ENDPOINT_URL = 'http://127.0.0.1:9000', + ACCESS_KEY_ID = 'ROOTUSER', + SECRET_ACCESS_KEY = 'CHANGEME123' +); +``` + +```sql +PRESIGN UPLOAD @my_external_stage/books.parquet; +``` + +结果: + +``` +┌─────────┬─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ +│ Name │ Value │ +├─────────┼─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤ +│ method │ PUT │ +│ headers │ {"host":"127.0.0.1:9000"} │ +│ url │ http://127.0.0.1:9000/lake/books.parquet?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=ROOTUSER%2F20230628%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20230628T040959Z&X-Amz-Expires=3600&X-Amz-SignedHeaders=host&X-Amz-Signature= │ +└─────────┴─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ +``` + +```shell +curl -X PUT -T books.parquet "http://127.0.0.1:9000/lake/books.parquet?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=ROOTUSER%2F20230628%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20230628T040959Z&X-Amz-Expires=3600&X-Amz-SignedHeaders=host&X-Amz-Signature=" +``` + +检查已暂存的文件: + +```sql +LIST @my_external_stage; +``` + +结果: + +``` +┌───────────────┬──────┬──────────────────────────────────────┬─────────────────────────────────┬─────────┐ +│ name │ size │ md5 │ last_modified │ creator │ +├───────────────┼──────┼──────────────────────────────────────┼─────────────────────────────────┼─────────┤ +│ books.parquet │ 998 │ "88432bf90aadb79073682988b39d461c" │ 2023-06-28 04:13:15.178 +0000 │ │ +└───────────────┴──────┴──────────────────────────────────────┴─────────────────────────────────┴─────────┘ +``` + +
+
+ +### 使用 PUT 命令上传 {#uploading-with-put-command} + +以下示例演示了如何使用 LakeSQL 通过 PUT 命令将示例文件([books.parquet](https://lakesql-bin.tidbcloud.com/datasets/books.parquet))上传到用户 stage、内部 stage 和外部 stage。 + + + +
+ +```sql +PUT fs:///Users/eric/Documents/books.parquet @~ +``` + +结果: + +``` +┌───────────────────────────────────────────────┐ +│ file │ status │ +├─────────────────────────────────────┼─────────┤ +│ /Users/eric/Documents/books.parquet │ SUCCESS │ +└───────────────────────────────────────────────┘ +``` + +检查已暂存的文件: + +```sql +LIST @~; +``` + +结果: + +``` +┌────────────────────────────────────────────────────────────────────────┐ +│ name │ size │ ··· │ last_modified │ creator │ +├───────────────┼────────┼─────┼──────────────────────┼──────────────────┤ +│ books.parquet │ 998 │ ... │ 2023-09-04 03:27:... │ NULL │ +└────────────────────────────────────────────────────────────────────────┘ +``` + +
+ +
+ +```sql +CREATE STAGE my_internal_stage; +``` + +```sql +PUT fs:///Users/eric/Documents/books.parquet @my_internal_stage; +``` + +结果: + +``` +┌───────────────────────────────────────────────┐ +│ file │ status │ +├─────────────────────────────────────┼─────────┤ +│ /Users/eric/Documents/books.parquet │ SUCCESS │ +└───────────────────────────────────────────────┘ +``` + +检查已暂存的文件: + +```sql +LIST @my_internal_stage; +``` + +结果: + +``` +┌────────────────────────────────────────────────────────────────────────┐ +│ name │ size │ ··· │ last_modified │ creator │ +├───────────────┼────────┼─────┼──────────────────────┼──────────────────┤ +│ books.parquet │ 998 │ ... │ 2023-09-04 03:32:... │ NULL │ +└────────────────────────────────────────────────────────────────────────┘ +``` + +
+ +
+ +``` +CREATE STAGE my_external_stage + URL = 's3://lake' + CONNECTION = ( + ENDPOINT_URL = 'http://127.0.0.1:9000', + ACCESS_KEY_ID = 'ROOTUSER', + SECRET_ACCESS_KEY = 'CHANGEME123' + ); +``` + +```sql +PUT fs:///Users/eric/Documents/books.parquet @my_external_stage +``` + +结果: + +``` +┌───────────────────────────────────────────────┐ +│ file │ status │ +├─────────────────────────────────────┼─────────┤ +│ /Users/eric/Documents/books.parquet │ SUCCESS │ +└───────────────────────────────────────────────┘ +``` + +检查已暂存的文件: + +```sql +LIST @my_external_stage; +``` + +结果: + +``` +┌──────────────────────────────────────────────────────────────────────┐ +│ name │ ··· │ last_modified │ creator │ +├──────────────────────┼─────┼──────────────────────┼──────────────────┤ +│ books.parquet │ ... │ 2023-09-04 03:37:... │ NULL │ +└──────────────────────────────────────────────────────────────────────┘ +``` + +
+
+ +### 使用 PUT 命令上传目录 {#uploading-a-directory-with-put-command} + +你还可以在 PUT 命令中使用通配符,从一个目录上传多个文件。当你需要一次性将大量文件暂存到 stage 时,这种方式非常有用。 + +```sql +PUT fs:///home/ubuntu/datas/event_data/*.parquet @your_stage; +``` + +结果: + +``` +┌───────────────────────────────────────────────────────┐ +│ file │status │ +├─────────────────────────────────────────────┼─────────┤ +│ /home/ubuntu/datas/event_data/file1.parquet │ SUCCESS │ +│ /home/ubuntu/datas/event_data/file2.parquet │ SUCCESS │ +│ /home/ubuntu/datas/event_data/file3.parquet │ SUCCESS │ +└───────────────────────────────────────────────────────┘ +``` + +### 使用 GET 命令下载 {#downloading-with-get-command} + +以下示例演示了如何使用 LakeSQL 通过 GET 命令,从用户 stage、内部 stage 和外部 stage 下载示例文件([books.parquet](https://lakesql-bin.tidbcloud.com/datasets/books.parquet))。 + + + +
+ +```sql +LIST @~; +``` + +结果: + +``` +┌────────────────────────────────────────────────────────────────────────┐ +│ name │ size │ ··· │ last_modified │ creator │ +├───────────────┼────────┼─────┼──────────────────────┼──────────────────┤ +│ books.parquet │ 998 │ ... │ 2023-09-04 03:27:... │ NULL │ +└────────────────────────────────────────────────────────────────────────┘ +``` + +```sql +GET @~/ fs:///Users/eric/Downloads/fromStage/; +``` + +结果: + +``` +┌─────────────────────────────────────────────────────────┐ +│ file │ status │ +├───────────────────────────────────────────────┼─────────┤ +│ /Users/eric/Downloads/fromStage/books.parquet │ SUCCESS │ +└─────────────────────────────────────────────────────────┘ +``` + +
+ +
+ +```sql +LIST @my_internal_stage; +``` + +结果: + +``` +┌────────────────────────────────────────────────────────────────────────┐ +│ name │ size │ ··· │ last_modified │ creator │ +├───────────────┼────────┼─────┼──────────────────────┼──────────────────┤ +│ books.parquet │ 998 │ ... │ 2023-09-04 03:32:... │ NULL │ +└────────────────────────────────────────────────────────────────────────┘ +``` + +```sql +GET @my_internal_stage/ fs:///Users/eric/Downloads/fromStage/; +``` + +结果: + +``` +┌─────────────────────────────────────────────────────────┐ +│ file │ status │ +├───────────────────────────────────────────────┼─────────┤ +│ /Users/eric/Downloads/fromStage/books.parquet │ SUCCESS │ +└─────────────────────────────────────────────────────────┘ +``` + +
+ +
+ +```sql + +LIST @my_external_stage; + +``` + +结果: + +``` +┌──────────────────────────────────────────────────────────────────────┐ +│ name │ ··· │ last_modified │ creator │ +├──────────────────────┼─────┼──────────────────────┼──────────────────┤ +│ books.parquet │ ... │ 2023-09-04 03:37:... │ NULL │ +└──────────────────────────────────────────────────────────────────────┘ +``` + +```sql +GET @my_external_stage/ fs:///Users/eric/Downloads/fromStage/; +``` + +结果: + +``` +┌─────────────────────────────────────────────────────────┐ +│ file │ status │ +├───────────────────────────────────────────────┼─────────┤ +│ /Users/eric/Downloads/fromStage/books.parquet │ SUCCESS │ +└─────────────────────────────────────────────────────────┘ +``` + +
+
\ No newline at end of file diff --git a/tidb-cloud-lake/guides/vector-search-guide.md b/tidb-cloud-lake/guides/vector-search-guide.md new file mode 100644 index 0000000000000..c9a2317e792b7 --- /dev/null +++ b/tidb-cloud-lake/guides/vector-search-guide.md @@ -0,0 +1,190 @@ +--- +title: 向量搜索 +summary: 在该场景中,CityDrive 将每一帧的 embedding 直接保存在 {{{ .lake }}} 中。这些向量 embedding 来自 AI 模型对视频关键帧的推导结果,用于捕获视觉语义特征。语义相似度搜索(“查找看起来像这样的帧”)可以与传统 SQL 分析同时运行——无需单独的向量服务。 +--- + +# 向量搜索 + +> **场景:** CityDrive 将每一帧的 embedding 直接保存在 {{{ .lake }}} 中。这些向量 embedding 来自 AI 模型对视频关键帧的推导结果,用于捕获视觉语义特征。语义相似度搜索(“查找看起来像这样的帧”)可以与传统 SQL 分析同时运行——无需单独的向量服务。 + +`frame_embeddings` 表与 `frame_events`、`frame_metadata_catalog` 和 `frame_geo_points` 共享相同的 `frame_id` 键,这使得语义搜索与经典 SQL 能够紧密结合。 + +## 1. 准备 embedding 表 {#1-prepare-the-embedding-table} + +生产模型通常会输出 512–1536 维。下面的示例使用 512 维,这样你可以直接将其复制到演示集群中,而无需修改 DDL。 + +```sql +CREATE OR REPLACE TABLE frame_embeddings ( + frame_id STRING, + video_id STRING, + sensor_view STRING, + embedding VECTOR(512), + encoder_build STRING, + created_at TIMESTAMP, + VECTOR INDEX idx_frame_embeddings(embedding) distance='cosine' +); + +-- SQL UDF: build 512 dims via ARRAY_AGG + window frame; tutorial placeholder only. +CREATE OR REPLACE FUNCTION demo_random_vector(seed STRING) +RETURNS TABLE(embedding VECTOR(512)) +AS $$ +SELECT CAST( + ARRAY_AGG(rand_val) OVER ( + PARTITION BY seed + ORDER BY seq + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) + AS VECTOR(512) + ) AS embedding +FROM ( + SELECT seed, + dims.number AS seq, + (RAND() * 0.2 - 0.1)::FLOAT AS rand_val + FROM numbers(512) AS dims +) vals +QUALIFY ROW_NUMBER() OVER (PARTITION BY seed ORDER BY seq) = 1; +$$; + +INSERT INTO frame_embeddings (frame_id, video_id, sensor_view, embedding, encoder_build, created_at) +SELECT 'FRAME-0101', 'VID-20250101-001', 'roof_cam', embedding, 'clip-lite-v1', '2025-01-01 08:15:21' +FROM demo_random_vector('FRAME-0101') +UNION ALL +SELECT 'FRAME-0102', 'VID-20250101-001', 'roof_cam', embedding, 'clip-lite-v1', '2025-01-01 08:33:54' +FROM demo_random_vector('FRAME-0102') +UNION ALL +SELECT 'FRAME-0201', 'VID-20250101-002', 'front_cam', embedding, 'night-fusion-v2', '2025-01-01 11:12:02' +FROM demo_random_vector('FRAME-0201') +UNION ALL +SELECT 'FRAME-0401', 'VID-20250103-001', 'rear_cam', embedding, 'night-fusion-v2', '2025-01-03 21:18:07' +FROM demo_random_vector('FRAME-0401'); +``` + +> 这个数组生成器只是为了让本教程自包含。在生产环境中,请将其替换为模型生成的真实 embedding。 + +如果你还没有运行 SQL Analytics 指南,请先创建配套的 `frame_events` 表,并填充与向量演练中关联查询相同的示例数据行: + +```sql +CREATE OR REPLACE TABLE frame_events ( + frame_id STRING, + video_id STRING, + frame_index INT, + collected_at TIMESTAMP, + event_tag STRING, + risk_score DOUBLE, + speed_kmh DOUBLE +); + +INSERT INTO frame_events VALUES + ('FRAME-0101', 'VID-20250101-001', 125, '2025-01-01 08:15:21', 'hard_brake', 0.81, 32.4), + ('FRAME-0102', 'VID-20250101-001', 416, '2025-01-01 08:33:54', 'pedestrian', 0.67, 24.8), + ('FRAME-0201', 'VID-20250101-002', 298, '2025-01-01 11:12:02', 'lane_merge', 0.74, 48.1), + ('FRAME-0301', 'VID-20250102-001', 188, '2025-01-02 09:44:18', 'hard_brake', 0.59, 52.6), + ('FRAME-0401', 'VID-20250103-001', 522, '2025-01-03 21:18:07', 'night_lowlight', 0.63, 38.9), + ('FRAME-0501', 'VID-MISSING-001', 10, '2025-01-04 10:00:00', 'sensor_fault', 0.25, 15.0); +``` + +文档: [Vector 类型](/tidb-cloud-lake/sql/vector.md) 和 [向量索引](/tidb-cloud-lake/sql/vector.md#vector-indexing)。 + +--- + +## 2. 运行余弦搜索 {#2-run-cosine-search} + +从某一帧中取出 embedding,并让 HNSW 索引返回最接近的邻居。 + +```sql +WITH query_embedding AS ( + SELECT embedding + FROM frame_embeddings + WHERE frame_id = 'FRAME-0101' +) +SELECT e.frame_id, + e.video_id, + COSINE_DISTANCE(e.embedding, q.embedding) AS distance +FROM frame_embeddings AS e +CROSS JOIN query_embedding AS q +ORDER BY distance +LIMIT 3; +``` + +示例输出: + +``` +frame_id | video_id | distance +FRAME-0101| VID-20250101-001 | 0.0000 +FRAME-0201| VID-20250101-002 | 0.9801 +FRAME-0102| VID-20250101-001 | 0.9842 +``` + +距离越小,表示越相似。即使有数百万帧,`VECTOR INDEX` 也能将延时保持在较低水平。 + +你可以在向量比较之前或之后添加传统谓词(route、video、sensor view),以缩小候选集。 + +```sql +WITH query_embedding AS ( + SELECT embedding + FROM frame_embeddings + WHERE frame_id = 'FRAME-0201' +) +SELECT e.frame_id, + e.sensor_view, + COSINE_DISTANCE(e.embedding, q.embedding) AS distance +FROM frame_embeddings AS e +CROSS JOIN query_embedding AS q +WHERE e.sensor_view = 'rear_cam' +ORDER BY distance +LIMIT 5; +``` + +示例输出: + +``` +frame_id | sensor_view | distance +FRAME-0401| rear_cam | 1.0537 +``` + +优化器在遵循 `sensor_view` 过滤条件的同时,仍会使用向量索引。 + +--- + +## 3. 丰富相似帧结果 {#3-enrich-similar-frames} + +先将最相似的匹配结果物化出来,再使用 `frame_events` 对其进行补充,以供下游分析使用。 + +```sql +WITH query_embedding AS ( + SELECT embedding + FROM frame_embeddings + WHERE frame_id = 'FRAME-0102' + ), + similar_frames AS ( + SELECT frame_id, + video_id, + COSINE_DISTANCE(e.embedding, q.embedding) AS distance + FROM frame_embeddings e + CROSS JOIN query_embedding q + ORDER BY distance + LIMIT 5 + ) +SELECT sf.frame_id, + sf.video_id, + fe.event_tag, + fe.risk_score, + sf.distance +FROM similar_frames sf +LEFT JOIN frame_events fe USING (frame_id) +ORDER BY sf.distance; +``` + +示例输出: + +``` +frame_id | video_id | event_tag | risk_score | distance +FRAME-0102| VID-20250101-001 | pedestrian | 0.67 | 0.0000 +FRAME-0201| VID-20250101-002 | lane_merge | 0.74 | 0.9802 +FRAME-0101| VID-20250101-001 | hard_brake | 0.81 | 0.9842 +FRAME-0401| VID-20250103-001 | night_lowlight | 0.63 | 1.0020 +``` + +由于 embedding 与关系型表存放在一起,你可以从“看起来相似的帧”进一步切换到“同时带有 `hard_brake` 标签、特定天气条件或 JSON 检测结果的帧”,而无需将数据导出到其他服务。 + +如果要限制某个角色在向量搜索期间可以检索哪些文档,可以附加一个 [行访问策略](/tidb-cloud-lake/guides/row-access-policy.md#vector--rag-document-visibility),这样可见性由引擎强制执行,而不是通过在查询中塞入文档 ID 来实现。 \ No newline at end of file diff --git a/tidb-cloud-lake/guides/virtual-column.md b/tidb-cloud-lake/guides/virtual-column.md new file mode 100644 index 0000000000000..ec5338c06dab0 --- /dev/null +++ b/tidb-cloud-lake/guides/virtual-column.md @@ -0,0 +1,161 @@ +--- +title: 虚拟列 +summary: 虚拟列会自动加速存储在 VARIANT 列中的半结构化数据查询。该功能为 JSON 数据访问提供零配置的性能优化。 +--- + +# 虚拟列 + +虚拟列会自动加速存储在 [VARIANT](/tidb-cloud-lake/sql/variant.md) 列中的半结构化数据查询。该功能为 JSON 数据访问提供**零配置的性能优化**。 + +## 它解决了什么问题? {#what-problem-does-it-solve} + +查询 JSON 数据时,传统数据库每次访问嵌套字段都必须解析整个 JSON 结构。这会带来以下性能瓶颈: + +| 问题 | 影响 | 虚拟列解决方案 | +|---------|--------|------------------------| +| **查询延时** | 复杂 JSON 查询需要数秒 | 亚秒级响应时间 | +| **数据读取过多** | 即使只查询单个字段,也必须读取整个 JSON 文档 | 只读取所需的特定字段 | +| **JSON 解析缓慢** | 每次查询都要重新解析整个 JSON 文档 | 预先物化字段,实现即时访问 | +| **CPU 使用率高** | JSON 遍历会消耗处理能力 | 像读取普通数据一样直接读取列 | +| **内存开销** | 需要将完整 JSON 结构加载到内存中 | 仅加载所需字段 | + +**示例场景**:一个电商分析表将产品数据以 JSON 格式存储。如果没有虚拟列,在数百万行数据上查询 `product_data['category']` 需要解析每一条 JSON 文档。使用虚拟列后,这会变成一次直接的列查找。 + +## 它如何自动工作 {#how-it-works-automatically} + +1. **数据摄取** → {{{ .lake }}} 分析 VARIANT 列中的 JSON 结构 +2. **智能检测** → 系统识别被频繁访问的嵌套字段 +3. **后台优化** → 自动创建虚拟列 +4. **查询加速** → 查询自动使用优化后的路径 + +![Virtual Column Workflow](/media/tidb-cloud-lake/virtual-column.png) + +## 配置 {#configuration} + +从 v1.2.832 开始,虚拟列默认启用,无需额外配置。 + +## 完整示例 {#complete-example} + +以下示例展示了虚拟列的自动创建及其性能收益: + +```sql +-- Create a table named 'test' with columns 'id' and 'val' of type Variant. +CREATE TABLE test(id int, val variant); + +-- Insert sample records into the 'test' table with Variant data. +INSERT INTO + test +VALUES + ( + 1, + '{"id":1,"name":"datalake","tags":["powerful","fast"],"pricings":[{"type":"Standard","price":"Pay as you go"},{"type":"Enterprise","price":"Custom"}]}' + ), + ( + 2, + '{"id":2,"name":"databricks","tags":["scalable","flexible"],"pricings":[{"type":"Free","price":"Trial"},{"type":"Premium","price":"Subscription"}]}' + ), + ( + 3, + '{"id":3,"name":"snowflake","tags":["cloud-native","secure"],"pricings":[{"type":"Basic","price":"Pay per second"},{"type":"Enterprise","price":"Annual"}]}' + ), + ( + 4, + '{"id":4,"name":"redshift","tags":["reliable","scalable"],"pricings":[{"type":"On-Demand","price":"Pay per usage"},{"type":"Reserved","price":"1 year contract"}]}' + ), + ( + 5, + '{"id":5,"name":"bigquery","tags":["innovative","cost-efficient"],"pricings":[{"type":"Flat Rate","price":"Monthly"},{"type":"Flex","price":"Per query"}]}' + ); + +INSERT INTO test SELECT * FROM test; +INSERT INTO test SELECT * FROM test; +INSERT INTO test SELECT * FROM test; +INSERT INTO test SELECT * FROM test; +INSERT INTO test SELECT * FROM test; + +-- Explain the query execution plan for selecting specific fields from the table. +EXPLAIN +SELECT + val ['name'], + val ['tags'] [0], + val ['pricings'] [0] ['type'] +FROM + test; + +-[ EXPLAIN ]----------------------------------- +Exchange +├── output columns: [test.val['name'] (#3), test.val['pricings'][0]['type'] (#5), test.val['tags'][0] (#8)] +├── exchange type: Merge +└── TableScan + ├── table: default.default.test + ├── output columns: [val['name'] (#3), val['pricings'][0]['type'] (#5), val['tags'][0] (#8)] + ├── read rows: 160 + ├── read size: 1.69 KiB + ├── partitions total: 6 + ├── partitions scanned: 6 + ├── pruning stats: [segments: , blocks: ] + ├── push downs: [filters: [], limit: NONE] + ├── virtual columns: [val['name'], val['pricings'][0]['type'], val['tags'][0]] + └── estimated rows: 160.00 + +-- Explain the query execution plan for selecting only the 'name' field from the table. +EXPLAIN +SELECT + val ['name'] +FROM + test; + +-[ EXPLAIN ]----------------------------------- +Exchange +├── output columns: [test.val['name'] (#2)] +├── exchange type: Merge +└── TableScan + ├── table: default.book_db.test + ├── output columns: [val['name'] (#2)] + ├── read rows: 160 + ├── read size: < 1 KiB + ├── partitions total: 16 + ├── partitions scanned: 16 + ├── pruning stats: [segments: , blocks: ] + ├── push downs: [filters: [], limit: NONE] + ├── virtual columns: [val['name']] + └── estimated rows: 160.00 + +-- Display all the auto generated virtual columns. +SHOW VIRTUAL COLUMNS WHERE table='test'; + +╭────────────────────────────────────────────────────────────────────────────────────────────────────────╮ +│ database │ table │ source_column │ virtual_column_id │ virtual_column_name │ virtual_column_type │ +│ String │ String │ String │ UInt32 │ String │ String │ +├──────────┼────────┼───────────────┼───────────────────┼──────────────────────────┼─────────────────────┤ +│ default │ test │ val │ 3000000000 │ ['id'] │ UInt64 │ +│ default │ test │ val │ 3000000001 │ ['name'] │ String │ +│ default │ test │ val │ 3000000002 │ ['pricings'][0]['price'] │ String │ +│ default │ test │ val │ 3000000003 │ ['pricings'][0]['type'] │ String │ +│ default │ test │ val │ 3000000004 │ ['pricings'][1]['price'] │ String │ +│ default │ test │ val │ 3000000005 │ ['pricings'][1]['type'] │ String │ +│ default │ test │ val │ 3000000006 │ ['tags'][0] │ String │ +│ default │ test │ val │ 3000000007 │ ['tags'][1] │ String │ +╰────────────────────────────────────────────────────────────────────────────────────────────────────────╯ +``` + +## 监控命令 {#monitoring-commands} + +| 命令 | 用途 | +|---------|---------| +| [`SHOW VIRTUAL COLUMNS`](/tidb-cloud-lake/sql/show-virtual-columns.md) | 查看自动创建的虚拟列 | +| [`REFRESH VIRTUAL COLUMN`](/tidb-cloud-lake/sql/refresh-virtual-column.md) | 手动刷新虚拟列 | +| [`FUSE_VIRTUAL_COLUMN`](/tidb-cloud-lake/sql/fuse-virtual-column.md) | 查看虚拟列元信息 | + +## 性能结果 {#performance-results} + +虚拟列通常可带来: + +- **5-10 倍更快**的 JSON 字段访问 +- **自动优化**,无需修改查询 +- **降低资源消耗**,减少查询处理期间的开销 +- 为现有应用提供**透明加速** + +--- + +*虚拟列会在后台自动工作——{{{ .lake }}} 以零配置方式优化你的 JSON 查询。* \ No newline at end of file diff --git a/tidb-cloud-lake/guides/warehouse.md b/tidb-cloud-lake/guides/warehouse.md new file mode 100644 index 0000000000000..9683dc5bac469 --- /dev/null +++ b/tidb-cloud-lake/guides/warehouse.md @@ -0,0 +1,277 @@ +--- +title: 计算集群 +summary: 计算集群是 TiDB Cloud Lake 的核心组件。计算集群表示一组计算资源,包括 CPU、内存和本地缓存。你必须运行一个计算集群才能执行 SQL 任务。 +--- + +# 计算集群 + +计算集群是 {{{ .lake }}} 的核心组件。计算集群表示一组计算资源,包括 CPU、内存和本地缓存。你必须运行一个计算集群才能执行 SQL 任务,例如: + +- 使用 SELECT 语句查询数据 +- 使用 INSERT、UPDATE 或 DELETE 语句修改数据 +- 使用 COPY INTO 命令将数据加载到表中 + +运行计算集群会产生费用。更多信息,请参见[计算集群定价](/tidb-cloud-lake/guides/pricing-billing.md)。 + +## 计算集群规格 {#warehouse-sizes} + +在 {{{ .lake }}} 中,计算集群提供多种规格,每种规格由其可处理的最大并发查询数定义。创建计算集群时,你可以从以下规格中进行选择: + +| 规格 | 推荐使用场景 | +| --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ | +| XSmall | 最适合测试或运行轻量查询等简单任务。适用于小型数据集(约 50GB)。 | +| Small | 非常适合运行常规报表和中等负载。适用于中型数据集(约 200GB)。 | +| Medium | 适合处理更复杂查询和更高并发的团队。适用于较大的数据集(约 1TB)。 | +| Large | 非常适合运行大量并发查询的组织。适用于大型数据集(约 5TB)。 | +| XLarge | 专为高并发的企业级负载打造。适用于超大型数据集(超过 10TB)。 | +| nXLarge | n=2,3,4,5,6 [联系我们](https://docs.pingcap.com/tidbcloud/tidb-cloud-support/?plan=lake) | +| 多集群扩展 | 根据你的工作负载自动扩容和缩容,基于你的需求以最具成本效益的方式提升并发能力。 | + +为了选择合适的计算集群规格,{{{ .lake }}} 建议从较小的规格开始。与中型或大型计算集群相比,较小的计算集群执行 SQL 任务可能需要更长时间。如果你发现查询执行时间过长(例如数分钟),请考虑扩展到中型或大型计算集群以获得更快的结果。 + +## 管理计算集群 {#managing-warehouses} + +一个组织可以根据需要拥有任意数量的计算集群。**Warehouses** 页面会显示你组织中的所有计算集群,并允许你对其进行管理。请注意,只有 `account_admin` 才能创建或删除计算集群。 + +> **提示:** +> +> 你也可以使用 SQL 命令管理计算集群。详情请参见 [计算集群 DDL 命令](/tidb-cloud-lake/sql/warehouse-overview.md)。 + +### 暂停 / 恢复计算集群 {#suspending-resuming-warehouses} + +已暂停的计算集群不会消耗任何 credits。你可以通过点击计算集群上的 按钮手动暂停或恢复计算集群。不过,在以下场景中,计算集群也可以自动暂停或恢复: + +- 如果没有活动,计算集群可以根据其自动暂停设置自动暂停。 +- 当你选择一个已暂停的计算集群来执行 SQL 任务时,该计算集群会自动恢复。 + +### 执行批量操作 {#performing-bulk-operations} + +你可以对计算集群执行批量操作,包括批量重启、批量暂停、批量恢复和批量删除。为此,请在计算集群列表中勾选复选框 以选择要批量操作的计算集群,然后点击省略号按钮 执行所需操作。 + +![Bulk operations](/media/tidb-cloud-lake/bulk.gif) + +### 为计算集群添加标签 {#tagging-warehouses} + +你可以为计算集群附加标签,以便对其进行组织和分类,例如按环境、团队或成本中心分类。标签是键值对,会显示在计算集群列表中,你可以按标签进行筛选和排序。 + +**约束:** + +- 每个计算集群最多 **10 个标签** +- 键:最多 **128 个字符** +- 值:最多 **256 个字符** + +要添加标签,请在创建或编辑计算集群时展开 **Tags** 部分,并输入你的键值对。 + +标签会在计算集群列表中显示为 `key: value`,并可用于按键或值筛选计算集群。 + +### 最佳实践 {#best-practices} + +为了有效管理你的计算集群并确保最佳性能和成本效率,请参考以下最佳实践。这些指南将帮助你针对不同负载和环境合理设置计算集群规格、组织方式并进行细致调优: + +- **选择合适的规格** + + - 对于 **开发与测试**,使用较小的计算集群(XSmall、Small)。 + - 对于 **生产环境**,选择较大的计算集群(Medium、Large、XLarge)。 + +- **分离计算集群** + + - 为**数据加载**和**查询执行**使用不同的计算集群。 + - 为 **开发**、**测试** 和 **生产** 环境创建独立的计算集群。 + +- **数据加载建议** + + - 较小的计算集群(Small、Medium)适合数据加载。 + - 优化文件大小和文件数量以提升性能。 + +- **优化成本与性能** + + - 避免运行 `SELECT 1` 之类的简单查询,以尽量减少 credits 使用量。 + - 使用批量加载(`COPY`),而不是逐条执行 `INSERT` 语句。 + - 监控长时间运行的查询,并对其进行优化以提升性能。 + +- **自动暂停** + + - 在计算集群空闲时启用自动暂停以节省 credits。 + +- **对频繁查询禁用自动暂停** + + - 对于频繁或重复的查询,保持计算集群处于活动状态,以维持缓存并避免延迟。 + +- **使用自动扩缩容(仅限 Business 和 Dedicated 计划)** + + - 多集群扩缩容会根据工作负载需求自动调整资源。 + +- **监控并调整使用情况** + - 定期检查计算集群使用情况,并根据需要调整规格,以平衡成本和性能。 + +## 计算集群访问控制 {#warehouse-access-control} + +{{{ .lake }}} 允许你通过基于角色的控制来管理计算集群访问权限,即为计算集群分配特定角色,从而只有拥有该角色的用户才能访问该计算集群。 + +> **注意:** +> +> 默认情况下,计算集群访问控制 _未_ 启用。要启用此功能,请前往 **Support** > **Create New Ticket** 并提交请求。 + +要为计算集群分配角色,请在创建或修改计算集群时,在 **Advanced Options** 中选择所需角色: + +![alt text](/media/tidb-cloud-lake/warehouse-role.png) + +- 可供选择的有两个[内置角色](/tidb-cloud-lake/guides/roles.md#built-in-roles),你也可以使用 [CREATE ROLE](/tidb-cloud-lake/sql/create-role.md) 命令创建其他角色。有关 {{{ .lake }}} 角色的更多信息,请参见 [角色](/tidb-cloud-lake/guides/roles.md)。 +- 未分配角色的计算集群默认使用 `public` 角色,允许所有用户访问。 +- 你可以使用 [GRANT](/tidb-cloud-lake/sql/grant.md) 命令将角色授予用户({{{ .lake }}} 登录邮箱或 SQL 用户)。以下示例将角色 `manager` 授予邮箱为 `name@example.com` 的用户,从而允许其访问任何分配给 `manager` 角色的计算集群: + + ```sql title='Examples:' + GRANT ROLE manager to 'name@example.com'; + ``` + +## 多集群计算集群 {#multi-cluster-warehouses} + +多集群计算集群会根据工作负载需求,通过添加或移除集群自动调整计算资源。它在根据需要扩容或缩容的同时,确保高并发和性能,并优化成本。 + +> **注意:** +> +> 默认情况下,多集群计算集群未启用。要启用此功能,请前往 **Support** > **Create New Ticket** 并提交请求。此功能仅适用于使用 Business 和 Dedicated 计划的 {{{ .lake }}} 用户。 + +### 工作原理 {#how-it-works} + +默认情况下,一个计算集群由单个计算资源集群组成,其可处理的最大并发查询数取决于其规格。当为某个计算集群启用 Multi-Cluster 后,它允许动态添加多个集群(由 **Max Clusters** 设置定义),以处理超出单个集群容量的工作负载。 + +当并发查询数量超过你的计算集群容量时,系统会添加一个额外集群来处理额外负载。如果需求持续增长,则会逐个添加更多集群。随着查询需求下降,超过 **Auto Suspend** 时长仍无活动的集群会被自动关闭。 + +![alt text](/media/tidb-cloud-lake/multi-cluster-how-it-works.png) + +### 启用 Multi-Cluster {#enabling-multi-cluster} + +你可以在创建计算集群时为其启用 Multi-Cluster,并设置该计算集群最多可以扩展到的集群数量。请注意,如果为某个计算集群启用了 Multi-Cluster,则 **Auto Suspend** 时长必须至少设置为 15 分钟。 + +![alt text](/media/tidb-cloud-lake/multi-cluster.png) + +### 成本计算 {#cost-calculation} + +多集群计算集群按特定时间区间内使用的活动集群数量计费。 + +例如,对于一个价格为每小时 $1.6 的 XSmall 计算集群,如果从 13:00 到 14:00 有一个集群处于活动状态,而从 14:00 到 15:00 有两个集群处于活动状态,则从 13:00 到 15:00 产生的总费用为 $4.8((1 cluster × 1 hour × $1.6) + (2 clusters × 1 hour × $1.6))。 + +## MySQL Endpoint {#mysql-endpoint} + +MySQL Endpoint 功能使计算集群能够接受来自仅支持 MySQL 协议的 BI 工具和应用程序的连接,例如 Tableau、Grafana 或其他兼容 MySQL 的客户端。 + +> **注意:** +> +> 默认情况下,MySQL Endpoint 未启用。要启用此功能,请前往 **Support** > **Create New Ticket** 并提交请求。 + +### 启用 MySQL Endpoint {#enabling-mysql-endpoint} + +你可以在创建计算集群时启用 MySQL Endpoint,也可以稍后修改时启用。该选项位于 **Advanced Options** 部分,以切换开关的形式提供。 + +> **警告:** +> +> 启用 MySQL Endpoint 后,系统会自动为该计算集群**禁用 Auto Suspend**(设置为 0)。这意味着即使在空闲时,计算集群也会持续运行并产生费用。请据此合理规划使用方式。 + +### 通过 MySQL 协议连接 {#connecting-via-mysql-protocol} + +启用后,你可以使用任何兼容 MySQL 的客户端,通过 **Connect** 对话框中显示的标准 MySQL 连接信息连接到该计算集群。这对于集成那些原生不支持 {{{ .lake }}} 协议的工具非常有用。 + +## 连接到计算集群 {#connecting-to-a-warehouse} + +连接到计算集群可提供在 {{{ .lake }}} 中运行查询和分析数据所需的计算资源。当你从应用程序或 SQL 客户端访问 {{{ .lake }}} 时,需要建立此连接。 + +### 连接方式 {#connection-methods} + +{{{ .lake }}} 支持多种连接方式,以满足你的特定需求。 + +#### SQL 客户端与工具 {#sql-clients-tools} + +| 客户端 | 类型 | 最适合 | 关键特性 | +| ------------------------------------------ | --------------- | ----------------------------- | ----------------------------------------------------- | +| **[LakeSQL](/tidb-cloud-lake/guides/connect-using-lakesql.md)** | 命令行 | 开发者、脚本 | 原生 CLI、丰富格式化、多种安装方式 | + +#### 开发者驱动 {#developer-drivers} + +| 语言 | 驱动 | 使用场景 | 文档 | +| ----------- | ----------------- | ----------------------- | ------------------------------------------------------ | +| **Go** | Golang 驱动 | 后端应用程序 | [Golang 指南](/tidb-cloud-lake/guides/connect-using-golang.md) | +| **Python** | Python 连接器 | 数据科学、分析 | [Python 指南](/tidb-cloud-lake/guides/connect-using-python.md) | +| **Node.js** | JavaScript 驱动 | Web 应用程序 | [Node.js 指南](/tidb-cloud-lake/guides/connect-using-node-js.md) | +| **Java** | JDBC 驱动 | 企业应用程序 | [JDBC 指南](/tidb-cloud-lake/guides/connect-using-java.md) | +| **Rust** | Rust 驱动 | 系统编程 | [Rust 指南](/tidb-cloud-lake/guides/connect-using-rust.md) | + +### 获取连接信息 {#obtaining-connection-information} + +要获取某个计算集群 (Warehouse) 的连接信息,请执行以下操作: + +1. 点击 **Overview** > **Connect**。 +2. 选择要连接的 **Database** 和 **Warehouse**。连接信息会根据你的选择自动更新。 +3. 连接详情中包含一个名为 `cloudapp` 的 SQL 用户及其随机生成的密码。{{{ .lake }}} 不会存储该密码。请务必复制并安全保存。如果忘记密码,请点击 **Reset** 生成新密码(需要 Admin 才能重置)。 + +### 连接字符串格式 {#connection-string-format} + +当你点击 **Connect** 时,{{{ .lake }}} 会自动生成连接字符串: + +``` +lake://:@.gw..default.tidbcloud.com:443/?warehouse= +``` + +其中: + +- ``:默认为 `cloudapp` +- ``:点击 **Reset** 可查看或修改 +- ``、``:你的账户信息(显示在连接详情中) +- ``:所选数据库(显示在连接详情中) +- ``:所选计算集群(显示在连接详情中) + +### 创建用于访问计算集群的 SQL 用户 {#creating-sql-users-for-warehouse-access} + +除了默认的 `cloudapp` 用户外,你还可以创建额外的 SQL 用户,以获得更好的安全性和访问控制。 + +#### 示例 1:跨所有数据库的完全访问权限 {#example-1-full-access-across-all-databases} + +为用户授予对所有数据库的读写访问权限——适用于需要跨数据库操作的管理员账户或自动化流水线: + +```sql +-- Create a role with global access +CREATE ROLE full_access_role; +GRANT ALL ON *.* TO ROLE full_access_role; + +-- Create the user and assign the role +CREATE USER admin_user IDENTIFIED BY 'SecurePass456!' WITH DEFAULT_ROLE = 'full_access_role'; +GRANT ROLE full_access_role TO admin_user; +``` + +#### 示例 2:单个数据库访问权限 {#example-2-single-database-access} + +仅授予用户访问某个特定数据库的权限: + +```sql +-- Create a role scoped to one database +CREATE ROLE warehouse_user1_role; +GRANT ALL ON my_database.* TO ROLE warehouse_user1_role; + +-- Create a new SQL user and assign the role +CREATE USER warehouse_user1 IDENTIFIED BY 'StrongPassword123' WITH DEFAULT_ROLE = 'warehouse_user1_role'; +GRANT ROLE warehouse_user1_role TO warehouse_user1; +``` + +#### 示例 3:跨所有数据库的只读访问权限 {#example-3-read-only-access-across-all-databases} + +适用于用户只应执行数据查询的场景(例如仪表盘、BI 工具、安全模式下的 AI 代理): + +```sql +-- Create a read-only role +CREATE ROLE readonly_role; +GRANT SELECT ON *.* TO ROLE readonly_role; + +-- Create the user +CREATE USER readonly_user IDENTIFIED BY 'ReadOnly789!' WITH DEFAULT_ROLE = 'readonly_role'; +GRANT ROLE readonly_role TO readonly_user; +``` + +> **提示:** +> +> 在 {{{ .lake }}} 中,`CREATE DATABASE` 这类权限只能授予角色,不能直接授予用户。请始终先创建角色,再将权限授予该角色,最后把角色分配给用户。 + +更多信息,请参见 [CREATE USER](/tidb-cloud-lake/sql/create-user.md) 和 [GRANT](/tidb-cloud-lake/sql/grant.md) 文档。 + +### 连接安全 {#connection-security} + +所有到 {{{ .lake }}} 计算集群的连接默认都使用 TLS 加密。对于需要更高安全性的企业用户,可以使用 [AWS PrivateLink](/tidb-cloud-lake/guides/connect-with-aws-privatelink.md) 在你的 VPC 与 {{{ .lake }}} 之间建立私有连接。 \ No newline at end of file diff --git a/tidb-cloud-lake/guides/worksheet.md b/tidb-cloud-lake/guides/worksheet.md new file mode 100644 index 0000000000000..85acad9e2a063 --- /dev/null +++ b/tidb-cloud-lake/guides/worksheet.md @@ -0,0 +1,63 @@ +--- +title: 工作区 +summary: TiDB Cloud Lake 中的工作区用于组织、运行和保存 SQL 语句。它们还可以与组织中的其他人共享。 +--- + +# 工作区 + +{{{ .lake }}} 中的工作区 (Worksheet) 用于组织、运行和保存 SQL 语句。它们还可以与组织中的其他人共享。 + +## 创建工作区 {#creating-a-worksheet} + +要创建新的工作区,请在侧边栏中点击 **Worksheets**,然后选择 **New Worksheet**。 + +如果你的 SQL 语句已经保存在 SQL 文件中,也可以直接从该文件创建工作区。为此,请点击 **New Worksheet** 右侧的省略号图标 ,然后选择 **Create from SQL File**。 + +## 编辑并运行 SQL 语句 {#editing-and-running-sql-statements} + +要编辑并运行 SQL 语句: + +1. 点击 SQL 编辑器上方的数据库图标 ,然后选择你要查询的数据库。 +2. 点击 SQL 编辑器上方的用户图标 ,然后选择要使用的角色。下拉列表会显示已授予你的所有角色,以及这些角色在层级结构中的所有子角色。有关角色层级的更多信息,请参见 [继承角色并建立层级关系](/tidb-cloud-lake/guides/roles.md#inheriting-roles--establishing-hierarchy)。 + +3. 在 SQL 编辑器中编辑 SQL 语句。 +4. 点击 SQL 编辑器下方的计算集群图标 ,然后从列表中选择一个计算集群。 +5. 点击 **Run Script**。 + +查询结果会显示在输出区域中。你可以点击 **Export** 将完整结果保存为 CSV 文件,或者在输出区域中选择一个或多个单元格,然后按 Command + C(Mac)或 Ctrl + C(Windows)将其复制到剪贴板。 + +> **提示:** +> +> - 单次 API 调用不支持包含多条 SQL 语句。请确保工作区中的每条 SQL 查询都以单个分号 (;) 结尾。 +> - 为了便于编辑 SQL 语句,你可以在数据库列表中选择一张表,并点击其旁边的 "..." 按钮。然后根据菜单提示,一键将表名或所有列名复制到右侧的 SQL 输入区域。 +> +> - 如果你在 SQL 输入区域中输入了多条语句,{{{ .lake }}} 只会执行光标所在位置的那条语句。你可以移动光标来执行其他语句。此外,你还可以使用快捷键:Ctrl + Enter(Windows)或 Command + Enter(Mac)执行当前语句,Ctrl + Shift + Enter(Windows)或 Command + Shift + Enter(Mac)执行所有语句。 + +## 查询结果默认限制 {#query-result-defaults} + +{{{ .lake }}} 会对工作区输出区域中显示的查询结果应用以下默认限制: + +| 设置 | 默认值 | 说明 | +|---|---|---| +| Max display rows | 10,000 | 预览中仅显示前 10,000 行。 | +| Max display columns | 200 | 预览中仅显示前 200 列。 | +| Max cell content length | 3,000 个字符 | 超过此长度的单元格值会在显示时被截断。 | + +行数和列数限制是固定的。要调整单元格内容的最大长度,请点击结果区域右下角的设置图标并选择一个值(3K–Unlimited)。请注意,将该值设置得非常大或设置为 **Unlimited** 时,在处理大型结果集时可能会导致浏览器变慢或无响应。 + +## 共享工作区 {#sharing-a-worksheet} + +你可以将工作区共享给组织中的所有人或特定个人。为此,请在要共享的工作区中点击 **Share**,或者点击 **Share this Folder** 以共享工作区文件夹。 + +![Alt text](/media/tidb-cloud-lake/share.png) + +在弹出的对话框中,选择共享范围。你可以复制并将链接分享给目标接收者,他们也会收到电子邮件通知。请注意,如果你选择 **Designated Members** 范围,接收者必须点击你分享的链接,共享才会成功。 + +- 要查看其他人共享给你的工作区,请点击侧边栏中的 **Worksheets**,然后点击右侧的 **Shared with Me** 标签页。 +- 当你将工作区共享给其他人时,如果他们具有所需权限,就可以执行其中的 SQL 语句,但无法对这些语句进行任何修改。 + +## 导出查询结果 {#exporting-query-results} + +{{{ .lake }}} 提供了导出查询结果的功能。不过,此功能需要组织 Owner 向团队成员授予 **EXPORT** 权限。出于数据安全考虑,该功能默认处于禁用状态。 + +如果你需要使用此功能,请联系组织 Owner 启用该权限(**Admin** > **Users & Roles**)。 \ No newline at end of file diff --git a/tidb-cloud-lake/lake-overview.md b/tidb-cloud-lake/lake-overview.md new file mode 100644 index 0000000000000..c8fb375758764 --- /dev/null +++ b/tidb-cloud-lake/lake-overview.md @@ -0,0 +1,34 @@ +--- +title: TiDB Cloud Lake 概览 +summary: TiDB Cloud Lake 是面向分析型工作负载的云原生数据仓库服务。它将计算与存储分离,并支持 ANSI SQL、半结构化数据处理以及面向 AI 的工作流。 +--- + +# TiDB Cloud Lake 概览 + +TiDB Cloud Lake 是面向分析型工作负载的云原生数据仓库服务。它将计算与存储分离,使你能够独立配置计算集群,并随着工作负载变化进行扩展,同时以更具成本效益的方式将数据存储在对象存储中。 + +TiDB Cloud Lake 在一个平台中支持 ANSI SQL、半结构化数据处理、向量搜索以及面向 AI 的工作流。它专为希望获得托管式分析体验、而无需自行运维底层基础设施的团队而设计。 + +> **警告:** +> +> TiDB Cloud Lake 当前处于 **public preview** 阶段。随着我们持续改进产品,功能可用性和服务限制可能会发生变化。 + +## 为什么选择 {{{ .lake }}}? {#why-lake} + +{{{ .lake }}} 将分析、向量、搜索和地理空间工作负载整合到一个云原生平台中。借助存储与计算分离、ANSI SQL 支持以及托管式基础设施,团队能够以更高的灵活性、更好的性能和更优的成本效率处理多模态数据。 + +| 功能 | 描述 | 了解更多 | +|---|---|---| +| **统一引擎** | 分析、向量、搜索和地理空间共享同一个优化器和运行时。 | [TiDB Cloud Lake 架构](/tidb-cloud-lake/guides/tidb-cloud-lake-architecture.md) | +| **统一数据** | 结构化、半结构化、非结构化和向量数据共享对象存储。 | [TiDB Cloud Lake 架构](/tidb-cloud-lake/guides/tidb-cloud-lake-architecture.md) | +| **原生分析** | ANSI SQL、窗口函数、增量聚合和流式 BI 在同一平台上运行。 | [工作区](/tidb-cloud-lake/guides/worksheet.md) | +| **原生向量** | Embeddings、向量索引和语义检索都可在 SQL 中运行。 | [向量搜索](/tidb-cloud-lake/guides/vector-search-guide.md) | +| **原生搜索** | 全文搜索和倒排索引为混合检索提供支持。 | [全文索引](/tidb-cloud-lake/guides/full-text-index.md) | +| **原生地理空间** | 地理空间索引和函数为地图与位置服务提供支持。 | [地理空间分析](/tidb-cloud-lake/guides/geo-analytics.md) | + +## 开始使用 {#get-started} + +1. [**快速入门**](/tidb-cloud-lake/lake-quick-start.md):创建你的账户并运行第一个工作流。 +2. [**连接到 TiDB Cloud Lake**](/tidb-cloud-lake/guides/connection-overview.md):为你的工作流选择合适的客户端或驱动。 +3. [**了解架构**](/tidb-cloud-lake/guides/tidb-cloud-lake-architecture.md):了解元信息、计算和存储层。 +4. [**探索产品功能**](/tidb-cloud-lake/guides/vector-search-guide.md):从分析、向量、搜索和地理空间能力开始探索。 \ No newline at end of file diff --git a/tidb-cloud-lake/lake-quick-start.md b/tidb-cloud-lake/lake-quick-start.md new file mode 100644 index 0000000000000..4cf9de5091890 --- /dev/null +++ b/tidb-cloud-lake/lake-quick-start.md @@ -0,0 +1,43 @@ +--- +title: TiDB Cloud Lake 快速入门 +summary: 通过三个步骤开始使用 TiDB Cloud Lake——注册、初始化你的 lake,并探索你的 lake 工作区。 +--- + +# TiDB Cloud Lake 快速入门 + +本教程将引导你通过一种简单的方式开始使用 TiDB Cloud Lake。 + +## 第 1 步:注册 TiDB Cloud {#step-1-sign-up-for-tidb-cloud} + +1. 前往 。 + +2. 注册一个 TiDB Cloud 账户,或使用现有账户登录。 + +## 第 2 步:初始化 TiDB Cloud Lake {#step-2-initialize-tidb-cloud-lake} + +1. 在左侧导航栏中,点击 **My Lake**。 + +2. 在右上角,点击 **Try TiDB Cloud Lake**。系统会打开一个新标签页。 + +3. 按照屏幕上的说明初始化 TiDB Cloud Lake: + + - **Name**:为你的 Lake 输入一个名称。 + - **Plan**:选择适合你的使用场景的套餐。 + - **Cloud Provider and Region**:选择部署 Region。 + +4. 点击 **Create**,并等待初始化完成。 + +## 第 3 步:探索你的 lake 工作区 (Worksheet) {#step-3-explore-your-lake-workspace} + +1. 初始化完成后,在主页上确认 lake 信息,例如 lake 名称、套餐、云服务提供商和 Region。 +2. 使用主页上的入口继续操作: + + - **Connect**:获取连接信息。 + - **Load Data** 或 **Load from Cloud Storage**:开始加载数据。 + - **Query Data**:创建一个 SQL 工作区。 + +## 接下来做什么 {#what-s-next} + +- [**连接到 TiDB Cloud Lake**](/tidb-cloud-lake/guides/connection-overview.md):为你的工作流选择合适的客户端或驱动。 +- [**了解架构**](/tidb-cloud-lake/guides/tidb-cloud-lake-architecture.md):了解元信息、计算和存储层。 +- [**探索产品功能**](/tidb-cloud-lake/guides/vector-search-guide.md):从分析、向量、搜索和地理空间能力开始。 \ No newline at end of file diff --git a/tidb-cloud-lake/sql/abs.md b/tidb-cloud-lake/sql/abs.md new file mode 100644 index 0000000000000..895e38d6731cb --- /dev/null +++ b/tidb-cloud-lake/sql/abs.md @@ -0,0 +1,26 @@ +--- +title: ABS +summary: 返回 x 的绝对值。 +--- + +# ABS + +返回 `x` 的绝对值。 + +## 语法 {#syntax} + +```sql +ABS( ) +``` + +## 示例 {#examples} + +```sql +SELECT ABS(-5); + +┌────────────┐ +│ abs((- 5)) │ +├────────────┤ +│ 5 │ +└────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/acos.md b/tidb-cloud-lake/sql/acos.md new file mode 100644 index 0000000000000..0acafb6bd2834 --- /dev/null +++ b/tidb-cloud-lake/sql/acos.md @@ -0,0 +1,26 @@ +--- +title: ACOS +summary: 返回 `x` 的反余弦,即余弦值为 `x` 的值。如果 `x` 不在 -1 到 1 的范围内,则返回 NULL。 +--- + +# ACOS + +返回 `x` 的反余弦,即余弦值为 `x` 的值。如果 `x` 不在 -1 到 1 的范围内,则返回 NULL。 + +## 语法 {#syntax} + +```sql +ACOS( ) +``` + +## 示例 {#examples} + +```sql +SELECT ACOS(1); + +┌─────────┐ +│ acos(1) │ +├─────────┤ +│ 0 │ +└─────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/add-interval.md b/tidb-cloud-lake/sql/add-interval.md new file mode 100644 index 0000000000000..5f2e8810eb2c5 --- /dev/null +++ b/tidb-cloud-lake/sql/add-interval.md @@ -0,0 +1,84 @@ +--- +title: ADD TIME INTERVAL +summary: 为日期或时间戳添加一个时间间隔,并返回日期或时间戳类型的结果。 +--- + +# ADD TIME INTERVAL + +为日期或时间戳添加一个时间间隔,并返回日期或时间戳类型的结果。 + +## 语法 {#syntax} + +```sql +ADD_YEARS(, ) +ADD_QUARTERs(, ) +ADD_MONTHS(, ) +ADD_DAYS(, ) +ADD_HOURS(, ) +ADD_MINUTES(, ) +ADD_SECONDS(, ) +``` + +## 返回类型 {#return-type} + +`DATE`、`TIMESTAMP`,取决于输入。 + +## 示例 {#examples} + +```sql +SELECT to_date(18875), add_years(to_date(18875), 2); + +┌───────────────────────────────────────────────┐ +│ to_date(18875) │ add_years(to_date(18875), 2) │ +├────────────────┼──────────────────────────────┤ +│ 2021-09-05 │ 2023-09-05 │ +└───────────────────────────────────────────────┘ + +SELECT to_date(18875), add_quarters(to_date(18875), 2); + +┌──────────────────────────────────────────────────┐ +│ to_date(18875) │ add_quarters(to_date(18875), 2) │ +├────────────────┼─────────────────────────────────┤ +│ 2021-09-05 │ 2022-03-05 │ +└──────────────────────────────────────────────────┘ + +SELECT to_date(18875), add_months(to_date(18875), 2); + +┌────────────────────────────────────────────────┐ +│ to_date(18875) │ add_months(to_date(18875), 2) │ +├────────────────┼───────────────────────────────┤ +│ 2021-09-05 │ 2021-11-05 │ +└────────────────────────────────────────────────┘ + +SELECT to_date(18875), add_days(to_date(18875), 2); + +┌──────────────────────────────────────────────┐ +│ to_date(18875) │ add_days(to_date(18875), 2) │ +├────────────────┼─────────────────────────────┤ +│ 2021-09-05 │ 2021-09-07 │ +└──────────────────────────────────────────────┘ + +SELECT to_datetime(1630833797), add_hours(to_datetime(1630833797), 2); + +┌─────────────────────────────────────────────────────────────────┐ +│ to_datetime(1630833797) │ add_hours(to_datetime(1630833797), 2) │ +├─────────────────────────┼───────────────────────────────────────┤ +│ 2021-09-05 09:23:17 │ 2021-09-05 11:23:17 │ +└─────────────────────────────────────────────────────────────────┘ + +SELECT to_datetime(1630833797), add_minutes(to_datetime(1630833797), 2); + +┌───────────────────────────────────────────────────────────────────┐ +│ to_datetime(1630833797) │ add_minutes(to_datetime(1630833797), 2) │ +├─────────────────────────┼─────────────────────────────────────────┤ +│ 2021-09-05 09:23:17 │ 2021-09-05 09:25:17 │ +└───────────────────────────────────────────────────────────────────┘ + +SELECT to_datetime(1630833797), add_seconds(to_datetime(1630833797), 2); + +┌───────────────────────────────────────────────────────────────────┐ +│ to_datetime(1630833797) │ add_seconds(to_datetime(1630833797), 2) │ +├─────────────────────────┼─────────────────────────────────────────┤ +│ 2021-09-05 09:23:17 │ 2021-09-05 09:23:19 │ +└───────────────────────────────────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/add-months.md b/tidb-cloud-lake/sql/add-months.md new file mode 100644 index 0000000000000..9da5b0d7bfd91 --- /dev/null +++ b/tidb-cloud-lake/sql/add-months.md @@ -0,0 +1,95 @@ +--- +title: ADD_MONTHS +summary: add_months() 函数将指定数量的月份添加到给定的日期或时间戳。 +--- + +# ADD_MONTHS + +add_months() 函数将指定数量的月份添加到给定的日期或时间戳。 + +如果输入日期是月末,或者超过结果月份的天数,则结果会调整为新月份的最后一天。否则,将保留原始日期中的日。 + +## 语法 {#syntax} + +```sql +ADD_MONTHS(, ) +``` + +| 参数 | 描述 | +|----------------------|-----------------------------------------------------------------------------| +| `` | 要添加月份的起始日期或时间戳 | +| `` | 要添加的月份整数值(可以为负数,表示减去月份) | + +## 返回类型 {#return-type} + +返回 TIMESTAMP 或 DATE 类型 + +## 示例 {#examples} + +### 基本月份加法 {#basic-month-addition} + +```sql +SELECT ADD_MONTHS('2023-01-15'::DATE, 3); +├───────────────────────────────────┤ +│ 2023-04-15 │ +╰───────────────────────────────────╯ +``` + +### 减去月份 {#subtracting-months} + +```sql +SELECT ADD_MONTHS('2023-06-20'::DATE, -4); +├─────────────────────────────────────┤ +│ 2023-02-20 │ +╰─────────────────────────────────────╯ +``` + +### 月末调整 {#month-end-adjustment} + +```sql +SELECT ADD_MONTHS('2023-01-31'::DATE, 1); +├───────────────────────────────────┤ +│ 2023-02-28 │ +╰───────────────────────────────────╯ +``` + +### 保留时间戳 {#with-timestamp-preservation} + +```sql +SELECT ADD_MONTHS('2023-03-15 14:30:00'::TIMESTAMP, 5); +├─────────────────────────────────────────────────┤ +│ 2023-08-15 14:30:00.000000 │ +╰─────────────────────────────────────────────────╯ +``` + +### 处理月末日期 {#with-last-day-of-month} + +```sql +CREATE TABLE contracts ( + id INT, + sign_date DATE, + duration_months INT +); + +INSERT INTO contracts VALUES + (1, '2023-01-15', 12), + (2, '2024-02-28', 6), + (3, '2023-11-30', 3); + +SELECT + id, + sign_date, + ADD_MONTHS(sign_date, duration_months) AS end_date +FROM contracts; +├─────────────────┼────────────────┼────────────────┤ +│ 1 │ 2023-01-15 │ 2024-01-15 │ +│ 2 │ 2024-02-28 │ 2024-08-28 │ +│ 3 │ 2023-11-30 │ 2024-02-29 │ +╰───────────────────────────────────────────────────╯ + +``` + +## 另请参阅 {#see-also} + +- [DATE_ADD](/tidb-cloud-lake/sql/date-add.md):用于添加特定时间间隔的替代函数 +- [DATE_SUB](/tidb-cloud-lake/sql/date-sub.md):用于减去时间间隔的函数 \ No newline at end of file diff --git a/tidb-cloud-lake/sql/add.md b/tidb-cloud-lake/sql/add.md new file mode 100644 index 0000000000000..44b1e1f870b8e --- /dev/null +++ b/tidb-cloud-lake/sql/add.md @@ -0,0 +1,8 @@ +--- +title: ADD +summary: [PLUS](/tidb-cloud-lake/sql/plus.md) 的别名。 +--- + +# ADD + +[PLUS](/tidb-cloud-lake/sql/plus.md) 的别名。 \ No newline at end of file diff --git a/tidb-cloud-lake/sql/administration-commands.md b/tidb-cloud-lake/sql/administration-commands.md new file mode 100644 index 0000000000000..8bc487a0f19a1 --- /dev/null +++ b/tidb-cloud-lake/sql/administration-commands.md @@ -0,0 +1,56 @@ +--- +title: 管理命令 +summary: 本页提供 {{{ .lake }}} 中系统管理命令的参考信息。 +--- + +# 管理命令 + +本页提供 {{{ .lake }}} 中系统管理命令的参考信息。 + +## 系统监控 {#system-monitoring} + +| 命令 | 描述 | +|---------|-------------| +| **[SHOW PROCESSLIST](/tidb-cloud-lake/sql/show-processlist.md)** | 显示活动查询和连接 | +| **[SHOW METRICS](/tidb-cloud-lake/sql/show-metrics.md)** | 查看系统性能指标 | +| **[KILL](/tidb-cloud-lake/sql/kill.md)** | 终止正在运行的查询或连接 | +| **[RUST BACKTRACE](/tidb-cloud-lake/sql/system-enable-disable-exception-backtrace.md)** | 调试 Rust 堆栈跟踪 | + +## 访问控制 {#access-control} + +| 命令 | 描述 | +|---------|-------------| +| **[FLUSH PRIVILEGES](/tidb-cloud-lake/guides/privileges.md)** | 强制每个查询节点重新加载角色和权限元信息 | + +## 配置管理 {#configuration-management} + +| 命令 | 描述 | +|---------|-------------| +| **[SET](/tidb-cloud-lake/sql/set.md)** | 设置全局配置参数 | +| **[UNSET](/tidb-cloud-lake/sql/unset.md)** | 移除配置设置 | +| **[SET VARIABLE](/tidb-cloud-lake/sql/set-var.md)** | 管理用户定义变量 | +| **[SHOW SETTINGS](/tidb-cloud-lake/sql/show-settings.md)** | 显示当前系统设置 | + +## 函数管理 {#function-management} + +| 命令 | 描述 | +|---------|-------------| +| **[SHOW FUNCTIONS](/tidb-cloud-lake/sql/show-functions.md)** | 列出内置函数 | +| **[SHOW USER FUNCTIONS](/tidb-cloud-lake/sql/show-user-functions.md)** | 列出用户定义函数 | +| **[SHOW TABLE FUNCTIONS](/tidb-cloud-lake/sql/show-table-functions.md)** | 列出表值函数 | + +## 存储维护 {#storage-maintenance} + +| 命令 | 描述 | +|---------|-------------| +| **[VACUUM TABLE](/tidb-cloud-lake/sql/vacuum-table.md)** | 回收表占用的存储空间 | +| **[VACUUM DROP TABLE](/tidb-cloud-lake/sql/vacuum-drop-table.md)** | 清理已删除表的数据 | +| **[VACUUM TEMP FILES](/tidb-cloud-lake/sql/vacuum-temporary-files.md)** | 移除临时文件 | +| **[VACUUM VIRTUAL COLUMN](/tidb-cloud-lake/sql/vacuum-virtual-column.md)** | 移除过时的虚拟列文件 | +| **[SHOW INDEXES](/tidb-cloud-lake/sql/show-indexes.md)** | 显示表索引 | + +## 动态执行 {#dynamic-execution} + +| 命令 | 描述 | +|---------|-------------| +| **[EXECUTE IMMEDIATE](/tidb-cloud-lake/sql/execute-immediate.md)** | 执行动态构造的 SQL 语句 | \ No newline at end of file diff --git a/tidb-cloud-lake/sql/age.md b/tidb-cloud-lake/sql/age.md new file mode 100644 index 0000000000000..d4c351143dbf5 --- /dev/null +++ b/tidb-cloud-lake/sql/age.md @@ -0,0 +1,92 @@ +--- +title: AGE +summary: age() 函数用于计算两个时间戳之间的差值,或一个时间戳与当前日期和时间之间的差值。 +--- + +# AGE + +age() 函数用于计算两个时间戳之间的差值,或一个时间戳与当前日期和时间之间的差值。 + +## 语法 {#syntax} + +```sql +AGE(, ) +``` + +| 参数 | 描述 | +|----------------------|-----------------------------------------------------------------------------| +| `` | 结束时间戳 | +| `` | 起始时间戳 | + +## 返回类型 {#return-type} + +返回 INTERVAL 类型 + +## 计算逻辑 {#calculation-logic} + +该函数计算以下内容: + +1. 完整的年份差值(考虑闰年) +2. 剩余的月份差值(考虑每个月长度不同) +3. 剩余的天数差值(包括时间部分) + +当 `` 早于 `` 时,返回负的时间间隔。 + +## 示例 {#examples} + +### 基本 age 计算 {#basic-age-calculation} + +```sql +SELECT AGE('2023-03-15'::TIMESTAMP, '2020-01-20'::TIMESTAMP); +├─────────────────────────┤ +│ 3 years 1 month 26 days │ +╰─────────────────────────╯ +``` + +### 逆向时间顺序 {#reverse-chronology} + +```sql +SELECT AGE('2018-12-25'::TIMESTAMP, '2022-05-10'::TIMESTAMP); +├─────────────────────────────┤ +│ -3 years -4 months -16 days │ +╰─────────────────────────────╯ +``` + +### 包含时间部分 {#with-time-components} + +```sql +SELECT AGE('2023-02-28 14:00:00'::TIMESTAMP, '2023-02-27 08:30:00'::TIMESTAMP); +├───────────────┤ +│ 1 day 5:30:00 │ +╰───────────────╯ +``` + +### 表数据处理 {#table-data-processing} + +```sql +CREATE TABLE projects ( + name String, + start_date TIMESTAMP, + end_date TIMESTAMP +); + +INSERT INTO projects VALUES + ('Alpha', '2020-06-01', '2023-09-30'), + ('Beta', '2022-01-15', '2022-11-01'); + +SELECT + name, + AGE(end_date, start_date) AS duration +FROM projects; +╭─────────────────────────────────────────────╮ +│ name │ duration │ +│ Nullable(String) │ Nullable(Interval) │ +├──────────────────┼──────────────────────────┤ +│ Alpha │ 3 years 3 months 29 days │ +│ Beta │ 9 months 17 days │ +╰─────────────────────────────────────────────╯ +``` + +## 另请参阅 {#see-also} + +- [DATE_DIFF](/tidb-cloud-lake/sql/date-diff.md):用于计算特定时间单位差值的替代函数 \ No newline at end of file diff --git a/tidb-cloud-lake/sql/aggregate-functions.md b/tidb-cloud-lake/sql/aggregate-functions.md new file mode 100644 index 0000000000000..93fe008630418 --- /dev/null +++ b/tidb-cloud-lake/sql/aggregate-functions.md @@ -0,0 +1,109 @@ +--- +title: 聚合函数 +summary: 本页按功能对 {{{ .lake }}} 中的聚合函数进行了全面概览,便于快速查阅。 +--- + +# 聚合函数 + +本页按功能对 {{{ .lake }}} 中的聚合函数进行了全面概览,便于快速查阅。 + +## 基本聚合 {#basic-aggregation} + +| 函数 | 描述 | 示例 | +|----------|-------------|---------| +| [COUNT](/tidb-cloud-lake/sql/count.md) | 统计行数或非 NULL 值的数量 | `COUNT(*)` → `10` | +| [COUNT_DISTINCT](/tidb-cloud-lake/sql/count-distinct.md) | 统计不同值的数量 | `COUNT(DISTINCT city)` → `5` | +| [APPROX_COUNT_DISTINCT](/tidb-cloud-lake/sql/approx-count-distinct.md) | 近似统计不同值的数量 | `APPROX_COUNT_DISTINCT(user_id)` → `9955` | +| [SUM](/tidb-cloud-lake/sql/sum.md) | 计算值的总和 | `SUM(sales)` → `1250.75` | +| [AVG](/tidb-cloud-lake/sql/avg.md) | 计算值的平均值 | `AVG(temperature)` → `72.5` | +| [MIN](/tidb-cloud-lake/sql/min.md) | 返回最小值 | `MIN(price)` → `9.99` | +| [MAX](/tidb-cloud-lake/sql/max.md) | 返回最大值 | `MAX(price)` → `99.99` | +| [ANY_VALUE](/tidb-cloud-lake/sql/any-value.md) | 返回组中的任意一个值 | `ANY_VALUE(status)` → `'active'` | + +## 条件聚合 {#conditional-aggregation} + +| 函数 | 描述 | 示例 | +|----------|-------------|---------| +| [COUNT_IF](/tidb-cloud-lake/sql/count-if.md) | 统计满足条件的行数 | `COUNT_IF(price > 100)` → `5` | +| [SUM_IF](/tidb-cloud-lake/sql/sum-if.md) | 对满足条件的值求和 | `SUM_IF(amount, status = 'completed')` → `750.25` | +| [AVG_IF](/tidb-cloud-lake/sql/avg-if.md) | 计算满足条件的值的平均值 | `AVG_IF(score, passed = true)` → `85.6` | +| [MIN_IF](/tidb-cloud-lake/sql/min-if.md) | 在条件为 true 时返回最小值 | `MIN_IF(temp, location = 'outside')` → `45.2` | +| [MAX_IF](/tidb-cloud-lake/sql/max-if.md) | 在条件为 true 时返回最大值 | `MAX_IF(speed, vehicle = 'car')` → `120.5` | + +## 统计函数 {#statistical-functions} + +| 函数 | 描述 | 示例 | +|----------|-------------|---------| +| [VAR_POP](/tidb-cloud-lake/sql/var-pop.md) / [VARIANCE_POP](/tidb-cloud-lake/sql/variance-pop.md) | 总体方差 | `VAR_POP(height)` → `10.25` | +| [VAR_SAMP](/tidb-cloud-lake/sql/var-samp.md) / [VARIANCE_SAMP](/tidb-cloud-lake/sql/variance-samp.md) | 样本方差 | `VAR_SAMP(height)` → `12.3` | +| [STDDEV_POP](/tidb-cloud-lake/sql/stddev-pop.md) | 总体标准差 | `STDDEV_POP(height)` → `3.2` | +| [STDDEV_SAMP](/tidb-cloud-lake/sql/stddev-samp.md) | 样本标准差 | `STDDEV_SAMP(height)` → `3.5` | +| [COVAR_POP](/tidb-cloud-lake/sql/covar-pop.md) | 总体协方差 | `COVAR_POP(x, y)` → `2.5` | +| [COVAR_SAMP](/tidb-cloud-lake/sql/covar-samp.md) | 样本协方差 | `COVAR_SAMP(x, y)` → `2.7` | +| [KURTOSIS](/tidb-cloud-lake/sql/kurtosis.md) | 衡量分布的峰度 | `KURTOSIS(values)` → `2.1` | +| [SKEWNESS](/tidb-cloud-lake/sql/skewness.md) | 衡量分布的偏斜程度 | `SKEWNESS(values)` → `0.2` | + +## 百分位与分布 {#percentile-and-distribution} + +| 函数 | 描述 | 示例 | +|----------|-------------|---------| +| [MEDIAN](/tidb-cloud-lake/sql/median.md) | 计算中位数 | `MEDIAN(response_time)` → `125` | +| [MODE](/tidb-cloud-lake/sql/mode.md) | 返回出现频率最高的值 | `MODE(category)` → `'electronics'` | +| [QUANTILE_CONT](/tidb-cloud-lake/sql/quantile-cont.md) | 连续插值分位数 | `QUANTILE_CONT(0.95)(response_time)` → `350.5` | +| [QUANTILE_DISC](/tidb-cloud-lake/sql/quantile-disc.md) | 离散分位数 | `QUANTILE_DISC(0.5)(age)` → `35` | +| [QUANTILE_TDIGEST](/tidb-cloud-lake/sql/quantile-tdigest.md) | 使用 t-digest 近似计算分位数 | `QUANTILE_TDIGEST(0.9)(values)` → `95.2` | +| [QUANTILE_TDIGEST_WEIGHTED](/tidb-cloud-lake/sql/quantile-tdigest-weighted.md) | 加权 t-digest 分位数 | `QUANTILE_TDIGEST_WEIGHTED(0.5)(values, weights)` → `50.5` | +| [MEDIAN_TDIGEST](/tidb-cloud-lake/sql/median-tdigest.md) | 使用 t-digest 近似计算中位数 | `MEDIAN_TDIGEST(response_time)` → `124.5` | +| [HISTOGRAM](/tidb-cloud-lake/sql/histogram.md) | 创建直方图存储桶 | `HISTOGRAM(10)(values)` → `[{...}]` | + +## 数组与集合聚合 {#array-and-collection-aggregation} + +| 函数 | 描述 | 示例 | +|----------|-------------|---------| +| [ARRAY_AGG](/tidb-cloud-lake/sql/array-agg.md) | 将值收集到数组中 | `ARRAY_AGG(product)` → `['A', 'B', 'C']` | +| [GROUP_ARRAY_MOVING_AVG](/tidb-cloud-lake/sql/group-array-moving-avg.md) | 计算数组上的移动平均值 | `GROUP_ARRAY_MOVING_AVG(3)(values)` → `[null, null, 3.0, 6.0, 9.0]` | +| [GROUP_ARRAY_MOVING_SUM](/tidb-cloud-lake/sql/group-array-moving-sum.md) | 计算数组上的移动和 | `GROUP_ARRAY_MOVING_SUM(2)(values)` → `[null, 3, 7, 11, 15]` | + +## 地理空间聚合 {#geospatial-aggregation} + +| 函数 | 描述 | 示例 | +|----------|-------------|---------| +| [ST_UNION_AGG](/tidb-cloud-lake/sql/st-union-agg.md) | 对组内的 GEOMETRY 值执行联合体操作 | `ST_UNION_AGG(geom)` → `MULTIPOINT(...)` | +| [ST_INTERSECTION_AGG](/tidb-cloud-lake/sql/st-intersection-agg.md) | 对组内的 GEOMETRY 值执行相交操作 | `ST_INTERSECTION_AGG(geom)` → `POLYGON(...)` | +| [ST_ENVELOPE_AGG](/tidb-cloud-lake/sql/st-envelope-agg.md) | 返回组内 GEOMETRY 值的外接矩形 | `ST_ENVELOPE_AGG(geom)` → `POLYGON(...)` | +| [ST_COLLECT](/tidb-cloud-lake/sql/st-collect.md) | 将 GEOMETRY 值收集为一个 GEOMETRY 结果 | `ST_COLLECT(geom)` → `GEOMETRYCOLLECTION(...)` | + +## 字符串聚合 {#string-aggregation} + +| 函数 | 描述 | 示例 | +|----------|-------------|---------| +| [GROUP_CONCAT](/tidb-cloud-lake/sql/group-concat.md) | 使用分隔符连接值 | `GROUP_CONCAT(city, ', ')` → `'New York, London, Tokyo'` | +| [STRING_AGG](/tidb-cloud-lake/sql/string-agg.md) | 使用分隔符连接字符串 | `STRING_AGG(tag, ',')` → `'red,green,blue'` | +| [LISTAGG](/tidb-cloud-lake/sql/listagg.md) | 使用分隔符连接值 | `LISTAGG(name, ', ')` → `'Alice, Bob, Charlie'` | + +## JSON 聚合 {#json-aggregation} + +| 函数 | 描述 | 示例 | +|----------|-------------|---------| +| [JSON_ARRAY_AGG](/tidb-cloud-lake/sql/json-array-agg.md) | 将值聚合为 JSON 数组 | `JSON_ARRAY_AGG(name)` → `'["Alice", "Bob", "Charlie"]'` | +| [JSON_OBJECT_AGG](/tidb-cloud-lake/sql/json-object-agg.md) | 从键值对创建 JSON 对象 | `JSON_OBJECT_AGG(name, score)` → `'{"Alice": 95, "Bob": 87}'` | + +## 参数选择 {#argument-selection} + +| 函数 | 描述 | 示例 | +|----------|-------------|---------| +| [ARG_MAX](/tidb-cloud-lake/sql/arg-max.md) | 返回 expr2 最大时对应的 expr1 值 | `ARG_MAX(name, score)` → `'Alice'` | +| [ARG_MIN](/tidb-cloud-lake/sql/arg-min.md) | 返回 expr2 最小时对应的 expr1 值 | `ARG_MIN(name, score)` → `'Charlie'` | + +## 漏斗分析 {#funnel-analysis} + +| 函数 | 描述 | 示例 | +|----------|-------------|---------| +| [RETENTION](/tidb-cloud-lake/sql/retention.md) | 计算留存率 | `RETENTION(action = 'signup', action = 'purchase')` → `[100, 40]` | +| [WINDOWFUNNEL](/tidb-cloud-lake/sql/window-funnel.md) | 在时间窗口内搜索事件序列 | `WINDOWFUNNEL(1800)(timestamp, event='view', event='click', event='purchase')` → `2` | + +## 匿名化 {#anonymization} + +| 函数 | 描述 | 示例 | +|----------|-------------|---------| +| [MARKOV_TRAIN](/tidb-cloud-lake/sql/markov-train.md) | 训练 markov 模型 | `MARKOV_TRAIN(address)` | \ No newline at end of file diff --git a/tidb-cloud-lake/sql/aggregating-index-sql.md b/tidb-cloud-lake/sql/aggregating-index-sql.md new file mode 100644 index 0000000000000..64c161a76da9f --- /dev/null +++ b/tidb-cloud-lake/sql/aggregating-index-sql.md @@ -0,0 +1,24 @@ +--- +title: 聚合索引 +summary: 本页按功能分类,全面概述了 {{{ .lake }}} 中聚合索引的相关操作,便于参考。 +--- + +# 聚合索引 + +本页按功能分类,全面概述了 {{{ .lake }}} 中聚合索引的相关操作,便于参考。 + +## 聚合索引管理 {#aggregating-index-management} + +| 命令 | 描述 | +|---------|-------------| +| [CREATE AGGREGATING INDEX](/tidb-cloud-lake/sql/create-aggregating-index.md) | 为表创建新的聚合索引 | +| [DROP AGGREGATING INDEX](/tidb-cloud-lake/sql/drop-aggregating-index.md) | 删除聚合索引 | +| [REFRESH AGGREGATING INDEX](/tidb-cloud-lake/sql/refresh-aggregating-index.md) | 使用最新数据更新聚合索引 | + +## 相关主题 {#related-topics} + +- [聚合索引](/tidb-cloud-lake/guides/aggregating-index.md) + +> **注意:** +> +> {{{ .lake }}} 中的聚合索引用于通过预先计算并存储聚合结果来提升聚合查询的性能。 \ No newline at end of file diff --git a/tidb-cloud-lake/sql/alter-cluster-key.md b/tidb-cloud-lake/sql/alter-cluster-key.md new file mode 100644 index 0000000000000..5ac9a5e3c74a0 --- /dev/null +++ b/tidb-cloud-lake/sql/alter-cluster-key.md @@ -0,0 +1,39 @@ +--- +title: ALTER CLUSTER KEY +summary: 更改表的 cluster key。 +--- + +# ALTER CLUSTER KEY + +更改表的 cluster key。 + +另请参阅:[DROP CLUSTER KEY](/tidb-cloud-lake/sql/drop-cluster-key.md) + +## 语法 {#syntax} + +```sql +ALTER TABLE [ IF EXISTS ] CLUSTER BY ( [ , ... ] ) +``` + +## 示例 {#examples} + +```sql +-- Create table +CREATE TABLE IF NOT EXISTS playground(a int, b int); + +-- Add cluster key by columns +ALTER TABLE playground CLUSTER BY(b,a); + +INSERT INTO playground VALUES(0,3),(1,1); +INSERT INTO playground VALUES(1,3),(2,1); +INSERT INTO playground VALUES(4,4); + +SELECT * FROM playground ORDER BY b,a; +SELECT * FROM clustering_information('db1','playground'); + +-- Delete cluster key +ALTER TABLE playground DROP CLUSTER KEY; + +-- Add cluster key by expressions +ALTER TABLE playground CLUSTER BY(rand()+a); +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/alter-database.md b/tidb-cloud-lake/sql/alter-database.md new file mode 100644 index 0000000000000..7bcebb35f0825 --- /dev/null +++ b/tidb-cloud-lake/sql/alter-database.md @@ -0,0 +1,97 @@ +--- +title: ALTER DATABASE +summary: 修改数据库名称,或为数据库设置默认存储选项。 +--- + +# ALTER DATABASE + +修改数据库名称,或为数据库设置默认存储选项。 + +## 语法 {#syntax} + +```sql +-- Rename a database +ALTER DATABASE [ IF EXISTS ] RENAME TO + +-- Set default storage options +ALTER DATABASE [ IF EXISTS ] SET OPTIONS ( + DEFAULT_STORAGE_CONNECTION = '' + | DEFAULT_STORAGE_PATH = '' +) +``` + +## 参数 {#parameters} + +| 参数 | 描述 | +|:-----------------------------|:-------------------------------------------------------------------------------------------------------------------------------------------------| +| `DEFAULT_STORAGE_CONNECTION` | 现有连接的名称(通过 `CREATE CONNECTION` 创建),用作此数据库中表的默认存储连接。 | +| `DEFAULT_STORAGE_PATH` | 此数据库中表的默认存储路径 URI(例如 `s3://bucket/path/`)。必须以 `/` 结尾,并且与连接的存储类型匹配。 | + +> **注意:** +> +> - `SET OPTIONS` 仅影响在语句执行后创建的表。现有表不会被修改。 +> - 你一次只能修改一个选项,前提是另一个选项已存在于该数据库上。 + +## 示例 {#examples} + +### 重命名数据库 {#rename-a-database} + +```sql +CREATE DATABASE LAKE; +``` + +```sql +SHOW DATABASES; ++--------------------+ +| Database | ++--------------------+ +| LAKE | +| information_schema | +| default | +| system | ++--------------------+ +``` + +```sql +ALTER DATABASE `LAKE` RENAME TO `NEW_LAKE`; +``` + +```sql +SHOW DATABASES; ++--------------------+ +| Database | ++--------------------+ +| information_schema | +| NEW_LAKE | +| default | +| system | ++--------------------+ +``` + +### 设置默认存储选项 {#set-default-storage-options} + +```sql +ALTER DATABASE analytics SET OPTIONS ( + DEFAULT_STORAGE_CONNECTION = 'my_s3', + DEFAULT_STORAGE_PATH = 's3://mybucket/analytics_v2/' +); +``` + +## 标签操作 {#tag-operations} + +为数据库分配或移除标签。必须先使用 [CREATE TAG](/tidb-cloud-lake/sql/create-tag.md) 创建标签。完整详情请参见 [SET TAG / UNSET TAG](/tidb-cloud-lake/sql/set-tag.md)。 + +### 语法 {#syntax} + +```sql +ALTER DATABASE [ IF EXISTS ] SET TAG = '' [, = '' ...] + +ALTER DATABASE [ IF EXISTS ] UNSET TAG [, ...] +``` + +### 示例 {#examples} + +```sql +ALTER DATABASE mydb SET TAG env = 'prod', owner = 'team_a'; +ALTER DATABASE mydb UNSET TAG env, owner; +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/alter-function-sql.md b/tidb-cloud-lake/sql/alter-function-sql.md new file mode 100644 index 0000000000000..d5dcfc1629830 --- /dev/null +++ b/tidb-cloud-lake/sql/alter-function-sql.md @@ -0,0 +1,39 @@ +--- +title: ALTER FUNCTION +summary: 修改外部函数。 +--- + +# ALTER FUNCTION + +修改外部函数。 + +## 语法 {#syntax} + +```sql +ALTER FUNCTION [ IF NOT EXISTS ] + AS ( ) RETURNS LANGUAGE + HANDLER = '' ADDRESS = '' + [DESC=''] +``` + +| 参数 | 描述 | +|-----------------------|---------------------------------------------------------------------------------------------------| +| `` | 函数的名称。 | +| `` | 定义函数行为的 lambda 表达式或代码片段。 | +| `DESC=''` | UDF 的描述。| +| `<`| 输入参数名称列表,以逗号分隔。| +| `<`| 输入参数类型列表,以逗号分隔。| +| `` | 函数的返回类型。 | +| `LANGUAGE` | 指定编写函数所使用的语言。可用值:`python`。 | +| `HANDLER = ''` | 指定函数 handler 的名称。 | +| `ADDRESS = ''` | 指定 UDF 服务器的地址。 | + +## 示例 {#examples} + +```sql +-- Create an external function +CREATE FUNCTION gcd (INT, INT) RETURNS INT LANGUAGE python HANDLER = 'gcd' ADDRESS = 'https://udf.example.com'; + +-- Modify the handler of the external function +ALTER FUNCTION gcd (INT, INT) RETURNS INT LANGUAGE python HANDLER = 'gcd_new' ADDRESS = 'https://udf.example.com'; +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/alter-function.md b/tidb-cloud-lake/sql/alter-function.md new file mode 100644 index 0000000000000..db64f5d261e1d --- /dev/null +++ b/tidb-cloud-lake/sql/alter-function.md @@ -0,0 +1,103 @@ +--- +title: ALTER FUNCTION +summary: 修改用户定义函数。支持所有函数类型:Scalar SQL、Tabular SQL 和 Embedded functions。 +--- + +# ALTER FUNCTION + +修改用户定义函数。支持所有函数类型:Scalar SQL、Tabular SQL 和 Embedded functions。 + +## 语法 {#syntax} + +### 对于 Scalar SQL Functions {#for-scalar-sql-functions} + +```sql +ALTER FUNCTION [ IF EXISTS ] + ( [] ) + RETURNS + AS $$ $$ + [ DESC='' ] +``` + +### 对于 Tabular SQL Functions {#for-tabular-sql-functions} + +```sql +ALTER FUNCTION [ IF EXISTS ] + ( [] ) + RETURNS TABLE ( ) + AS $$ $$ + [ DESC='' ] +``` + +### 对于 Embedded Functions {#for-embedded-functions} + +```sql +ALTER FUNCTION [ IF EXISTS ] + ( [] ) + RETURNS + LANGUAGE + [IMPORTS = ('', ...)] + [PACKAGES = ('', ...)] + HANDLER = '' + AS $$ $$ + [ DESC='' ] +``` + +## 示例 {#examples} + +### 修改 Scalar SQL Function {#altering-scalar-sql-function} + +```sql +-- Create a scalar function +CREATE FUNCTION calculate_tax(income DECIMAL) +RETURNS DECIMAL +AS $$ income * 0.2 $$; + +-- Modify the function to use progressive tax rate +ALTER FUNCTION calculate_tax(income DECIMAL) +RETURNS DECIMAL +AS $$ + CASE + WHEN income <= 50000 THEN income * 0.15 + ELSE income * 0.25 + END +$$; +``` + +### 修改 Tabular SQL Function {#altering-tabular-sql-function} + +```sql +-- Create a table function +CREATE FUNCTION get_employees() +RETURNS TABLE (id INT, name VARCHAR(100)) +AS $$ SELECT id, name FROM employees $$; + +-- Modify to include department and salary +ALTER FUNCTION get_employees() +RETURNS TABLE (id INT, name VARCHAR(100), department VARCHAR(100), salary DECIMAL) +AS $$ SELECT id, name, department, salary FROM employees $$; +``` + +### 修改 Embedded Function {#altering-embedded-function} + +```sql +-- Create a Python function +CREATE FUNCTION simple_calc(x INT) +RETURNS INT +LANGUAGE python +HANDLER = 'calc' +AS $$ +def calc(x): + return x * 2 +$$; + +-- Modify to use a different calculation +ALTER FUNCTION simple_calc(x INT) +RETURNS INT +LANGUAGE python +HANDLER = 'calc' +AS $$ +def calc(x): + return x * 3 + 1 +$$; +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/alter-network-policy.md b/tidb-cloud-lake/sql/alter-network-policy.md new file mode 100644 index 0000000000000..da48924e8af42 --- /dev/null +++ b/tidb-cloud-lake/sql/alter-network-policy.md @@ -0,0 +1,39 @@ +--- +title: ALTER NETWORK POLICY +summary: 修改 {{{ .lake }}} 中现有的网络策略。 +--- + +# ALTER NETWORK POLICY + +修改 {{{ .lake }}} 中现有的网络策略。 + +## 语法 {#syntax} + +```sql +ALTER NETWORK POLICY [ IF EXISTS ] + SET [ ALLOWED_IP_LIST = ('allowed_ip1', 'allowed_ip2', ...) ] + [ BLOCKED_IP_LIST = ('blocked_ip1', 'blocked_ip2', ...) ] + [ COMMENT = 'comment' ] +``` + +| 参数 | 描述 | +|----------------- |----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| policy_name | 指定要修改的网络策略名称。 | +| ALLOWED_IP_LIST | 指定要为该策略修改的、以逗号分隔的允许 IP 地址范围列表。这会用新提供的列表覆盖现有的允许 IP 地址列表。 | +| BLOCKED_IP_LIST | 指定要为该策略修改的、以逗号分隔的阻止 IP 地址范围列表。这会用新提供的列表覆盖现有的阻止 IP 地址列表。如果将此参数设置为空列表 `()`,则会移除所有阻止 IP 地址限制。 | +| COMMENT | 可选参数,用于修改与网络策略关联的描述或注释。 | + +> **注意:** +> +> 此命令支持灵活地仅修改允许 IP 列表或阻止 IP 列表中的任意一个,同时保持另一个列表不变。`ALLOWED_IP_LIST` 和 `BLOCKED_IP_LIST` 都是可选参数。 + +## 示例 {#examples} + +```sql +-- Modify the network policy test_policy to change the blocked IP address list from ('192.168.1.99') to ('192.168.1.10'): +ALTER NETWORK POLICY test_policy SET BLOCKED_IP_LIST=('192.168.1.10') + +-- Update the network policy test_policy to allow IP address ranges ('192.168.10.0', '192.168.20.0') and remove any blocked IP address restrictions. Also, change the comment to 'new comment': + +ALTER NETWORK POLICY test_policy SET ALLOWED_IP_LIST=('192.168.10.0', '192.168.20.0') BLOCKED_IP_LIST=() COMMENT='new comment' +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/alter-notification-integration.md b/tidb-cloud-lake/sql/alter-notification-integration.md new file mode 100644 index 0000000000000..fb5bed7c99e67 --- /dev/null +++ b/tidb-cloud-lake/sql/alter-notification-integration.md @@ -0,0 +1,43 @@ +--- +title: ALTER NOTIFICATION INTEGRATION +summary: 修改已命名通知集成的设置,该集成可用于向外部消息服务发送通知。 +--- + +# ALTER NOTIFICATION INTEGRATION + +修改已命名通知集成的设置,该集成可用于向外部消息服务发送通知。 + +**注意:** 此功能开箱即用仅适用于 {{{ .lake }}}。 + +## 语法 {#syntax} + +### Webhook 通知 {#webhook-notification} + +```sql +ALTER NOTIFICATION INTEGRATION [ IF NOT EXISTS ] SET + [ ENABLED = TRUE | FALSE ] + [ WEBHOOK = ( url = , method = , authorization_header = ) ] + [ COMMENT = '' ] +``` + +| 必需参数 | 描述 | +|---------------------|-------------| +| name | 通知集成的名称。这是一个必填字段。 | + +| 可选参数 [(Webhook)](#webhook-notification) | 描述 | +|---------------------|-------------| +| enabled | 通知集成是否启用。 | +| url | webhook 的 URL。 | +| method | 发送 webhook 时使用的 HTTP 方法。默认值为 `GET`| +| authorization_header| 发送 webhook 时使用的授权请求头。 | +| comment | 与通知集成关联的注释。 | + +## 示例 {#examples} + +### Webhook 通知 {#webhook-notification} + +```sql +ALTER NOTIFICATION INTEGRATION SampleNotification SET enabled = true +``` + +此示例启用了名为 `SampleNotification` 的通知集成。 \ No newline at end of file diff --git a/tidb-cloud-lake/sql/alter-password-policy.md b/tidb-cloud-lake/sql/alter-password-policy.md new file mode 100644 index 0000000000000..2d0f1b2d7c9b9 --- /dev/null +++ b/tidb-cloud-lake/sql/alter-password-policy.md @@ -0,0 +1,57 @@ +--- +title: ALTER PASSWORD POLICY +summary: 修改 {{{ .lake }}} 中现有的密码策略。 +--- + +# ALTER PASSWORD POLICY + +修改 {{{ .lake }}} 中现有的密码策略。 + +## 语法 {#syntax} + +```sql +-- Modify existing password policy attributes +ALTER PASSWORD POLICY [ IF EXISTS ] SET + [ PASSWORD_MIN_LENGTH = ] + [ PASSWORD_MAX_LENGTH = ] + [ PASSWORD_MIN_UPPER_CASE_CHARS = ] + [ PASSWORD_MIN_LOWER_CASE_CHARS = ] + [ PASSWORD_MIN_NUMERIC_CHARS = ] + [ PASSWORD_MIN_SPECIAL_CHARS = ] + [ PASSWORD_MIN_AGE_DAYS = ] + [ PASSWORD_MAX_AGE_DAYS = ] + [ PASSWORD_MAX_RETRIES = ] + [ PASSWORD_LOCKOUT_TIME_MINS = ] + [ PASSWORD_HISTORY = ] + [ COMMENT = '' ] + +-- Remove specific password policy attributes +ALTER PASSWORD POLICY [ IF EXISTS ] UNSET + [ PASSWORD_MIN_LENGTH ] + [ PASSWORD_MAX_LENGTH ] + [ PASSWORD_MIN_UPPER_CASE_CHARS ] + [ PASSWORD_MIN_LOWER_CASE_CHARS ] + [ PASSWORD_MIN_NUMERIC_CHARS ] + [ PASSWORD_MIN_SPECIAL_CHARS ] + [ PASSWORD_MIN_AGE_DAYS ] + [ PASSWORD_MAX_AGE_DAYS ] + [ PASSWORD_MAX_RETRIES ] + [ PASSWORD_LOCKOUT_TIME_MINS ] + [ PASSWORD_HISTORY ] + [ COMMENT ] +``` + +有关密码策略属性的详细说明,请参见[密码策略属性](/tidb-cloud-lake/sql/create-password-policy.md#password-policy-attributes)。 + +## 示例 {#examples} + +以下示例创建了一个名为 `SecureLogin` 的密码策略,将密码最小长度要求设置为 10 个字符,随后将其修改为允许密码长度在 10 到 16 个字符之间: + +```sql +CREATE PASSWORD POLICY SecureLogin + PASSWORD_MIN_LENGTH = 10; + +ALTER PASSWORD POLICY SecureLogin SET + PASSWORD_MIN_LENGTH = 10 + PASSWORD_MAX_LENGTH = 16; +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/alter-table.md b/tidb-cloud-lake/sql/alter-table.md new file mode 100644 index 0000000000000..3c51f7855da26 --- /dev/null +++ b/tidb-cloud-lake/sql/alter-table.md @@ -0,0 +1,484 @@ +--- +title: ALTER TABLE +summary: 使用 ALTER TABLE 修改现有表的结构和属性,包括其列、注释、存储选项、外部连接,甚至与另一张表交换元信息。以下各小节介绍了每种受支持的功能。 +--- + +# ALTER TABLE + +使用 `ALTER TABLE` 修改现有表的结构和属性,包括其列、注释、存储选项、外部连接,甚至与另一张表交换元信息。以下各小节介绍了每种受支持的功能。 + +## 列操作 {#column-operations} + +通过添加、转换、重命名、更改或删除列来修改表。 + +### 语法 {#syntax} + +```sql +-- Add a column to the end of the table +ALTER TABLE [ IF EXISTS ] [ . ] +ADD [ COLUMN ] [ NOT NULL | NULL ] [ DEFAULT ] + +-- Add a column to a specified position +ALTER TABLE [ IF EXISTS ] [ . ] +ADD [ COLUMN ] [ NOT NULL | NULL ] [ DEFAULT ] [ FIRST | AFTER ] + +-- Add a virtual computed column +ALTER TABLE [ IF EXISTS ] [ . ] +ADD [ COLUMN ] AS () VIRTUAL + +-- Convert a stored computed column to a regular column +ALTER TABLE [ IF EXISTS ] [ . ] +MODIFY [ COLUMN ] DROP STORED + +-- Rename a column +ALTER TABLE [ IF EXISTS ] [ . ] +RENAME [ COLUMN ] TO + +-- Change data type +ALTER TABLE [ IF EXISTS ] [ . ] +MODIFY [ COLUMN ] [ DEFAULT ] + [ , [ COLUMN ] [ DEFAULT ] ] + ... + +-- Change comment +ALTER TABLE [ IF EXISTS ] [ . ] +MODIFY [ COLUMN ] [ COMMENT '' ] +[ , [ COLUMN ] [ COMMENT '' ] ] +... + +-- Set / Unset masking policy for a column +ALTER TABLE [ IF EXISTS ] [ . ] +MODIFY [ COLUMN ] SET MASKING POLICY + [ USING ( [ , ... ] ) ] + +ALTER TABLE [ IF EXISTS ] [ . ] +MODIFY [ COLUMN ] UNSET MASKING POLICY + +-- Remove a column +ALTER TABLE [ IF EXISTS ] [ . ] +DROP [ COLUMN ] +``` + +**注意:** + +- 添加或修改列时,默认值只能接受常量值。如果使用非常量表达式,则会报错。 +- 目前尚不支持使用 ALTER TABLE 添加 stored computed column。 +- 更改表列的数据类型时,存在转换错误的风险。例如,如果尝试将包含文本(String)的列转换为数字(Float),可能会导致问题。 +- 为列设置 masking policy 时,请确保策略中定义的数据类型(参见 [CREATE MASKING POLICY](/tidb-cloud-lake/sql/create-masking-policy.md) 语法中的参数 *arg_type_to_mask*)与该列匹配。 +- 当策略定义需要额外参数时,请使用可选的 `USING` 子句。按顺序列出映射到每个策略参数的列;第一个参数始终表示被脱敏的列。 +- 如果包含 `USING`,则至少需要提供被脱敏的列,以及策略所需的其他附加列。`USING (...)` 中的第一个标识符必须与正在修改的列一致。 +- masking policy 只能附加到普通表。视图、stream 和临时表不允许使用 `SET MASKING POLICY`。 +- 一列最多只能属于一个安全策略(masking 或 row-level)。在附加新策略之前,请先移除现有策略。 +- 附加、分离、描述或删除 masking policy 需要全局 `APPLY MASKING POLICY` 权限,或针对特定 masking policy 的 APPLY/OWNERSHIP 权限。 +- 添加或删除 row access policy 需要目标表上的 `ALTER` 权限,以及全局 `APPLY ROW ACCESS POLICY` 权限,或该策略上的 APPLY/OWNERSHIP 权限。描述或删除策略需要相同的策略权限。 + +> **注意:** +> +> 在更改列定义或删除列之前,必须先执行 `ALTER TABLE ... MODIFY COLUMN
UNSET MASKING POLICY`;否则该语句会失败,因为该列仍受安全策略保护。 + +### 示例 {#examples} + +#### 示例 1:添加、重命名和删除列 {#example-1-adding-renaming-and-removing-a-column} + +本示例展示了如何创建名为 "default.users" 的表,其中包含 'username'、'email' 和 'age' 列。示例还演示了如何添加带有不同约束的 'id' 和 'middle_name' 列,以及如何重命名并随后删除 "age" 列。 + +```sql +-- Create a table +CREATE TABLE default.users ( + username VARCHAR(50) NOT NULL, + email VARCHAR(255), + age INT +); + +-- Add a column to the end of the table +ALTER TABLE default.users +ADD COLUMN business_email VARCHAR(255) NOT NULL DEFAULT 'example@example.com'; + +DESC default.users; + +Field |Type |Null|Default |Extra| +--------------+-------+----+---------------------+-----+ +username |VARCHAR|NO |'' | | +email |VARCHAR|YES |NULL | | +age |INT |YES |NULL | | +business_email|VARCHAR|NO |'example@example.com'| | + +-- Add a column to the beginning of the table +ALTER TABLE default.users +ADD COLUMN id int NOT NULL FIRST; + +DESC default.users; + +Field |Type |Null|Default |Extra| +--------------+-------+----+---------------------+-----+ +id |INT |NO |0 | | +username |VARCHAR|NO |'' | | +email |VARCHAR|YES |NULL | | +age |INT |YES |NULL | | +business_email|VARCHAR|NO |'example@example.com'| | + +-- Add a column after the column 'username' +ALTER TABLE default.users +ADD COLUMN middle_name VARCHAR(50) NULL AFTER username; + +DESC default.users; + +Field |Type |Null|Default |Extra| +--------------+-------+----+---------------------+-----+ +id |INT |NO |0 | | +username |VARCHAR|NO |'' | | +middle_name |VARCHAR|YES |NULL | | +email |VARCHAR|YES |NULL | | +age |INT |YES |NULL | | +business_email|VARCHAR|NO |'example@example.com'| | + +-- Rename a column +ALTER TABLE default.users +RENAME COLUMN age TO new_age; + +DESC default.users; + +Field |Type |Null|Default |Extra| +--------------+-------+----+---------------------+-----+ +id |INT |NO |0 | | +username |VARCHAR|NO |'' | | +middle_name |VARCHAR|YES |NULL | | +email |VARCHAR|YES |NULL | | +new_age |INT |YES |NULL | | +business_email|VARCHAR|NO |'example@example.com'| | + +-- Remove a column +ALTER TABLE default.users +DROP COLUMN new_age; + +DESC default.users; + +Field |Type |Null|Default |Extra| +--------------+-------+----+---------------------+-----+ +id |INT |NO |0 | | +username |VARCHAR|NO |'' | | +middle_name |VARCHAR|YES |NULL | | +email |VARCHAR|YES |NULL | | +``` + +#### 示例 2:修改列和 masking policy {#example-2-modify-columns-and-masking-policies} + +```sql +-- Change column types and defaults +ALTER TABLE users +MODIFY COLUMN age BIGINT DEFAULT 18, + COLUMN email VARCHAR(320) DEFAULT ''; + +-- Add masking policy that expects extra arguments +ALTER TABLE users +MODIFY COLUMN email SET MASKING POLICY pii_email USING (email, username); + +-- To drop or alter the column, remove the policy first +ALTER TABLE users +MODIFY COLUMN email UNSET MASKING POLICY; +``` + +## 行访问策略操作 {#row-access-policy-operations} + +为表附加或分离行访问策略。行访问策略会在查询时以及 DML 目标行匹配期间过滤行。 + +### 语法 {#syntax} + +```sql +-- Add a row access policy to a table +ALTER TABLE [ IF EXISTS ] [ . ] +ADD ROW ACCESS POLICY ON ( [ , ... ] ) + +-- Drop a specific row access policy from a table +ALTER TABLE [ IF EXISTS ] [ . ] +DROP ROW ACCESS POLICY + +-- Drop all row access policies from a table +ALTER TABLE [ IF EXISTS ] [ . ] +DROP ALL ROW ACCESS POLICIES +``` + +> **注意:** +> +> - 行访问策略当前为实验特性。可使用 `SET enable_experimental_row_access_policy = 1` 或 `SET GLOBAL enable_experimental_row_access_policy = 1` 启用。 +> - 一张表在同一时间最多只能有一个行访问策略。 +> - `ON (...)` 中的列按位置绑定到策略参数。列的数量及其数据类型必须与策略签名匹配。 +> - 行访问策略只能附加到普通表。视图、流和临时表不允许使用 `ADD ROW ACCESS POLICY`。 +> - 一列最多只能属于一个安全策略,即脱敏策略或行访问策略中的一种。 +> - 添加或移除行访问策略需要目标表上的 `ALTER` 权限,以及全局 `APPLY ROW ACCESS POLICY` 权限,或该策略上的 APPLY/OWNERSHIP 权限。描述或删除策略也需要相同的策略权限。 + +> **警告:** +> +> 在修改或删除受保护列之前,必须先解除关联的行访问策略。否则,由于该列仍被安全策略引用,语句会失败。 + +### 示例 {#example} + +```sql +SET enable_experimental_row_access_policy = 1; + +CREATE TABLE employees(id INT, name STRING, department STRING); + +CREATE ROW ACCESS POLICY rap_engineering +AS (dept STRING) +RETURNS BOOLEAN -> dept = 'Engineering'; + +ALTER TABLE employees +ADD ROW ACCESS POLICY rap_engineering ON (department); + +ALTER TABLE employees +DROP ROW ACCESS POLICY rap_engineering; +``` + +## 表注释 {#table-comment} + +修改表的注释。如果该表尚未设置注释,此命令会为表添加指定的注释。 + +### 语法 {#syntax} + +```sql +ALTER TABLE [ IF EXISTS ] [ . ] +COMMENT = '' +``` + +### 示例 {#examples} + +```sql +-- Create a table with a comment +CREATE TABLE t(id INT) COMMENT ='original-comment'; + +SHOW CREATE TABLE t; + +┌──────────────────────────────────────────────────────────────────────────────────────┐ +│ Table │ Create Table │ +├────────┼─────────────────────────────────────────────────────────────────────────────┤ +│ t │ CREATE TABLE t (\n id INT NULL\n) ENGINE=FUSE COMMENT = 'original-comment' │ +└──────────────────────────────────────────────────────────────────────────────────────┘ + +-- Modify the comment +ALTER TABLE t COMMENT = 'new-comment'; + +SHOW CREATE TABLE t; + +┌─────────────────────────────────────────────────────────────────────────────────┐ +│ Table │ Create Table │ +├────────┼────────────────────────────────────────────────────────────────────────┤ +│ t │ CREATE TABLE t (\n id INT NULL\n) ENGINE=FUSE COMMENT = 'new-comment' │ +└─────────────────────────────────────────────────────────────────────────────────┘ +``` + +```sql +-- Create a table without comment +CREATE TABLE t(id INT); + +-- Add a comment later +ALTER TABLE t COMMENT = 'new-comment'; +``` + +## Fuse Engine 选项 {#fuse-engine-options} + +为表设置或取消设置 [Fuse Engine 选项](/tidb-cloud-lake/sql/fuse-engine-tables.md#fuse-engine-options)。 + +### 语法 {#syntax} + +```sql +-- Set Fuse Engine options +ALTER TABLE [ . ] SET OPTIONS () + +-- Unset Fuse Engine options, reverting them to their default values +ALTER TABLE [ . ] UNSET OPTIONS () +``` + +只有以下 Fuse Engine 选项可以取消设置: + +- `block_per_segment` +- `block_size_threshold` +- `data_retention_period_in_hours` +- `data_retention_num_snapshots_to_keep` +- `enable_schema_evolution` +- `row_avg_depth_threshold` +- `row_per_block` +- `row_per_page` + +### 示例 {#examples} + +```sql +CREATE TABLE fuse_table (a int); + +SET hide_options_in_show_create_table=0; + +-- Show current options +SHOW CREATE TABLE fuse_table; + +-- Change Fuse options +ALTER TABLE fuse_table SET OPTIONS (block_per_segment = 500, data_retention_period_in_hours = 240); + +-- Show updated options +SHOW CREATE TABLE fuse_table; +``` + +```sql +-- Limit snapshots and enable auto vacuum +CREATE OR REPLACE TABLE t(c INT); +ALTER TABLE t SET OPTIONS(data_retention_num_snapshots_to_keep = 1); +SET enable_auto_vacuum = 1; +INSERT INTO t VALUES(1); +INSERT INTO t VALUES(2); +INSERT INTO t VALUES(3); + +-- Revert options to defaults +ALTER TABLE fuse_table UNSET OPTIONS (block_per_segment, data_retention_period_in_hours); +``` + +## 外部表连接 {#external-table-connection} + +更新外部表的连接设置。命令执行时,仅会应用与凭证相关的字段(`access_key_id`、`secret_access_key`、`role_arn`)。其他属性(如 `bucket`、`region` 或 `root`)保持不变。 + +### 语法 {#syntax} + +```sql +ALTER TABLE [ . ] CONNECTION = ( connection_name = '' ) +``` + +| 参数 | 描述 | 必填 | +|-----------|-------------|----------| +| connection_name | 用于外部表的连接名称。该连接必须已存在于系统中。 | 是 | + +当需要轮转凭证或 IAM 角色发生变化时,此命令特别有用。使用此命令前,指定的连接必须已存在。 + +**安全最佳实践** + +在使用外部表时,相比 access keys,AWS IAM roles 具有显著的安全优势: + +- 无需存储凭证:无需在配置中存储 access keys +- 自动轮转:自动处理凭证轮转 +- 细粒度控制:可实现更精确的访问控制 + +如需在 {{{ .lake }}} 中使用 IAM roles,请参见[使用 AWS IAM Role 进行身份验证](/tidb-cloud-lake/guides/authenticate-with-aws-iam-role.md)。 + +### 示例 {#examples} + +```sql +-- Create connections +CREATE CONNECTION external_table_conn + STORAGE_TYPE = 's3' + ACCESS_KEY_ID = '' + SECRET_ACCESS_KEY = ''; + +CREATE CONNECTION external_table_conn_new + STORAGE_TYPE = 's3' + ACCESS_KEY_ID = '' + SECRET_ACCESS_KEY = ''; + +-- Create an external table using the first connection +CREATE OR REPLACE TABLE external_table_test ( + id INT, + name VARCHAR, + age INT +) +'s3://testbucket/13_fuse_external_table/' +CONNECTION=(connection_name = 'external_table_conn'); + +-- Update to use the new connection +ALTER TABLE external_table_test CONNECTION=( connection_name = 'external_table_conn_new' ); +``` + +```sql +-- Migrate to IAM role authentication +CREATE CONNECTION s3_access_key_conn + STORAGE_TYPE = 's3' + ACCESS_KEY_ID = '' + SECRET_ACCESS_KEY = ''; + +CREATE TABLE sales_data ( + order_id INT, + product_name VARCHAR, + quantity INT +) +'s3://sales-bucket/data/' +CONNECTION=(connection_name = 's3_access_key_conn'); + +CREATE CONNECTION s3_role_conn + STORAGE_TYPE = 's3' + ROLE_ARN = 'arn:aws:iam::123456789012:role/lake-access'; + +ALTER TABLE sales_data CONNECTION=( connection_name = 's3_role_conn' ); +``` + +## 快照标签操作 {#snapshot-tag-operations} + + + +创建或删除一个命名的快照标签,该标签引用特定的 FUSE 表快照。快照标签可让你为表的某个时间点状态添加书签,以便后续通过 [AT](/tidb-cloud-lake/sql/at.md) 子句进行查询。 + +完整详情请参见: + +- [CREATE SNAPSHOT TAG](/tidb-cloud-lake/sql/create-snapshot-tag.md) +- [DROP SNAPSHOT TAG](/tidb-cloud-lake/sql/drop-snapshot-tag.md) + +> **注意:** +> +> 快照标签不同于[治理标签](#tag-operations)。快照标签用于为表快照添加时间旅行书签,而治理标签则用于将键值元信息附加到对象上,以便进行分类。 + +## 交换表 {#swap-tables} + +在单个事务中以原子方式交换两个表之间的所有表元信息和数据。此操作会交换表结构,包括所有列、约束和数据,从而使每个表实际上获得对方的身份。 + +### 语法 {#syntax} + +```sql +ALTER TABLE [ IF EXISTS ] SWAP WITH +``` + +| 参数 | 描述 | +|----------------------|------------------------------------------------| +| `source_table_name` | 要交换的第一个表的名称 | +| `target_table_name` | 要与之交换的第二个表的名称 | + +### 使用说明 {#usage-notes} + +- 仅适用于 Fuse Engine 表。不支持外部表、系统表以及其他非 Fuse 表。 +- 临时表不能与永久表或 transient 表进行交换。 +- 当前角色必须同时是这两个表的所有者,才能执行交换操作。 +- 两个表必须位于同一个数据库中。不支持跨数据库交换。 +- 交换操作是原子的。要么两个表都成功交换,要么都不会发生变化。 +- 交换期间会保留所有数据和元信息。不会丢失或修改任何数据。 + +### 示例 {#examples} + +```sql +-- Create two tables with different schemas +CREATE OR REPLACE TABLE t1(a1 INT, a2 VARCHAR, a3 DATE); +CREATE OR REPLACE TABLE t2(b1 VARCHAR); + +-- Check table schemas before swap +DESC t1; +DESC t2; + +-- Swap the tables +ALTER TABLE t1 SWAP WITH t2; + +-- After swapping, t1 now has t2's schema, and t2 has t1's schema +DESC t1; +DESC t2; +``` + +## 标签操作 {#tag-operations} + +为表分配或移除治理标签。治理标签是用于分类和数据治理的键值元信息。必须先使用 [CREATE TAG](/tidb-cloud-lake/sql/create-tag.md) 创建标签。完整详情请参见 [SET TAG / UNSET TAG](/tidb-cloud-lake/sql/set-tag.md)。 + +### 语法 {#syntax} + +```sql +ALTER TABLE [ IF EXISTS ] [ . ] + SET TAG = '' [, = '' ...] + +ALTER TABLE [ IF EXISTS ] [ . ] + UNSET TAG [, ...] +``` + +### 示例 {#examples} + +```sql +ALTER TABLE default.users SET TAG env = 'prod', owner = 'team_a'; +ALTER TABLE default.users UNSET TAG env, owner; +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/alter-task.md b/tidb-cloud-lake/sql/alter-task.md new file mode 100644 index 0000000000000..08c28eac9e3c4 --- /dev/null +++ b/tidb-cloud-lake/sql/alter-task.md @@ -0,0 +1,87 @@ +--- +title: ALTER TASK +summary: ALTER TASK 语句用于修改现有任务。 +--- + +# ALTER TASK + +`ALTER TASK` 语句用于修改现有任务。 + +**注意:** 此功能仅在 {{{ .lake }}} 中开箱即用。 + +## 语法 {#syntax} + +```sql +--- suspend or resume a task +ALTER TASK [ IF EXISTS ] RESUME | SUSPEND + +--- change task settings +ALTER TASK [ IF EXISTS ] SET + [ WAREHOUSE = ] + [ SCHEDULE = { MINUTE | SECOND | USING CRON } ] + [ SUSPEND_TASK_AFTER_NUM_FAILURES = ] + [ = [ , = ... ] ] + [ COMMENT = ] + +--- change task SQL +ALTER TASK [ IF EXISTS ] MODIFY AS + +--- modify DAG when condition and after condition +ALTER TASK [ IF EXISTS ] REMOVE AFTER | ADD AFTER +--- allow to change condition for task execution +ALTER TASK [ IF EXISTS ] MODIFY WHEN +``` + +| 参数 | 描述 | +|----------------------------------|------------------------------------------------------------------------------------------------------| +| IF EXISTS | 可选。如果指定了该选项,仅当已存在同名任务时才会修改该任务。 | +| name | 任务名称。这是必填字段。 | +| RESUME \| SUSPEND | 恢复或暂停任务。 | +| SET | 更改任务设置。有关详细参数说明,请参见 [Create Task](/tidb-cloud-lake/sql/create-task.md)。 | +| MODIFY AS | 更改任务 SQL。 | +| REMOVE AFTER | 从任务 DAG 中移除前置任务;如果没有剩余前置任务,该任务将变为独立任务或根任务。 | +| ADD AFTER | 向任务 DAG 中添加前置任务。 | +| MODIFY WHEN | 更改任务执行条件。 | + +## 示例 {#examples} + +```sql +ALTER TASK IF EXISTS mytask SUSPEND; +``` + +此命令会在任务 `mytask` 存在时将其暂停。 + +```sql +ALTER TASK IF EXISTS mytask SET + WAREHOUSE = 'new_warehouse' + SCHEDULE = USING CRON '0 12 * * * *' 'UTC'; +``` + +此示例修改了 `mytask` 任务,将其计算集群更改为 `new_warehouse`,并将其调度更新为每天 UTC 中午运行。 + +```sql +ALTER TASK IF EXISTS mytask MODIFY +AS +INSERT INTO new_table SELECT * FROM source_table; +``` + +这里,`mytask` 执行的 SQL 语句被更改为将数据从 `source_table` 插入到 `new_table`。 + +```sql +ALTER TASK mytaskchild MODIFY WHEN STREAM_STATUS('stream3') = False; +``` + +在此示例中,我们修改了 `mytaskchild` 任务的 `WHEN` 条件。现在,只有当 `stream3` 的 `STREAM_STATUS` 函数结果为 `False` 时,该任务才会运行。这意味着当 `stream3` 不包含变更数据时,任务会执行。 + +```sql +ALTER TASK MyTask1 ADD AFTER 'task2'; +``` + +在此示例中,我们为 `MyTask1` 任务添加了依赖关系。现在,它将在 `task2` 和 `task3` 都成功完成后运行。这会在任务的有向无环图(DAG)中创建依赖关系。 + +```sql +ALTER TASK MyTask1 REMOVE AFTER 'task2'; +``` + +这里,我们移除了 `MyTask1` 任务的一项特定依赖关系。它将不再在 `task2` 之后运行。如果你想修改任务 DAG 中的依赖关系,这会很有用。 \ No newline at end of file diff --git a/tidb-cloud-lake/sql/alter-user.md b/tidb-cloud-lake/sql/alter-user.md new file mode 100644 index 0000000000000..f9746a0d38020 --- /dev/null +++ b/tidb-cloud-lake/sql/alter-user.md @@ -0,0 +1,149 @@ +--- +title: ALTER USER +summary: 修改用户账户,包括。 +--- + +# ALTER USER + +修改用户账户,包括: + +- 更改用户的密码和认证类型。 +- 设置或取消设置密码策略。 +- 设置或取消设置网络策略。 +- 设置或修改默认角色。如果未显式设置,{{{ .lake }}} 默认使用内置角色 `public` 作为默认角色。 + +## 语法 {#syntax} + +```sql +-- Modify password / authentication type +ALTER USER IDENTIFIED [ WITH auth_type ] BY '' [ WITH MUST_CHANGE_PASSWORD = true | false ] + +-- Require user to modify password at next login +ALTER USER WITH MUST_CHANGE_PASSWORD = true + +-- Modify password for currently logged-in user +ALTER USER USER() IDENTIFIED BY '' + +-- Set password policy +ALTER USER WITH SET PASSWORD POLICY = '' + +-- Unset password policy +ALTER USER WITH UNSET PASSWORD POLICY + +-- Set network policy +ALTER USER WITH SET NETWORK POLICY = '' + +-- Unset network policy +ALTER USER WITH UNSET NETWORK POLICY + +-- Set default role +ALTER USER WITH DEFAULT_ROLE = '' + +-- Enable or disable user +ALTER USER WITH DISABLED = true | false + +-- Set workload group +ALTER USER WITH SET WORKLOAD GROUP = '' + +-- Unset workload group +ALTER USER WITH UNSET WORKLOAD GROUP +``` + +- *auth_type* 可以是 `double_sha1_password`(默认)、`sha256_password` 或 `no_password`。 +- 当 `MUST_CHANGE_PASSWORD` 设置为 `true` 时,用户必须在下次登录时修改密码。请注意,这仅对自账户创建以来从未修改过密码的用户生效。如果用户曾经自行修改过密码,则无需再次修改。 +- 当你使用 [CREATE USER](/tidb-cloud-lake/sql/create-user.md) 或 ALTER USER 为用户设置默认角色时,{{{ .lake }}} 不会验证该角色是否存在,也不会自动将该角色授予用户。你必须显式将该角色授予用户,该角色才会生效。 +- `DISABLED` 允许你启用或禁用用户。被禁用的用户在重新启用之前无法登录到 {{{ .lake }}}。参见[语法](/tidb-cloud-lake/sql/create-user.md#syntax)。 + +## 示例 {#examples} + +### 示例 1:更改密码和认证类型 {#example-1-changing-password-authentication-type} + +```sql +CREATE USER user1 IDENTIFIED BY 'abc123'; + +SHOW USERS; ++-----------+----------+----------------------+---------------+ +| name | hostname | auth_type | is_configured | ++-----------+----------+----------------------+---------------+ +| user1 | % | double_sha1_password | NO | ++-----------+----------+----------------------+---------------+ + +ALTER USER user1 IDENTIFIED WITH sha256_password BY '123abc'; + +SHOW USERS; ++-------+----------+-----------------+---------------+ +| name | hostname | auth_type | is_configured | ++-------+----------+-----------------+---------------+ +| user1 | % | sha256_password | NO | ++-------+----------+-----------------+---------------+ + +ALTER USER 'user1' IDENTIFIED WITH no_password; + +show users; ++-------+----------+-------------+---------------+ +| name | hostname | auth_type | is_configured | ++-------+----------+-------------+---------------+ +| user1 | % | no_password | NO | ++-------+----------+-------------+---------------+ +``` + +### 示例 2:设置和取消设置网络策略 {#example-2-setting-unsetting-network-policy} + +```sql +SHOW NETWORK POLICIES; + +Name |Allowed Ip List |Blocked Ip List|Comment | +------------+-------------------------+---------------+-----------+ +test_policy |192.168.10.0,192.168.20.0| |new comment| +test_policy1|192.168.100.0/24 | | | + +CREATE USER user1 IDENTIFIED BY 'abc123'; + +ALTER USER user1 WITH SET NETWORK POLICY='test_policy'; + +ALTER USER user1 WITH SET NETWORK POLICY='test_policy1'; + +ALTER USER user1 WITH UNSET NETWORK POLICY; +``` + +### 示例 3:设置默认角色 {#example-3-setting-default-role} + +1. 创建一个名为 "user1" 的用户,并将默认角色设置为 "writer": + + ```sql title='Connect as user "root":' + + CREATE USER user1 IDENTIFIED BY 'abc123'; + + GRANT ROLE developer TO user1; + + GRANT ROLE writer TO user1; + + ALTER USER user1 WITH DEFAULT_ROLE = 'writer'; + ``` + +2. 使用 [SHOW ROLES](/tidb-cloud-lake/sql/show-roles.md) 命令验证用户 "user1" 的默认角色: + +```sql title='Connect as user "user1":' +eric@Erics-iMac ~ % lakesql --user user1 --password abc123 +show roles; +┌───────────────────────────────────────────────────────┐ +│ name │ inherited_roles │ is_current │ is_default │ +│ String │ UInt64 │ Boolean │ Boolean │ +├───────────┼─────────────────┼────────────┼────────────┤ +│ developer │ 0 │ false │ false │ +│ public │ 0 │ false │ false │ +│ writer │ 0 │ true │ true │ +└───────────────────────────────────────────────────────┘ +``` + +### 示例 2:设置和取消设置 Workload Group {#example-2-setting-unsetting-workload-group} + +```sql +CREATE USER user1 IDENTIFIED BY 'abc123'; + +ALTER USER user1 WITH SET WORKLOAD GROUP='wg'; + +ALTER USER user1 WITH SET WORKLOAD GROUP='wg1'; + +ALTER USER user1 WITH UNSET WORKLOAD GROUP; +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/alter-view.md b/tidb-cloud-lake/sql/alter-view.md new file mode 100644 index 0000000000000..d312a7da8aa1a --- /dev/null +++ b/tidb-cloud-lake/sql/alter-view.md @@ -0,0 +1,29 @@ +--- +title: ALTER VIEW +summary: 使用另一个 QUERY 修改现有视图。 +--- + +# ALTER VIEW + +为现有视图设置或移除标签。标签必须先通过 [CREATE TAG](/tidb-cloud-lake/sql/create-tag.md) 创建。完整说明请参见 [SET TAG / UNSET TAG](/tidb-cloud-lake/sql/set-tag.md)。 + +> **Note:** +> +> 不支持 `ALTER VIEW ... AS ...`。如需更改视图的查询或输出列,请改用 [CREATE OR REPLACE VIEW](/tidb-cloud-lake/sql/create-view.md)。 + +## 语法 {#syntax} + +```sql +ALTER VIEW [ IF EXISTS ] [ . ] + SET TAG = '' [, = '' ...] + +ALTER VIEW [ IF EXISTS ] [ . ] + UNSET TAG [, ...] +``` + +## 示例 {#examples} + +```sql +ALTER VIEW default.active_users SET TAG env = 'prod', owner = 'analytics'; +ALTER VIEW default.active_users UNSET TAG env, owner; +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/alter-warehouse-assign-nodes.md b/tidb-cloud-lake/sql/alter-warehouse-assign-nodes.md new file mode 100644 index 0000000000000..7c66ab2b49c9e --- /dev/null +++ b/tidb-cloud-lake/sql/alter-warehouse-assign-nodes.md @@ -0,0 +1,41 @@ +--- +title: ALTER WAREHOUSE ASSIGN NODES +summary: "了解如何在 {{{ .lake }}} 中使用 ALTER WAREHOUSE ASSIGN NODES 命令,将节点分配给计算集群中的一个或多个集群。" +--- + +# ALTER WAREHOUSE ASSIGN NODES + +将节点分配给计算集群 (Warehouse) 中的一个或多个集群。 + +> **注意:** +> +> 此命令需要系统管理支持和企业版许可证。 + +## 语法 {#syntax} + +```sql +ALTER WAREHOUSE ASSIGN NODES +( + ASSIGN NODES [ FROM '' ] FOR + [ , ASSIGN NODES [ FROM '' ] FOR , ... ] +) +``` + +## 参数 {#parameters} + +| 参数 | 描述 | +|-----------|-------------| +| `` | 目标计算集群。 | +| `` | 要分配的节点数量。 | +| `FROM ''` | 可选的节点组选择器。 | +| `` | 计算集群内部的目标集群。 | + +## 示例 {#example} + +```sql +ALTER WAREHOUSE etl_wh ASSIGN NODES +( + ASSIGN 2 NODES FOR c1, + ASSIGN 1 NODES FROM 'default' FOR c2 +); +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/alter-warehouse-unassign-nodes.md b/tidb-cloud-lake/sql/alter-warehouse-unassign-nodes.md new file mode 100644 index 0000000000000..4744d4f00a272 --- /dev/null +++ b/tidb-cloud-lake/sql/alter-warehouse-unassign-nodes.md @@ -0,0 +1,41 @@ +--- +title: ALTER WAREHOUSE UNASSIGN NODES +summary: "了解如何在 {{{ .lake }}} 中使用 ALTER WAREHOUSE UNASSIGN NODES 命令,从计算集群中的一个 warehouse 内的集群移除已分配的节点。" +--- + +# ALTER WAREHOUSE UNASSIGN NODES + +从计算集群 (Warehouse) 中的一个或多个集群移除已分配的节点。 + +> **注意:** +> +> 此命令需要系统管理支持和企业版许可证。 + +## 语法 {#syntax} + +```sql +ALTER WAREHOUSE UNASSIGN NODES +( + UNASSIGN NODES [ FROM '' ] FOR + [ , UNASSIGN NODES [ FROM '' ] FOR , ... ] +) +``` + +## 参数 {#parameters} + +| 参数 | 描述 | +|-----------|-------------| +| `` | 目标 warehouse。 | +| `` | 要移除的节点数量。 | +| `FROM ''` | 可选的节点组选择器。 | +| `` | 计算集群中的目标集群。 | + +## 示例 {#example} + +```sql +ALTER WAREHOUSE etl_wh UNASSIGN NODES +( + UNASSIGN 1 NODES FOR c1, + UNASSIGN 1 NODES FROM 'default' FOR c2 +); +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/alter-warehouse.md b/tidb-cloud-lake/sql/alter-warehouse.md new file mode 100644 index 0000000000000..518c606d2e67c --- /dev/null +++ b/tidb-cloud-lake/sql/alter-warehouse.md @@ -0,0 +1,93 @@ +--- +title: ALTER WAREHOUSE +summary: 暂停、恢复或修改现有计算集群的设置。 +--- + +# ALTER WAREHOUSE + +暂停、恢复或修改现有计算集群 (Warehouse) 的设置。 + +## 语法 {#syntax} + +```sql +-- Suspend or resume a warehouse +ALTER WAREHOUSE { SUSPEND | RESUME } + +-- Modify warehouse settings +ALTER WAREHOUSE + SET [ warehouse_size = ] + [ auto_suspend = ] + [ auto_resume = ] + [ max_cluster_count = ] + [ min_cluster_count = ] + [ comment = '' ] + +ALTER WAREHOUSE SET TAG = '' [ , = '' ... ] + +ALTER WAREHOUSE UNSET TAG [ , ... ] + +ALTER WAREHOUSE RENAME TO +``` + +| 参数 | 描述 | +| --------- | ---------------------------------------------------------------------------- | +| `SUSPEND` | 立即暂停该计算集群。 | +| `RESUME` | 立即恢复该计算集群。 | +| `SET` | 修改一个或多个计算集群选项。未指定的字段保持不变。 | + +## 选项 {#options} + +`SET` 子句接受与 [CREATE WAREHOUSE](/tidb-cloud-lake/sql/create-warehouse.md) 相同的选项: + +| 选项 | 类型 / 值 | 描述 | +| ------------------- | ------------------------------------------------------------------- | -------------------------------------------------------------------- | +| `WAREHOUSE_SIZE` | `XSmall`, `Small`, `Medium`, `Large`, `XLarge`, `2XLarge`–`6XLarge` | 修改计算规模。 | +| `AUTO_SUSPEND` | `NULL`, `0`, 或 ≥300 秒 | 自动暂停前的空闲超时时间。`NULL` 会禁用自动暂停。 | +| `AUTO_RESUME` | 布尔值 | 控制传入查询是否会自动唤醒该计算集群。 | +| `MAX_CLUSTER_COUNT` | `NULL` 或非负整数型 | 自动扩缩容集群数的上限。 | +| `MIN_CLUSTER_COUNT` | `NULL` 或非负整数型 | 自动扩缩容集群数的下限。 | +| `COMMENT` | 字符串 | 自由格式的文本描述。 | + +- 对于数值选项,可以使用 `NULL` 将其重置为 `0`。 +- 如果提供了 `SET` 但未指定任何选项,会报错。 +- `SET TAG` 用于添加或修改一个或多个标签。多个标签可以在同一条语句中使用逗号分隔进行设置。 +- `UNSET TAG` 按键移除一个或多个标签。不存在的标签键会被静默忽略。 +- `RENAME TO` 要求该计算集群处于已暂停状态,并且使用与 `CREATE` 相同的命名规则。 + +## 示例 {#examples} + +暂停一个计算集群: + +```sql +ALTER WAREHOUSE 'my-wh' SUSPEND; +``` + +恢复一个计算集群: + +```sql +ALTER WAREHOUSE 'my-wh' RESUME; +``` + +修改计算集群设置: + +```sql +ALTER WAREHOUSE 'my-wh' + SET warehouse_size = Large + auto_resume = TRUE + comment = 'Serving tier'; +``` + +禁用自动暂停: + +```sql +ALTER WAREHOUSE 'my-wh' SET auto_suspend = NULL; +``` + +管理标签: + +```sql +ALTER WAREHOUSE 'wh-hot' SET TAG environment = 'production'; +ALTER WAREHOUSE 'wh-hot' SET TAG environment = 'staging', owner = 'john', cost_center = 'eng'; +ALTER WAREHOUSE 'wh-hot' UNSET TAG environment; +ALTER WAREHOUSE 'wh-hot' UNSET TAG environment, owner, cost_center; +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/alter-worker.md b/tidb-cloud-lake/sql/alter-worker.md new file mode 100644 index 0000000000000..91a9e883618a4 --- /dev/null +++ b/tidb-cloud-lake/sql/alter-worker.md @@ -0,0 +1,79 @@ +--- +title: ALTER WORKER +summary: 使用 ALTER WORKER 修改 worker 的标签、选项或状态。 +--- + +# ALTER WORKER + +> **注意:** +> +> 于 v1.3.0 中引入。 + +用于修改 worker 的标签、选项或状态。 + +> **注意:** +> +> 此命令要求启用 cloud control。 + +## 语法 {#syntax} + +```sql +ALTER WORKER SET TAG = '' [ , = '' ... ] + +ALTER WORKER UNSET TAG [ , ... ] + +ALTER WORKER SET = [ , = ... ] + +ALTER WORKER UNSET [ , ... ] + +ALTER WORKER SUSPEND + +ALTER WORKER RESUME +``` + +## 参数 {#parameters} + +| 形式 | 说明 | +|------|-------------| +| `SET TAG` | 添加或修改 worker 标签。标签值必须是字符串字面量。 | +| `UNSET TAG` | 删除一个或多个 worker 标签。 | +| `SET` | 添加或修改 worker 选项。选项名称会被规范化为小写。 | +| `UNSET` | 删除一个或多个 worker 选项。 | +| `SUSPEND` | 挂起 worker。 | +| `RESUME` | 恢复 worker。 | + +## 示例 {#examples} + +为 worker 设置标签: + +```sql +ALTER WORKER read_env +SET TAG purpose = 'sandbox', owner = 'ci'; +``` + +修改 worker 选项: + +```sql +ALTER WORKER read_env +SET size = 'medium', auto_suspend = '600'; +``` + +删除一个标签和一个选项: + +```sql +ALTER WORKER read_env UNSET TAG owner; +ALTER WORKER read_env UNSET auto_suspend; +``` + +更改 worker 状态: + +```sql +ALTER WORKER read_env SUSPEND; +ALTER WORKER read_env RESUME; +``` + +## 相关主题 {#related-topics} + +- [CREATE WORKER](/tidb-cloud-lake/sql/create-worker.md) - 创建 worker +- [SHOW WORKERS](/tidb-cloud-lake/sql/show-workers.md) - 列出 worker 及其元信息 +- [DROP WORKER](/tidb-cloud-lake/sql/drop-worker.md) - 删除 worker \ No newline at end of file diff --git a/tidb-cloud-lake/sql/alter-workload-group.md b/tidb-cloud-lake/sql/alter-workload-group.md new file mode 100644 index 0000000000000..8cd11894c150b --- /dev/null +++ b/tidb-cloud-lake/sql/alter-workload-group.md @@ -0,0 +1,31 @@ +--- +title: ALTER WORKLOAD GROUP +summary: 使用指定的配额设置修改 workload group。 +--- + +# ALTER WORKLOAD GROUP + +使用指定的配额设置修改 workload group。 + +## 语法 {#syntax} + +```sql +ALTER WORKLOAD GROUP +[SET cpu_quota = '', query_timeout = ''] +``` + +## 参数 {#parameters} + +| 参数 | 类型 | 必填 | 默认值 | 描述 | +|------------------------|----------|----------|--------------|-----------------------------------------------------------------------------| +| `cpu_quota` | string | 否 | (无限制) | 以百分比字符串表示的 CPU 资源配额(例如 `"20%"`) | +| `query_timeout` | duration | 否 | (无限制) | 查询超时时长(单位:`s`/`sec`=秒,`m`/`min`=分钟,`h`/`hour`=小时,`d`/`day`=天,`ms`=毫秒,无单位=秒) | +| `memory_quota` | string or integer | 否 | (无限制) | 工作负载组的最大内存使用限制(百分比或绝对值) | +| `max_concurrency` | integer | 否 | (无限制) | 工作负载组的最大并发数 | +| `query_queued_timeout` | duration | 否 | (无限制) | 当工作负载组超过最大并发数时,排队等待的最长时间(单位:`s`/`sec`=秒,`m`/`min`=分钟,`h`/`hour`=小时,`d`/`day`=天,`ms`=毫秒,无单位=秒) | + +## 示例 {#examples} + +```sql +ALTER WORKLOAD GROUP analytics SET cpu_quota = '20%', query_timeout = '10m'; +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/any-value.md b/tidb-cloud-lake/sql/any-value.md new file mode 100644 index 0000000000000..e8ec3d7b7b431 --- /dev/null +++ b/tidb-cloud-lake/sql/any-value.md @@ -0,0 +1,84 @@ +--- +title: ANY_VALUE +summary: 聚合函数。 +--- + +# ANY_VALUE + +聚合函数。 + +`ANY_VALUE()` 函数从输入表达式中返回一个任意的非 `NULL` 值。当你在 `GROUP BY` 查询中需要选择一个未分组或未聚合的列时,可以使用该函数。 + +> **别名:** `ANY()` 返回与 `ANY_VALUE()` 相同的结果,并且为了兼容性仍然可用。 + +## 语法 {#syntax} + +```sql +ANY_VALUE() +``` + +## 参数 {#arguments} + +| 参数 | 描述 | +|-----------|----------------| +| `` | 任意表达式 | + +## 返回类型 {#return-type} + +`` 的类型。如果所有值都是 `NULL`,则返回值为 `NULL`。 + +> **注意:** +> +> - `ANY_VALUE()` 是非确定性的,在不同执行中可能返回不同的值。 +> - 如需可预测的结果,请改用 `MIN()` 或 `MAX()`。 + +## 示例 {#example} + +**示例数据:** + +```sql +CREATE TABLE sales ( + region VARCHAR, + manager VARCHAR, + sales_amount DECIMAL(10, 2) +); + +INSERT INTO sales VALUES + ('North', 'Alice', 15000.00), + ('North', 'Alice', 12000.00), + ('South', 'Bob', 20000.00); +``` + +**问题:** 以下查询会失败,因为 `manager` 不在 GROUP BY 中: + +```sql +SELECT region, manager, SUM(sales_amount) -- ❌ Error +FROM sales GROUP BY region; +``` + +**旧方法:** 将 `manager` 添加到 GROUP BY 中,但这会产生比所需更多的分组,并影响性能: + +```sql +SELECT region, manager, SUM(sales_amount) +FROM sales GROUP BY region, manager; -- ❌ Poor performance due to extra grouping +``` + +**更好的解决方案:** 使用 `ANY_VALUE()` 选择 `manager`: + +```sql +SELECT + region, + ANY_VALUE(manager) AS manager, -- ✅ Works + SUM(sales_amount) AS total_sales +FROM sales +GROUP BY region; +``` + +**结果:** + +```text +| region | manager | total_sales | +|--------|---------|-------------| +| North | Alice | 27000.00 | +| South | Bob | 20000.00 | +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/apache-hive-tables.md b/tidb-cloud-lake/sql/apache-hive-tables.md new file mode 100644 index 0000000000000..720f2e6e11510 --- /dev/null +++ b/tidb-cloud-lake/sql/apache-hive-tables.md @@ -0,0 +1,72 @@ +--- +title: Apache Hive Tables +summary: "{{{ .lake }}} 可以直接查询由 Apache Hive 编目管理的数据,而无需复制数据。将 Hive Metastore 注册为 {{{ .lake }}} catalog,指向存放表数据的对象存储,然后即可像查询原生 {{{ .lake }}} 对象一样查询这些表。" +--- + +# Apache Hive Tables + +{{{ .lake }}} 可以直接查询由 Apache Hive 编目管理的数据,而无需复制数据。将 Hive Metastore 注册为 {{{ .lake }}} catalog,指向存放表数据的对象存储,然后即可像查询原生 {{{ .lake }}} 对象一样查询这些表。 + +## 快速开始 {#quick-start} + +1. **注册 Hive Metastore** + + ```sql + CREATE CATALOG hive_prod + TYPE = HIVE + CONNECTION = ( + METASTORE_ADDRESS = '127.0.0.1:9083' + URL = 's3://lakehouse/' + ACCESS_KEY_ID = '' + SECRET_ACCESS_KEY = '' + ); + ``` + +2. **浏览 catalog** + + ```sql + USE CATALOG hive_prod; + SHOW DATABASES; + SHOW TABLES FROM tpch; + ``` + +3. **查询 Hive 表** + + ```sql + SELECT l_orderkey, SUM(l_extendedprice) AS revenue + FROM tpch.lineitem + GROUP BY l_orderkey + ORDER BY revenue DESC + LIMIT 10; + ``` + +## 保持元信息最新 {#keep-metadata-fresh} + +Hive schema 或 partition 可能会在 {{{ .lake }}} 之外发生变化。出现这种情况时,请刷新 {{{ .lake }}} 的缓存元信息: + +```sql +ALTER TABLE tpch.lineitem REFRESH CACHE; +``` + +## 数据类型映射 {#data-type-mapping} + +查询运行时,{{{ .lake }}} 会自动将 Hive 原语类型转换为最接近的原生类型: + +| Hive 类型 | {{{ .lake }}} 类型 | +| --------- | ------------- | +| `BOOLEAN` | [BOOLEAN](/tidb-cloud-lake/sql/boolean.md) | +| `TINYINT`, `SMALLINT`, `INT`, `BIGINT` | [整数型类型](/tidb-cloud-lake/sql/numeric.md#integer-data-types) | +| `FLOAT`, `DOUBLE` | [浮点类型](/tidb-cloud-lake/sql/numeric.md#floating-point-data-types) | +| `DECIMAL(p,s)` | [DECIMAL](/tidb-cloud-lake/sql/decimal.md) | +| `STRING`, `VARCHAR`, `CHAR` | [STRING](/tidb-cloud-lake/sql/string.md) | +| `DATE`, `TIMESTAMP` | [DATETIME](/tidb-cloud-lake/sql/datetime.md) | +| `ARRAY` | [ARRAY](/tidb-cloud-lake/sql/array.md) | +| `MAP` | [MAP](/tidb-cloud-lake/sql/map.md) | + +`STRUCT` 等嵌套结构会通过 [VARIANT](/tidb-cloud-lake/sql/variant.md) 类型呈现。 + +## 注意事项和限制 {#notes-and-limitations} + +- 在 {{{ .lake }}} 中,Hive catalog 为**只读**(写入必须通过兼容 Hive 的引擎完成)。 +- 需要能够访问底层对象存储;请使用[连接参数](/tidb-cloud-lake/sql/connection-parameters.md)配置凭证。 +- 每当表布局发生变化(例如新增 partition)时,请使用 `ALTER TABLE ... REFRESH CACHE` 以保持查询结果为最新。 \ No newline at end of file diff --git a/tidb-cloud-lake/sql/apache-icebergtm-tables.md b/tidb-cloud-lake/sql/apache-icebergtm-tables.md new file mode 100644 index 0000000000000..1c213c14abcc4 --- /dev/null +++ b/tidb-cloud-lake/sql/apache-icebergtm-tables.md @@ -0,0 +1,200 @@ +--- +title: Apache Iceberg™ Tables +summary: 了解如何将 TiDB Cloud Lake 连接到 Apache Iceberg catalog,并查询或写入 Iceberg 表。 +--- + +# Apache Iceberg™ Tables + +{{{ .lake }}} 可以连接到 [Apache Iceberg™](https://iceberg.apache.org/) catalog,这样你无需将数据加载到 Fuse 表中即可查询 Iceberg 表。当所连接的 catalog 支持写操作时,你还可以创建并写入 Iceberg 表。 + +## 何时使用 Iceberg {#when-to-use-iceberg} + +在以下情况下使用 Iceberg: + +- 你的数据已经由 Iceberg catalog 管理。 +- 多个查询引擎需要共享相同的表元信息和对象存储。 +- 你需要 Iceberg 提供的能力,例如 schema evolution 和快照。 +- 你希望从 {{{ .lake }}} 查询或写入 Iceberg 表。 + +## 创建 Iceberg Catalog {#create-an-iceberg-catalog} + +在访问 Iceberg 数据库和表之前,请先创建 catalog。 + +### 语法 {#syntax} + +```sql +CREATE CATALOG +TYPE = ICEBERG +CONNECTION = ( + TYPE = '' + [ ADDRESS = '' ] + [ WAREHOUSE = '' ] + [ "" = '' ] + ... +); +``` + +### 参数 {#parameters} + +| 参数 | 必填? | 说明 | +| --- | --- | --- | +| `` | 是 | {{{ .lake }}} 中的 catalog 名称。 | +| `TYPE` | 是 | Catalog 引擎。将该值设置为 `ICEBERG`。 | +| `CONNECTION` | 是 | Iceberg catalog 及其存储的连接属性。 | +| `TYPE` inside `CONNECTION` | 是 | Iceberg catalog 类型:`rest`、`glue`、`storage` 或 `hive`。 | +| `ADDRESS` | 取决于 catalog 类型 | Catalog 服务端点或 Hive Metastore 地址。 | +| `WAREHOUSE` | 取决于 catalog 类型 | Catalog 使用的计算集群位置。 | +| `` | 取决于 catalog 类型 | Catalog、认证和对象存储属性。 | + +以下连接参数可用于兼容 S3 的存储: + +| 连接参数 | 说明 | +| --- | --- | +| `s3.endpoint` | 兼容 S3 的服务端点。 | +| `s3.access-key-id` | S3 access key ID。 | +| `s3.secret-access-key` | S3 secret access key。 | +| `s3.session-token` | 与临时凭证一起使用的 session token。 | +| `s3.region` | S3 Region。 | +| `client.region` | 客户端使用的 Region。该值优先于 `s3.region`。 | +| `s3.path-style-access` | 是否使用 path-style 的 S3 访问方式。 | +| `s3.sse.type` | 服务端加密类型。 | +| `s3.sse.key` | KMS key ID 或客户提供的加密密钥。 | +| `s3.sse.md5` | 客户提供的加密密钥的 MD5 校验和。 | +| `client.assume-role.arn` | 要承担的 IAM role 的 ARN。 | +| `client.assume-role.external-id` | 承担 IAM role 时使用的 external ID。 | +| `client.assume-role.session-name` | 承担 IAM role 时使用的 session 名称。 | +| `s3.allow-anonymous` | 是否允许对公共存储进行匿名访问。 | +| `s3.disable-ec2-metadata` | 是否禁用来自 EC2 实例元信息的凭证。 | +| `s3.disable-config-load` | 是否禁用来自本地配置源的凭证和设置。 | + +## 支持的 Catalog 类型 {#supported-catalog-types} + +{{{ .lake }}} 支持以下 Iceberg catalog 类型: + +| Catalog 类型 | `TYPE` 值 | 连接要求 | +| --- | --- | --- | +| REST | `rest` | REST catalog 地址、计算集群位置以及存储属性。 | +| AWS Glue | `glue` | Glue Region 和身份验证属性,以及 S3 存储属性。 | +| Storage (Amazon S3 Tables) | `storage` | 表存储桶 ARN 和 AWS 客户端身份验证属性。 | +| Hive Metastore | `hive` | Hive Metastore 地址、计算集群位置以及存储属性。 | + +Storage catalog 支持以下 AWS 客户端属性: + +| 连接参数 | 说明 | +| --- | --- | +| `table_bucket_arn` | Amazon S3 Tables 表存储桶的 ARN。 | +| `profile_name` | AWS profile 名称。 | +| `region_name` | AWS Region。 | +| `aws_access_key_id` | AWS access key ID。 | +| `aws_secret_access_key` | AWS secret access key。 | +| `aws_session_token` | 与临时凭证一起使用的 AWS session token。 | + +## 管理和查询 Iceberg Catalog {#manage-and-query-iceberg-catalogs} + +使用以下语句查看和选择 catalog: + +```sql +SHOW CREATE CATALOG ; +``` + +```sql +SHOW CATALOGS [ LIKE '' | WHERE ]; +``` + +```sql +USE CATALOG ; +``` + +更多信息,请参见 [SHOW CREATE CATALOG](/tidb-cloud-lake/sql/show-create-catalog.md) 和 [SHOW CATALOGS](/tidb-cloud-lake/sql/show-catalogs.md)。 + +选择 catalog 后,使用标准 SQL 查询其中的表: + +```sql +SELECT +FROM [ . ]. +[ WHERE ]; +``` + +## 数据类型映射 {#data-type-mapping} + +下表展示了从 Iceberg 类型到 {{{ .lake }}} 类型的支持映射。此处未列出的 Iceberg 类型不受支持。 + +| Apache Iceberg™ | {{{ .lake }}} | +| --- | --- | +| BOOLEAN | [BOOLEAN](/tidb-cloud-lake/sql/boolean.md) | +| INT | [INT32](/tidb-cloud-lake/sql/numeric.md#integer-data-types) | +| LONG | [INT64](/tidb-cloud-lake/sql/numeric.md#integer-data-types) | +| DATE | [DATE](/tidb-cloud-lake/sql/date-time.md) | +| TIMESTAMP / TIMESTAMPZ | [TIMESTAMP](/tidb-cloud-lake/sql/date-time.md) | +| FLOAT | [FLOAT](/tidb-cloud-lake/sql/numeric.md#floating-point-data-types) | +| DOUBLE | [DOUBLE](/tidb-cloud-lake/sql/numeric.md#floating-point-data-types) | +| STRING / BINARY | [STRING](/tidb-cloud-lake/sql/string.md) | +| DECIMAL | [DECIMAL](/tidb-cloud-lake/sql/decimal.md) | +| LIST | [ARRAY](/tidb-cloud-lake/sql/array.md) | +| MAP | [MAP](/tidb-cloud-lake/sql/map.md) | +| STRUCT | [TUPLE](/tidb-cloud-lake/sql/tuple.md) | + +## 刷新缓存的元信息 {#refresh-cached-metadata} + +{{{ .lake }}} 在首次查询后会缓存 Iceberg catalog 的元信息。默认情况下,元信息缓存有效期为 10 分钟,并会异步刷新。 + +当你需要立即刷新缓存的元信息时,请使用以下语句: + +```sql +USE CATALOG ; +ALTER DATABASE REFRESH CACHE; +ALTER TABLE . REFRESH CACHE; +``` + +{{{ .lake }}} 还支持缓存从 Iceberg catalog 读取的表数据。 + +## 写入 Iceberg 表 {#write-to-iceberg-tables} + +你可以在支持写操作的 catalog 中创建并写入 Iceberg 表。 + +### 创建表 {#create-a-table} + +```sql +CREATE TABLE [ . ] ( + [ , ... ] +) +ENGINE = ICEBERG +[ PARTITION BY ( [ , ... ] ) ]; +``` + +| 参数 | 说明 | +| --- | --- | +| `ENGINE = ICEBERG` | 以 Iceberg 格式存储该表。 | +| `PARTITION BY` | 定义一个或多个分区列。 | + +写入 Iceberg 表时支持以下 {{{ .lake }}} 数据类型: + +| {{{ .lake }}} 类型 | Apache Iceberg™ 类型 | +| --- | --- | +| BOOLEAN | Boolean | +| INT | Int | +| BIGINT | Long | +| FLOAT | Float | +| DOUBLE | Double | +| STRING | String | +| DATE | Date | +| TIMESTAMP | Timestamp | + +### 插入数据 {#insert-data} + +使用 `INSERT INTO` 将行写入 Iceberg 表: + +```sql +INSERT INTO [ . ] +[ ( [ , ... ] ) ] +VALUES ( [ , ... ] ) [ , ... ]; +``` + +分区和非分区 Iceberg 表都支持单行和多行插入。对于分区表,{{{ .lake }}} 会将行路由到相应的分区。 + +## Iceberg 表函数 {#iceberg-table-functions} + +使用以下表函数检查 Iceberg 元信息: + +- [ICEBERG_MANIFEST](/tidb-cloud-lake/sql/iceberg-manifest.md) +- [ICEBERG_SNAPSHOT](/tidb-cloud-lake/sql/iceberg-snapshot.md) \ No newline at end of file diff --git a/tidb-cloud-lake/sql/approx-count-distinct.md b/tidb-cloud-lake/sql/approx-count-distinct.md new file mode 100644 index 0000000000000..7db5a86a04f20 --- /dev/null +++ b/tidb-cloud-lake/sql/approx-count-distinct.md @@ -0,0 +1,58 @@ +--- +title: APPROX_COUNT_DISTINCT +summary: 使用 HyperLogLog 算法估算数据集中不同值的数量。 +--- + +# APPROX_COUNT_DISTINCT + +使用 [HyperLogLog](https://en.wikipedia.org/wiki/HyperLogLog) 算法估算数据集中不同值的数量。 + +HyperLogLog 算法能够以较少的内存和时间近似计算唯一元素的数量。在处理大型数据集且可以接受估算结果时,建议使用此函数。它以牺牲一定准确性为代价,提供了一种快速且高效的返回去重计数的方法。 + +如需获得准确结果,请使用 [COUNT_DISTINCT](/tidb-cloud-lake/sql/count-distinct.md)。更多说明请参见[示例](#example)。 + +## 语法 {#syntax} + +```sql +APPROX_COUNT_DISTINCT() +``` + +## 返回类型 {#return-type} + +整数型。 + +## 示例 {#example} + +**创建表并插入示例数据** + +```sql +CREATE TABLE user_events ( + id INT, + user_id INT, + event_name VARCHAR +); + +INSERT INTO user_events (id, user_id, event_name) +VALUES (1, 1, 'Login'), + (2, 2, 'Login'), + (3, 3, 'Login'), + (4, 1, 'Logout'), + (5, 2, 'Logout'), + (6, 4, 'Login'), + (7, 1, 'Login'); +``` + +**查询演示:估算不同用户 ID 的数量** + +```sql +SELECT APPROX_COUNT_DISTINCT(user_id) AS approx_distinct_user_count +FROM user_events; +``` + +**结果** + +```sql +| approx_distinct_user_count | +|----------------------------| +| 4 | +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/arg-max.md b/tidb-cloud-lake/sql/arg-max.md new file mode 100644 index 0000000000000..3190f90c229b8 --- /dev/null +++ b/tidb-cloud-lake/sql/arg-max.md @@ -0,0 +1,65 @@ +--- +title: ARG_MAX +summary: 计算最大 `val` 值对应的 `arg` 值。如果最大 `val` 值对应多个 `arg` 值,则返回遇到的第一个值。 +--- + +# ARG_MAX + +计算最大 `val` 值对应的 `arg` 值。如果最大 `val` 值对应多个 `arg` 值,则返回遇到的第一个值。 + +## 语法 {#syntax} + +```sql +ARG_MAX(, ) +``` + +## 参数 {#arguments} + +| 参数 | 描述 | +|-----------|---------------------------------------------------------------------------------------------------| +| `` | [{{{ .lake }}} 支持的任意数据类型](/tidb-cloud-lake/sql/data-types.md)的参数 | +| `` | [{{{ .lake }}} 支持的任意数据类型](/tidb-cloud-lake/sql/data-types.md)的值 | + +## 返回类型 {#return-type} + +与最大 `val` 值对应的 `arg` 值。 + +与 `arg` 类型匹配。 + +## 示例 {#example} + +**创建表并插入示例数据** + +让我们创建一个名为 "sales" 的表,并插入一些示例数据: + +```sql +CREATE TABLE sales ( + id INTEGER, + product VARCHAR(50), + price FLOAT +); + +INSERT INTO sales (id, product, price) +VALUES (1, 'Product A', 10.5), + (2, 'Product B', 20.75), + (3, 'Product C', 30.0), + (4, 'Product D', 15.25), + (5, 'Product E', 25.5); +``` + +**查询:使用 ARG_MAX() 函数** + +现在,使用 ARG_MAX() 函数查找价格最高的产品: + +```sql +SELECT ARG_MAX(product, price) AS max_price_product +FROM sales; +``` + +结果应如下所示: + +```sql +| max_price_product | +| ----------------- | +| Product C | +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/arg-min.md b/tidb-cloud-lake/sql/arg-min.md new file mode 100644 index 0000000000000..bbd8803e6b443 --- /dev/null +++ b/tidb-cloud-lake/sql/arg-min.md @@ -0,0 +1,60 @@ +--- +title: ARG_MIN +summary: 计算最小 `val` 值对应的 `arg` 值。如果最小 `val` 值对应多个不同的 `arg` 值,则返回遇到的第一个值。 +--- + +# ARG_MIN + +计算最小 `val` 值对应的 `arg` 值。如果最小 `val` 值对应多个不同的 `arg` 值,则返回遇到的第一个值。 + +## 语法 {#syntax} + +```sql +ARG_MIN(, ) +``` + +## 参数 {#arguments} + +| 参数 | 描述 | +| --------- | ------------------------------------------------------------------------------------------------- | +| `` | [{{{ .lake }}} 支持的任意数据类型](/tidb-cloud-lake/sql/data-types.md)的参数 | +| `` | [{{{ .lake }}} 支持的任意数据类型](/tidb-cloud-lake/sql/data-types.md)的值 | + +## 返回类型 {#return-type} + +与最小 `val` 值对应的 `arg` 值。 + +与 `arg` 类型匹配。 + +## 示例 {#example} + +创建一个包含 `id`、`name` 和 `score` 列的 `students` 表,并插入一些数据: + +```sql +CREATE TABLE students ( + id INT, + name VARCHAR, + score INT +); + +INSERT INTO students (id, name, score) VALUES + (1, 'Alice', 80), + (2, 'Bob', 75), + (3, 'Charlie', 90), + (4, 'Dave', 80); +``` + +现在,可以使用 ARG_MIN 查找分数最低的学生姓名: + +```sql +SELECT ARG_MIN(name, score) AS student_name +FROM students; +``` + +结果: + +```sql +| student_name | +|--------------| +| Bob | +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/arithmetic-operators.md b/tidb-cloud-lake/sql/arithmetic-operators.md new file mode 100644 index 0000000000000..89561e118260d --- /dev/null +++ b/tidb-cloud-lake/sql/arithmetic-operators.md @@ -0,0 +1,28 @@ +--- +title: 算术运算符 +summary: 本页介绍 TiDB Cloud Lake 中的算术运算符。 +--- + +# 算术运算符 + +| 运算符 | 描述 | 示例 | 结果 | +| --------------------- | --------------------------------------------------------- | -------------------------- | --------- | +| **+ (unary)** | 返回 `a` | **+5** | 5 | +| **+** | 对两个数值表达式求和 | **4 + 1** | 5 | +| **- (unary)** | 对数值表达式取负 | **-5** | -5 | +| **-** | 两个数值表达式相减 | **4 - 1** | 3 | +| **\*** | 两个数值表达式相乘 | **4 \* 1** | 4 | +| **/** | 用一个数值表达式(`a`)除以另一个数值表达式(`b`) | **4 / 2** | 2 | +| **//** | 计算数值表达式的整数除法 | **4 // 3** | 1 | +| **%** | 计算数值表达式的取模 | **4 % 2** | 0 | +| **^** | 计算数值表达式的幂 | **4 ^ 2** | 16 | +| **|/** | 计算数值表达式的平方根 | **|/ 25.0** | 5 | +| **||/** | 计算数值表达式的立方根 | **||/ 27.0** | 3 | +| **@** | 计算数值表达式的绝对值 | **@ -5.0** | 5 | +| **&** | 计算数值表达式的按位与 | **91 & 15** | 11 | +| **|** | 计算数值表达式的按位或 | **32 | 3** | 35 | +| **#** | 计算数值表达式的按位异或 | **17 # 5** | 20 | +| **~** | 计算数值表达式的按位取反 | **~ 1** | ~2 | +| **`<<`** | 计算数值表达式的按位左移 | **1 `<<` 4** | 16 | +| **>>** | 计算数值表达式的按位右移 | **8 >> 2** | 2 | +| **`<->`** | 计算向量之间的欧几里得距离(L2 范数) | **[1, 2] `<->` [2, 3]** | 1.4142135 | \ No newline at end of file diff --git a/tidb-cloud-lake/sql/array-agg.md b/tidb-cloud-lake/sql/array-agg.md new file mode 100644 index 0000000000000..361830890b3ec --- /dev/null +++ b/tidb-cloud-lake/sql/array-agg.md @@ -0,0 +1,73 @@ +--- +title: ARRAY_AGG +summary: ARRAY_AGG 函数(也称其别名 LIST)将查询结果中特定列的所有值(不包括 NULL)转换为数组。 +--- + +# ARRAY_AGG + +ARRAY_AGG 函数(也称其别名 LIST)将查询结果中特定列的所有值(不包括 NULL)转换为数组。 + +## 语法 {#syntax} + +```sql +ARRAY_AGG() [ WITHIN GROUP ( ) ] + +LIST() +``` + +## 参数 {#arguments} + +| 参数 | 描述 | +|-----------| -------------- | +| `` | 任意表达式 | + +## 可选项 {#optional} + +| 可选项 | 描述 | +|-------------------------------------|-------------------------------------------------------| +| WITHIN GROUP [<orderby_clause>](https://docs.pingcap.com/tidbcloudlake/select/#order-by-clause) | 定义有序集合聚合中值的顺序 | + +## 返回类型 {#return-type} + +返回一个 [数组](/tidb-cloud-lake/sql/array.md),其元素与原始数据具有相同的类型。 + +## 示例 {#examples} + +以下示例演示了如何使用 ARRAY_AGG 函数以便捷的数组格式聚合并展示数据: + +```sql +-- Create a table and insert sample data +CREATE TABLE movie_ratings ( + id INT, + movie_title VARCHAR, + user_id INT, + rating INT +); + +INSERT INTO movie_ratings (id, movie_title, user_id, rating) +VALUES (1, 'Inception', 1, 5), + (2, 'Inception', 2, 4), + (3, 'Inception', 3, 5), + (4, 'Interstellar', 1, 4), + (5, 'Interstellar', 2, 3); + +-- List all ratings for Inception in an array +SELECT movie_title, ARRAY_AGG(rating) AS ratings +FROM movie_ratings +WHERE movie_title = 'Inception' +GROUP BY movie_title; + +| movie_title | ratings | +|-------------|------------| +| Inception | [5, 4, 5] | + +-- List all ratings for Inception in an array Using `WITHIN GROUP` +SELECT movie_title, ARRAY_AGG(rating) WITHIN GROUP ( ORDER BY rating DESC ) AS ratings +FROM movie_ratings +WHERE movie_title = 'Inception' +GROUP BY movie_title; + +| movie_title | ratings | +|-------------|------------| +| Inception | [5, 5, 4] | +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/array-aggregate.md b/tidb-cloud-lake/sql/array-aggregate.md new file mode 100644 index 0000000000000..9fb13bc537bb7 --- /dev/null +++ b/tidb-cloud-lake/sql/array-aggregate.md @@ -0,0 +1,30 @@ +--- +title: ARRAY_AGGREGATE +summary: 使用聚合函数对数组中的元素进行聚合。 +--- + +# ARRAY_AGGREGATE + +使用聚合函数对数组中的元素进行聚合。 + +## 语法 {#syntax} + +```sql +ARRAY_AGGREGATE( , '' ) +``` + +- 支持的聚合函数包括 `avg`、`count`、`max`、`min`、`sum`、`any`、`stddev_samp`、`stddev_pop`、`stddev`、`std`、`median`、`approx_count_distinct`、`kurtosis` 和 `skewness`。 + +- 该语法可以改写为 `ARRAY_( )`。例如,`ARRAY_AVG( )`。 + +## 示例 {#examples} + +```sql +SELECT ARRAY_AGGREGATE([1, 2, 3, 4], 'SUM'), ARRAY_SUM([1, 2, 3, 4]); + +┌────────────────────────────────────────────────────────────────┐ +│ array_aggregate([1, 2, 3, 4], 'sum') │ array_sum([1, 2, 3, 4]) │ +├──────────────────────────────────────┼─────────────────────────┤ +│ 10 │ 10 │ +└────────────────────────────────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/array-any.md b/tidb-cloud-lake/sql/array-any.md new file mode 100644 index 0000000000000..a28c1a38acc4a --- /dev/null +++ b/tidb-cloud-lake/sql/array-any.md @@ -0,0 +1,50 @@ +--- +title: ARRAY_ANY +summary: 返回数组中第一个非 `NULL` 元素。等价于 `ARRAY_AGGREGATE(, 'ANY')`。 +--- + +# ARRAY_ANY + +返回数组中第一个非 `NULL` 元素。等价于 `ARRAY_AGGREGATE(, 'ANY')`。 + +## 语法 {#syntax} + +```sql +ARRAY_ANY() +``` + +## 返回类型 {#return-type} + +与数组元素类型相同。 + +## 示例 {#examples} + +```sql +SELECT ARRAY_ANY(['a', 'b', 'c']) AS first_item; + +┌────────────┐ +│ first_item │ +├────────────┤ +│ a │ +└────────────┘ +``` + +```sql +SELECT ARRAY_ANY([NULL, 'x', 'y']) AS first_non_null; + +┌────────────────┐ +│ first_non_null │ +├────────────────┤ +│ x │ +└────────────────┘ +``` + +```sql +SELECT ARRAY_ANY([NULL, 10, 20]) AS first_number; + +┌──────────────┐ +│ first_number │ +├──────────────┤ +│ 10 │ +└──────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/array-append.md b/tidb-cloud-lake/sql/array-append.md new file mode 100644 index 0000000000000..c7d8ac7bfa4e5 --- /dev/null +++ b/tidb-cloud-lake/sql/array-append.md @@ -0,0 +1,72 @@ +--- +title: ARRAY_APPEND +summary: 将一个元素追加到数组末尾。 +--- + +# ARRAY_APPEND + +将一个元素追加到数组末尾。 + +## 语法 {#syntax} + +```sql +ARRAY_APPEND(array, element) +``` + +## 参数 {#parameters} + +| 参数 | 描述 | +|-----------|-------------| +| array | 要向其追加元素的源数组。 | +| element | 要追加到数组中的元素。 | + +## 返回类型 {#return-type} + +追加元素后的数组。 + +## 注意事项 {#notes} + +此函数同时适用于标准数组类型和 variant 数组类型。 + +## 示例 {#examples} + +### 示例 1:追加到标准数组 {#example-1-appending-to-a-standard-array} + +```sql +SELECT ARRAY_APPEND([1, 2, 3], 4); +``` + +结果: + +``` +[1, 2, 3, 4] +``` + +### 示例 2:追加到 variant 数组 {#example-2-appending-to-a-variant-array} + +```sql +SELECT ARRAY_APPEND(PARSE_JSON('[1, 2, 3]'), 4); +``` + +结果: + +``` +[1, 2, 3, 4] +``` + +### 示例 3:追加不同的数据类型 {#example-3-appending-different-data-types} + +```sql +SELECT ARRAY_APPEND(['a', 'b'], 'c'); +``` + +结果: + +``` +["a", "b", "c"] +``` + +## 相关函数 {#related-functions} + +- [ARRAY_PREPEND](/tidb-cloud-lake/sql/array-prepend.md):将一个元素前置到数组开头 +- [ARRAY_CONCAT](/tidb-cloud-lake/sql/array-concat.md):连接两个数组 \ No newline at end of file diff --git a/tidb-cloud-lake/sql/array-approx-count-distinct.md b/tidb-cloud-lake/sql/array-approx-count-distinct.md new file mode 100644 index 0000000000000..772f5c310f439 --- /dev/null +++ b/tidb-cloud-lake/sql/array-approx-count-distinct.md @@ -0,0 +1,40 @@ +--- +title: ARRAY_APPROX_COUNT_DISTINCT +summary: 返回数组中不同元素的近似计数,并忽略 `NULL` 值。它使用与 [`APPROX_COUNT_DISTINCT`](/tidb-cloud-lake/sql/approx-count-distinct.md) 相同的基于 HyperLogLog 的估算器。 +--- + +# ARRAY_APPROX_COUNT_DISTINCT + +返回数组中不同元素的近似计数,并忽略 `NULL` 值。它使用与 [`APPROX_COUNT_DISTINCT`](/tidb-cloud-lake/sql/approx-count-distinct.md) 相同的基于 HyperLogLog 的估算器。 + +## 语法 {#syntax} + +```sql +ARRAY_APPROX_COUNT_DISTINCT() +``` + +## 返回类型 {#return-type} + +`BIGINT` + +## 示例 {#examples} + +```sql +SELECT ARRAY_APPROX_COUNT_DISTINCT([1, 1, 2, 3, 3, 3]) AS approx_cnt; + +┌────────────┐ +│ approx_cnt │ +├────────────┤ +│ 3 │ +└────────────┘ +``` + +```sql +SELECT ARRAY_APPROX_COUNT_DISTINCT([NULL, 'a', 'a', 'b']) AS approx_cnt_text; + +┌──────────────────┐ +│ approx_cnt_text │ +├──────────────────┤ +│ 2 │ +└──────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/array-avg.md b/tidb-cloud-lake/sql/array-avg.md new file mode 100644 index 0000000000000..85c3951fdcfd7 --- /dev/null +++ b/tidb-cloud-lake/sql/array-avg.md @@ -0,0 +1,50 @@ +--- +title: ARRAY_AVG +summary: 返回数组中数值项的平均值。`NULL` 元素会被忽略;非数值会引发错误。 +--- + +# ARRAY_AVG + +返回数组中数值项的平均值。`NULL` 元素会被忽略;非数值会引发错误。 + +## 语法 {#syntax} + +```sql +ARRAY_AVG() +``` + +## 返回类型 {#return-type} + +数值型(使用能够表示结果的最小数值类型)。 + +## 示例 {#examples} + +```sql +SELECT ARRAY_AVG([1, 2, 3, 4]) AS avg_int; + +┌─────────┐ +│ avg_int │ +├─────────┤ +│ 2.5 │ +└─────────┘ +``` + +```sql +SELECT ARRAY_AVG([1.5, 2.5, 3.5]) AS avg_decimal; + +┌──────────────┐ +│ avg_decimal │ +├──────────────┤ +│ 2.5000 │ +└──────────────┘ +``` + +```sql +SELECT ARRAY_AVG([10, NULL, 4]) AS avg_with_null; + +┌──────────────┐ +│ avg_with_null│ +├──────────────┤ +│ 7.0 │ +└──────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/array-compact.md b/tidb-cloud-lake/sql/array-compact.md new file mode 100644 index 0000000000000..2a95549f392f0 --- /dev/null +++ b/tidb-cloud-lake/sql/array-compact.md @@ -0,0 +1,66 @@ +--- +title: ARRAY_COMPACT +summary: 从数组中移除所有 NULL 值。 +--- + +# ARRAY_COMPACT + +从数组中移除所有 NULL 值。 + +## 语法 {#syntax} + +```sql +ARRAY_COMPACT(array) +``` + +## 参数 {#parameters} + +| 参数 | 描述 | +|-----------|-------------| +| array | 要从中移除 NULL 值的数组。 | + +## 返回类型 {#return-type} + +不包含 NULL 值的数组。 + +## 注意事项 {#notes} + +此函数同时适用于标准数组类型和 variant 数组类型。 + +## 示例 {#examples} + +### 示例 1:从标准数组中移除 NULL 值 {#example-1-removing-nulls-from-a-standard-array} + +```sql +SELECT ARRAY_COMPACT([1, NULL, 2, NULL, 3]); +``` + +结果: + +``` +[1, 2, 3] +``` + +### 示例 2:从 variant 数组中移除 NULL 值 {#example-2-removing-nulls-from-a-variant-array} + +```sql +SELECT ARRAY_COMPACT(PARSE_JSON('["apple", null, "banana", null, "orange"]')); +``` + +结果: + +``` +["apple", "banana", "orange"] +``` + +### 示例 3:不包含 NULL 值的数组 {#example-3-array-with-no-nulls} + +```sql +SELECT ARRAY_COMPACT([1, 2, 3]); +``` + +结果: + +``` +[1, 2, 3] +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/array-concat.md b/tidb-cloud-lake/sql/array-concat.md new file mode 100644 index 0000000000000..43450d440151b --- /dev/null +++ b/tidb-cloud-lake/sql/array-concat.md @@ -0,0 +1,26 @@ +--- +title: ARRAY_CONCAT +summary: 拼接两个数组。 +--- + +# ARRAY_CONCAT + +拼接两个数组。 + +## 语法 {#syntax} + +```sql +ARRAY_CONCAT( , ) +``` + +## 示例 {#examples} + +```sql +SELECT ARRAY_CONCAT([1, 2], [3, 4]); + +┌──────────────────────────────┐ +│ array_concat([1, 2], [3, 4]) │ +├──────────────────────────────┤ +│ [1,2,3,4] │ +└──────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/array-construct.md b/tidb-cloud-lake/sql/array-construct.md new file mode 100644 index 0000000000000..e78f78f1533fa --- /dev/null +++ b/tidb-cloud-lake/sql/array-construct.md @@ -0,0 +1,63 @@ +--- +title: ARRAY_CONSTRUCT +summary: 使用指定的值创建 JSON 数组。 +--- + +# ARRAY_CONSTRUCT + +使用指定的值创建 JSON 数组。 + +## 别名 {#aliases} + +- `JSON_ARRAY` + +## 语法 {#syntax} + +```sql +ARRAY_CONSTRUCT(value1[, value2[, ...]]) +``` + +## 返回类型 {#return-type} + +JSON 数组。 + +## 示例 {#examples} + +### 示例 1:使用常量值或表达式创建 JSON 数组 {#example-1-creating-json-array-with-constant-values-or-expressions} + +```sql +SELECT ARRAY_CONSTRUCT('Datalake', 3.14, NOW(), TRUE, NULL); + +array_construct('datalake', 3.14, now(), true, null) | +--------------------------------------------------------+ +["Datalake",3.14,"2023-09-06 07:23:55.399070",true,null]| + +SELECT ARRAY_CONSTRUCT('fruits', ARRAY_CONSTRUCT('apple', 'banana', 'orange'), OBJECT_CONSTRUCT('price', 1.2, 'quantity', 3)); + +array_construct('fruits', array_construct('apple', 'banana', 'orange'), object_construct('price', 1.2, 'quantity', 3))| +-------------------------------------------------------------------------------------------------------+ +["fruits",["apple","banana","orange"],{"price":1.2,"quantity":3}] | +``` + +### 示例 2:根据表数据创建 JSON 数组 {#example-2-creating-json-array-from-table-data} + +```sql +CREATE TABLE products ( + ProductName VARCHAR(255), + Price DECIMAL(10, 2) +); + +INSERT INTO products (ProductName, Price) +VALUES + ('Apple', 1.2), + ('Banana', 0.5), + ('Orange', 0.8); + +SELECT ARRAY_CONSTRUCT(ProductName, Price) FROM products; + +array_construct(productname, price)| +------------------------------+ +["Apple",1.2] | +["Banana",0.5] | +["Orange",0.8] | +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/array-contains.md b/tidb-cloud-lake/sql/array-contains.md new file mode 100644 index 0000000000000..ffb55800dc560 --- /dev/null +++ b/tidb-cloud-lake/sql/array-contains.md @@ -0,0 +1,67 @@ +--- +title: ARRAY_CONTAINS +summary: 如果数组包含指定元素,则返回 true。 +--- + +# ARRAY_CONTAINS + +如果数组包含指定元素,则返回 true。 + +## 语法 {#syntax} + +```sql +ARRAY_CONTAINS(array, element) +``` + +## 参数 {#parameters} + +| 参数 | 描述 | +|-----------|-------------| +| array | 要在其中搜索的数组。 | +| element | 要搜索的元素。 | + +## 返回类型 {#return-type} + +BOOLEAN + +## 注意事项 {#notes} + +此函数同时适用于标准数组类型和 variant 数组类型。 + +## 示例 {#examples} + +### 示例 1:检查标准数组 {#example-1-checking-a-standard-array} + +```sql +SELECT ARRAY_CONTAINS([1, 2, 3], 2); +``` + +结果: + +``` +true +``` + +### 示例 2:检查 variant 数组 {#example-2-checking-a-variant-array} + +```sql +SELECT ARRAY_CONTAINS(PARSE_JSON('["apple", "banana", "orange"]'), 'banana'); +``` + +结果: + +``` +true +``` + +### 示例 3:未找到元素 {#example-3-element-not-found} + +```sql +SELECT ARRAY_CONTAINS([1, 2, 3], 4); +``` + +结果: + +``` +false +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/array-count.md b/tidb-cloud-lake/sql/array-count.md new file mode 100644 index 0000000000000..413a58d0e0fdb --- /dev/null +++ b/tidb-cloud-lake/sql/array-count.md @@ -0,0 +1,50 @@ +--- +title: ARRAY_COUNT +summary: 统计数组中非 `NULL` 元素的数量。 +--- + +# ARRAY_COUNT + +统计数组中非 `NULL` 元素的数量。 + +## 语法 {#syntax} + +```sql +ARRAY_COUNT() +``` + +## 返回类型 {#return-type} + +`BIGINT` + +## 示例 {#examples} + +```sql +SELECT ARRAY_COUNT([1, 2, 3]) AS cnt; + +┌─────┐ +│ cnt │ +├─────┤ +│ 3 │ +└─────┘ +``` + +```sql +SELECT ARRAY_COUNT([1, NULL, 3]) AS cnt_with_null; + +┌──────────────┐ +│ cnt_with_null│ +├──────────────┤ +│ 2 │ +└──────────────┘ +``` + +```sql +SELECT ARRAY_COUNT(['a', 'b', NULL]) AS cnt_text; + +┌─────────┐ +│ cnt_text│ +├─────────┤ +│ 2 │ +└─────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/array-distinct.md b/tidb-cloud-lake/sql/array-distinct.md new file mode 100644 index 0000000000000..f439ba6f237c7 --- /dev/null +++ b/tidb-cloud-lake/sql/array-distinct.md @@ -0,0 +1,31 @@ +--- +title: ARRAY_DISTINCT +summary: 从 JSON 数组中移除重复元素,并返回仅包含不同元素的数组。 +--- + +# ARRAY_DISTINCT + +从 JSON 数组中移除重复元素,并返回仅包含不同元素的数组。 + +## 别名 {#aliases} + +- `JSON_ARRAY_DISTINCT` + +## 语法 {#syntax} + +```sql +ARRAY_DISTINCT() +``` + +## 返回类型 {#return-type} + +JSON 数组。 + +## 示例 {#examples} + +```sql +SELECT ARRAY_DISTINCT('["apple", "banana", "apple", "orange", "banana"]'::VARIANT); + +-[ RECORD 1 ]----------------------------------- +array_distinct('["apple", "banana", "apple", "orange", "banana"]'::VARIANT): ["apple","banana","orange"] +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/array-except.md b/tidb-cloud-lake/sql/array-except.md new file mode 100644 index 0000000000000..169e0d1be291b --- /dev/null +++ b/tidb-cloud-lake/sql/array-except.md @@ -0,0 +1,40 @@ +--- +title: ARRAY_EXCEPT +summary: 返回一个新的 JSON 数组,其中包含第一个 JSON 数组中存在但第二个 JSON 数组中不存在的元素。 +--- + +# ARRAY_EXCEPT + +返回一个新的 JSON 数组,其中包含第一个 JSON 数组中存在但第二个 JSON 数组中不存在的元素。 + +## 别名 {#aliases} + +- `JSON_ARRAY_EXCEPT` + +## 语法 {#syntax} + +```sql +ARRAY_EXCEPT(, ) +``` + +## 返回类型 {#return-type} + +JSON 数组。 + +## 示例 {#examples} + +```sql +SELECT ARRAY_EXCEPT( + '["apple", "banana", "orange"]'::VARIANT, + '["banana", "grapes"]'::VARIANT +); + +-[ RECORD 1 ]----------------------------------- +array_except('["apple", "banana", "orange"]'::VARIANT, '["banana", "grapes"]'::VARIANT): ["apple","orange"] + +-- 返回空数组,因为第一个数组中的所有元素都存在于第二个数组中。 +SELECT ARRAY_EXCEPT('["apple", "banana", "orange"]'::VARIANT, '["apple", "banana", "orange"]'::VARIANT) + +-[ RECORD 1 ]----------------------------------- +array_except('["apple", "banana", "orange"]'::VARIANT, '["apple", "banana", "orange"]'::VARIANT): [] +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/array-filter.md b/tidb-cloud-lake/sql/array-filter.md new file mode 100644 index 0000000000000..83075d9ec66ce --- /dev/null +++ b/tidb-cloud-lake/sql/array-filter.md @@ -0,0 +1,32 @@ +--- +title: ARRAY_FILTER +summary: 根据指定的 Lambda 表达式从 JSON 数组中过滤元素,仅返回满足条件的元素。有关 Lambda 表达式的更多信息,请参见 Lambda Expressions。 +--- + +# ARRAY_FILTER + +根据指定的 Lambda 表达式从 JSON 数组中过滤元素,仅返回满足条件的元素。有关 Lambda 表达式的更多信息,请参见 [Lambda 表达式](/tidb-cloud-lake/sql/stored-procedure-scripting.md#lambda-expressions)。 + +## 语法 {#syntax} + +```sql +ARRAY_FILTER(, ) +``` + +## 返回类型 {#return-type} + +JSON 数组。 + +## 示例 {#examples} + +以下示例对数组进行过滤,仅返回以字母 `a` 开头的字符串,结果为 `["apple", "avocado"]`: + +```sql +SELECT ARRAY_FILTER( + ['apple', 'banana', 'avocado', 'grape'], + d -> d::String LIKE 'a%' +); + +-[ RECORD 1 ]----------------------------------- +array_filter(['apple', 'banana', 'avocado', 'grape'], d -> d::STRING LIKE 'a%'): ["apple","avocado"] +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/array-flatten.md b/tidb-cloud-lake/sql/array-flatten.md new file mode 100644 index 0000000000000..2bae8bc47fe59 --- /dev/null +++ b/tidb-cloud-lake/sql/array-flatten.md @@ -0,0 +1,54 @@ +--- +title: ARRAY_FLATTEN +summary: 将嵌套数组展平为单维数组。 +--- + +# ARRAY_FLATTEN + +将嵌套数组展平为单维数组。 + +## 语法 {#syntax} + +```sql +ARRAY_FLATTEN(array) +``` + +## 参数 {#parameters} + +| 参数 | 描述 | +|-----------|-------------| +| array | 要展平的嵌套数组。 | + +## 返回类型 {#return-type} + +数组(展平后)。 + +## 注意事项 {#notes} + +此函数同时适用于标准数组类型和 variant 数组类型。 + +## 示例 {#examples} + +### 示例 1:展平嵌套数组 {#example-1-flattening-a-nested-array} + +```sql +SELECT ARRAY_FLATTEN([[1, 2], [3, 4]]); +``` + +结果: + +``` +[1, 2, 3, 4] +``` + +### 示例 2:展平 variant 数组 {#example-2-flattening-a-variant-array} + +```sql +SELECT ARRAY_FLATTEN(PARSE_JSON('[["a", "b"], ["c", "d"]]')); +``` + +结果: + +``` +["a", "b", "c", "d"] +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/array-functions.md b/tidb-cloud-lake/sql/array-functions.md new file mode 100644 index 0000000000000..1353fc5055a32 --- /dev/null +++ b/tidb-cloud-lake/sql/array-functions.md @@ -0,0 +1,100 @@ +--- +title: 数组函数 +summary: 本节提供 {{{ .lake }}} 中数组函数的参考信息。数组函数支持创建、操作、搜索和转换数组数据结构。 +--- + +# 数组函数 + +本节提供 {{{ .lake }}} 中数组函数的参考信息。数组函数支持创建、操作、搜索和转换数组数据结构。 + +## 数组创建与构造 {#array-creation-construction} + +| 函数 | 描述 | 示例 | +|----------|-------------|---------| +| [ARRAY](/tidb-cloud-lake/sql/array.md) | 从表达式构建数组 | `ARRAY(1, 2, 3)` → `[1,2,3]` | +| [ARRAY_CONSTRUCT](/tidb-cloud-lake/sql/array-construct.md) | 从单个值创建数组 | `ARRAY_CONSTRUCT(1, 2, 3)` → `[1,2,3]` | +| [RANGE](/tidb-cloud-lake/sql/range.md) | 生成顺序数字组成的数组 | `RANGE(1, 5)` → `[1,2,3,4]` | +| [ARRAY_GENERATE_RANGE](/tidb-cloud-lake/sql/array-generate-range.md) | 生成可选步长的序列 | `ARRAY_GENERATE_RANGE(0, 6, 2)` → `[0,2,4]` | + +## 数组访问与信息 {#array-access-information} + +| 函数 | 描述 | 示例 | +|----------|-------------|---------| +| [GET](/tidb-cloud-lake/sql/get.md) | 按索引从数组中获取元素 | `GET([1,2,3], 1)` → `1` | +| [ARRAY_GET](/tidb-cloud-lake/sql/array-get.md) | GET 函数的别名 | `ARRAY_GET([1,2,3], 1)` → `1` | +| [CONTAINS](/tidb-cloud-lake/sql/contains.md) | 检查数组是否包含指定值 | `CONTAINS([1,2,3], 2)` → `true` | +| [ARRAY_CONTAINS](/tidb-cloud-lake/sql/array-contains.md) | 检查数组是否包含指定值 | `ARRAY_CONTAINS([1,2,3], 2)` → `true` | +| [ARRAY_SIZE](/tidb-cloud-lake/sql/array-size.md) | 返回数组长度(别名:`ARRAY_LENGTH`) | `ARRAY_SIZE([1,2,3])` → `3` | +| [ARRAY_COUNT](/tidb-cloud-lake/sql/array-count.md) | 统计非 `NULL` 条目数量 | `ARRAY_COUNT([1,NULL,2])` → `2` | +| [ARRAY_ANY](/tidb-cloud-lake/sql/array-any.md) | 返回第一个非 `NULL` 值 | `ARRAY_ANY([NULL,'a','b'])` → `'a'` | + +## 数组修改 {#array-modification} + +| 函数 | 描述 | 示例 | +|----------|-------------|---------| +| [ARRAY_APPEND](/tidb-cloud-lake/sql/array-append.md) | 在数组末尾追加元素 | `ARRAY_APPEND([1,2], 3)` → `[1,2,3]` | +| [ARRAY_PREPEND](/tidb-cloud-lake/sql/array-prepend.md) | 在数组开头前置元素 | `ARRAY_PREPEND(0, [1,2])` → `[0,1,2]` | +| [ARRAY_INSERT](/tidb-cloud-lake/sql/array-insert.md) | 在指定位置插入元素 | `ARRAY_INSERT([1,3], 1, 2)` → `[1,2,3]` | +| [ARRAY_REMOVE](/tidb-cloud-lake/sql/array-remove.md) | 删除指定元素的所有出现项 | `ARRAY_REMOVE([1,2,2,3], 2)` → `[1,3]` | +| [ARRAY_REMOVE_FIRST](/tidb-cloud-lake/sql/array-remove-first.md) | 删除数组中的第一个元素 | `ARRAY_REMOVE_FIRST([1,2,3])` → `[2,3]` | +| [ARRAY_REMOVE_LAST](/tidb-cloud-lake/sql/array-remove-last.md) | 删除数组中的最后一个元素 | `ARRAY_REMOVE_LAST([1,2,3])` → `[1,2]` | + +## 数组组合与操作 {#array-combination-manipulation} + +| 函数 | 描述 | 示例 | +|----------|-------------|---------| +| [ARRAY_CONCAT](/tidb-cloud-lake/sql/array-concat.md) | 连接多个数组 | `ARRAY_CONCAT([1,2], [3,4])` → `[1,2,3,4]` | +| [ARRAY_SLICE](/tidb-cloud-lake/sql/array-slice.md) | 提取数组的一部分 | `ARRAY_SLICE([1,2,3,4], 1, 2)` → `[1,2]` | +| [SLICE](/tidb-cloud-lake/sql/slice.md) | ARRAY_SLICE 函数的别名 | `SLICE([1,2,3,4], 1, 2)` → `[1,2]` | +| [ARRAYS_ZIP](/tidb-cloud-lake/sql/arrays-zip.md) | 按元素位置组合多个数组 | `ARRAYS_ZIP([1,2], ['a','b'])` → `[(1,'a'),(2,'b')]` | +| [ARRAY_SORT](/tidb-cloud-lake/sql/array-sort.md) | 对值进行排序;不同变体可控制顺序和空值 | `ARRAY_SORT([3,1,2])` → `[1,2,3]` | + +## 数组集合操作 {#array-set-operations} + +| 函数 | 描述 | 示例 | +|----------|-------------|---------| +| [ARRAY_DISTINCT](/tidb-cloud-lake/sql/array-distinct.md) | 返回数组中的唯一元素 | `ARRAY_DISTINCT([1,2,2,3])` → `[1,2,3]` | +| [ARRAY_UNIQUE](/tidb-cloud-lake/sql/array-unique.md) | ARRAY_DISTINCT 函数的别名 | `ARRAY_UNIQUE([1,2,2,3])` → `[1,2,3]` | +| [ARRAY_INTERSECTION](/tidb-cloud-lake/sql/array-intersection.md) | 返回数组之间的公共元素 | `ARRAY_INTERSECTION([1,2,3], [2,3,4])` → `[2,3]` | +| [ARRAY_EXCEPT](/tidb-cloud-lake/sql/array-except.md) | 返回第一个数组中存在但第二个数组中不存在的元素 | `ARRAY_EXCEPT([1,2,3], [2,4])` → `[1,3]` | +| [ARRAY_OVERLAP](/tidb-cloud-lake/sql/array-overlap.md) | 检查数组是否有公共元素 | `ARRAY_OVERLAP([1,2,3], [3,4,5])` → `true` | + +## 数组处理与转换 {#array-processing-transformation} + +| 函数 | 描述 | 示例 | +|----------|-------------|---------| +| [ARRAY_TRANSFORM](/tidb-cloud-lake/sql/json-array-transform.md) | 对每个数组元素应用函数 | `ARRAY_TRANSFORM([1,2,3], x -> x * 2)` → `[2,4,6]` | +| [ARRAY_FILTER](/tidb-cloud-lake/sql/array-filter.md) | 根据条件过滤数组元素 | `ARRAY_FILTER([1,2,3,4], x -> x > 2)` → `[3,4]` | +| [ARRAY_REDUCE](/tidb-cloud-lake/sql/array-reduce.md) | 使用聚合将数组归约为单个值 | `ARRAY_REDUCE([1,2,3], 0, (acc,x) -> acc + x)` → `6` | +| [ARRAY_AGGREGATE](/tidb-cloud-lake/sql/array-aggregate.md) | 使用函数聚合数组元素 | `ARRAY_AGGREGATE([1,2,3], 'sum')` → `6` | + +## 数组聚合与统计 {#array-aggregations-statistics} + +| 函数 | 描述 | 示例 | +|----------|-------------|---------| +| [ARRAY_SUM](/tidb-cloud-lake/sql/array-sum.md) | 数值之和 | `ARRAY_SUM([1,2,3])` → `6` | +| [ARRAY_AVG](/tidb-cloud-lake/sql/array-avg.md) | 数值平均值 | `ARRAY_AVG([1,2,3])` → `2` | +| [ARRAY_MEDIAN](/tidb-cloud-lake/sql/array-median.md) | 数值中位数 | `ARRAY_MEDIAN([1,3,2])` → `2` | +| [ARRAY_MIN](/tidb-cloud-lake/sql/array-min.md) | 最小值 | `ARRAY_MIN([3,1,2])` → `1` | +| [ARRAY_MAX](/tidb-cloud-lake/sql/array-max.md) | 最大值 | `ARRAY_MAX([3,1,2])` → `3` | +| [ARRAY_STDDEV_POP](/tidb-cloud-lake/sql/array-stddev-pop.md) | 总体标准差(别名:`ARRAY_STD`) | `ARRAY_STDDEV_POP([1,2,3])` | +| [ARRAY_STDDEV_SAMP](/tidb-cloud-lake/sql/array-stddev-samp.md) | 样本标准差(别名:`ARRAY_STDDEV`) | `ARRAY_STDDEV_SAMP([1,2,3])` | +| [ARRAY_KURTOSIS](/tidb-cloud-lake/sql/array-kurtosis.md) | 值的超额峰度 | `ARRAY_KURTOSIS([1,2,3,4])` | +| [ARRAY_SKEWNESS](/tidb-cloud-lake/sql/array-skewness.md) | 值的偏度 | `ARRAY_SKEWNESS([1,2,3,4])` | +| [ARRAY_APPROX_COUNT_DISTINCT](/tidb-cloud-lake/sql/array-approx-count-distinct.md) | 近似去重计数 | `ARRAY_APPROX_COUNT_DISTINCT([1,1,2])` → `2` | + +## 数组格式化 {#array-formatting} + +| 函数 | 描述 | 示例 | +|----------|-------------|---------| +| [ARRAY_TO_STRING](/tidb-cloud-lake/sql/array-to-string.md) | 将数组元素连接为字符串 | `ARRAY_TO_STRING(['a','b'], ',')` → `'a,b'` | + +## 数组实用函数 {#array-utility-functions} + +| 函数 | 描述 | 示例 | +|----------|-------------|---------| +| [ARRAY_COMPACT](/tidb-cloud-lake/sql/array-compact.md) | 从数组中移除空值 | `ARRAY_COMPACT([1,null,2,null,3])` → `[1,2,3]` | +| [ARRAY_FLATTEN](/tidb-cloud-lake/sql/array-flatten.md) | 将嵌套数组展平为单个数组 | `ARRAY_FLATTEN([[1,2],[3,4]])` → `[1,2,3,4]` | +| [ARRAY_REVERSE](/tidb-cloud-lake/sql/array-reverse.md) | 反转数组元素的顺序 | `ARRAY_REVERSE([1,2,3])` → `[3,2,1]` | +| [ARRAY_INDEXOF](/tidb-cloud-lake/sql/array-indexof.md) | 返回元素首次出现的索引 | `ARRAY_INDEXOF([1,2,3,2], 2)` → `1` | +| [UNNEST](/tidb-cloud-lake/sql/unnest.md) | 将数组展开为单独的行 | `UNNEST([1,2,3])` → `1, 2, 3`(作为单独的行) | \ No newline at end of file diff --git a/tidb-cloud-lake/sql/array-generate-range.md b/tidb-cloud-lake/sql/array-generate-range.md new file mode 100644 index 0000000000000..8178f7b6c4c3a --- /dev/null +++ b/tidb-cloud-lake/sql/array-generate-range.md @@ -0,0 +1,54 @@ +--- +title: ARRAY_GENERATE_RANGE +summary: 构建一个由起始值到结束值之间按固定间隔排列的整数数组。结束边界为排他。 +--- + +# ARRAY_GENERATE_RANGE + +构建一个由起始值到结束值之间按固定间隔排列的整数数组。`end` 边界为排他。 + +## 语法 {#syntax} + +```sql +ARRAY_GENERATE_RANGE(, [, ]) +``` + +- ``:要包含的第一个值。 +- ``:排他的上界(或下界)。 +- ``:可选的增量(默认为 `1`)。负步长会生成降序序列。 + +## 返回类型 {#return-type} + +`ARRAY` + +## 示例 {#examples} + +```sql +SELECT ARRAY_GENERATE_RANGE(1, 5) AS seq; + +┌──────────┐ +│ seq │ +├──────────┤ +│ [1,2,3,4]│ +└──────────┘ +``` + +```sql +SELECT ARRAY_GENERATE_RANGE(0, 6, 2) AS seq_step; + +┌────────────┐ +│ seq_step │ +├────────────┤ +│ [0,2,4] │ +└────────────┘ +``` + +```sql +SELECT ARRAY_GENERATE_RANGE(5, 0, -2) AS seq_down; + +┌────────────┐ +│ seq_down │ +├────────────┤ +│ [5,3,1] │ +└────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/array-get.md b/tidb-cloud-lake/sql/array-get.md new file mode 100644 index 0000000000000..a178e198871ad --- /dev/null +++ b/tidb-cloud-lake/sql/array-get.md @@ -0,0 +1,8 @@ +--- +title: ARRAY_GET +summary: GET 的别名。 +--- + +# ARRAY_GET + +[GET](/tidb-cloud-lake/sql/get.md) 的别名。 \ No newline at end of file diff --git a/tidb-cloud-lake/sql/array-indexof.md b/tidb-cloud-lake/sql/array-indexof.md new file mode 100644 index 0000000000000..5291079d890e1 --- /dev/null +++ b/tidb-cloud-lake/sql/array-indexof.md @@ -0,0 +1,68 @@ +--- +title: ARRAY_INDEXOF +summary: 返回数组中某个元素首次出现的位置索引。 +--- + +# ARRAY_INDEXOF + +返回数组中某个元素首次出现的位置索引。 + +## 语法 {#syntax} + +```sql +ARRAY_INDEXOF(array, element) +``` + +## 参数 {#parameters} + +| 参数 | 描述 | +|-----------|-------------| +| array | 要在其中搜索的数组。 | +| element | 要搜索的元素。 | + +## 返回类型 {#return-type} + +INTEGER + +## 关于索引的重要说明 {#important-note-on-indexing} + +- 对于标准数组类型:索引从 **1** 开始(第一个元素的位置是 1)。 +- 对于 variant 数组类型:索引从 **0** 开始(第一个元素的位置是 0),以兼容 Snowflake。 + +## 示例 {#examples} + +### 示例 1:在标准数组中查找元素(索引从 1 开始) {#example-1-finding-an-element-in-a-standard-array-1-based-indexing} + +```sql +SELECT ARRAY_INDEXOF([10, 20, 30, 20], 20); +``` + +结果: + +``` +2 +``` + +### 示例 2:在 Variant 数组中查找元素(索引从 0 开始) {#example-2-finding-an-element-in-a-variant-array-0-based-indexing} + +```sql +SELECT ARRAY_INDEXOF(PARSE_JSON('["apple", "banana", "orange"]'), 'banana'); +``` + +结果: + +``` +1 +``` + +### 示例 3:未找到元素 {#example-3-element-not-found} + +```sql +SELECT ARRAY_INDEXOF([1, 2, 3], 4); +``` + +结果: + +``` +0 +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/array-insert.md b/tidb-cloud-lake/sql/array-insert.md new file mode 100644 index 0000000000000..3e1561de5b3e9 --- /dev/null +++ b/tidb-cloud-lake/sql/array-insert.md @@ -0,0 +1,68 @@ +--- +title: ARRAY_INSERT +summary: 在指定索引处向 JSON 数组中插入一个值,并返回修改后的 JSON 数组。 +--- + +# ARRAY_INSERT + +在指定索引处向 JSON 数组中插入一个值,并返回修改后的 JSON 数组。 + +## 别名 {#aliases} + +- `JSON_ARRAY_INSERT` + +## 语法 {#syntax} + +```sql +ARRAY_INSERT(, , ) +``` + +| 参数 | 描述 | +|----------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `` | 要修改的 JSON 数组。 | +| `` | 要插入值的位置。正索引会在指定位置插入;如果超出范围,则追加到末尾。负索引从数组末尾开始计数;如果超出范围,则插入到开头。 | +| `` | 要插入到数组中的 JSON 值。 | + +## 返回类型 {#return-type} + +JSON 数组。 + +## 示例 {#examples} + +当 `` 为非负整数时,新元素会插入到指定位置,现有元素会向右移动。 + +```sql +-- The new element is inserted at position 0 (the beginning of the array), shifting all original elements to the right +SELECT ARRAY_INSERT('["task1", "task2", "task3"]'::VARIANT, 0, '"new_task"'::VARIANT); + +-[ RECORD 1 ]----------------------------------- +array_insert('["task1", "task2", "task3"]'::VARIANT, 0, '"new_task"'::VARIANT): ["new_task","task1","task2","task3"] + +-- The new element is inserted at position 1, between task1 and task2 +SELECT ARRAY_INSERT('["task1", "task2", "task3"]'::VARIANT, 1, '"new_task"'::VARIANT); + +-[ RECORD 1 ]----------------------------------- +array_insert('["task1", "task2", "task3"]'::VARIANT, 1, '"new_task"'::VARIANT): ["task1","new_task","task2","task3"] + +-- If the index exceeds the length of the array, the new element is appended at the end of the array +SELECT ARRAY_INSERT('["task1", "task2", "task3"]'::VARIANT, 6, '"new_task"'::VARIANT); + +-[ RECORD 1 ]----------------------------------- +array_insert('["task1", "task2", "task3"]'::VARIANT, 6, '"new_task"'::VARIANT): ["task1","task2","task3","new_task"] +``` + +负数 `` 表示从数组末尾开始计数,其中 `-1` 表示最后一个元素之前的位置,`-2` 表示倒数第二个元素之前的位置,依此类推。 + +```sql +-- The new element is inserted just before the last element (task3) +SELECT ARRAY_INSERT('["task1", "task2", "task3"]'::VARIANT, -1, '"new_task"'::VARIANT); + +-[ RECORD 1 ]----------------------------------- +array_insert('["task1", "task2", "task3"]'::VARIANT, - 1, '"new_task"'::VARIANT): ["task1","task2","new_task","task3"] + +-- Since the negative index exceeds the array’s length, the new element is inserted at the beginning +SELECT ARRAY_INSERT('["task1", "task2", "task3"]'::VARIANT, -6, '"new_task"'::VARIANT); + +-[ RECORD 1 ]----------------------------------- +array_insert('["task1", "task2", "task3"]'::VARIANT, - 6, '"new_task"'::VARIANT): ["new_task","task1","task2","task3"] +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/array-intersection.md b/tidb-cloud-lake/sql/array-intersection.md new file mode 100644 index 0000000000000..198eff390de87 --- /dev/null +++ b/tidb-cloud-lake/sql/array-intersection.md @@ -0,0 +1,41 @@ +--- +title: ARRAY_INTERSECTION +summary: 返回两个 JSON 数组之间的公共元素。 +--- + +# ARRAY_INTERSECTION + +返回两个 JSON 数组之间的公共元素。 + +## 别名 {#aliases} + +- `JSON_ARRAY_INTERSECTION` + +## 语法 {#syntax} + +```sql +ARRAY_INTERSECTION(, ) +``` + +## 返回类型 {#return-type} + +JSON 数组。 + +## 示例 {#examples} + +```sql +-- 查找两个 JSON 数组的交集 +SELECT ARRAY_INTERSECTION('["Electronics", "Books", "Toys"]'::JSON, '["Books", "Fashion", "Electronics"]'::JSON); + +-[ RECORD 1 ]----------------------------------- +array_intersection('["Electronics", "Books", "Toys"]'::VARIANT, '["Books", "Fashion", "Electronics"]'::VARIANT): ["Electronics","Books"] + +-- 使用迭代方法,将第一次查询的结果与第三个 JSON 数组求交集 +SELECT ARRAY_INTERSECTION( + ARRAY_INTERSECTION('["Electronics", "Books", "Toys"]'::JSON, '["Books", "Fashion", "Electronics"]'::JSON), + '["Electronics", "Books", "Clothing"]'::JSON +); + +-[ RECORD 1 ]----------------------------------- +array_intersection(array_intersection('["Electronics", "Books", "Toys"]'::VARIANT, '["Books", "Fashion", "Electronics"]'::VARIANT), '["Electronics", "Books", "Clothing"]'::VARIANT): ["Electronics","Books"] +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/array-kurtosis.md b/tidb-cloud-lake/sql/array-kurtosis.md new file mode 100644 index 0000000000000..787c64e4ee958 --- /dev/null +++ b/tidb-cloud-lake/sql/array-kurtosis.md @@ -0,0 +1,50 @@ +--- +title: ARRAY_KURTOSIS +summary: 返回数组中数值的超额峰度。`NULL` 元素会被忽略;非数值元素会引发错误。 +--- + +# ARRAY_KURTOSIS + +返回数组中数值的超额峰度。`NULL` 元素会被忽略;非数值元素会引发错误。 + +## 语法 {#syntax} + +```sql +ARRAY_KURTOSIS() +``` + +## 返回类型 {#return-type} + +浮点型。 + +## 示例 {#examples} + +```sql +SELECT ARRAY_KURTOSIS([1, 2, 3, 4]) AS kurt; + +┌────────────────────────┐ +│ kurt │ +├────────────────────────┤ +│ -1.200000000000001 │ +└────────────────────────┘ +``` + +```sql +SELECT ARRAY_KURTOSIS([1.5, 2.5, 3.5, 4.5]) AS kurt_decimal; + +┌────────────────────────┐ +│ kurt_decimal │ +├────────────────────────┤ +│ -1.200000000000001 │ +└────────────────────────┘ +``` + +```sql +SELECT ARRAY_KURTOSIS([NULL, 2, 3, 4]) AS kurt_null; + +┌────────────────┐ +│ kurt_null │ +├────────────────┤ +│ 0 │ +└────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/array-max.md b/tidb-cloud-lake/sql/array-max.md new file mode 100644 index 0000000000000..6dfe7703de843 --- /dev/null +++ b/tidb-cloud-lake/sql/array-max.md @@ -0,0 +1,50 @@ +--- +title: ARRAY_MAX +summary: 返回数组中的最大数值。`NULL` 元素会被跳过;非数值会导致错误。 +--- + +# ARRAY_MAX + +返回数组中的最大数值。`NULL` 元素会被跳过;非数值会导致错误。 + +## 语法 {#syntax} + +```sql +ARRAY_MAX() +``` + +## 返回类型 {#return-type} + +与数组元素相同的数值类型。 + +## 示例 {#examples} + +```sql +SELECT ARRAY_MAX([5, 2, 9, -1]) AS max_int; + +┌─────────┐ +│ max_int │ +├─────────┤ +│ 9 │ +└─────────┘ +``` + +```sql +SELECT ARRAY_MAX([1.5, -2.25, 3.0]) AS max_decimal; + +┌─────────────┐ +│ max_decimal │ +├─────────────┤ +│ 3.00 │ +└─────────────┘ +``` + +```sql +SELECT ARRAY_MAX([NULL, 10, 4]) AS max_with_null; + +┌───────────────┐ +│ max_with_null │ +├───────────────┤ +│ 10 │ +└───────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/array-median.md b/tidb-cloud-lake/sql/array-median.md new file mode 100644 index 0000000000000..54525f7ea99ae --- /dev/null +++ b/tidb-cloud-lake/sql/array-median.md @@ -0,0 +1,50 @@ +--- +title: ARRAY_MEDIAN +summary: 返回数组中数值的中位数。`NULL` 元素会被忽略。 +--- + +# ARRAY_MEDIAN + +返回数组中数值的中位数。`NULL` 元素会被忽略。 + +## 语法 {#syntax} + +```sql +ARRAY_MEDIAN() +``` + +## 返回类型 {#return-type} + +数值类型。对于偶数长度的输入,结果是中间两个值的平均值。 + +## 示例 {#examples} + +```sql +SELECT ARRAY_MEDIAN([1, 3, 2, 4]) AS med_even; + +┌────────┐ +│ med_even │ +├────────┤ +│ 2.5 │ +└────────┘ +``` + +```sql +SELECT ARRAY_MEDIAN([1, 3, 5]) AS med_odd; + +┌────────┐ +│ med_odd│ +├────────┤ +│ 3.0 │ +└────────┘ +``` + +```sql +SELECT ARRAY_MEDIAN([NULL, 10, 20, 30]) AS med_null; + +┌────────┐ +│ med_null│ +├────────┤ +│ 20.0 │ +└────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/array-min.md b/tidb-cloud-lake/sql/array-min.md new file mode 100644 index 0000000000000..88ac853e1c606 --- /dev/null +++ b/tidb-cloud-lake/sql/array-min.md @@ -0,0 +1,50 @@ +--- +title: ARRAY_MIN +summary: 返回数组中的最小数值。`NULL` 元素会被跳过;非数值会导致错误。 +--- + +# ARRAY_MIN + +返回数组中的最小数值。`NULL` 元素会被跳过;非数值会导致错误。 + +## 语法 {#syntax} + +```sql +ARRAY_MIN() +``` + +## 返回类型 {#return-type} + +与数组元素相同的数值类型。 + +## 示例 {#examples} + +```sql +SELECT ARRAY_MIN([5, 2, 9, -1]) AS min_int; + +┌─────────┐ +│ min_int │ +├─────────┤ +│ -1 │ +└─────────┘ +``` + +```sql +SELECT ARRAY_MIN([1.5, -2.25, 3.0]) AS min_decimal; + +┌──────────────┐ +│ min_decimal │ +├──────────────┤ +│ -2.25 │ +└──────────────┘ +``` + +```sql +SELECT ARRAY_MIN([NULL, 10, 4]) AS min_with_null; + +┌──────────────┐ +│ min_with_null│ +├──────────────┤ +│ 4 │ +└──────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/array-overlap.md b/tidb-cloud-lake/sql/array-overlap.md new file mode 100644 index 0000000000000..a3fe60982074d --- /dev/null +++ b/tidb-cloud-lake/sql/array-overlap.md @@ -0,0 +1,45 @@ +--- +title: ARRAY_OVERLAP +summary: 检查两个 JSON 数组是否存在重叠;如果有公共元素则返回 true,否则返回 false。 +--- + +# ARRAY_OVERLAP + +检查两个 JSON 数组是否存在重叠;如果有公共元素则返回 `true`,否则返回 `false`。 + +## 别名 {#aliases} + +- `JSON_ARRAY_OVERLAP` + +## 语法 {#syntax} + +```sql +ARRAY_OVERLAP(, ) +``` + +## 返回类型 {#return-type} + +该函数返回一个布尔值: + +- 如果两个 JSON 数组之间至少有一个公共元素,则返回 `true`; +- 如果没有公共元素,则返回 `false`。 + +## 示例 {#examples} + +```sql +SELECT ARRAY_OVERLAP( + '["apple", "banana", "cherry"]'::JSON, + '["banana", "kiwi", "mango"]'::JSON +); + +-[ RECORD 1 ]----------------------------------- +array_overlap('["apple", "banana", "cherry"]'::VARIANT, '["banana", "kiwi", "mango"]'::VARIANT): true + +SELECT ARRAY_OVERLAP( + '["grape", "orange"]'::JSON, + '["apple", "kiwi"]'::JSON +); + +-[ RECORD 1 ]----------------------------------- +array_overlap('["grape", "orange"]'::VARIANT, '["apple", "kiwi"]'::VARIANT): false +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/array-prepend.md b/tidb-cloud-lake/sql/array-prepend.md new file mode 100644 index 0000000000000..cd56f5d22b1b9 --- /dev/null +++ b/tidb-cloud-lake/sql/array-prepend.md @@ -0,0 +1,67 @@ +--- +title: ARRAY_PREPEND +summary: 将一个元素添加到数组的开头。 +--- + +# ARRAY_PREPEND + +将一个元素添加到数组的开头。 + +## 语法 {#syntax} + +```sql +ARRAY_PREPEND(element, array) +``` + +## 参数 {#parameters} + +| 参数 | 描述 | +|-----------|-------------| +| element | 要添加到数组开头的元素。 | +| array | 将在其开头添加该元素的源数组。 | + +## 返回类型 {#return-type} + +返回添加了前置元素后的数组。 + +## 注意事项 {#notes} + +此函数同时适用于标准数组类型和 variant 数组类型。 + +## 示例 {#examples} + +### 示例 1:向标准数组开头添加元素 {#example-1-prepending-to-a-standard-array} + +```sql +SELECT ARRAY_PREPEND(0, [1, 2, 3]); +``` + +结果: + +``` +[0, 1, 2, 3] +``` + +### 示例 2:向 variant 数组开头添加元素 {#example-2-prepending-to-a-variant-array} + +```sql +SELECT ARRAY_PREPEND('apple', PARSE_JSON('["banana", "orange"]')); +``` + +结果: + +``` +["apple", "banana", "orange"] +``` + +### 示例 3:添加复杂元素到数组开头 {#example-3-prepending-a-complex-element} + +```sql +SELECT ARRAY_PREPEND(PARSE_JSON('{"value": 0}'), [1, 2, 3]); +``` + +结果: + +``` +[{"value": 0}, 1, 2, 3] +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/array-reduce.md b/tidb-cloud-lake/sql/array-reduce.md new file mode 100644 index 0000000000000..0c09611410432 --- /dev/null +++ b/tidb-cloud-lake/sql/array-reduce.md @@ -0,0 +1,28 @@ +--- +title: ARRAY_REDUCE +summary: 通过应用指定的 Lambda 表达式,将 JSON 数组归约为单个值。有关 Lambda 表达式的更多信息,请参见 Lambda Expressions。 +--- + +# ARRAY_REDUCE + +通过应用指定的 Lambda 表达式,将 JSON 数组归约为单个值。有关 Lambda 表达式的更多信息,请参见 [Lambda 表达式](/tidb-cloud-lake/sql/stored-procedure-scripting.md#lambda-expressions)。 + +## 语法 {#syntax} + +```sql +ARRAY_REDUCE(, ) +``` + +## 示例 {#examples} + +以下示例将数组中的所有元素相乘(2 _3_ 4): + +```sql +SELECT ARRAY_REDUCE( + [2, 3, 4], + (acc, d) -> acc::Int * d::Int +); + +-[ RECORD 1 ]----------------------------------- +array_reduce([2, 3, 4], (acc, d) -> acc::Int32 * d::Int32): 24 +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/array-remove-first.md b/tidb-cloud-lake/sql/array-remove-first.md new file mode 100644 index 0000000000000..f4174360e5acd --- /dev/null +++ b/tidb-cloud-lake/sql/array-remove-first.md @@ -0,0 +1,67 @@ +--- +title: ARRAY_REMOVE_FIRST +summary: 从数组中移除某个元素第一次出现的位置。 +--- + +# ARRAY_REMOVE_FIRST + +从数组中移除某个元素第一次出现的位置。 + +## 语法 {#syntax} + +```sql +ARRAY_REMOVE_FIRST(array, element) +``` + +## 参数 {#parameters} + +| 参数 | 描述 | +|-----------|-------------| +| array | 要从中移除元素的源数组。 | +| element | 要从数组中移除的元素。 | + +## 返回类型 {#return-type} + +返回移除了指定元素第一次出现位置后的数组。 + +## 注意事项 {#notes} + +此函数同时适用于标准数组类型和 variant array 类型。 + +## 示例 {#examples} + +### 示例 1:从标准数组中移除 {#example-1-removing-from-a-standard-array} + +```sql +SELECT ARRAY_REMOVE_FIRST([1, 2, 2, 3], 2); +``` + +结果: + +``` +[1, 2, 3] +``` + +### 示例 2:从 variant array 中移除 {#example-2-removing-from-a-variant-array} + +```sql +SELECT ARRAY_REMOVE_FIRST(PARSE_JSON('["apple", "banana", "apple", "orange"]'), 'apple'); +``` + +结果: + +``` +["banana", "apple", "orange"] +``` + +### 示例 3:未找到元素 {#example-3-element-not-found} + +```sql +SELECT ARRAY_REMOVE_FIRST([1, 2, 3], 4); +``` + +结果: + +``` +[1, 2, 3] +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/array-remove-last.md b/tidb-cloud-lake/sql/array-remove-last.md new file mode 100644 index 0000000000000..d81635e2ae3cb --- /dev/null +++ b/tidb-cloud-lake/sql/array-remove-last.md @@ -0,0 +1,67 @@ +--- +title: ARRAY_REMOVE_LAST +summary: 从数组中移除某个元素最后一次出现的位置。 +--- + +# ARRAY_REMOVE_LAST + +从数组中移除某个元素最后一次出现的位置。 + +## 语法 {#syntax} + +```sql +ARRAY_REMOVE_LAST(array, element) +``` + +## 参数 {#parameters} + +| 参数 | 描述 | +|-----------|-------------| +| array | 要从中移除元素的源数组。 | +| element | 要从数组中移除的元素。 | + +## 返回类型 {#return-type} + +返回移除了指定元素最后一次出现位置后的数组。 + +## 注意事项 {#notes} + +此函数同时适用于标准数组类型和 variant 数组类型。 + +## 示例 {#examples} + +### 示例 1:从标准数组中移除 {#example-1-removing-from-a-standard-array} + +```sql +SELECT ARRAY_REMOVE_LAST([1, 2, 2, 3], 2); +``` + +结果: + +``` +[1, 2, 3] +``` + +### 示例 2:从 variant 数组中移除 {#example-2-removing-from-a-variant-array} + +```sql +SELECT ARRAY_REMOVE_LAST(PARSE_JSON('["apple", "banana", "apple", "orange"]'), 'apple'); +``` + +结果: + +``` +["apple", "banana", "orange"] +``` + +### 示例 3:未找到元素 {#example-3-element-not-found} + +```sql +SELECT ARRAY_REMOVE_LAST([1, 2, 3], 4); +``` + +结果: + +``` +[1, 2, 3] +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/array-remove.md b/tidb-cloud-lake/sql/array-remove.md new file mode 100644 index 0000000000000..07d5e9fe9acdd --- /dev/null +++ b/tidb-cloud-lake/sql/array-remove.md @@ -0,0 +1,67 @@ +--- +title: ARRAY_REMOVE +summary: 从数组中移除某个元素的所有出现项。 +--- + +# ARRAY_REMOVE + +从数组中移除某个元素的所有出现项。 + +## 语法 {#syntax} + +```sql +ARRAY_REMOVE(array, element) +``` + +## 参数 {#parameters} + +| 参数 | 描述 | +|-----------|-------------| +| array | 要从中移除元素的源数组。 | +| element | 要从数组中移除的元素。 | + +## 返回类型 {#return-type} + +返回移除了指定元素所有出现项后的数组。 + +## 注意事项 {#notes} + +此函数同时适用于标准数组类型和 variant 数组类型。 + +## 示例 {#examples} + +### 示例 1:从标准数组中移除元素 {#example-1-removing-from-a-standard-array} + +```sql +SELECT ARRAY_REMOVE([1, 2, 2, 3, 2], 2); +``` + +结果: + +``` +[1, 3] +``` + +### 示例 2:从 variant 数组中移除元素 {#example-2-removing-from-a-variant-array} + +```sql +SELECT ARRAY_REMOVE(PARSE_JSON('["apple", "banana", "apple", "orange"]'), 'apple'); +``` + +结果: + +``` +["banana", "orange"] +``` + +### 示例 3:未找到元素 {#example-3-element-not-found} + +```sql +SELECT ARRAY_REMOVE([1, 2, 3], 4); +``` + +结果: + +``` +[1, 2, 3] +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/array-reverse.md b/tidb-cloud-lake/sql/array-reverse.md new file mode 100644 index 0000000000000..ecd89a22d0798 --- /dev/null +++ b/tidb-cloud-lake/sql/array-reverse.md @@ -0,0 +1,66 @@ +--- +title: ARRAY_REVERSE +summary: 反转数组中元素的顺序。 +--- + +# ARRAY_REVERSE + +反转数组中元素的顺序。 + +## 语法 {#syntax} + +```sql +ARRAY_REVERSE(array) +``` + +## 参数 {#parameters} + +| 参数 | 描述 | +|-----------|-------------| +| array | 要反转的数组。 | + +## 返回类型 {#return-type} + +返回元素顺序被反转后的数组。 + +## 注意事项 {#notes} + +此函数同时适用于标准数组类型和 variant 数组类型。 + +## 示例 {#examples} + +### 示例 1:反转标准数组 {#example-1-reversing-a-standard-array} + +```sql +SELECT ARRAY_REVERSE([1, 2, 3, 4, 5]); +``` + +结果: + +``` +[5, 4, 3, 2, 1] +``` + +### 示例 2:反转 variant 数组 {#example-2-reversing-a-variant-array} + +```sql +SELECT ARRAY_REVERSE(PARSE_JSON('["apple", "banana", "orange"]')); +``` + +结果: + +``` +["orange", "banana", "apple"] +``` + +### 示例 3:反转空数组 {#example-3-reversing-an-empty-array} + +```sql +SELECT ARRAY_REVERSE([]); +``` + +结果: + +``` +[] +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/array-size.md b/tidb-cloud-lake/sql/array-size.md new file mode 100644 index 0000000000000..9e65ad938a1c0 --- /dev/null +++ b/tidb-cloud-lake/sql/array-size.md @@ -0,0 +1,42 @@ +--- +title: ARRAY_SIZE +summary: 返回数组的长度,`NULL` 元素也会计入。 +--- + +# ARRAY_SIZE + +返回数组的长度,`NULL` 元素也会计入。 + +别名:`ARRAY_LENGTH` + +## 语法 {#syntax} + +```sql +ARRAY_SIZE() +``` + +## 返回类型 {#return-type} + +`BIGINT` + +## 示例 {#examples} + +```sql +SELECT ARRAY_SIZE([1, 2, 3]) AS size_plain; + +┌──────────┐ +│ size_plain │ +├──────────┤ +│ 3 │ +└──────────┘ +``` + +```sql +SELECT ARRAY_SIZE([1, NULL, 3]) AS size_with_null; + +┌──────────────┐ +│ size_with_null│ +├──────────────┤ +│ 3 │ +└──────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/array-skewness.md b/tidb-cloud-lake/sql/array-skewness.md new file mode 100644 index 0000000000000..33ecf121054d0 --- /dev/null +++ b/tidb-cloud-lake/sql/array-skewness.md @@ -0,0 +1,50 @@ +--- +title: ARRAY_SKEWNESS +summary: 返回数组中数值的偏度。`NULL` 项会被忽略;非数值项会引发错误。 +--- + +# ARRAY_SKEWNESS + +返回数组中数值的偏度。`NULL` 项会被忽略;非数值项会引发错误。 + +## 语法 {#syntax} + +```sql +ARRAY_SKEWNESS() +``` + +## 返回类型 {#return-type} + +浮点型。 + +## 示例 {#examples} + +```sql +SELECT ARRAY_SKEWNESS([1, 2, 3, 4]) AS skew; + +┌──────┐ +│ skew │ +├──────┤ +│ 0 │ +└──────┘ +``` + +```sql +SELECT ARRAY_SKEWNESS([1.5, 2.5, 3.5, 4.5]) AS skew_decimal; + +┌────────────┐ +│ skew_decimal│ +├────────────┤ +│ 0 │ +└────────────┘ +``` + +```sql +SELECT ARRAY_SKEWNESS([NULL, 2, 3, 10]) AS skew_null; + +┌────────────────────┐ +│ skew_null │ +├────────────────────┤ +│ 1.6300591617118865 │ +└────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/array-slice.md b/tidb-cloud-lake/sql/array-slice.md new file mode 100644 index 0000000000000..4c6cf884502f6 --- /dev/null +++ b/tidb-cloud-lake/sql/array-slice.md @@ -0,0 +1,69 @@ +--- +title: ARRAY_SLICE +summary: 使用 start 和 end 参数之间的切片提取子数组。 +--- + +# ARRAY_SLICE + +使用 start 和 end 参数之间的切片提取子数组。 + +## 语法 {#syntax} + +```sql +ARRAY_SLICE(array, start, end) +``` + +## 参数 {#parameters} + +| 参数 | 描述 | +|-----------|-------------| +| array | 要从中提取切片的源数组。 | +| start | 切片的起始位置(包含)。 | +| end | 切片的结束位置(不包含)。 | + +## 返回类型 {#return-type} + +数组(原数组的切片)。 + +## 关于索引的重要说明 {#important-note-on-indexing} + +- 对于标准数组类型:索引从 **1** 开始(第一个元素的位置为 1)。 +- 对于 variant 数组类型:索引从 **0** 开始(第一个元素的位置为 0),以兼容 Snowflake。 + +## 示例 {#examples} + +### 示例 1:切片标准数组(1-based 索引) {#example-1-slicing-a-standard-array-1-based-indexing} + +```sql +SELECT ARRAY_SLICE([10, 20, 30, 40, 50], 2, 4); +``` + +结果: + +``` +[20, 30] +``` + +### 示例 2:切片 Variant 数组(0-based 索引) {#example-2-slicing-a-variant-array-0-based-indexing} + +```sql +SELECT ARRAY_SLICE(PARSE_JSON('["apple", "banana", "orange", "grape", "kiwi"]'), 1, 3); +``` + +结果: + +``` +["banana", "orange"] +``` + +### 示例 3:越界切片 {#example-3-out-of-bounds-slice} + +```sql +SELECT ARRAY_SLICE([1, 2, 3], 4, 6); +``` + +结果: + +``` +[] +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/array-sort.md b/tidb-cloud-lake/sql/array-sort.md new file mode 100644 index 0000000000000..abe6ed8f5292d --- /dev/null +++ b/tidb-cloud-lake/sql/array-sort.md @@ -0,0 +1,72 @@ +--- +title: ARRAY_SORT +summary: 对数组中的元素进行排序。默认情况下,ARRAY_SORT 按升序排序,并将 NULL 值放在最后。使用显式变体可以控制排序顺序和 NULL 的放置位置。 +--- + +# ARRAY_SORT + +对数组中的元素进行排序。默认情况下,`ARRAY_SORT` 按升序排序,并将 `NULL` 值放在最后。使用显式变体可以控制排序顺序和 `NULL` 的放置位置。 + +## 语法 {#syntax} + +```sql +ARRAY_SORT() +ARRAY_SORT_ASC_NULL_FIRST() +ARRAY_SORT_ASC_NULL_LAST() +ARRAY_SORT_DESC_NULL_FIRST() +ARRAY_SORT_DESC_NULL_LAST() +``` + +## 返回类型 {#return-type} + +`ARRAY` + +## 示例 {#examples} + +```sql +SELECT ARRAY_SORT([3, 1, 2]) AS sort_default; + +┌──────────────┐ +│ sort_default │ +├──────────────┤ +│ [1,2,3] │ +└──────────────┘ +``` + +```sql +SELECT ARRAY_SORT([NULL, 2, 1]) AS sort_with_nulls; + +┌────────────────┐ +│ sort_with_nulls│ +├────────────────┤ +│ [1,2,NULL] │ +└────────────────┘ +``` + +```sql +SELECT ARRAY_SORT_ASC_NULL_FIRST([NULL, 2, 1]) AS asc_null_first; + +┌────────────────┐ +│ asc_null_first │ +├────────────────┤ +│ [NULL,1,2] │ +└────────────────┘ +``` + +```sql +SELECT ARRAY_SORT_DESC_NULL_LAST([NULL, 2, 1]) AS desc_null_last; + +┌────────────────┐ +│ desc_null_last │ +├────────────────┤ +│ [2,1,NULL] │ +└────────────────┘ + +SELECT ARRAY_SORT_DESC_NULL_FIRST([NULL, 2, 1]) AS desc_null_first; + +┌─────────────────┐ +│ desc_null_first │ +├─────────────────┤ +│ [NULL,2,1] │ +└─────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/array-sql.md b/tidb-cloud-lake/sql/array-sql.md new file mode 100644 index 0000000000000..a9ca26bc3834e --- /dev/null +++ b/tidb-cloud-lake/sql/array-sql.md @@ -0,0 +1,50 @@ +--- +title: ARRAY +summary: 根据提供的表达式构建数组字面量。每个参数都会按顺序求值并存储。所有元素都必须能够转换为同一种公共类型。 +--- + +# ARRAY + +根据提供的表达式构建数组字面量。每个参数都会按顺序求值并存储。所有元素都必须能够转换为同一种公共类型。 + +## 语法 {#syntax} + +```sql +ARRAY(, , ... ) +``` + +## 返回类型 {#return-type} + +`ARRAY` + +## 示例 {#examples} + +```sql +SELECT ARRAY(1, 2, 3) AS arr_int; + +┌─────────┐ +│ arr_int │ +├─────────┤ +│ [1,2,3] │ +└─────────┘ +``` + +```sql +SELECT ARRAY('alpha', UPPER('beta')) AS arr_text; + +┌───────────┐ +│ arr_text │ +├───────────┤ +│ ["alpha","BETA"] │ +└───────────┘ +``` + +```sql +SELECT ARRAY(1, NULL, 3) AS arr_with_null; + +┌────────────────┐ +│ arr_with_null │ +├────────────────┤ +│ [1,NULL,3] │ +└────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/array-stddev-pop.md b/tidb-cloud-lake/sql/array-stddev-pop.md new file mode 100644 index 0000000000000..c185d5af8e481 --- /dev/null +++ b/tidb-cloud-lake/sql/array-stddev-pop.md @@ -0,0 +1,40 @@ +--- +title: ARRAY_STDDEV_POP +summary: 计算数值数组值的总体标准差。忽略 `NULL` 条目;非数值条目会引发错误。 +--- + +# ARRAY_STDDEV_POP + +计算数值数组值的总体标准差。忽略 `NULL` 条目;非数值条目会引发错误。 + +## 语法 {#syntax} + +```sql +ARRAY_STDDEV_POP() +``` + +## 返回类型 {#return-type} + +浮点型。 + +## 示例 {#examples} + +```sql +SELECT ARRAY_STDDEV_POP([2, 4, 4, 4, 5, 5, 7, 9]) AS stddev_pop; + +┌────────────┐ +│ stddev_pop │ +├────────────┤ +│ 2 │ +└────────────┘ +``` + +```sql +SELECT ARRAY_STDDEV_POP([1.5, 2.5, NULL, 3.5]) AS stddev_pop_null; + +┌─────────────────┐ +│ stddev_pop_null │ +├─────────────────┤ +│ 0.816496580927726 │ +└─────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/array-stddev-samp.md b/tidb-cloud-lake/sql/array-stddev-samp.md new file mode 100644 index 0000000000000..906cf535464da --- /dev/null +++ b/tidb-cloud-lake/sql/array-stddev-samp.md @@ -0,0 +1,40 @@ +--- +title: ARRAY_STDDEV_SAMP +summary: 计算数值数组值的样本标准差。`NULL` 项会被忽略;非数值条目会引发错误。 +--- + +# ARRAY_STDDEV_SAMP + +计算数值数组值的样本标准差。`NULL` 项会被忽略;非数值条目会引发错误。 + +## 语法 {#syntax} + +```sql +ARRAY_STDDEV_SAMP() +``` + +## 返回类型 {#return-type} + +浮点型。 + +## 示例 {#examples} + +```sql +SELECT ARRAY_STDDEV_SAMP([2, 4, 4, 4, 5, 5, 7, 9]) AS stddev_samp; + +┌─────────────┐ +│ stddev_samp │ +├─────────────┤ +│ 2.138089935299395 │ +└─────────────┘ +``` + +```sql +SELECT ARRAY_STDDEV_SAMP([1.5, 2.5, NULL, 3.5]) AS stddev_samp_null; + +┌─────────────────┐ +│ stddev_samp_null │ +├─────────────────┤ +│ 1 │ +└─────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/array-sum.md b/tidb-cloud-lake/sql/array-sum.md new file mode 100644 index 0000000000000..bb58347199ad4 --- /dev/null +++ b/tidb-cloud-lake/sql/array-sum.md @@ -0,0 +1,54 @@ +--- +title: ARRAY_SUM +summary: 对数组中的数值元素求和。`NULL` 项会被跳过,非数值会引发错误。 +--- + +# ARRAY_SUM + +对数组中的数值元素求和。`NULL` 项会被跳过,非数值会引发错误。 + +## 语法 {#syntax} + +```sql +ARRAY_SUM() +``` + +## 返回类型 {#return-type} + +数值型(与数组中最宽的数值类型一致)。 + +## 示例 {#examples} + +```sql +SELECT ARRAY_SUM([1, 2, 3, 4]) AS total; + +┌───────┐ +│ total │ +├───────┤ +│ 10 │ +└───────┘ +``` + +```sql +SELECT ARRAY_SUM([1.5, 2.25, 3.0]) AS total; + +┌────────┐ +│ total │ +├────────┤ +│ 6.75 │ +└────────┘ +``` + +```sql +SELECT ARRAY_SUM([10, NULL, -3]) AS total; + +┌───────┐ +│ total │ +├───────┤ +│ 7 │ +└───────┘ +``` + +## 相关内容 {#related} + +- [ARRAY_AGGREGATE](/tidb-cloud-lake/sql/array-aggregate.md) \ No newline at end of file diff --git a/tidb-cloud-lake/sql/array-to-string.md b/tidb-cloud-lake/sql/array-to-string.md new file mode 100644 index 0000000000000..6fc04923bf569 --- /dev/null +++ b/tidb-cloud-lake/sql/array-to-string.md @@ -0,0 +1,40 @@ +--- +title: ARRAY_TO_STRING +summary: 将数组中的字符串元素连接为一个字符串,并使用分隔符分隔。`NULL` 元素会被跳过。 +--- + +# ARRAY_TO_STRING + +将数组中的字符串元素连接为一个字符串,并使用分隔符分隔。`NULL` 元素会被跳过。 + +## 语法 {#syntax} + +```sql +ARRAY_TO_STRING(, ) +``` + +## 返回类型 {#return-type} + +`STRING` + +## 示例 {#examples} + +```sql +SELECT ARRAY_TO_STRING(['a', 'b', 'c'], ',') AS joined; + +┌────────┐ +│ joined │ +├────────┤ +│ a,b,c │ +└────────┘ +``` + +```sql +SELECT ARRAY_TO_STRING([NULL, 'x', 'y'], '-') AS joined_no_nulls; + +┌──────────────────┐ +│ joined_no_nulls │ +├──────────────────┤ +│ x-y │ +└──────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/array-unique.md b/tidb-cloud-lake/sql/array-unique.md new file mode 100644 index 0000000000000..543f8566969bf --- /dev/null +++ b/tidb-cloud-lake/sql/array-unique.md @@ -0,0 +1,66 @@ +--- +title: ARRAY_UNIQUE +summary: 返回数组中唯一元素的数量。 +--- + +# ARRAY_UNIQUE + +返回数组中唯一元素的数量。 + +## 语法 {#syntax} + +```sql +ARRAY_UNIQUE(array) +``` + +## 参数 {#parameters} + +| 参数 | 描述 | +|-----------|-------------| +| array | 要分析其唯一元素的数组。 | + +## 返回类型 {#return-type} + +INTEGER + +## 注意事项 {#notes} + +此函数同时适用于标准数组类型和 variant 数组类型。 + +## 示例 {#examples} + +### 示例 1:统计标准数组中的唯一元素 {#example-1-counting-unique-elements-in-a-standard-array} + +```sql +SELECT ARRAY_UNIQUE([1, 2, 2, 3, 3, 3]); +``` + +结果: + +``` +3 +``` + +### 示例 2:统计 variant 数组中的唯一元素 {#example-2-counting-unique-elements-in-a-variant-array} + +```sql +SELECT ARRAY_UNIQUE(PARSE_JSON('["apple", "banana", "apple", "orange", "banana"]')); +``` + +结果: + +``` +3 +``` + +### 示例 3:空数组 {#example-3-empty-array} + +```sql +SELECT ARRAY_UNIQUE([]); +``` + +结果: + +``` +0 +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/array.md b/tidb-cloud-lake/sql/array.md new file mode 100644 index 0000000000000..e31cd5c96ded7 --- /dev/null +++ b/tidb-cloud-lake/sql/array.md @@ -0,0 +1,55 @@ +--- +title: 数组 +summary: 已定义数据类型的数组。 +--- + +# 数组 + +## 概述 {#overview} + +`ARRAY(T)` 用于存储变长集合,其中所有元素都具有相同的类型 `T`。在创建表时定义元素类型,并使用数组函数来读或转换这些值。 + +> **注意:** +> +> {{{ .lake }}} 数组从 1 开始计数。`arr[1]` 返回第一个元素,`arr[n]` 返回最后一个元素。 + +## 示例 {#examples} + +```sql +CREATE TABLE array_samples (arr ARRAY(INT64)); + +INSERT INTO array_samples VALUES ([1, 2, 3]), ([10, 20]); + +SELECT + arr, + arr[1] AS first_elem, + arr[2] AS second_elem +FROM array_samples; +``` + +结果: + +``` +┌────────────┬────────────┬──────────────┐ +│ arr │ first_elem │ second_elem │ +├────────────┼────────────┼──────────────┤ +│ [1,2,3] │ 1 │ 2 │ +│ [10,20] │ 10 │ 20 │ +└────────────┴────────────┴──────────────┘ +``` + +```sql +-- Index 0 always returns NULL because arrays are 1-based. +SELECT arr[0] AS zeroth_elem FROM array_samples; +``` + +结果: + +``` +┌─────────────┐ +│ zeroth_elem │ +├─────────────┤ +│ NULL │ +│ NULL │ +└─────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/arrays-zip.md b/tidb-cloud-lake/sql/arrays-zip.md new file mode 100644 index 0000000000000..cac01dbad5d56 --- /dev/null +++ b/tidb-cloud-lake/sql/arrays-zip.md @@ -0,0 +1,39 @@ +--- +title: ARRAYS_ZIP +summary: 将多个数组合并为单个数组元组。 +--- + +# ARRAYS_ZIP + +将多个数组合并为单个数组元组。 + +## 语法 {#syntax} + +```sql +ARRAYS_ZIP( [, ...] ) +``` + +## 参数 {#arguments} + +| 参数 | 描述 | +|------------|-------------------| +| `` | 输入的 ARRAY。 | + +> **注意:** +> +> - 每个数组的长度必须相同。 + +## 返回类型 {#return-type} + +Array(Tuple)。 + +## 示例 {#examples} + +```sql +SELECT ARRAYS_ZIP([1, 2, 3], ['a', 'b', 'c']); +┌────────────────────────────────────────┐ +│ arrays_zip([1, 2, 3], ['a', 'b', 'c']) │ +├────────────────────────────────────────┤ +│ [(1,'a'),(2,'b'),(3,'c')] │ +└────────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/as-array.md b/tidb-cloud-lake/sql/as-array.md new file mode 100644 index 0000000000000..b72579d08272e --- /dev/null +++ b/tidb-cloud-lake/sql/as-array.md @@ -0,0 +1,50 @@ +--- +title: AS_ARRAY +summary: 将 `VARIANT` 值严格转换为 ARRAY 数据类型。如果输入数据类型不是 `VARIANT`,则输出为 `NULL`。如果 `VARIANT` 中的值类型与输出值不匹配,则输出为 `NULL`。 +--- + +# AS_ARRAY + +将 `VARIANT` 值严格转换为 ARRAY 数据类型。如果输入数据类型不是 `VARIANT`,则输出为 `NULL`。如果 `VARIANT` 中的值类型与输出值不匹配,则输出为 `NULL`。 + +## 语法 {#syntax} + +```sql +AS_ARRAY( ) +``` + +## 参数 {#arguments} + +| 参数 | 描述 | +|-------------|------| +| `` | `VARIANT` 值 | + +## 返回类型 {#return-type} + +Variant 包含 Array + +## 示例 {#examples} + +```sql +SELECT as_array(parse_json('[1,2,3]')); ++---------------------------------+ +| as_array(parse_json('[1,2,3]')) | ++---------------------------------+ +| [1,2,3] | ++---------------------------------+ + +SELECT as_array(parse_json('["a","b","c"]')); ++---------------------------------------+ +| as_array(parse_json('["a","b","c"]')) | ++---------------------------------------+ +| ["a","b","c"] | ++---------------------------------------+ + +-- Returns NULL for non-array values +SELECT as_array(parse_json('{"key":"value"}')); ++-----------------------------------------+ +| as_array(parse_json('{"key":"value"}')) | ++-----------------------------------------+ +| NULL | ++-----------------------------------------+ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/as-binary.md b/tidb-cloud-lake/sql/as-binary.md new file mode 100644 index 0000000000000..f01841d4ac1c8 --- /dev/null +++ b/tidb-cloud-lake/sql/as-binary.md @@ -0,0 +1,50 @@ +--- +title: AS_BINARY +summary: 将 `VARIANT` 值严格转换为 BINARY 数据类型。如果输入数据类型不是 `VARIANT`,则输出为 `NULL`。如果 `VARIANT` 中值的类型与输出值不匹配,则输出为 `NULL`。 +--- + +# AS_BINARY + +将 `VARIANT` 值严格转换为 BINARY 数据类型。如果输入数据类型不是 `VARIANT`,则输出为 `NULL`。如果 `VARIANT` 中值的类型与输出值不匹配,则输出为 `NULL`。 + +## 语法 {#syntax} + +```sql +AS_BINARY( ) +``` + +## 参数 {#arguments} + +| 参数 | 描述 | +|-------------|-------------------| +| `` | `VARIANT` 值 | + +## 返回类型 {#return-type} + +BINARY + +## 示例 {#examples} + +```sql +SELECT as_binary(to_binary('abcd')::variant); ++---------------------------------------+ +| as_binary(to_binary('abcd')::variant) | ++---------------------------------------+ +| 61626364 | ++---------------------------------------+ + +SELECT as_binary(to_binary('hello')::variant); ++-----------------------------------------+ +| as_binary(to_binary('hello')::variant) | ++-----------------------------------------+ +| 68656C6C6F | ++-----------------------------------------+ + +-- 对于非二进制值,返回 NULL +SELECT as_binary(parse_json('"text"')); ++---------------------------------+ +| as_binary(parse_json('"text"')) | ++---------------------------------+ +| NULL | ++---------------------------------+ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/as-boolean.md b/tidb-cloud-lake/sql/as-boolean.md new file mode 100644 index 0000000000000..aa656726ecc38 --- /dev/null +++ b/tidb-cloud-lake/sql/as-boolean.md @@ -0,0 +1,50 @@ +--- +title: AS_BOOLEAN +summary: 将 `VARIANT` 值严格转换为 BOOLEAN 数据类型。如果输入数据类型不是 `VARIANT`,则输出为 `NULL`。如果 `VARIANT` 中的值类型与输出值不匹配,则输出为 `NULL`。 +--- + +# AS_BOOLEAN + +将 `VARIANT` 值严格转换为 BOOLEAN 数据类型。如果输入数据类型不是 `VARIANT`,则输出为 `NULL`。如果 `VARIANT` 中的值类型与输出值不匹配,则输出为 `NULL`。 + +## 语法 {#syntax} + +```sql +AS_BOOLEAN( ) +``` + +## 参数 {#arguments} + +| 参数 | 描述 | +|-------------|-------------------| +| `` | `VARIANT` 值 | + +## 返回类型 {#return-type} + +BOOLEAN + +## 示例 {#examples} + +```sql +SELECT as_boolean(parse_json('true')); ++--------------------------------+ +| as_boolean(parse_json('true')) | ++--------------------------------+ +| 1 | ++--------------------------------+ + +SELECT as_boolean(parse_json('false')); ++---------------------------------+ +| as_boolean(parse_json('false')) | ++---------------------------------+ +| 0 | ++---------------------------------+ + +-- 对于非布尔值,返回 NULL +SELECT as_boolean(parse_json('123')); ++-------------------------------+ +| as_boolean(parse_json('123')) | ++-------------------------------+ +| NULL | ++-------------------------------+ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/as-date.md b/tidb-cloud-lake/sql/as-date.md new file mode 100644 index 0000000000000..f375c7a69ca82 --- /dev/null +++ b/tidb-cloud-lake/sql/as-date.md @@ -0,0 +1,50 @@ +--- +title: AS_DATE +summary: 将 `VARIANT` 值严格转换为 DATE 数据类型。如果输入数据类型不是 `VARIANT`,则输出为 `NULL`。如果 `VARIANT` 中值的类型与输出值不匹配,则输出为 `NULL`。 +--- + +# AS_DATE + +将 `VARIANT` 值严格转换为 DATE 数据类型。如果输入数据类型不是 `VARIANT`,则输出为 `NULL`。如果 `VARIANT` 中值的类型与输出值不匹配,则输出为 `NULL`。 + +## 语法 {#syntax} + +```sql +AS_DATE( ) +``` + +## 参数 {#arguments} + +| 参数 | 描述 | +|-------------|------| +| `` | `VARIANT` 值 | + +## 返回类型 {#return-type} + +DATE + +## 示例 {#examples} + +```sql +SELECT as_date(to_date('2025-10-11')::variant); ++-----------------------------------------+ +| as_date(to_date('2025-10-11')::variant) | ++-----------------------------------------+ +| 2025-10-11 | ++-----------------------------------------+ + +SELECT as_date(parse_json('"2024-12-25"')::variant); ++-----------------------------------------------+ +| as_date(parse_json('"2024-12-25"')::variant) | ++-----------------------------------------------+ +| 2024-12-25 | ++-----------------------------------------------+ + +-- 对于非日期值,返回 NULL +SELECT as_date(parse_json('123')); ++----------------------------+ +| as_date(parse_json('123')) | ++----------------------------+ +| NULL | ++----------------------------+ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/as-decimal.md b/tidb-cloud-lake/sql/as-decimal.md new file mode 100644 index 0000000000000..086b0fdfedf62 --- /dev/null +++ b/tidb-cloud-lake/sql/as-decimal.md @@ -0,0 +1,50 @@ +--- +title: AS_DECIMAL +summary: 将 `VARIANT` 值严格转换为 DECIMAL 数据类型。如果输入数据类型不是 `VARIANT`,则输出为 `NULL`。如果 `VARIANT` 中的值类型与输出值不匹配,则输出为 `NULL`。 +--- + +# AS_DECIMAL + +将 `VARIANT` 值严格转换为 DECIMAL 数据类型。如果输入数据类型不是 `VARIANT`,则输出为 `NULL`。如果 `VARIANT` 中的值类型与输出值不匹配,则输出为 `NULL`。 + +## 语法 {#syntax} + +```sql +AS_DECIMAL( ) +``` + +## 参数 {#arguments} + +| 参数 | 描述 | +|-------------|-------------------| +| `` | `VARIANT` 值 | + +## 返回类型 {#return-type} + +DECIMAL + +## 示例 {#examples} + +```sql +SELECT as_decimal(parse_json('12.34')); ++---------------------------------+ +| as_decimal(parse_json('12.34')) | ++---------------------------------+ +| 12.34 | ++---------------------------------+ + +SELECT as_decimal(parse_json('123.456789')); ++--------------------------------------+ +| as_decimal(parse_json('123.456789')) | ++--------------------------------------+ +| 123.456789 | ++--------------------------------------+ + +-- Returns NULL for non-decimal values +SELECT as_decimal(parse_json('"abc"')); ++---------------------------------+ +| as_decimal(parse_json('"abc"')) | ++---------------------------------+ +| NULL | ++---------------------------------+ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/as-float.md b/tidb-cloud-lake/sql/as-float.md new file mode 100644 index 0000000000000..7fdc8a0571bc4 --- /dev/null +++ b/tidb-cloud-lake/sql/as-float.md @@ -0,0 +1,50 @@ +--- +title: AS_FLOAT +summary: 将 `VARIANT` 值严格转换为 DOUBLE 数据类型。如果输入数据类型不是 `VARIANT`,则输出为 `NULL`。如果 `VARIANT` 中值的类型与输出值不匹配,则输出为 `NULL`。 +--- + +# AS_FLOAT + +将 `VARIANT` 值严格转换为 DOUBLE 数据类型。如果输入数据类型不是 `VARIANT`,则输出为 `NULL`。如果 `VARIANT` 中值的类型与输出值不匹配,则输出为 `NULL`。 + +## 语法 {#syntax} + +```sql +AS_FLOAT( ) +``` + +## 参数 {#arguments} + +| 参数 | 描述 | +|-------------|-------------------| +| `` | VARIANT 值 | + +## 返回类型 {#return-type} + +DOUBLE + +## 示例 {#examples} + +```sql +SELECT as_float(parse_json('12.34')); ++-------------------------------+ +| as_float(parse_json('12.34')) | ++-------------------------------+ +| 12.34 | ++-------------------------------+ + +SELECT as_float(parse_json('123')); ++-----------------------------+ +| as_float(parse_json('123')) | ++-----------------------------+ +| 123.0 | ++-----------------------------+ + +-- 对于非数值类型,返回 NULL +SELECT as_float(parse_json('"abc"')); ++-------------------------------+ +| as_float(parse_json('"abc"')) | ++-------------------------------+ +| NULL | ++-------------------------------+ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/as-integer.md b/tidb-cloud-lake/sql/as-integer.md new file mode 100644 index 0000000000000..61667a48e78ac --- /dev/null +++ b/tidb-cloud-lake/sql/as-integer.md @@ -0,0 +1,50 @@ +--- +title: AS_INTEGER +summary: 将 `VARIANT` 值严格转换为 BIGINT 数据类型。如果输入数据类型不是 `VARIANT`,则输出为 `NULL`。如果 `VARIANT` 中的值类型与输出值不匹配,则输出为 `NULL`。 +--- + +# AS_INTEGER + +将 `VARIANT` 值严格转换为 BIGINT 数据类型。如果输入数据类型不是 `VARIANT`,则输出为 `NULL`。如果 `VARIANT` 中的值类型与输出值不匹配,则输出为 `NULL`。 + +## 语法 {#syntax} + +```sql +AS_INTEGER( ) +``` + +## 参数 {#arguments} + +| 参数 | 描述 | +|-------------|-------------------| +| `` | `VARIANT` 值 | + +## 返回类型 {#return-type} + +BIGINT + +## 示例 {#examples} + +```sql +SELECT as_integer(parse_json('123')); ++-------------------------------+ +| as_integer(parse_json('123')) | ++-------------------------------+ +| 123 | ++-------------------------------+ + +SELECT as_integer(parse_json('-456')); ++--------------------------------+ +| as_integer(parse_json('-456')) | ++--------------------------------+ +| -456 | ++--------------------------------+ + +-- Returns NULL for non-integer values +SELECT as_integer(parse_json('12.34')); ++---------------------------------+ +| as_integer(parse_json('12.34')) | ++---------------------------------+ +| NULL | ++---------------------------------+ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/as-object.md b/tidb-cloud-lake/sql/as-object.md new file mode 100644 index 0000000000000..73361d319d67b --- /dev/null +++ b/tidb-cloud-lake/sql/as-object.md @@ -0,0 +1,50 @@ +--- +title: AS_OBJECT +summary: 将 `VARIANT` 值严格转换为 OBJECT 数据类型。如果输入数据类型不是 `VARIANT`,则输出为 `NULL`。如果 `VARIANT` 中的值类型与输出值不匹配,则输出为 `NULL`。 +--- + +# AS_OBJECT + +将 `VARIANT` 值严格转换为 OBJECT 数据类型。如果输入数据类型不是 `VARIANT`,则输出为 `NULL`。如果 `VARIANT` 中的值类型与输出值不匹配,则输出为 `NULL`。 + +## 语法 {#syntax} + +```sql +AS_OBJECT( ) +``` + +## 参数 {#arguments} + +| 参数 | 描述 | +|-------------|-------------------| +| `` | `VARIANT` 值 | + +## 返回类型 {#return-type} + +Variant 包含 Object + +## 示例 {#examples} + +```sql +SELECT as_object(parse_json('{"k":"v","a":"b"}')); ++--------------------------------------------+ +| as_object(parse_json('{"k":"v","a":"b"}')) | ++--------------------------------------------+ +| {"k":"v","a":"b"} | ++--------------------------------------------+ + +SELECT as_object(parse_json('{"name":"John","age":30}')); ++-----------------------------------------------+ +| as_object(parse_json('{"name":"John","age":30}')) | ++-----------------------------------------------+ +| {"name":"John","age":30} | ++-----------------------------------------------+ + +-- Returns NULL for non-object values +SELECT as_object(parse_json('[1,2,3]')); ++----------------------------------+ +| as_object(parse_json('[1,2,3]')) | ++----------------------------------+ +| NULL | ++----------------------------------+ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/as-string.md b/tidb-cloud-lake/sql/as-string.md new file mode 100644 index 0000000000000..b60a5592479dd --- /dev/null +++ b/tidb-cloud-lake/sql/as-string.md @@ -0,0 +1,50 @@ +--- +title: AS_STRING +summary: 将 `VARIANT` 值严格转换为 VARCHAR 数据类型。如果输入数据类型不是 `VARIANT`,则输出为 `NULL`。如果 `VARIANT` 中值的类型与输出值不匹配,则输出为 `NULL`。 +--- + +# AS_STRING + +将 `VARIANT` 值严格转换为 VARCHAR 数据类型。如果输入数据类型不是 `VARIANT`,则输出为 `NULL`。如果 `VARIANT` 中值的类型与输出值不匹配,则输出为 `NULL`。 + +## 语法 {#syntax} + +```sql +AS_STRING( ) +``` + +## 参数 {#arguments} + +| 参数 | 描述 | +|-------------|-------------------| +| `` | `VARIANT` 值 | + +## 返回类型 {#return-type} + +VARCHAR + +## 示例 {#examples} + +```sql +SELECT as_string(parse_json('"abc"')); ++--------------------------------+ +| as_string(parse_json('"abc"')) | ++--------------------------------+ +| abc | ++--------------------------------+ + +SELECT as_string(parse_json('"hello world"')); ++----------------------------------------+ +| as_string(parse_json('"hello world"')) | ++----------------------------------------+ +| hello world | ++----------------------------------------+ + +-- Returns NULL for non-string values +SELECT as_string(parse_json('123')); ++------------------------------+ +| as_string(parse_json('123')) | ++------------------------------+ +| NULL | ++------------------------------+ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/ascii.md b/tidb-cloud-lake/sql/ascii.md new file mode 100644 index 0000000000000..7c1798795e77b --- /dev/null +++ b/tidb-cloud-lake/sql/ascii.md @@ -0,0 +1,35 @@ +--- +title: ASCII +summary: 返回字符串 str 最左侧字符的数值。 +--- + +# ASCII + +返回字符串 str 最左侧字符的数值。 + +## 语法 {#syntax} + +```sql +ASCII() +``` + +## 参数 {#arguments} + +| 参数 | 描述 | +|-----------|-------------| +| `` | 该字符串。 | + +## 返回类型 {#return-type} + +`TINYINT` + +## 示例 {#examples} + +```sql +SELECT ASCII('2'); ++------------+ +| ASCII('2') | ++------------+ +| 50 | ++------------+ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/asin.md b/tidb-cloud-lake/sql/asin.md new file mode 100644 index 0000000000000..2f195c8bcb06e --- /dev/null +++ b/tidb-cloud-lake/sql/asin.md @@ -0,0 +1,26 @@ +--- +title: ASIN +summary: 返回 `x` 的反正弦,即正弦值为 `x` 的值。如果 `x` 不在 -1 到 1 的范围内,则返回 NULL。 +--- + +# ASIN + +返回 `x` 的反正弦,即正弦值为 `x` 的值。如果 `x` 不在 -1 到 1 的范围内,则返回 NULL。 + +## 语法 {#syntax} + +```sql +ASIN( ) +``` + +## 示例 {#examples} + +```sql +SELECT ASIN(0.2); + +┌────────────────────┐ +│ asin(0.2) │ +├────────────────────┤ +│ 0.2013579207903308 │ +└────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/assume-not-null.md b/tidb-cloud-lake/sql/assume-not-null.md new file mode 100644 index 0000000000000..67a1e6d8ab888 --- /dev/null +++ b/tidb-cloud-lake/sql/assume-not-null.md @@ -0,0 +1,39 @@ +--- +title: ASSUME_NOT_NULL +summary: 对于 Nullable 类型,返回等价的非 Nullable 值。如果原始值为 NULL,则结果未定义。 +--- + +# ASSUME_NOT_NULL + +对于 Nullable 类型,返回等价的非 `Nullable` 值。如果原始值为 `NULL`,则结果未定义。 + +## 语法 {#syntax} + +```sql +ASSUME_NOT_NULL() +``` + +## 别名 {#aliases} + +- [REMOVE_NULLABLE](/tidb-cloud-lake/sql/remove-nullable.md) + +## 返回类型 {#return-type} + +对于非 `Nullable` 类型,返回原始数据类型;对于 `Nullable` 类型,返回其内部嵌套的非 `Nullable` 数据类型。 + +## 示例 {#examples} + +```sql +CREATE TABLE default.t_null ( x int, y int null); + +INSERT INTO default.t_null values (1, null), (2, 3); + +SELECT ASSUME_NOT_NULL(y), REMOVE_NULLABLE(y) FROM t_null; + +┌─────────────────────────────────────────┐ +│ assume_not_null(y) │ remove_nullable(y) │ +├────────────────────┼────────────────────┤ +│ 0 │ 0 │ +│ 3 │ 3 │ +└─────────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/at.md b/tidb-cloud-lake/sql/at.md new file mode 100644 index 0000000000000..46f9b185333bc --- /dev/null +++ b/tidb-cloud-lake/sql/at.md @@ -0,0 +1,96 @@ +--- +title: AT +summary: AT 子句支持通过指定 snapshot ID、时间戳、stream 名称或时间间隔来检索数据的历史版本。 +--- + +# AT + +AT 子句支持通过指定 snapshot ID、时间戳、stream 名称或时间间隔来检索数据的历史版本。 + +{{{ .lake }}} 会在数据发生修改时自动创建快照,因此可以将快照视为过去某一时间点的数据视图。你可以通过 snapshot ID 或创建该快照时的时间戳来访问快照。关于如何获取 snapshot ID 和时间戳,请参见[获取 Snapshot ID 和时间戳](#obtaining-snapshot-id-and-timestamp)。 + +这是 {{{ .lake }}} Time Travel 功能的一部分。该功能允许你在保留时间内(默认 24 小时)对数据的历史版本进行查询、备份和恢复。 + +## 语法 {#syntax} + +```sql +SELECT ... +FROM ... +AT ( + SNAPSHOT => '' | + TIMESTAMP => | + STREAM => | + OFFSET => + ) +``` + +| 参数 | 描述 | +|-----------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| SNAPSHOT | 指定一个特定的 snapshot ID,用于查询历史数据。 | +| TIMESTAMP | 指定一个特定的时间戳,用于检索该时间点的数据。 | +| STREAM | 表示查询指定 stream 创建时刻的数据。 | +| OFFSET | 指定从当前时间向前回溯的秒数。其形式应为负整数,绝对值表示以秒为单位的时间差。例如,`-3600` 表示回到 1 小时前(3,600 秒)。 | +| TAG | 指定通过 `ALTER TABLE ... CREATE TAG` 创建的命名 tag,以查询与该 tag 关联的快照。这是一个实验特性,需要执行 `SET enable_experimental_table_ref = 1`。参见 [快照标签操作](/tidb-cloud-lake/sql/alter-table.md#snapshot-tag-operations)。 | + +## 获取 Snapshot ID 和时间戳 {#obtaining-snapshot-id-and-timestamp} + +如需返回某个表所有快照的 snapshot ID 和时间戳,请使用 [FUSE_SNAPSHOT](/tidb-cloud-lake/sql/fuse-snapshot.md) 函数: + +```sql +SELECT snapshot_id, + timestamp +FROM FUSE_SNAPSHOT('', ''); +``` + +## 示例 {#examples} + +以下示例演示了 AT 子句如何基于 snapshot ID、时间戳和 stream 检索数据的历史版本: + +1. 创建一个名为 `t` 的表,该表只有一列 `a`,然后向表中插入两行数据,值分别为 1 和 2。 + + ```sql + CREATE TABLE t(a INT); + + INSERT INTO t VALUES(1); + INSERT INTO t VALUES(2); + ``` + +2. 在表 `t` 上创建一个名为 `s` 的 stream,然后向表中额外插入一行值为 3 的数据。 + + ```sql + CREATE STREAM s ON TABLE t; + + INSERT INTO t VALUES(3); + ``` + +3. 执行时间旅行查询以检索历史数据版本。 + +```sql +-- Return snapshot IDs and corresponding timestamps for table 't' +SELECT snapshot_id, timestamp FROM FUSE_SNAPSHOT('default', 't'); +┌───────────────────────────────────────────────────────────────┐ +│ snapshot_id │ timestamp │ +├──────────────────────────────────┼────────────────────────────┤ +│ 296349da841d4fa8820bbf8e228d75f3 │ 2024-04-02 15:25:21.456574 │ +│ aaa4857c5935401790db2c9f0f2818be │ 2024-04-02 15:19:02.484304 │ +│ e66ad2bc3f21416e87903dc9cd0388a3 │ 2024-04-02 15:18:40.766361 │ +└───────────────────────────────────────────────────────────────┘ + +-- These queries retrieve the same data but using different methods: +-- by snapshot_id: +SELECT * FROM t AT (SNAPSHOT => 'aaa4857c5935401790db2c9f0f2818be'); +-- by timestamp: +SELECT * FROM t AT (TIMESTAMP => '2024-04-02 15:19:02.484304'::TIMESTAMP); +-- by stream: +SELECT * FROM t AT (STREAM => s); + +┌─────────────────┐ +│ a │ +├─────────────────┤ +│ 1 │ +│ 2 │ +└─────────────────┘ + +-- Retrieve all columns from table 't' with data from 60 seconds ago +SELECT * FROM t AT (OFFSET => -60); +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/atan-sql.md b/tidb-cloud-lake/sql/atan-sql.md new file mode 100644 index 0000000000000..72aca903435c9 --- /dev/null +++ b/tidb-cloud-lake/sql/atan-sql.md @@ -0,0 +1,26 @@ +--- +title: ATAN2 +summary: 返回两个变量 `x` 和 `y` 的反正切。它类似于计算 `y / x` 的反正切,不同之处在于会使用两个参数的符号来确定结果所在的象限。`ATAN(y, x)` 是 `ATAN2(y, x)` 的同义词。 +--- + +# ATAN2 + +返回两个变量 `x` 和 `y` 的反正切。它类似于计算 `y` / `x` 的反正切,不同之处在于会使用两个参数的符号来确定结果所在的象限。`ATAN(y, x)` 是 `ATAN2(y, x)` 的同义词。 + +## 语法 {#syntax} + +```sql +ATAN2( ) +``` + +## 示例 {#examples} + +```sql +SELECT ATAN2(-2, 2); + +┌─────────────────────┐ +│ atan2((- 2), 2) │ +├─────────────────────┤ +│ -0.7853981633974483 │ +└─────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/atan.md b/tidb-cloud-lake/sql/atan.md new file mode 100644 index 0000000000000..3f54785269018 --- /dev/null +++ b/tidb-cloud-lake/sql/atan.md @@ -0,0 +1,26 @@ +--- +title: ATAN +summary: 返回 `x` 的反正切值,即正切值为 `x` 的值。 +--- + +# ATAN + +返回 `x` 的反正切值,即正切值为 `x` 的值。 + +## 语法 {#syntax} + +```sql +ATAN( ) +``` + +## 示例 {#examples} + +```sql +SELECT ATAN(-2); + +┌─────────────────────┐ +│ atan((- 2)) │ +├─────────────────────┤ +│ -1.1071487177940906 │ +└─────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/attach-table.md b/tidb-cloud-lake/sql/attach-table.md new file mode 100644 index 0000000000000..3a75231a942f0 --- /dev/null +++ b/tidb-cloud-lake/sql/attach-table.md @@ -0,0 +1,133 @@ +--- +title: ATTACH TABLE +summary: ATTACH TABLE 创建指向现有表数据的只读链接,无需复制数据。 +--- + +# ATTACH TABLE + +ATTACH TABLE 创建指向现有表数据的只读链接,无需复制数据。 + +## 主要特性 {#key-features} + +- **零拷贝数据访问**:链接到源数据,无需进行物理数据移动 +- **实时更新**:源表中的变更会立即在附加表中可见 +- **只读模式**:仅支持 `SELECT` 查询(不支持 `INSERT`、`UPDATE` 或 `DELETE` 操作) +- **列级访问**:可选择仅包含特定列,以提升安全性和性能 + +## 语法 {#syntax} + +```sql +ATTACH TABLE [ ( ) ] '' +CONNECTION = ( CONNECTION_NAME = '' ) +``` + +### 参数 {#parameters} + +- **``**:要创建的新附加表名称 + +- **``**:可选的列列表,用于指定从源表中包含哪些列 + - 省略时,将包含所有列 + - 提供列级安全性和访问控制 + - 示例:`(customer_id, product, amount)` + +- **``**:对象存储中源表数据的路径 + - 格式:`s3://///` + - 示例:`s3://lake-toronto/1/23351/` + +- **`CONNECTION_NAME`**:引用通过 [CREATE CONNECTION](/tidb-cloud-lake/sql/create-connection.md) 创建的连接 + +### 查找源表路径 {#finding-the-source-table-path} + +使用 [FUSE_SNAPSHOT](/tidb-cloud-lake/sql/fuse-snapshot.md) 函数获取数据库和表 ID: + +```sql +SELECT snapshot_location FROM FUSE_SNAPSHOT('default', 'employees'); +-- Result contains: 1/23351/_ss/... → Path is s3://your-bucket/1/23351/ +``` + +## 数据共享优势 {#data-sharing-benefits} + +### 工作原理 {#how-it-works} + +``` + 对象存储 (S3, MinIO, Azure 等) + ┌─────────────┐ + │ 源数据 │ + └──────┬──────┘ + │ + ┌───────────────────────┼───────────────────────┐ + │ │ │ + ▼ ▼ ▼ +┌─────────────┐ ┌─────────────┐ ┌─────────────┐ +│ 市场团队 │ │ 财务团队 │ │ 销售团队 │ +│ 视图 │ │ 视图 │ │ 视图 │ +└─────────────┘ └─────────────┘ └─────────────┘ +``` + +### 主要优势 {#key-advantages} + +| 传统方式 | {{{ .lake }}} ATTACH TABLE | +|---------------------|----------------------| +| 多份数据副本 | 所有人共享单一副本 | +| ETL 延迟、同步问题 | 实时,始终为最新 | +| 维护复杂 | 零维护 | +| 副本越多,安全风险越高 | 细粒度列访问 | +| 因数据移动而变慢 | 在原始数据上进行完整优化 | + +### 安全性和性能 {#security-and-performance} + +- **列级安全性**:团队只能看到其所需的列 +- **实时更新**:源数据变更会立即在所有附加表中可见 +- **强一致性**:始终看到完整的数据快照,而不是部分修改 +- **完整性能**:继承源表的所有索引和优化能力 + +## 示例 {#examples} + +### 基本用法 {#basic-usage} + +```sql +-- Step 1: Create a connection to your storage +CREATE CONNECTION my_s3_connection + STORAGE_TYPE = 's3' + ACCESS_KEY_ID = '' + SECRET_ACCESS_KEY = ''; + +-- Step 2: Attach a table with all columns +ATTACH TABLE population_all_columns 's3://lake-doc/1/16/' + CONNECTION = (CONNECTION_NAME = 'my_s3_connection'); +``` + +### 出于安全考虑选择列 {#column-selection-for-security} + +```sql +-- Attach only specific columns for data security +ATTACH TABLE population_selected (city, population) 's3://lake-doc/1/16/' + CONNECTION = (CONNECTION_NAME = 'my_s3_connection'); +``` + +### 使用 IAM Role 身份验证 {#using-iam-role-authentication} + +```sql +-- Create a connection using IAM role (more secure than access keys) +CREATE CONNECTION s3_role_connection + STORAGE_TYPE = 's3' + ROLE_ARN = 'arn:aws:iam::123456789012:role/lake-role'; + +-- Attach table using the IAM role connection +ATTACH TABLE population_all_columns 's3://lake-doc/1/16/' + CONNECTION = (CONNECTION_NAME = 's3_role_connection'); +``` + +### 团队专用视图 {#team-specific-views} + +```sql +-- Marketing: Customer behavior analysis +ATTACH TABLE marketing_view (customer_id, product, amount, order_date) +'s3://your-bucket/1/23351/' +CONNECTION = (CONNECTION_NAME = 'my_s3_connection'); + +-- Finance: Revenue tracking (different columns) +ATTACH TABLE finance_view (order_id, amount, profit, order_date) +'s3://your-bucket/1/23351/' +CONNECTION = (CONNECTION_NAME = 'my_s3_connection'); +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/avg-if.md b/tidb-cloud-lake/sql/avg-if.md new file mode 100644 index 0000000000000..871270c2ac209 --- /dev/null +++ b/tidb-cloud-lake/sql/avg-if.md @@ -0,0 +1,48 @@ +--- +title: AVG_IF +summary: 后缀 -If 可以附加到任何聚合函数的名称后。在这种情况下,聚合函数会接受一个额外的参数——条件。 +--- + +# AVG_IF + +## AVG_IF {#avg-if} + +后缀 -If 可以附加到任何聚合函数的名称后。在这种情况下,聚合函数会接受一个额外的参数——条件。 + +```sql +AVG_IF(, ) +``` + +## 示例 {#example} + +**创建表并插入示例数据** + +```sql +CREATE TABLE employees ( + id INT, + salary INT, + department VARCHAR +); + +INSERT INTO employees (id, salary, department) +VALUES (1, 50000, 'HR'), + (2, 60000, 'IT'), + (3, 55000, 'HR'), + (4, 70000, 'IT'), + (5, 65000, 'IT'); +``` + +**查询示例:计算 IT 部门的平均薪资** + +```sql +SELECT AVG_IF(salary, department = 'IT') AS avg_salary_it +FROM employees; +``` + +**结果** + +```sql +| avg_salary_it | +|-----------------| +| 65000.0 | +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/avg.md b/tidb-cloud-lake/sql/avg.md new file mode 100644 index 0000000000000..4ec0606a62245 --- /dev/null +++ b/tidb-cloud-lake/sql/avg.md @@ -0,0 +1,66 @@ +--- +title: AVG +summary: 聚合函数。 +--- + +# AVG + +聚合函数。 + +`AVG()` 函数返回一个表达式的平均值。 + +**注意:** 不会统计 `NULL` 值。 + +## 语法 {#syntax} + +```sql +AVG() +``` + +## 参数 {#arguments} + +| 参数 | 描述 | +|-----------|--------------------------| +| `` | 任何数值表达式 | + +## 返回类型 {#return-type} + +double + +## 示例 {#examples} + +**创建表并插入示例数据** + +让我们创建一个名为 "sales" 的表,并插入一些示例数据: + +```sql +CREATE TABLE sales ( + id INTEGER, + product VARCHAR(50), + price FLOAT +); + +INSERT INTO sales (id, product, price) +VALUES (1, 'Product A', 10.5), + (2, 'Product B', 20.75), + (3, 'Product C', 30.0), + (4, 'Product D', 15.25), + (5, 'Product E', 25.5); +``` + +**查询:使用 AVG() 函数** + +现在,让我们使用 `AVG()` 函数来查找 "sales" 表中所有产品的平均价格: + +```sql +SELECT AVG(price) AS avg_price +FROM sales; +``` + +结果应如下所示: + +```sql +| avg_price | +| --------- | +| 20.4 | +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/begin.md b/tidb-cloud-lake/sql/begin.md new file mode 100644 index 0000000000000..847776a5b431b --- /dev/null +++ b/tidb-cloud-lake/sql/begin.md @@ -0,0 +1,186 @@ +--- +title: BEGIN +summary: 开始一个新事务。BEGIN 和 COMMIT/ROLLBACK 必须配合使用,以启动事务并最终提交或回滚该事务。 +--- + +# BEGIN + +开始一个新事务。BEGIN 和 [COMMIT](/tidb-cloud-lake/sql/commit.md)/[ROLLBACK](/tidb-cloud-lake/sql/rollback.md) 必须配合使用,以启动事务并最终提交或回滚该事务。 + +- {{{ .lake }}} *不*支持嵌套事务,因此不匹配的事务语句会被忽略。 + + ```sql title="Example:" + BEGIN; -- Start a transaction + + MERGE INTO ... -- This statement belongs to the transaction + + BEGIN; -- Executing BEGIN within a transaction is ignored, no new transaction is started, no error is raised + + INSERT INTO ... -- This statement also belongs to the transaction + + COMMIT; -- End the transaction + + INSERT INTO ... -- This statement belongs to a single-statement transaction + + COMMIT; -- Executing COMMIT outside of a multi-statement transaction is ignored, no commit operation is performed, no error is raised + + BEGIN; -- Start another transaction + ... + ``` + +- 当在多语句事务中执行 DDL 语句时,它会提交当前多语句事务,并将后续语句作为单语句事务执行,直到再次发出另一个 BEGIN。 + + ```sql title="Example:" + BEGIN; -- Start a multi-statement transaction + + -- DML statements here are part of the current transaction + INSERT INTO table_name (column1, column2) VALUES (value1, value2); + + -- Executing a DDL statement within the transaction + CREATE TABLE new_table (column1 data_type, column2 data_type); + -- This will commit the current transaction + + -- Subsequent statements are executed as single-statement transactions + UPDATE table_name SET column1 = value WHERE condition; + + BEGIN; -- Start a new multi-statement transaction + + -- New DML statements here are part of the new transaction + DELETE FROM table_name WHERE condition; + + COMMIT; -- End the new transaction + ``` + +## 语法 {#syntax} + +```sql +BEGIN [ TRANSACTION ] +``` + +## 事务 ID 和状态 {#transaction-ids-statuses} + +{{{ .lake }}} 会自动为每个事务生成一个事务 ID。该 ID 使用户能够识别哪些语句属于同一个事务,从而便于排查问题。 + +如果你使用的是 {{{ .lake }}},可以在 **Monitor** > **SQL History** 中找到事务 ID: + +![alt text](/media/tidb-cloud-lake/transaction-id.png) + +在 **Transaction** 列中,你还可以看到 SQL 语句执行期间的事务状态: + +| 事务状态 | 说明 | +|--------------------|-----------------------------------------------------------------------------------------------------------------------------| +| AutoCommit | 该语句不属于多语句事务。 | +| Active | 该语句属于多语句事务,并且该事务中位于它之前的所有语句都已成功执行。 | +| Fail | 该语句属于多语句事务,并且该事务中位于它之前的语句至少有一条执行失败。 | + +## 示例 {#examples} + +在此示例中,三个语句(INSERT、UPDATE、DELETE)都属于同一个多语句事务。它们作为一个整体执行,并在发出 COMMIT 时一起提交修改。 + +```sql +-- Start by creating a table +CREATE TABLE employees ( + id INT, + name VARCHAR(50), + department VARCHAR(50) +); + +-- Start a multi-statement transaction +BEGIN; + +-- First statement in the transaction: Insert a new employee +INSERT INTO employees (id, name, department) VALUES (1, 'Alice', 'HR'); + +-- Second statement in the transaction: Insert another new employee +INSERT INTO employees (id, name, department) VALUES (2, 'Bob', 'Engineering'); + +-- Third statement in the transaction: Update the department of the first employee +UPDATE employees SET department = 'Finance' WHERE id = 1; + +-- Commit all the changes +COMMIT; + +-- Verify that the data in the table +SELECT * FROM employees; + +┌───────────────────────────────────────────────────────┐ +│ id │ name │ department │ +├─────────────────┼──────────────────┼──────────────────┤ +│ 1 │ Alice │ Finance │ +│ 2 │ Bob │ Engineering │ +└───────────────────────────────────────────────────────┘ +``` + +在此示例中,ROLLBACK 语句会撤销事务期间所做的所有修改。因此,最后的 SELECT 查询应显示一个空的 employees 表,以确认没有任何修改被提交。 + +```sql +-- Start by creating a table +CREATE TABLE employees ( + id INT, + name VARCHAR(50), + department VARCHAR(50) +); + +-- Start a multi-statement transaction +BEGIN; + +-- First statement in the transaction: Insert a new employee +INSERT INTO employees (id, name, department) VALUES (1, 'Alice', 'HR'); + +-- Second statement in the transaction: Insert another new employee +INSERT INTO employees (id, name, department) VALUES (2, 'Bob', 'Engineering'); + +-- Third statement in the transaction: Update the department of the first employee +UPDATE employees SET department = 'Finance' WHERE id = 1; + +-- Rollback the transaction +ROLLBACK; + +-- Verify that the table is empty +SELECT * FROM employees; +``` + +此示例创建了一个 stream 和一个用于消费该 stream 的 task,并使用事务块(BEGIN; COMMIT)将数据插入到两个目标表中。 + +```sql +CREATE DATABASE my_db; +USE my_db; + +CREATE TABLE source_table ( + id INT, + source_flag VARCHAR(50),value VARCHAR(50) +); + +CREATE TABLE target_table_1 ( + id INT,value VARCHAR(50) +); + +CREATE TABLE target_table_2 ( + id INT,value VARCHAR(50) +); + +CREATE STREAM source_stream ON TABLE source_table; + +INSERT INTO source_table VALUES +(1, 'source1', 'value1'), +(2, 'source2', 'value2'), +(3, 'source3', 'value3'), +(4, 'source4', 'value4'); + +CREATE TASK insert_task +WAREHOUSE = 'system' +SCHEDULE = 1 SECOND AS +BEGIN + BEGIN; + INSERT INTO my_db.target_table_1 + SELECT id, value + FROM my_db.source_stream; + + INSERT INTO my_db.target_table_2 + SELECT id, value + FROM my_db.source_stream; + COMMIT; +END; + +EXECUTE TASK insert_task; +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/between.md b/tidb-cloud-lake/sql/between.md new file mode 100644 index 0000000000000..29e01741a7d68 --- /dev/null +++ b/tidb-cloud-lake/sql/between.md @@ -0,0 +1,34 @@ +--- +title: BETWEEN +summary: 如果给定的数值或字符串 `` 落在定义的下限和上限之间,则返回 true。 +--- + +# BETWEEN + +如果给定的数值或字符串 `` 落在定义的下限和上限之间,则返回 `true`。 + +## 语法 {#syntax} + +```sql + [ NOT ] BETWEEN AND +``` + +## 示例 {#examples} + +```sql +SELECT 'true' WHERE 5 BETWEEN 0 AND 5; + +┌────────┐ +│ 'true' │ +├────────┤ +│ true │ +└────────┘ + +SELECT 'true' WHERE 'data' BETWEEN 'data' AND 'datalakecloud'; + +┌────────┐ +│ 'true' │ +├────────┤ +│ true │ +└────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/bin.md b/tidb-cloud-lake/sql/bin.md new file mode 100644 index 0000000000000..88699a872ea77 --- /dev/null +++ b/tidb-cloud-lake/sql/bin.md @@ -0,0 +1,35 @@ +--- +title: BIN +summary: 返回 N 的二进制值的字符串表示。 +--- + +# BIN + +返回 N 的二进制值的字符串表示。 + +## 语法 {#syntax} + +```sql +BIN() +``` + +## 参数 {#arguments} + +| 参数 | 描述 | +|-----------|-------------| +| `` | 该数字。 | + +## 返回类型 {#return-type} + +`VARCHAR` + +## 示例 {#examples} + +```sql +SELECT BIN(12); ++---------+ +| BIN(12) | ++---------+ +| 1100 | ++---------+ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/binary.md b/tidb-cloud-lake/sql/binary.md new file mode 100644 index 0000000000000..d6ac861c8e41c --- /dev/null +++ b/tidb-cloud-lake/sql/binary.md @@ -0,0 +1,70 @@ +--- +title: Binary +summary: 原始字节的变长序列。 +--- + +# Binary + +## 概述 {#overview} + +`BINARY`(别名 `VARBINARY`)用于存储变长字节序列。与 `STRING` 不同,其值不会被解释为 UTF-8 文本,因此适合存储摘要、压缩数据或序列化对象等负载。在读写数据时,可以使用 [UNHEX](/tidb-cloud-lake/sql/unhex.md)、[FROM_BASE64](/tidb-cloud-lake/sql/from-base64.md) 和 [TO_HEX](/tidb-cloud-lake/sql/to-hex.md) 等转换函数对值进行编码或解码。 + +## 示例 {#examples} + +### 插入原始字节 {#insert-raw-bytes} + +```sql +CREATE TABLE binary_samples ( + id INT, + raw BINARY +); + +INSERT INTO binary_samples VALUES + (1, UNHEX('68656c6c6f')), -- "hello" + (2, FROM_BASE64('ZGF0YWxha2U=')); -- "datalake" +``` + +```sql +SELECT + id, + HEX(raw) AS hex_value, + LENGTH(raw) AS byte_len +FROM binary_samples +ORDER BY id; +``` + +结果: + +``` +┌────┬──────────────┬──────────┐ +│ id │ hex_value │ byte_len │ +├────┼──────────────┼──────────┤ +│ 1 │ 68656c6c6f │ 5 │ +│ 2 │ 646174616c616b65 │ 8 │ +└────┴──────────────┴──────────┘ +``` + +### 转换回文本 {#convert-back-to-text} + +在需要时,可以将二进制值转换为字符串: + +```sql +SELECT + id, + TO_VARCHAR(raw) AS text_value +FROM binary_samples +ORDER BY id; +``` + +结果: + +``` +┌────┬─────────────┐ +│ id │ text_value │ +├────┼─────────────┤ +│ 1 │ hello │ +│ 2 │ datalake │ +└────┴─────────────┘ +``` + +二进制列可以接受 NULL 值;当你需要将字节负载与其他数据一起存储时,也可以将其嵌套在 ARRAY、MAP 或 TUPLE 结构中。 \ No newline at end of file diff --git a/tidb-cloud-lake/sql/bit-length.md b/tidb-cloud-lake/sql/bit-length.md new file mode 100644 index 0000000000000..a8c9aa5ee78fb --- /dev/null +++ b/tidb-cloud-lake/sql/bit-length.md @@ -0,0 +1,35 @@ +--- +title: BIT_LENGTH +summary: 返回字符串的长度(以位为单位)。 +--- + +# BIT_LENGTH + +返回字符串的长度(以位为单位)。 + +## 语法 {#syntax} + +```sql +BIT_LENGTH() +``` + +## 参数 {#arguments} + +| 参数 | 描述 | +|-----------| ----------- | +| `` | 字符串。 | + +## 返回类型 {#return-type} + +`BIGINT` + +## 示例 {#examples} + +```sql +SELECT BIT_LENGTH('Word'); ++----------------------------+ +| SELECT BIT_LENGTH('Word'); | ++----------------------------+ +| 32 | ++----------------------------+ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/bitmap-and-count.md b/tidb-cloud-lake/sql/bitmap-and-count.md new file mode 100644 index 0000000000000..9f33ba37ea078 --- /dev/null +++ b/tidb-cloud-lake/sql/bitmap-and-count.md @@ -0,0 +1,26 @@ +--- +title: BITMAP_AND_COUNT +summary: 通过执行逻辑 AND 运算,统计位图中设置为 1 的位数。 +--- + +# BITMAP_AND_COUNT + +通过执行逻辑 AND 运算,统计位图中设置为 1 的位数。 + +## 语法 {#syntax} + +```sql +BITMAP_AND_COUNT( ) +``` + +## 示例 {#examples} + +```sql +SELECT BITMAP_AND_COUNT(TO_BITMAP('1, 3, 5')); + +┌────────────────────────────────────────┐ +│ bitmap_and_count(to_bitmap('1, 3, 5')) │ +├────────────────────────────────────────┤ +│ 3 │ +└────────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/bitmap-and-not.md b/tidb-cloud-lake/sql/bitmap-and-not.md new file mode 100644 index 0000000000000..a9e46aa6bfbf2 --- /dev/null +++ b/tidb-cloud-lake/sql/bitmap-and-not.md @@ -0,0 +1,8 @@ +--- +title: BITMAP_AND_NOT +summary: BITMAP_NOT 的别名。 +--- + +# BITMAP_AND_NOT + +[BITMAP_NOT](/tidb-cloud-lake/sql/bitmap-not.md) 的别名。 \ No newline at end of file diff --git a/tidb-cloud-lake/sql/bitmap-and.md b/tidb-cloud-lake/sql/bitmap-and.md new file mode 100644 index 0000000000000..7d97f2f45d026 --- /dev/null +++ b/tidb-cloud-lake/sql/bitmap-and.md @@ -0,0 +1,26 @@ +--- +title: BITMAP_AND +summary: 对两个位图执行按位与运算。 +--- + +# BITMAP_AND + +对两个位图执行按位与运算。 + +## 语法 {#syntax} + +```sql +BITMAP_AND( , ) +``` + +## 示例 {#examples} + +```sql +SELECT BITMAP_AND(BUILD_BITMAP([1,4,5]), BUILD_BITMAP([4,5]))::String; + +┌───────────────────────────────────────────────────────────────────┐ +│ bitmap_and(build_bitmap([1, 4, 5]), build_bitmap([4, 5]))::string │ +├───────────────────────────────────────────────────────────────────┤ +│ 4,5 │ +└───────────────────────────────────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/bitmap-array.md b/tidb-cloud-lake/sql/bitmap-array.md new file mode 100644 index 0000000000000..15934cca3e498 --- /dev/null +++ b/tidb-cloud-lake/sql/bitmap-array.md @@ -0,0 +1,30 @@ +--- +title: BITMAP_TO_ARRAY +summary: 将 Bitmap 转换为 Array。 +--- + +# BITMAP_TO_ARRAY + +将 Bitmap 转换为 Array。 + +## 语法 {#syntax} + +```sql +BITMAP_TO_ARRAY( ) +``` + +## 返回类型 {#return-type} + +`Array (UInt64)` + +## 示例 {#examples} + +```sql +SELECT BITMAP_TO_ARRAY(TO_BITMAP('1, 3, 5')); + +╭───────────────────────────────────────╮ +│ bitmap_to_array(to_bitmap('1, 3, 5')) │ +├───────────────────────────────────────┤ +│ [1,3,5] │ +╰───────────────────────────────────────╯ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/bitmap-cardinality.md b/tidb-cloud-lake/sql/bitmap-cardinality.md new file mode 100644 index 0000000000000..18757a6f0b652 --- /dev/null +++ b/tidb-cloud-lake/sql/bitmap-cardinality.md @@ -0,0 +1,8 @@ +--- +title: BITMAP_CARDINALITY +summary: BITMAP_COUNT 的别名。 +--- + +# BITMAP_CARDINALITY + +[BITMAP_COUNT](/tidb-cloud-lake/sql/bitmap-count.md) 的别名。 \ No newline at end of file diff --git a/tidb-cloud-lake/sql/bitmap-contains.md b/tidb-cloud-lake/sql/bitmap-contains.md new file mode 100644 index 0000000000000..bf2802ea24e5d --- /dev/null +++ b/tidb-cloud-lake/sql/bitmap-contains.md @@ -0,0 +1,26 @@ +--- +title: BITMAP_CONTAINS +summary: 检查 bitmap 是否包含特定值。 +--- + +# BITMAP_CONTAINS + +检查 bitmap 是否包含特定值。 + +## 语法 {#syntax} + +```sql +BITMAP_CONTAINS( , ) +``` + +## 示例 {#examples} + +```sql +SELECT BITMAP_CONTAINS(BUILD_BITMAP([1,4,5]), 1); + +┌─────────────────────────────────────────────┐ +│ bitmap_contains(build_bitmap([1, 4, 5]), 1) │ +├─────────────────────────────────────────────┤ +│ true │ +└─────────────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/bitmap-count.md b/tidb-cloud-lake/sql/bitmap-count.md new file mode 100644 index 0000000000000..1e6e464f29343 --- /dev/null +++ b/tidb-cloud-lake/sql/bitmap-count.md @@ -0,0 +1,30 @@ +--- +title: BITMAP_COUNT +summary: 统计位图中设置为 1 的位数。 +--- + +# BITMAP_COUNT + +统计位图中设置为 1 的位数。 + +## 语法 {#syntax} + +```sql +BITMAP_COUNT( ) +``` + +## 别名 {#aliases} + +- [BITMAP_CARDINALITY](/tidb-cloud-lake/sql/bitmap-cardinality.md) + +## 示例 {#examples} + +```sql +SELECT BITMAP_COUNT(BUILD_BITMAP([1,4,5])), BITMAP_CARDINALITY(BUILD_BITMAP([1,4,5])); + +┌─────────────────────────────────────────────────────────────────────────────────────┐ +│ bitmap_count(build_bitmap([1, 4, 5])) │ bitmap_cardinality(build_bitmap([1, 4, 5])) │ +├───────────────────────────────────────┼─────────────────────────────────────────────┤ +│ 3 │ 3 │ +└─────────────────────────────────────────────────────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/bitmap-functions.md b/tidb-cloud-lake/sql/bitmap-functions.md new file mode 100644 index 0000000000000..0de5417fd7c70 --- /dev/null +++ b/tidb-cloud-lake/sql/bitmap-functions.md @@ -0,0 +1,50 @@ +--- +title: Bitmap 函数 +summary: 本页按功能分类,全面概述 {{{ .lake }}} 中的 Bitmap 函数,便于参考。 +--- + +# Bitmap 函数 + +本页按功能分类,全面概述 {{{ .lake }}} 中的 Bitmap 函数,便于参考。 + +## Bitmap 操作 {#bitmap-operations} + +| 函数 | 描述 | 示例 | +|----------|-------------|---------| +| [BITMAP_AND](/tidb-cloud-lake/sql/bitmap-and.md) | 对两个 bitmap 执行按位 AND 运算 | `BITMAP_AND(BUILD_BITMAP([1,4,5]), BUILD_BITMAP([4,5]))` → `{4,5}` | +| [BITMAP_OR](/tidb-cloud-lake/sql/bitmap-or.md) | 对两个 bitmap 执行按位 OR 运算 | `BITMAP_OR(BUILD_BITMAP([1,2]), BUILD_BITMAP([2,3]))` → `{1,2,3}` | +| [BITMAP_XOR](/tidb-cloud-lake/sql/bitmap-xor.md) | 对两个 bitmap 执行按位 XOR 运算 | `BITMAP_XOR(BUILD_BITMAP([1,2,3]), BUILD_BITMAP([2,3,4]))` → `{1,4}` | +| [BITMAP_NOT](/tidb-cloud-lake/sql/bitmap-not.md) | 对一个 bitmap 执行按位 NOT 运算 | `BITMAP_NOT(BUILD_BITMAP([1,2,3]), 5)` → `{0,4}` | +| [BITMAP_AND_NOT](/tidb-cloud-lake/sql/bitmap-and-not.md) | 返回第一个 bitmap 中存在但第二个 bitmap 中不存在的元素 | `BITMAP_AND_NOT(BUILD_BITMAP([1,2,3]), BUILD_BITMAP([2,3]))` → `{1}` | +| [BITMAP_UNION](/tidb-cloud-lake/sql/bitmap-union.md) | 将多个 bitmap 合并为一个 | `BITMAP_UNION([BUILD_BITMAP([1,2]), BUILD_BITMAP([2,3])])` → `{1,2,3}` | +| [BITMAP_INTERSECT](/tidb-cloud-lake/sql/bitmap-intersect.md) | 返回多个 bitmap 的交集 | `BITMAP_INTERSECT([BUILD_BITMAP([1,2,3]), BUILD_BITMAP([2,3,4])])` → `{2,3}` | + +## Bitmap 信息 {#bitmap-information} + +| 函数 | 描述 | 示例 | +|----------|-------------|---------| +| [BITMAP_COUNT](/tidb-cloud-lake/sql/bitmap-count.md) | 返回 bitmap 中的元素个数 | `BITMAP_COUNT(BUILD_BITMAP([1,2,3]))` → `3` | +| [BITMAP_CONTAINS](/tidb-cloud-lake/sql/bitmap-contains.md) | 检查 bitmap 是否包含指定元素 | `BITMAP_CONTAINS(BUILD_BITMAP([1,2,3]), 2)` → `true` | +| [BITMAP_HAS_ANY](/tidb-cloud-lake/sql/bitmap-has-any.md) | 检查一个 bitmap 是否包含另一个 bitmap 中的任意元素 | `BITMAP_HAS_ANY(BUILD_BITMAP([1,2,3]), BUILD_BITMAP([3,4]))` → `true` | +| [BITMAP_HAS_ALL](/tidb-cloud-lake/sql/bitmap-has-all.md) | 检查一个 bitmap 是否包含另一个 bitmap 中的所有元素 | `BITMAP_HAS_ALL(BUILD_BITMAP([1,2,3]), BUILD_BITMAP([2,3]))` → `true` | +| [BITMAP_MIN](/tidb-cloud-lake/sql/bitmap-min.md) | 返回 bitmap 中的最小元素 | `BITMAP_MIN(BUILD_BITMAP([1,2,3]))` → `1` | +| [BITMAP_MAX](/tidb-cloud-lake/sql/bitmap-max.md) | 返回 bitmap 中的最大元素 | `BITMAP_MAX(BUILD_BITMAP([1,2,3]))` → `3` | +| [BITMAP_CARDINALITY](/tidb-cloud-lake/sql/bitmap-cardinality.md) | 返回 bitmap 中的元素个数 | `BITMAP_CARDINALITY(BUILD_BITMAP([1,2,3]))` → `3` | + +## Bitmap 计数操作 {#bitmap-count-operations} + +| 函数 | 描述 | 示例 | +|----------|-------------|---------| +| [BITMAP_AND_COUNT](/tidb-cloud-lake/sql/bitmap-and-count.md) | 返回两个 bitmap 按位 AND 结果中的元素个数 | `BITMAP_AND_COUNT(BUILD_BITMAP([1,2,3]), BUILD_BITMAP([2,3,4]))` → `2` | +| [BITMAP_OR_COUNT](/tidb-cloud-lake/sql/bitmap-or-count.md) | 返回两个 bitmap 按位 OR 结果中的元素个数 | `BITMAP_OR_COUNT(BUILD_BITMAP([1,2]), BUILD_BITMAP([2,3]))` → `3` | +| [BITMAP_XOR_COUNT](/tidb-cloud-lake/sql/bitmap-xor-count.md) | 返回两个 bitmap 按位 XOR 结果中的元素个数 | `BITMAP_XOR_COUNT(BUILD_BITMAP([1,2,3]), BUILD_BITMAP([2,3,4]))` → `2` | +| [BITMAP_NOT_COUNT](/tidb-cloud-lake/sql/bitmap-not-count.md) | 返回一个 bitmap 按位 NOT 结果中的元素个数 | `BITMAP_NOT_COUNT(BUILD_BITMAP([1,2,3]), 5)` → `2` | +| [INTERSECT_COUNT](/tidb-cloud-lake/sql/intersect-count.md) | 返回多个 bitmap 交集中的元素个数 | `INTERSECT_COUNT([BUILD_BITMAP([1,2,3]), BUILD_BITMAP([2,3,4])])` → `2` | + +## Bitmap 子集操作 {#bitmap-subset-operations} + +| 函数 | 描述 | 示例 | +|----------|-------------|---------| +| [SUB_BITMAP](/tidb-cloud-lake/sql/sub-bitmap.md) | 提取 bitmap 的一个子集 | `SUB_BITMAP(BUILD_BITMAP([1,2,3,4,5]), 1, 3)` → `{2,3,4}` | +| [BITMAP_SUBSET_IN_RANGE](/tidb-cloud-lake/sql/bitmap-subset-in-range.md) | 返回 bitmap 在指定范围内的子集 | `BITMAP_SUBSET_IN_RANGE(BUILD_BITMAP([1,2,3,4,5]), 2, 4)` → `{2,3}` | +| [BITMAP_SUBSET_LIMIT](/tidb-cloud-lake/sql/bitmap-subset-limit.md) | 返回带限制条件的 bitmap 子集 | `BITMAP_SUBSET_LIMIT(BUILD_BITMAP([1,2,3,4,5]), 2, 2)` → `{3,4}` | \ No newline at end of file diff --git a/tidb-cloud-lake/sql/bitmap-has-all.md b/tidb-cloud-lake/sql/bitmap-has-all.md new file mode 100644 index 0000000000000..f8a596bc052a6 --- /dev/null +++ b/tidb-cloud-lake/sql/bitmap-has-all.md @@ -0,0 +1,26 @@ +--- +title: BITMAP_HAS_ALL +summary: 检查第一个位图是否包含第二个位图中的所有位。 +--- + +# BITMAP_HAS_ALL + +检查第一个位图是否包含第二个位图中的所有位。 + +## 语法 {#syntax} + +```sql +BITMAP_HAS_ALL( , ) +``` + +## 示例 {#examples} + +```sql +SELECT BITMAP_HAS_ALL(BUILD_BITMAP([1,4,5]), BUILD_BITMAP([1,2])); + +┌───────────────────────────────────────────────────────────────┐ +│ bitmap_has_all(build_bitmap([1, 4, 5]), build_bitmap([1, 2])) │ +├───────────────────────────────────────────────────────────────┤ +│ false │ +└───────────────────────────────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/bitmap-has-any.md b/tidb-cloud-lake/sql/bitmap-has-any.md new file mode 100644 index 0000000000000..786567392786f --- /dev/null +++ b/tidb-cloud-lake/sql/bitmap-has-any.md @@ -0,0 +1,26 @@ +--- +title: BITMAP_HAS_ANY +summary: 检查第一个 bitmap 是否包含与第二个 bitmap 中任意位匹配的位。 +--- + +# BITMAP_HAS_ANY + +检查第一个 bitmap 是否包含与第二个 bitmap 中任意位匹配的位。 + +## 语法 {#syntax} + +```sql +BITMAP_HAS_ANY( , ) +``` + +## 示例 {#examples} + +```sql +SELECT BITMAP_HAS_ANY(BUILD_BITMAP([1,4,5]), BUILD_BITMAP([1,2])); + +┌───────────────────────────────────────────────────────────────┐ +│ bitmap_has_any(build_bitmap([1, 4, 5]), build_bitmap([1, 2])) │ +├───────────────────────────────────────────────────────────────┤ +│ true │ +└───────────────────────────────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/bitmap-intersect.md b/tidb-cloud-lake/sql/bitmap-intersect.md new file mode 100644 index 0000000000000..b1145dda91ad7 --- /dev/null +++ b/tidb-cloud-lake/sql/bitmap-intersect.md @@ -0,0 +1,26 @@ +--- +title: BITMAP_INTERSECT +summary: 通过执行逻辑 INTERSECT 操作,统计 bitmap 中值为 1 的位数。 +--- + +# BITMAP_INTERSECT + +通过执行逻辑 INTERSECT 操作,统计 bitmap 中值为 1 的位数。 + +## 语法 {#syntax} + +```sql +BITMAP_INTERSECT( ) +``` + +## 示例 {#examples} + +```sql +SELECT BITMAP_INTERSECT(TO_BITMAP('1, 3, 5'))::String; + +┌────────────────────────────────────────────────┐ +│ bitmap_intersect(to_bitmap('1, 3, 5'))::string │ +├────────────────────────────────────────────────┤ +│ 1,3,5 │ +└────────────────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/bitmap-max.md b/tidb-cloud-lake/sql/bitmap-max.md new file mode 100644 index 0000000000000..0970eef98a3a5 --- /dev/null +++ b/tidb-cloud-lake/sql/bitmap-max.md @@ -0,0 +1,26 @@ +--- +title: BITMAP_MAX +summary: 获取 bitmap 中的最大值。 +--- + +# BITMAP_MAX + +获取 bitmap 中的最大值。 + +## 语法 {#syntax} + +```sql +BITMAP_MAX( ) +``` + +## 示例 {#examples} + +```sql +SELECT BITMAP_MAX(BUILD_BITMAP([1,4,5])); + +┌─────────────────────────────────────┐ +│ bitmap_max(build_bitmap([1, 4, 5])) │ +├─────────────────────────────────────┤ +│ 5 │ +└─────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/bitmap-min.md b/tidb-cloud-lake/sql/bitmap-min.md new file mode 100644 index 0000000000000..2e0efd4d418c4 --- /dev/null +++ b/tidb-cloud-lake/sql/bitmap-min.md @@ -0,0 +1,26 @@ +--- +title: BITMAP_MIN +summary: 获取 bitmap 中的最小值。 +--- + +# BITMAP_MIN + +获取 bitmap 中的最小值。 + +## 语法 {#syntax} + +```sql +BITMAP_MIN( ) +``` + +## 示例 {#examples} + +```sql +SELECT BITMAP_MIN(BUILD_BITMAP([1,4,5])); + +┌─────────────────────────────────────┐ +│ bitmap_min(build_bitmap([1, 4, 5])) │ +├─────────────────────────────────────┤ +│ 1 │ +└─────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/bitmap-not-count.md b/tidb-cloud-lake/sql/bitmap-not-count.md new file mode 100644 index 0000000000000..a5fb7df1090d1 --- /dev/null +++ b/tidb-cloud-lake/sql/bitmap-not-count.md @@ -0,0 +1,26 @@ +--- +title: BITMAP_NOT_COUNT +summary: 通过执行逻辑 NOT 操作,统计 bitmap 中值为 0 的位数。 +--- + +# BITMAP_NOT_COUNT + +通过执行逻辑 NOT 操作,统计 bitmap 中值为 0 的位数。 + +## 语法 {#syntax} + +```sql +BITMAP_NOT_COUNT( ) +``` + +## 示例 {#examples} + +```sql +SELECT BITMAP_NOT_COUNT(TO_BITMAP('1, 3, 5')); + +┌────────────────────────────────────────┐ +│ bitmap_not_count(to_bitmap('1, 3, 5')) │ +├────────────────────────────────────────┤ +│ 3 │ +└────────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/bitmap-not.md b/tidb-cloud-lake/sql/bitmap-not.md new file mode 100644 index 0000000000000..eaa1f619dadac --- /dev/null +++ b/tidb-cloud-lake/sql/bitmap-not.md @@ -0,0 +1,38 @@ +--- +title: BITMAP_NOT +summary: 生成一个新位图,其中包含第一个位图中存在但不在第二个位图中的元素。 +--- + +# BITMAP_NOT + +生成一个新位图,其中包含第一个位图中存在但不在第二个位图中的元素。 + +## 语法 {#syntax} + +```sql +BITMAP_NOT( , ) +``` + +## 别名 {#aliases} + +- [BITMAP_AND_NOT](/tidb-cloud-lake/sql/bitmap-and-not.md) + +## 示例 {#examples} + +```sql +SELECT BITMAP_NOT(BUILD_BITMAP([1,4,5]), BUILD_BITMAP([5,6,7]))::String; + +┌──────────────────────────────────────────────────────────────────────┐ +│ bitmap_not(build_bitmap([1, 4, 5]), build_bitmap([5, 6, 7]))::string │ +├──────────────────────────────────────────────────────────────────────┤ +│ 1,4 │ +└──────────────────────────────────────────────────────────────────────┘ + +SELECT BITMAP_AND_NOT(BUILD_BITMAP([1,4,5]), BUILD_BITMAP([5,6,7]))::String; + +┌──────────────────────────────────────────────────────────────────────────┐ +│ bitmap_and_not(build_bitmap([1, 4, 5]), build_bitmap([5, 6, 7]))::string │ +├──────────────────────────────────────────────────────────────────────────┤ +│ 1,4 │ +└──────────────────────────────────────────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/bitmap-or-count.md b/tidb-cloud-lake/sql/bitmap-or-count.md new file mode 100644 index 0000000000000..0605190629e47 --- /dev/null +++ b/tidb-cloud-lake/sql/bitmap-or-count.md @@ -0,0 +1,26 @@ +--- +title: BITMAP_OR_COUNT +summary: 通过执行逻辑 OR 操作,统计 bitmap 中设置为 1 的位数。 +--- + +# BITMAP_OR_COUNT + +通过执行逻辑 OR 操作,统计 bitmap 中设置为 1 的位数。 + +## 语法 {#syntax} + +```sql +BITMAP_OR_COUNT( ) +``` + +## 示例 {#examples} + +```sql +SELECT BITMAP_OR_COUNT(TO_BITMAP('1, 3, 5')); + +┌───────────────────────────────────────┐ +│ bitmap_or_count(to_bitmap('1, 3, 5')) │ +├───────────────────────────────────────┤ +│ 3 │ +└───────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/bitmap-or.md b/tidb-cloud-lake/sql/bitmap-or.md new file mode 100644 index 0000000000000..844ecb2edced0 --- /dev/null +++ b/tidb-cloud-lake/sql/bitmap-or.md @@ -0,0 +1,26 @@ +--- +title: BITMAP_OR +summary: 对两个位图执行按位 OR 运算。 +--- + +# BITMAP_OR + +对两个位图执行按位 OR 运算。 + +## 语法 {#syntax} + +```sql +BITMAP_OR( , ) +``` + +## 示例 {#examples} + +```sql +SELECT BITMAP_OR(BUILD_BITMAP([1,4,5]), BUILD_BITMAP([6,7]))::String; + +┌──────────────────────────────────────────────────────────────────┐ +│ bitmap_or(build_bitmap([1, 4, 5]), build_bitmap([6, 7]))::string │ +├──────────────────────────────────────────────────────────────────┤ +│ 1,4,5,6,7 │ +└──────────────────────────────────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/bitmap-subset-in-range.md b/tidb-cloud-lake/sql/bitmap-subset-in-range.md new file mode 100644 index 0000000000000..fa2fd11f2f949 --- /dev/null +++ b/tidb-cloud-lake/sql/bitmap-subset-in-range.md @@ -0,0 +1,26 @@ +--- +title: BITMAP_SUBSET_IN_RANGE +summary: 在指定范围内生成源位图的子位图。 +--- + +# BITMAP_SUBSET_IN_RANGE + +在指定范围内生成源位图的子位图。 + +## 语法 {#syntax} + +```sql +BITMAP_SUBSET_IN_RANGE( , , ) +``` + +## 示例 {#examples} + +```sql +SELECT BITMAP_SUBSET_IN_RANGE(BUILD_BITMAP([5,7,9]), 6, 9)::String; + +┌───────────────────────────────────────────────────────────────┐ +│ bitmap_subset_in_range(build_bitmap([5, 7, 9]), 6, 9)::string │ +├───────────────────────────────────────────────────────────────┤ +│ 7 │ +└───────────────────────────────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/bitmap-subset-limit.md b/tidb-cloud-lake/sql/bitmap-subset-limit.md new file mode 100644 index 0000000000000..c5766a29dc476 --- /dev/null +++ b/tidb-cloud-lake/sql/bitmap-subset-limit.md @@ -0,0 +1,26 @@ +--- +title: BITMAP_SUBSET_LIMIT +summary: 从源位图中生成一个子位图,从 start 值指定的范围开始,并带有大小限制。 +--- + +# BITMAP_SUBSET_LIMIT + +从源位图中生成一个子位图,从 start 值指定的范围开始,并带有大小限制。 + +## 语法 {#syntax} + +```sql +BITMAP_SUBSET_LIMIT( , , ) +``` + +## 示例 {#examples} + +```sql +SELECT BITMAP_SUBSET_LIMIT(BUILD_BITMAP([1,4,5]), 2, 2)::String; + +┌────────────────────────────────────────────────────────────┐ +│ bitmap_subset_limit(build_bitmap([1, 4, 5]), 2, 2)::string │ +├────────────────────────────────────────────────────────────┤ +│ 4,5 │ +└────────────────────────────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/bitmap-union.md b/tidb-cloud-lake/sql/bitmap-union.md new file mode 100644 index 0000000000000..b67c91f9ddce7 --- /dev/null +++ b/tidb-cloud-lake/sql/bitmap-union.md @@ -0,0 +1,26 @@ +--- +title: BITMAP_UNION +summary: 通过执行逻辑 UNION 操作,统计 bitmap 中被设置为 1 的位数。 +--- + +# BITMAP_UNION + +通过执行逻辑 UNION 操作,统计 bitmap 中被设置为 1 的位数。 + +## 语法 {#syntax} + +```sql +BITMAP_UNION( ) +``` + +## 示例 {#examples} + +```sql +SELECT BITMAP_UNION(TO_BITMAP('1, 3, 5'))::String; + +┌────────────────────────────────────────────┐ +│ bitmap_union(to_bitmap('1, 3, 5'))::string │ +├────────────────────────────────────────────┤ +│ 1,3,5 │ +└────────────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/bitmap-xor-count.md b/tidb-cloud-lake/sql/bitmap-xor-count.md new file mode 100644 index 0000000000000..3338ce9953579 --- /dev/null +++ b/tidb-cloud-lake/sql/bitmap-xor-count.md @@ -0,0 +1,26 @@ +--- +title: BITMAP_XOR_COUNT +summary: 通过执行逻辑 XOR(异或)运算,统计 bitmap 中值为 1 的位数。 +--- + +# BITMAP_XOR_COUNT + +通过执行逻辑 XOR(异或)运算,统计 bitmap 中值为 1 的位数。 + +## 语法 {#syntax} + +```sql +BITMAP_XOR_COUNT( ) +``` + +## 示例 {#examples} + +```sql +SELECT BITMAP_XOR_COUNT(TO_BITMAP('1, 3, 5')); + +┌────────────────────────────────────────┐ +│ bitmap_xor_count(to_bitmap('1, 3, 5')) │ +├────────────────────────────────────────┤ +│ 3 │ +└────────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/bitmap-xor.md b/tidb-cloud-lake/sql/bitmap-xor.md new file mode 100644 index 0000000000000..9a10f30fd78ec --- /dev/null +++ b/tidb-cloud-lake/sql/bitmap-xor.md @@ -0,0 +1,26 @@ +--- +title: BITMAP_XOR +summary: 对两个位图执行按位 XOR(异或)运算。 +--- + +# BITMAP_XOR + +对两个位图执行按位 XOR(异或)运算。 + +## 语法 {#syntax} + +```sql +BITMAP_XOR( , ) +``` + +## 示例 {#examples} + +```sql +SELECT BITMAP_XOR(BUILD_BITMAP([1,4,5]), BUILD_BITMAP([5,6,7]))::String; + +┌──────────────────────────────────────────────────────────────────────┐ +│ bitmap_xor(build_bitmap([1, 4, 5]), build_bitmap([5, 6, 7]))::string │ +├──────────────────────────────────────────────────────────────────────┤ +│ 1,4,6,7 │ +└──────────────────────────────────────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/bitmap.md b/tidb-cloud-lake/sql/bitmap.md new file mode 100644 index 0000000000000..17900fafd62dc --- /dev/null +++ b/tidb-cloud-lake/sql/bitmap.md @@ -0,0 +1,71 @@ +--- +title: Bitmap +summary: BITMAP 用于存储无符号 64 位整数的成员信息,并支持快速集合运算(计数、并集、交集等)。SELECT 语句会显示二进制 blob,因此请使用 Bitmap Functions 来解析这些值。 +--- + +# Bitmap + +> **注意:** +> +> 于 v1.1.45 引入。 + +## 概述 {#overview} + +`BITMAP` 用于存储无符号 64 位整数的成员信息,并支持快速集合运算(计数、并集、交集等)。`SELECT` 语句会显示二进制 blob,因此请使用 [Bitmap 函数](/tidb-cloud-lake/sql/bitmap-functions.md) 来解析这些值。 + +## 示例 {#examples} + +### 构建 Bitmap {#build-bitmaps} + +`TO_BITMAP` 接受逗号分隔的字符串或 `UINT64` 值(视为单个元素)。`TO_STRING` 会将 bitmap 序列化回可读文本。 + +```sql +SELECT + TO_BITMAP('1,2,3') AS str_input, + TO_STRING(TO_BITMAP('1,2,3')) AS round_tripped, + TO_STRING(TO_BITMAP(123)) AS from_uint64; +``` + +结果: + +``` +┌────────────────────────────────┬──────────────────────────────────┬────────────────┐ +│ str_input │ round_tripped │ from_uint64 │ +├────────────────────────────────┼──────────────────────────────────┼────────────────┤ +│ │ 1,2,3 │ 123 │ +└────────────────────────────────┴──────────────────────────────────┴────────────────┘ +``` + +### 持久化 Bitmap {#persist-bitmaps} + +在将数组插入表之前,使用 `BUILD_BITMAP` 将其转换为 bitmap。随后,`BITMAP_COUNT` 等聚合函数即可快速读取已存储的值。 + +```sql +CREATE TABLE user_visits ( + user_id INT, + page_visits BITMAP +); + +INSERT INTO user_visits VALUES + (1, BUILD_BITMAP([2, 5, 8, 10])), + (2, BUILD_BITMAP([3, 7, 9])), + (3, BUILD_BITMAP([1, 4, 6, 10])); + +SELECT + user_id, + BITMAP_COUNT(page_visits) AS distinct_pages, + BITMAP_HAS_ALL(page_visits, BUILD_BITMAP([10])) AS saw_page_10 +FROM user_visits; +``` + +结果: + +``` +┌────────┬────────────────┬─────────────┐ +│ user_id │ distinct_pages │ saw_page_10 │ +├────────┼────────────────┼─────────────┤ +│ 1 │ 4 │ true │ +│ 2 │ 3 │ false │ +│ 3 │ 4 │ true │ +└────────┴────────────────┴─────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/blake.md b/tidb-cloud-lake/sql/blake.md new file mode 100644 index 0000000000000..22d856103d462 --- /dev/null +++ b/tidb-cloud-lake/sql/blake.md @@ -0,0 +1,26 @@ +--- +title: BLAKE3 +summary: 计算字符串的 BLAKE3 256 位校验和。如果参数为 NULL,则返回值为 64 个十六进制数字组成的字符串或 NULL。 +--- + +# BLAKE3 + +计算字符串的 BLAKE3 256 位校验和。如果参数为 NULL,则返回值为 64 个十六进制数字组成的字符串或 NULL。 + +## 语法 {#syntax} + +```sql +BLAKE3() +``` + +## 示例 {#examples} + +```sql +SELECT BLAKE3('1234567890'); + +┌──────────────────────────────────────────────────────────────────┐ +│ blake3('1234567890') │ +├──────────────────────────────────────────────────────────────────┤ +│ d12e417e04494572b561ba2c12c3d7f9e5107c4747e27b9a8a54f8480c63e841 │ +└──────────────────────────────────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/bool-and.md b/tidb-cloud-lake/sql/bool-and.md new file mode 100644 index 0000000000000..99296a851f88d --- /dev/null +++ b/tidb-cloud-lake/sql/bool-and.md @@ -0,0 +1,51 @@ +--- +title: bool_and +summary: 如果所有输入值都为 true,则返回 true;否则返回 false。 +--- + +# bool_and + +如果所有输入值都为 true,则返回 true;否则返回 false。 + +- 会忽略 NULL 值。 +- 如果所有输入值都为 null,结果为 null。 +- 支持布尔类型 + +## 语法 {#syntax} + +```sql +bool_and() +``` + +## 返回类型 {#return-type} + +与输入类型相同。 + +## 示例 {#examples} + +```sql +select bool_and(t) from (values (true), (true), (null)) a(t); +╭───────────────────╮ +│ bool_and(t) │ +│ Nullable(Boolean) │ +├───────────────────┤ +│ true │ +╰───────────────────╯ + +select bool_and(t) from (values (true), (true), (true)) a(t); + +╭───────────────────╮ +│ bool_and(t) │ +│ Nullable(Boolean) │ +├───────────────────┤ +│ true │ +╰───────────────────╯ + +select bool_and(t) from (values (true), (true), (false)) a(t); +╭───────────────────╮ +│ bool_and(t) │ +│ Nullable(Boolean) │ +├───────────────────┤ +│ false │ +╰───────────────────╯ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/bool-or.md b/tidb-cloud-lake/sql/bool-or.md new file mode 100644 index 0000000000000..8ee55b7d05b86 --- /dev/null +++ b/tidb-cloud-lake/sql/bool-or.md @@ -0,0 +1,50 @@ +--- +title: bool_or +summary: 如果至少有一个输入值为 true,则返回 true;否则返回 false。 +--- + +# bool_or + +如果至少有一个输入值为 true,则返回 true;否则返回 false + +- 会忽略 NULL 值。 +- 如果所有输入值都是 null,结果为 null。 +- 支持布尔类型 + +## 语法 {#syntax} + +```sql +bool_or() +``` + +## 返回类型 {#return-type} + +与输入类型相同。 + +## 示例 {#examples} + +```sql +select bool_or(t) from (values (true), (true), (null)) a(t); +╭───────────────────╮ +│ bool_or(t) │ +│ Nullable(Boolean) │ +├───────────────────┤ +│ true │ +╰───────────────────╯ + +select bool_or(t) from (values (true), (true), (false)) a(t); +╭───────────────────╮ +│ bool_or(t) │ +│ Nullable(Boolean) │ +├───────────────────┤ +│ true │ +╰───────────────────╯ + +select bool_or(t) from (values (false), (false), (false)) a(t); +╭───────────────────╮ +│ bool_or(t) │ +│ Nullable(Boolean) │ +├───────────────────┤ +│ false │ +╰───────────────────╯ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/boolean.md b/tidb-cloud-lake/sql/boolean.md new file mode 100644 index 0000000000000..0dfccd2122b21 --- /dev/null +++ b/tidb-cloud-lake/sql/boolean.md @@ -0,0 +1,46 @@ +--- +title: Boolean +summary: 基本逻辑数据类型。 +--- + +# Boolean + +## 概述 {#overview} + +`BOOLEAN`(别名 `BOOL`)表示 `TRUE` 或 `FALSE`,并且始终使用一个字节的存储空间。在可能的情况下,数值和字符串输入会自动强制转换为布尔值。 + +| 输入类型 | 转换为 TRUE | 转换为 FALSE | 说明 | +|------------|-----------------|-------------------|-------| +| 数值 | 任何非零值 | 0 | 负数会转换为 TRUE。 | +| 字符串 | `TRUE` | `FALSE` | 不区分大小写;其他文本无法转换。 | + +## 示例 {#examples} + +```sql +SELECT + 0::BOOLEAN AS zero_is_false, + 42::BOOLEAN AS nonzero_is_true, + 'True'::BOOLEAN AS string_true, + 'false'::BOOLEAN AS string_false; +``` + +结果: + +``` +┌───────────────┬──────────────────┬───────────────┬────────────────┐ +│ zero_is_false │ nonzero_is_true │ string_true │ string_false │ +├───────────────┼──────────────────┼───────────────┼────────────────┤ +│ false │ true │ true │ false │ +└───────────────┴──────────────────┴───────────────┴────────────────┘ +``` + +```sql +-- Casting unsupported text raises an error. +SELECT 'yes'::BOOLEAN; +``` + +结果: + +``` +ERROR 1105 (HY000): QueryFailed: [1006]cannot parse to type `BOOLEAN` while evaluating function `to_boolean('yes')` in expr `CAST('yes' AS Boolean)` +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/build-bitmap.md b/tidb-cloud-lake/sql/build-bitmap.md new file mode 100644 index 0000000000000..198752512d472 --- /dev/null +++ b/tidb-cloud-lake/sql/build-bitmap.md @@ -0,0 +1,26 @@ +--- +title: BUILD_BITMAP +summary: 将正整数数组转换为 BITMAP 值。 +--- + +# BUILD_BITMAP + +将正整数数组转换为 BITMAP 值。 + +## 语法 {#syntax} + +```sql +BUILD_BITMAP( ) +``` + +## 示例 {#examples} + +```sql +SELECT BUILD_BITMAP([1,4,5])::String; + +┌─────────────────────────────────┐ +│ build_bitmap([1, 4, 5])::string │ +├─────────────────────────────────┤ +│ 1,4,5 │ +└─────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/call-procedure.md b/tidb-cloud-lake/sql/call-procedure.md new file mode 100644 index 0000000000000..acdd5fd322361 --- /dev/null +++ b/tidb-cloud-lake/sql/call-procedure.md @@ -0,0 +1,38 @@ +--- +title: CALL PROCEDURE +summary: 通过调用存储过程名称来执行存储过程;如果该过程需要参数,也可以选择传入参数。 +--- + +# CALL PROCEDURE + +通过调用存储过程名称来执行存储过程;如果该过程需要参数,也可以选择传入参数。 + +## 语法 {#syntax} + +```sql +CALL PROCEDURE ([, , ...]) +``` + +## 示例 {#examples} + +以下示例演示了如何创建并调用一个将重量从千克(kg)转换为磅(lb)的存储过程: + +```sql +CREATE PROCEDURE convert_kg_to_lb(kg DECIMAL(4, 2)) +RETURNS DECIMAL(10, 2) +LANGUAGE SQL +COMMENT = 'Converts kilograms to pounds' +AS $$ +BEGIN + RETURN kg * 2.20462; +END; +$$; + +CALL PROCEDURE convert_kg_to_lb(10.00); + +┌────────────┐ +│ Result │ +├────────────┤ +│ 22.0462000 │ +└────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/case.md b/tidb-cloud-lake/sql/case.md new file mode 100644 index 0000000000000..19ed25b64af89 --- /dev/null +++ b/tidb-cloud-lake/sql/case.md @@ -0,0 +1,64 @@ +--- +title: CASE +summary: 处理 IF/THEN 逻辑。它由至少一对 `WHEN` 和 `THEN` 语句组成。每个 `CASE` 语句都必须以 `END` 关键字结束。`ELSE` 语句是可选的,用于捕获未在 `WHEN` 和 `THEN` 语句中显式指定的值。 +--- + +# CASE + +处理 IF/THEN 逻辑。它由至少一对 `WHEN` 和 `THEN` 语句组成。每个 `CASE` 语句都必须以 `END` 关键字结束。`ELSE` 语句是可选的,用于捕获未在 `WHEN` 和 `THEN` 语句中显式指定的值。 + +## 语法 {#syntax} + +```sql +CASE + WHEN THEN + [ WHEN THEN ] + [ ... ] + [ ELSE ] +END AS +``` + +## 示例 {#examples} + +以下示例使用 CASE 语句对员工薪资进行分类,并通过动态分配的列 `"SalaryCategory"` 展示结果详情: + +```sql +-- Create a sample table +CREATE TABLE Employee ( + EmployeeID INT, + FirstName VARCHAR(50), + LastName VARCHAR(50), + Salary INT +); + +-- Insert some sample data +INSERT INTO Employee VALUES (1, 'John', 'Doe', 50000); +INSERT INTO Employee VALUES (2, 'Jane', 'Smith', 60000); +INSERT INTO Employee VALUES (3, 'Bob', 'Johnson', 75000); +INSERT INTO Employee VALUES (4, 'Alice', 'Williams', 90000); + +-- Add a new column 'SalaryCategory' using CASE statement +-- Categorize employees based on their salary +SELECT + EmployeeID, + FirstName, + LastName, + Salary, + CASE + WHEN Salary < 60000 THEN 'Low' + WHEN Salary >= 60000 AND Salary < 80000 THEN 'Medium' + WHEN Salary >= 80000 THEN 'High' + ELSE 'Unknown' + END AS SalaryCategory +FROM + Employee; + +┌──────────────────────────────────────────────────────────────────────────────────────────┐ +│ employeeid │ firstname │ lastname │ salary │ salarycategory │ +├─────────────────┼──────────────────┼──────────────────┼─────────────────┼────────────────┤ +│ 1 │ John │ Doe │ 50000 │ Low │ +│ 2 │ Jane │ Smith │ 60000 │ Medium │ +│ 4 │ Alice │ Williams │ 90000 │ High │ +│ 3 │ Bob │ Johnson │ 75000 │ Medium │ +└──────────────────────────────────────────────────────────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/cast.md b/tidb-cloud-lake/sql/cast.md new file mode 100644 index 0000000000000..c0adf08264767 --- /dev/null +++ b/tidb-cloud-lake/sql/cast.md @@ -0,0 +1,41 @@ +--- +title: CAST +summary: 将一个值从一种数据类型转换为另一种。`::` 是 CAST 的别名。 +--- + +# CAST + +将一个值从一种数据类型转换为另一种。`::` 是 CAST 的别名。 + +另请参阅:[TRY_CAST](/tidb-cloud-lake/sql/try-cast.md) + +## 语法 {#syntax} + +```sql +CAST( AS ) + +:: +``` + +## 示例 {#examples} + +```sql +SELECT CAST(1 AS VARCHAR), 1::VARCHAR; + +┌───────────────────────────────┐ +│ cast(1 as string) │ 1::string │ +├───────────────────┼───────────┤ +│ 1 │ 1 │ +└───────────────────────────────┘ +``` + +将字符串转换为 Variant,并将 Variant 转换为 `Map` + +```sql +select '{"k1":"v1","k2":"v2"}'::Variant a, a::Map(String, String) b, b::Variant = a; +┌──────────────────────┬──────────────────────┬────────────────┐ +│ a │ b │ b::VARIANT = a │ +├──────────────────────┼──────────────────────┼────────────────┤ +│ {"k1":"v1","k2":"v2"}│ {'k1':'v1','k2':'v2'}│ 1 │ +└──────────────────────┴──────────────────────┴────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/catalog.md b/tidb-cloud-lake/sql/catalog.md new file mode 100644 index 0000000000000..ab909ed452ade --- /dev/null +++ b/tidb-cloud-lake/sql/catalog.md @@ -0,0 +1,13 @@ +--- +title: Catalog +summary: "介绍 {{{ .lake }}} 中 Catalog 操作的概览。" +--- + +# Catalog + +本文档概述了 {{{ .lake }}} 中的 catalog 操作。 + +| 命令 | 描述 | +|---------|-------------| +| [SHOW CATALOGS](/tidb-cloud-lake/sql/show-catalogs.md) | 列出 catalogs | +| [SHOW CREATE CATALOG](/tidb-cloud-lake/sql/show-create-catalog.md) | 显示 catalog 定义信息 | \ No newline at end of file diff --git a/tidb-cloud-lake/sql/cbrt.md b/tidb-cloud-lake/sql/cbrt.md new file mode 100644 index 0000000000000..a930eacabb782 --- /dev/null +++ b/tidb-cloud-lake/sql/cbrt.md @@ -0,0 +1,26 @@ +--- +title: CBRT +summary: 返回非负数 `x` 的立方根。 +--- + +# CBRT + +返回非负数 `x` 的立方根。 + +## 语法 {#syntax} + +```sql +CBRT( ) +``` + +## 示例 {#examples} + +```sql +SELECT CBRT(27); + +┌──────────┐ +│ cbrt(27) │ +├──────────┤ +│ 3 │ +└──────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/ceil.md b/tidb-cloud-lake/sql/ceil.md new file mode 100644 index 0000000000000..0b84f9f25f702 --- /dev/null +++ b/tidb-cloud-lake/sql/ceil.md @@ -0,0 +1,30 @@ +--- +title: CEIL +summary: 将数字向上取整。 +--- + +# CEIL + +将数字向上取整。 + +## 语法 {#syntax} + +```sql +CEIL( ) +``` + +## 别名 {#aliases} + +- [CEILING](/tidb-cloud-lake/sql/ceiling.md) + +## 示例 {#examples} + +```sql +SELECT CEILING(-1.23), CEIL(-1.23); + +┌────────────────────────────────────┐ +│ ceiling((- 1.23)) │ ceil((- 1.23)) │ +├───────────────────┼────────────────┤ +│ -1 │ -1 │ +└────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/ceiling.md b/tidb-cloud-lake/sql/ceiling.md new file mode 100644 index 0000000000000..e37493bee21e8 --- /dev/null +++ b/tidb-cloud-lake/sql/ceiling.md @@ -0,0 +1,8 @@ +--- +title: CEILING +summary: CEIL 的别名。 +--- + +# CEILING + +[CEIL](/tidb-cloud-lake/sql/ceil.md) 的别名。 \ No newline at end of file diff --git a/tidb-cloud-lake/sql/changes.md b/tidb-cloud-lake/sql/changes.md new file mode 100644 index 0000000000000..e68f7fce073ab --- /dev/null +++ b/tidb-cloud-lake/sql/changes.md @@ -0,0 +1,132 @@ +--- +title: CHANGES +summary: `CHANGES` 子句允许在定义的时间区间内查询表的变更跟踪元信息。请注意,时间区间必须落在数据保留时间内(默认为 24 小时)。要定义时间区间,可以使用 `AT` 关键字指定某个时间点作为区间起点,区间终点默认使用当前时间。如果希望将过去的某个时间指定为区间终点,请结合使用 `END` 关键字和 `AT` 关键字来设置该区间。 +--- + +# CHANGES + +`CHANGES` 子句允许在定义的时间区间内查询表的变更跟踪元信息。请注意,时间区间必须落在数据保留时间内(默认为 24 小时)。要定义时间区间,可以使用 `AT` 关键字指定某个时间点作为区间起点,区间终点默认使用当前时间。如果希望将过去的某个时间指定为区间终点,请结合使用 `END` 关键字和 `AT` 关键字来设置该区间。 + +![alt text](/media/tidb-cloud-lake/changes.png) + +## 语法 {#syntax} + +```sql +SELECT ... +FROM ... + CHANGES ( INFORMATION => { DEFAULT | APPEND_ONLY } ) + AT ( { TIMESTAMP => | + OFFSET => | + SNAPSHOT => '' | + STREAM => } ) + + [ END ( { TIMESTAMP => | + OFFSET => | + SNAPSHOT => '' } ) ] +``` + +| 参数 | 描述 | +| ----------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| INFORMATION | 指定要检索的变更跟踪元信息类型。可以设置为 `DEFAULT` 或 `APPEND_ONLY`。`DEFAULT` 返回所有 DML 变更,包括插入、修改和删除。设置为 `APPEND_ONLY` 时,仅返回追加的行。 | +| AT | 指定查询变更跟踪元信息的时间区间起点。 | +| END | 可选参数,用于指定查询变更跟踪元信息的时间区间终点。如果未提供,则默认使用当前时间作为终点。 | +| TIMESTAMP | 指定一个特定的时间戳,作为查询变更跟踪元信息的参考点。 | +| OFFSET | 指定一个相对于当前时间、以秒为单位的时间区间,作为查询变更跟踪元信息的参考点。其形式应为负整数,绝对值表示相差的秒数。例如,`-3600` 表示回到 1 小时前(3,600 秒)。 | +| SNAPSHOT | 指定一个快照 ID,作为查询变更跟踪元信息的参考点。 | +| STREAM | 指定一个 stream 名称,作为查询变更跟踪元信息的参考点。 | + +## 启用变更跟踪 {#enabling-change-tracking} + +`CHANGES` 子句要求表上的 Fuse 引擎选项 `change_tracking` 必须设置为 `true`。有关 `change_tracking` 选项的更多信息,请参见 [Fuse Engine 选项](/tidb-cloud-lake/sql/table-engines.md#available-engines)。 + +```sql title='Example:' +-- Enable change tracking for table 't' +ALTER TABLE t SET OPTIONS(change_tracking = true); +``` + +## 示例 {#examples} + +以下示例演示了 `CHANGES` 子句的用法,可用于跟踪和查询对表所做的变更: + +1. 创建一个用于存储用户资料信息的表,并启用变更跟踪。 + + ```sql + CREATE TABLE user_profiles ( + user_id INT, + username VARCHAR(255), + bio TEXT + ) change_tracking = true; + + INSERT INTO user_profiles VALUES (1, 'john_doe', 'Software Engineer'); + INSERT INTO user_profiles VALUES (2, 'jane_smith', 'Marketing Specialist'); + ``` + +2. 创建一个 stream 来捕获资料更新,然后修改一个现有资料并插入一条新记录。 + + ```sql + CREATE STREAM profile_updates ON TABLE user_profiles APPEND_ONLY = TRUE; + + UPDATE user_profiles SET bio = 'Data Scientist' WHERE user_id = 1; + INSERT INTO user_profiles VALUES (3, 'alex_wong', 'Data Analyst'); + ``` + +3. 通过该 stream 查询用户资料中的变更。 + + ```sql + -- Return all changes in user profiles captured in the stream + SELECT * + FROM user_profiles + CHANGES (INFORMATION => DEFAULT) + AT (STREAM => profile_updates); + + ┌───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ + │ user_id │ username │ bio │ change$action │ change$row_id │ change$is_update │ + ├─────────────────┼──────────────────┼───────────────────┼──────────────────┼────────────────────────────────────────┼──────────────────┤ + │ 1 │ john_doe │ Data Scientist │ INSERT │ 69cffb02264144c384d56f7b6cedee41000000 │ true │ + │ 3 │ alex_wong │ Data Analyst │ INSERT │ 59f315c8655c49eab35ba1959e269430000000 │ false │ + │ 1 │ john_doe │ Software Engineer │ DELETE │ 69cffb02264144c384d56f7b6cedee41000000 │ true │ + └───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ + + -- Return appended rows in user profiles captured in the stream + SELECT * + FROM user_profiles + CHANGES (INFORMATION => APPEND_ONLY) + AT (STREAM => profile_updates); + + ┌───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ + │ user_id │ username │ bio │ change$action │ change$is_update │ change$row_id │ + ├─────────────────┼──────────────────┼──────────────────┼───────────────┼──────────────────┼────────────────────────────────────────┤ + │ 3 │ alex_wong │ Data Analyst │ INSERT │ false │ 59f315c8655c49eab35ba1959e269430000000 │ + └───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ + ``` + +4. 同时使用 `AT` 和 `END` 关键字,查询某个快照与某个时间戳之间的变更。 + +```sql +-- Step 6: Take a snapshot of the user profile data. +SELECT snapshot_id, timestamp +FROM FUSE_SNAPSHOT('default', 'user_profiles'); + +┌───────────────────────────────────────────────────────────────┐ +│ snapshot_id │ timestamp │ +├──────────────────────────────────┼────────────────────────────┤ +│ 6a11c94433714970895edd38577ac8b0 │ 2024-04-10 02:51:39.422832 │ +│ 53dc4750af92423da91c50dcee547cfb │ 2024-04-10 02:51:39.399568 │ +│ 910af7424f764891b0c6fa60aa99fc3a │ 2024-04-10 02:50:14.522416 │ +│ 1225000916f44819a0d23178b2d0d1af │ 2024-04-10 02:50:14.500417 │ +└───────────────────────────────────────────────────────────────┘ + +SELECT * +FROM user_profiles +CHANGES (INFORMATION => DEFAULT) +AT (SNAPSHOT => '1225000916f44819a0d23178b2d0d1af') +END (TIMESTAMP => '2024-04-10 02:51:39.399568'::TIMESTAMP); + +┌──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ +│ user_id │ username │ bio │ change$action │ change$row_id │ change$is_update │ +├─────────────────┼──────────────────┼──────────────────────┼──────────────────┼────────────────────────────────────────┼──────────────────┤ +│ 1 │ john_doe │ Data Scientist │ INSERT │ 69cffb02264144c384d56f7b6cedee41000000 │ true │ +│ 1 │ john_doe │ Software Engineer │ DELETE │ 69cffb02264144c384d56f7b6cedee41000000 │ true │ +│ 2 │ jane_smith │ Marketing Specialist │ INSERT │ 3db484ac18174223851dc9de22f6bfec000000 │ false │ +└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/char-length.md b/tidb-cloud-lake/sql/char-length.md new file mode 100644 index 0000000000000..a84e5ec25ed73 --- /dev/null +++ b/tidb-cloud-lake/sql/char-length.md @@ -0,0 +1,8 @@ +--- +title: CHAR_LENGTH +summary: LENGTH 的别名。 +--- + +# CHAR_LENGTH + +[LENGTH](/tidb-cloud-lake/sql/length.md) 的别名。 \ No newline at end of file diff --git a/tidb-cloud-lake/sql/char.md b/tidb-cloud-lake/sql/char.md new file mode 100644 index 0000000000000..2da3bff291727 --- /dev/null +++ b/tidb-cloud-lake/sql/char.md @@ -0,0 +1,81 @@ +--- +title: CHAR +summary: 返回为每个传入的整数对应的字符。该函数会将每个整数转换为其对应的 Unicode 字符。 +--- + +# CHAR + +返回为每个传入的整数对应的字符。该函数会将每个整数转换为其对应的 Unicode 字符。 + +## 语法 {#syntax} + +```sql +CHAR(N, ...) +CHR(N) +``` + +## 参数 {#arguments} + +| 参数 | 描述 | +|-----------|----------------------------------------------------------------| +| N | 表示 Unicode 码点的整数值(0 到 2^32-1) | + +## 返回类型 {#return-type} + +`STRING` + +## 说明 {#remarks} + +- 接受任意整数类型(自动转换为 Int64)。 +- 对于无效的码点,返回空字符串('')并记录错误日志。 +- `chr` 是 `char` 的别名。 +- 输入为 NULL 时,输出结果为 NULL。 + +## 示例 {#examples} + +```sql +-- Basic usage +SELECT CHAR(65, 66, 67); +┌───────┐ +│ char │ +│ String│ +├───────┤ +│ ABC │ +└───────┘ + +-- Using the CHR alias +SELECT CHR(68); +┌───────┐ +│ chr │ +│ String│ +├───────┤ +│ D │ +└───────┘ + +-- Creating a string from multiple code points +SELECT CHAR(77,121,83,81,76); +┌───────┐ +│ char │ +│ String│ +├───────┤ +│ MySQL │ +└───────┘ + +-- Auto-casting from different integer types +SELECT CHAR(CAST(65 AS UInt16)); +┌───────┐ +│ char │ +│ String│ +├───────┤ +│ A │ +└───────┘ + +-- NULL handling +SELECT CHAR(NULL); +┌───────┐ +│ char │ +│ String│ +├───────┤ +│ NULL │ +└───────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/character-length.md b/tidb-cloud-lake/sql/character-length.md new file mode 100644 index 0000000000000..1ba0b2a7849d7 --- /dev/null +++ b/tidb-cloud-lake/sql/character-length.md @@ -0,0 +1,8 @@ +--- +title: CHARACTER_LENGTH +summary: LENGTH 的别名。 +--- + +# CHARACTER_LENGTH + +[LENGTH](/tidb-cloud-lake/sql/length.md) 的别名。 \ No newline at end of file diff --git a/tidb-cloud-lake/sql/check-json.md b/tidb-cloud-lake/sql/check-json.md new file mode 100644 index 0000000000000..0c50152296b99 --- /dev/null +++ b/tidb-cloud-lake/sql/check-json.md @@ -0,0 +1,49 @@ +--- +title: CHECK_JSON +summary: 检查 JSON 文档的有效性。如果输入字符串是有效的 JSON 文档或 `NULL`,则输出为 `NULL`。如果输入无法转换为有效的 JSON 值,则输出字符串包含错误信息。 +--- + +# CHECK_JSON + +检查 JSON 文档的有效性。如果输入字符串是有效的 JSON 文档或 `NULL`,则输出为 `NULL`。如果输入无法转换为有效的 JSON 值,则输出字符串包含错误信息。 + +## 语法 {#syntax} + +```sql +CHECK_JSON( ) +``` + +## 参数 {#arguments} + +| 参数 | 描述 | +|-----------|------------------------------| +| `` | 一个字符串类型的表达式 | + +## 返回类型 {#return-type} + +字符串 + +## 示例 {#examples} + +```sql +SELECT check_json('[1,2,3]'); ++-----------------------+ +| check_json('[1,2,3]') | ++-----------------------+ +| NULL | ++-----------------------+ + +SELECT check_json('{"key":"val"}'); ++-----------------------------+ +| check_json('{"key":"val"}') | ++-----------------------------+ +| NULL | ++-----------------------------+ + +SELECT check_json('{"key":'); ++----------------------------------------------+ +| check_json('{"key":') | ++----------------------------------------------+ +| EOF while parsing a value at line 1 column 7 | ++----------------------------------------------+ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/city-withseed.md b/tidb-cloud-lake/sql/city-withseed.md new file mode 100644 index 0000000000000..51e768a8f077f --- /dev/null +++ b/tidb-cloud-lake/sql/city-withseed.md @@ -0,0 +1,26 @@ +--- +title: CITY64WITHSEED +summary: 计算字符串的 City64WithSeed 64 位哈希值。 +--- + +# CITY64WITHSEED + +计算字符串的 City64WithSeed 64 位哈希值。 + +## 语法 {#syntax} + +```sql +CITY64WITHSEED(, ) +``` + +## 示例 {#examples} + +```sql +SELECT CITY64WITHSEED('1234567890', 12); + +┌──────────────────────────────────┐ +│ city64withseed('1234567890', 12) │ +├──────────────────────────────────┤ +│ 10660895976650300430 │ +└──────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/clause.md b/tidb-cloud-lake/sql/clause.md new file mode 100644 index 0000000000000..3aa9219f69c09 --- /dev/null +++ b/tidb-cloud-lake/sql/clause.md @@ -0,0 +1,107 @@ +--- +title: WITH 子句 +summary: WITH 子句是位于 SELECT 语句主体之前的可选子句,用于定义一个或多个 CTE(公共表表达式),以便在该语句的后续部分中引用。 +--- + +# WITH 子句 + +WITH 子句是位于 SELECT 语句主体之前的可选子句,用于定义一个或多个 CTE(公共表表达式),以便在该语句的后续部分中引用。 + +## 语法 {#syntax} + +### 基本 CTE {#basic-cte} + +```sql +[ WITH + cte_name1 [ ( cte_column_list ) ] AS ( SELECT ... ) + [ , cte_name2 [ ( cte_column_list ) ] AS ( SELECT ... ) ] + [ , cte_nameN [ ( cte_column_list ) ] AS ( SELECT ... ) ] +] +SELECT ... +``` + +### 递归 CTE {#recursive-cte} + +```sql +[ WITH [ RECURSIVE ] + cte_name1 ( cte_column_list ) AS ( anchorClause UNION ALL recursiveClause ) + [ , cte_name2 ( cte_column_list ) AS ( anchorClause UNION ALL recursiveClause ) ] + [ , cte_nameN ( cte_column_list ) AS ( anchorClause UNION ALL recursiveClause ) ] +] +SELECT ... +``` + +其中: + +- `anchorClause`:`SELECT anchor_column_list FROM ...` +- `recursiveClause`:`SELECT recursive_column_list FROM ... [ JOIN ... ]` + +## 参数 {#parameters} + +| 参数 | 描述 | +|-----------|-------------| +| `cte_name` | CTE 名称必须遵循标准标识符规则 | +| `cte_column_list` | CTE 中各列的名称 | +| `anchor_column_list` | 递归 CTE 的锚定子句中使用的列 | +| `recursive_column_list` | 递归 CTE 的递归子句中使用的列 | + +## 示例 {#examples} + +### 基本 CTE {#basic-cte} + +```sql +WITH high_value_customers AS ( + SELECT customer_id, customer_name, total_spent + FROM customers + WHERE total_spent > 10000 +) +SELECT c.customer_name, o.order_date, o.order_amount +FROM high_value_customers c +JOIN orders o ON c.customer_id = o.customer_id +ORDER BY o.order_date DESC; +``` + +### 多个 CTE {#multiple-ctes} + +```sql +WITH + regional_sales AS ( + SELECT region, SUM(sales_amount) as total_sales + FROM sales_data + GROUP BY region + ), + top_regions AS ( + SELECT region, total_sales + FROM regional_sales + WHERE total_sales > 1000000 + ) +SELECT r.region, r.total_sales +FROM top_regions r +ORDER BY r.total_sales DESC; +``` + +### 递归 CTE {#recursive-cte} + +```sql +WITH RECURSIVE countdown AS ( + -- Anchor clause: starting point + SELECT 10 as num + + UNION ALL + + -- Recursive clause: repeat until condition + SELECT num - 1 + FROM countdown + WHERE num > 1 -- Stop condition +) +SELECT num FROM countdown +ORDER BY num DESC; +``` + +## 使用说明 {#usage-notes} + +- CTE 是临时的具名结果集,仅在查询执行期间存在 +- 在同一个 WITH 子句中,CTE 名称必须唯一 +- CTE 可以引用同一个 WITH 子句中先前定义的 CTE +- 递归 CTE 必须同时包含锚定子句和递归子句,并通过 UNION ALL 连接 +- 使用递归 CTE 时,必须指定 RECURSIVE 关键字 \ No newline at end of file diff --git a/tidb-cloud-lake/sql/cluster-key.md b/tidb-cloud-lake/sql/cluster-key.md new file mode 100644 index 0000000000000..0a15cd403925e --- /dev/null +++ b/tidb-cloud-lake/sql/cluster-key.md @@ -0,0 +1,25 @@ +--- +title: Cluster Key +summary: 本页按功能组织,全面概述了 {{{ .lake }}} 中的 cluster key 操作,便于参考。 +--- + +# Cluster Key + +本页按功能组织,全面概述了 {{{ .lake }}} 中的 cluster key 操作,便于参考。 + +## cluster key 管理 {#cluster-key-management} + +| 命令 | 描述 | +|---------|-------------| +| [SET CLUSTER KEY](/tidb-cloud-lake/sql/set-cluster-key.md) | 为表创建或替换 cluster key | +| [ALTER CLUSTER KEY](/tidb-cloud-lake/sql/alter-cluster-key.md) | 修改现有的 cluster key | +| [DROP CLUSTER KEY](/tidb-cloud-lake/sql/drop-cluster-key.md) | 从表中移除 cluster key | +| [RECLUSTER TABLE](/tidb-cloud-lake/sql/recluster-table.md) | 基于 cluster key 重新组织表数据 | + +## 相关主题 {#related-topics} + +- [Cluster Key](/tidb-cloud-lake/guides/cluster-key-performance.md) + +> **注意:** +> +> {{{ .lake }}} 中的 cluster key 用于在表中以物理方式组织数据,通过将相关数据放置在一起以提升查询性能。 \ No newline at end of file diff --git a/tidb-cloud-lake/sql/clustering-information.md b/tidb-cloud-lake/sql/clustering-information.md new file mode 100644 index 0000000000000..9fb2ec1d6c20a --- /dev/null +++ b/tidb-cloud-lake/sql/clustering-information.md @@ -0,0 +1,44 @@ +--- +title: CLUSTERING_INFORMATION +summary: 返回表的聚簇信息。 +--- + +# CLUSTERING_INFORMATION + +返回表的聚簇信息。 + +## 语法 {#syntax} + +```sql +CLUSTERING_INFORMATION('', '') +``` + +## 示例 {#examples} + +```sql +CREATE TABLE mytable(a int, b int) CLUSTER BY(a+1); + +INSERT INTO mytable VALUES(1,1),(3,3); +INSERT INTO mytable VALUES(2,2),(5,5); +INSERT INTO mytable VALUES(4,4); + +SELECT * FROM CLUSTERING_INFORMATION('default','mytable')\G +*************************** 1. row *************************** + cluster_key: ((a + 1)) + total_block_count: 3 + constant_block_count: 1 +unclustered_block_count: 0 + average_overlaps: 1.3333 + average_depth: 2.0 + block_depth_histogram: {"00002":3} +``` + +| 参数 | 描述 | +|------------------------- |------------------------------------------------------------------------------------------------------------------------ | +| cluster_key | 已定义的 cluster key。 | +| total_block_count | 当前块的数量。 | +| constant_block_count | min/max 值相等的块数量,这意味着每个块仅包含一个(一组)cluster_key 值。 | +| unclustered_block_count | 尚未完成聚簇的块数量。 | +| average_overlaps | 给定范围内重叠块的平均比例。 | +| average_depth | cluster key 的重叠分区的平均深度。 | +| block_depth_histogram | 每个深度级别上的分区数量。较低深度上的分区越集中,表示表聚簇效果越好。 | \ No newline at end of file diff --git a/tidb-cloud-lake/sql/coalesce.md b/tidb-cloud-lake/sql/coalesce.md new file mode 100644 index 0000000000000..4d0f74eecdbb1 --- /dev/null +++ b/tidb-cloud-lake/sql/coalesce.md @@ -0,0 +1,34 @@ +--- +title: COALESCE +summary: 返回其参数中的第一个非 NULL 表达式;如果所有参数都为 NULL,则返回 NULL。 +--- + +# COALESCE + +返回其参数中的第一个非 NULL 表达式;如果所有参数都为 NULL,则返回 NULL。 + +## 语法 {#syntax} + +```sql +COALESCE([, ...]) +``` + +## 示例 {#examples} + +```sql +SELECT COALESCE(1), COALESCE(1, NULL), COALESCE(NULL, 1, 2); + +┌────────────────────────────────────────────────────────┐ +│ coalesce(1) │ coalesce(1, null) │ coalesce(null, 1, 2) │ +├─────────────┼───────────────────┼──────────────────────┤ +│ 1 │ 1 │ 1 │ +└────────────────────────────────────────────────────────┘ + +SELECT COALESCE('a'), COALESCE('a', NULL), COALESCE(NULL, 'a', 'b'); + +┌────────────────────────────────────────────────────────────────┐ +│ coalesce('a') │ coalesce('a', null) │ coalesce(null, 'a', 'b') │ +├───────────────┼─────────────────────┼──────────────────────────┤ +│ a │ a │ a │ +└────────────────────────────────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/commit.md b/tidb-cloud-lake/sql/commit.md new file mode 100644 index 0000000000000..aa599d2dde6e9 --- /dev/null +++ b/tidb-cloud-lake/sql/commit.md @@ -0,0 +1,18 @@ +--- +title: COMMIT +summary: 保存事务期间所做的所有更改。BEGIN 和 COMMIT/ROLLBACK 必须配合使用,以启动事务,并在之后保存或撤销该事务。 +--- + +# COMMIT + +保存事务期间所做的所有更改。[BEGIN](/tidb-cloud-lake/sql/begin.md) 和 COMMIT/[ROLLBACK](/tidb-cloud-lake/sql/rollback.md) 必须配合使用,以启动事务,并在之后保存或撤销该事务。 + +## 语法 {#syntax} + +```sql +COMMIT +``` + +## 示例 {#examples} + +参见[示例](/tidb-cloud-lake/sql/begin.md#examples)。 \ No newline at end of file diff --git a/tidb-cloud-lake/sql/comparison-operators.md b/tidb-cloud-lake/sql/comparison-operators.md new file mode 100644 index 0000000000000..2e5d5a9447f19 --- /dev/null +++ b/tidb-cloud-lake/sql/comparison-operators.md @@ -0,0 +1,18 @@ +--- +title: 比较运算符 +summary: 本页介绍 TiDB Cloud Lake 中的比较运算符。 +--- + +# 比较运算符 + +| 运算符 | 描述 | 示例 | 结果 | +| ------------- | ------------------------------------------- | ------------------------- | ------ | +| `=` | a 等于 b | `2 = 2` | TRUE | +| `!=` | a 不等于 b | `2 != 3` | TRUE | +| `<>` | a 不等于 b | `2 <> 2` | FALSE | +| `>` | a 大于 b | `2 > 3` | FALSE | +| `>=` | a 大于或等于 b | `4 >= NULL` | NULL | +| `<` | a 小于 b | `2 < 3` | TRUE | +| `<=` | a 小于或等于 b | `2 <= 3` | TRUE | +| `IS NULL` | 如果表达式为 NULL,则为 TRUE;否则为 FALSE | `(4 >= NULL) IS NULL` | TRUE | +| `IS NOT NULL` | 如果表达式为 NULL,则为 FALSE;否则为 TRUE | `(4 >= NULL) IS NOT NULL` | FALSE | \ No newline at end of file diff --git a/tidb-cloud-lake/sql/concat-ws.md b/tidb-cloud-lake/sql/concat-ws.md new file mode 100644 index 0000000000000..f28be6ab3344c --- /dev/null +++ b/tidb-cloud-lake/sql/concat-ws.md @@ -0,0 +1,66 @@ +--- +title: CONCAT_WS +summary: CONCAT_WS() 表示 Concatenate With Separator,是 CONCAT() 的一种特殊形式。第一个参数是其余参数的分隔符。分隔符会添加在要连接的字符串之间。分隔符可以是字符串,其余参数也可以是字符串。如果分隔符为 NULL,则结果为 NULL。 +--- + +# CONCAT_WS + +CONCAT_WS() 表示 Concatenate With Separator,是 CONCAT() 的一种特殊形式。第一个参数是其余参数的分隔符。分隔符会添加在要连接的字符串之间。分隔符可以是字符串,其余参数也可以是字符串。如果分隔符为 NULL,则结果为 NULL。 + +CONCAT_WS() 不会跳过空字符串。但是,它会跳过分隔符参数之后的任何 NULL 值。 + +## 语法 {#syntax} + +```sql +CONCAT_WS(, , ...) +``` + +## 参数 {#arguments} + +| 参数 | 描述 | +|---------------| ------------- | +| `` | 字符串列 | +| `` | 值列 | + +## 返回类型 {#return-type} + +返回 `VARCHAR` 数据类型的值或 `NULL` 数据类型。 + +## 示例 {#examples} + +```sql +SELECT CONCAT_WS(',', 'data', 'fuse', 'labs', '2021'); ++------------------------------------------------+ +| CONCAT_WS(',', 'data', 'fuse', 'labs', '2021') | ++------------------------------------------------+ +| data,fuse,labs,2021 | ++------------------------------------------------+ + +SELECT CONCAT_WS(',', 'data', NULL, 'bend'); ++--------------------------------------+ +| CONCAT_WS(',', 'data', NULL, 'bend') | ++--------------------------------------+ +| data,bend | ++--------------------------------------+ + +SELECT CONCAT_WS(',', 'data', NULL, NULL, 'bend'); ++--------------------------------------------+ +| CONCAT_WS(',', 'data', NULL, NULL, 'bend') | ++--------------------------------------------+ +| data,bend | ++--------------------------------------------+ + +SELECT CONCAT_WS(NULL, 'data', 'fuse', 'labs'); ++-----------------------------------------+ +| CONCAT_WS(NULL, 'data', 'fuse', 'labs') | ++-----------------------------------------+ +| NULL | ++-----------------------------------------+ + +SELECT CONCAT_WS(',', NULL); ++----------------------+ +| CONCAT_WS(',', NULL) | ++----------------------+ +| | ++----------------------+ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/concat.md b/tidb-cloud-lake/sql/concat.md new file mode 100644 index 0000000000000..58f71f39d2645 --- /dev/null +++ b/tidb-cloud-lake/sql/concat.md @@ -0,0 +1,49 @@ +--- +title: CONCAT +summary: 返回连接参数后得到的字符串。可以有一个或多个参数。如果所有参数都是非二进制字符串,则结果为非二进制字符串。如果参数中包含任意二进制字符串,则结果为二进制字符串。数值参数会被转换为其等效的非二进制字符串形式。 +--- + +# CONCAT + +返回连接参数后得到的字符串。可以有一个或多个参数。如果所有参数都是非二进制字符串,则结果为非二进制字符串。如果参数中包含任意二进制字符串,则结果为二进制字符串。数值参数会被转换为其等效的非二进制字符串形式。 + +## 语法 {#syntax} + +```sql +CONCAT(, ...) +``` + +## 参数 {#arguments} + +| 参数 | 描述 | +|-----------|-------------| +| `` | 字符串 | + +## 返回类型 {#return-type} + +返回 `VARCHAR` 数据类型的值或 `NULL` 数据类型。 + +## 示例 {#examples} + +```sql +SELECT CONCAT('data', 'lake'); ++------------------------+ +| concat('data', 'lake') | ++------------------------+ +| datalake | ++------------------------+ + +SELECT CONCAT('data', NULL, 'lake'); ++------------------------------+ +| CONCAT('data', NULL, 'lake') | ++------------------------------+ +| NULL | ++------------------------------+ + +SELECT CONCAT('14.3'); ++----------------+ +| concat('14.3') | ++----------------+ +| 14.3 | ++----------------+ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/conditional-functions.md b/tidb-cloud-lake/sql/conditional-functions.md new file mode 100644 index 0000000000000..bf57c82fc8782 --- /dev/null +++ b/tidb-cloud-lake/sql/conditional-functions.md @@ -0,0 +1,43 @@ +--- +title: 条件函数 +summary: 本页按功能分类,全面概述了 {{{ .lake }}} 中的条件函数,便于参考。 +--- + +# 条件函数 + +本页按功能分类,全面概述了 {{{ .lake }}} 中的条件函数,便于参考。 + +## 基本条件函数 {#basic-conditional-functions} + +| 函数 | 描述 | 示例 | +|----------|-------------|---------| +| [IF](/tidb-cloud-lake/sql/if.md) / [IFF](/tidb-cloud-lake/sql/iff.md) | 根据条件返回一个值 | `IF(1 > 0, 'yes', 'no')` → `'yes'` | +| [CASE](/tidb-cloud-lake/sql/case.md) | 对条件进行求值并返回匹配的结果 | `CASE WHEN 1 > 0 THEN 'yes' ELSE 'no' END` → `'yes'` | +| [DECODE](/tidb-cloud-lake/sql/decode.md) | 将表达式与搜索值进行比较并返回结果 | `DECODE(2, 1, 'one', 2, 'two', 'other')` → `'two'` | +| [COALESCE](/tidb-cloud-lake/sql/coalesce.md) | 返回第一个非 NULL 表达式 | `COALESCE(NULL, 'hello', 'world')` → `'hello'` | +| [NULLIF](/tidb-cloud-lake/sql/nullif.md) | 如果两个表达式相等则返回 NULL,否则返回第一个表达式 | `NULLIF(5, 5)` → `NULL` | +| [IFNULL](/tidb-cloud-lake/sql/ifnull.md) | 如果第一个表达式不是 NULL,则返回该表达式,否则返回第二个表达式 | `IFNULL(NULL, 'default')` → `'default'` | +| [NVL](/tidb-cloud-lake/sql/nvl.md) | 返回第一个非 NULL 表达式 | `NVL(NULL, 'default')` → `'default'` | +| [NVL2](/tidb-cloud-lake/sql/nvl2.md) | 如果 expr1 不是 NULL,则返回 expr2,否则返回 expr3 | `NVL2('value', 'not null', 'is null')` → `'not null'` | + +## 比较函数 {#comparison-functions} + +| 函数 | 描述 | 示例 | +|----------|-------------|---------| +| [GREATEST](/tidb-cloud-lake/sql/greatest.md) | 返回列表中的最大值 | `GREATEST(1, 5, 3)` → `5` | +| [LEAST](/tidb-cloud-lake/sql/least.md) | 返回列表中的最小值 | `LEAST(1, 5, 3)` → `1` | +| [GREATEST_IGNORE_NULLS](/tidb-cloud-lake/sql/greatest-ignore-nulls.md) | 返回最大的非 NULL 值 | `GREATEST_IGNORE_NULLS(NULL, 5, 3)` → `5` | +| [LEAST_IGNORE_NULLS](/tidb-cloud-lake/sql/least-ignore-nulls.md) | 返回最小的非 NULL 值 | `LEAST_IGNORE_NULLS(NULL, 5, 3)` → `3` | +| [BETWEEN](/tidb-cloud-lake/sql/between.md) | 检查某个值是否位于指定范围内 | `5 BETWEEN 1 AND 10` → `true` | +| [IN](/tidb-cloud-lake/sql/in.md) | 检查某个值是否与列表中的任一值匹配 | `5 IN (1, 5, 10)` → `true` | + +## NULL 和错误处理函数 {#null-and-error-handling-functions} + +| 函数 | 描述 | 示例 | +|----------|-------------|---------| +| [IS_NULL](/tidb-cloud-lake/sql/is-null.md) | 检查某个值是否为 NULL | `IS_NULL(NULL)` → `true` | +| [IS_NOT_NULL](/tidb-cloud-lake/sql/is-not-null.md) | 检查某个值是否不为 NULL | `IS_NOT_NULL('value')` → `true` | +| [IS_DISTINCT_FROM](/tidb-cloud-lake/sql/is-distinct-from.md) | 检查两个值是否不同,并将 NULL 视为相等 | `NULL IS DISTINCT FROM 0` → `true` | +| [IS_ERROR](/tidb-cloud-lake/sql/is-error.md) | 检查表达式求值是否产生错误 | `IS_ERROR(1/0)` → `true` | +| [IS_NOT_ERROR](/tidb-cloud-lake/sql/is-not-error.md) | 检查表达式求值是否未产生错误 | `IS_NOT_ERROR(1/1)` → `true` | +| [ERROR_OR](/tidb-cloud-lake/sql/error-or.md) | 如果第一个表达式不是错误,则返回该表达式,否则返回第二个表达式 | `ERROR_OR(1/0, 0)` → `0` | \ No newline at end of file diff --git a/tidb-cloud-lake/sql/connection-id.md b/tidb-cloud-lake/sql/connection-id.md new file mode 100644 index 0000000000000..ccd6cc94c9e2c --- /dev/null +++ b/tidb-cloud-lake/sql/connection-id.md @@ -0,0 +1,26 @@ +--- +title: CONNECTION_ID +summary: 返回当前连接的连接 ID。 +--- + +# CONNECTION_ID + +返回当前连接的连接 ID。 + +## 语法 {#syntax} + +```sql +CONNECTION_ID() +``` + +## 示例 {#examples} + +```sql +SELECT CONNECTION_ID(); + +┌──────────────────────────────────────┐ +│ connection_id() │ +├──────────────────────────────────────┤ +│ 23cb06ec-583e-4eba-b790-7c8cf72a53f8 │ +└──────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/connection-parameters.md b/tidb-cloud-lake/sql/connection-parameters.md new file mode 100644 index 0000000000000..f8688392b13f3 --- /dev/null +++ b/tidb-cloud-lake/sql/connection-parameters.md @@ -0,0 +1,214 @@ +--- +title: 连接参数 +summary: 连接参数是你在使用 CREATE CONNECTION 创建可复用连接时提供的键值对。连接创建后,可以通过 CONNECTION = (CONNECTION_NAME = '') 在 stage、COPY 命令以及其他 SQL 功能中引用它。完整语法和用法,请参见 CREATE CONNECTION。 +--- + +# 连接参数 + +连接参数是在使用 `CREATE CONNECTION` 创建可复用连接时提供的键值对。连接创建后,可以通过 `CONNECTION = (CONNECTION_NAME = '')` 在 stage、COPY 命令以及其他 SQL 功能中引用该连接。完整语法和用法请参见 [CREATE CONNECTION](/tidb-cloud-lake/sql/create-connection.md)。 + +有关不同存储类型的连接详情,请参见下表。 + + + +
+ +下表列出了访问 Amazon S3 类存储服务的连接参数: + +| 参数 | 必填? | 描述 | +|--------------------------- |------- |------------------------------------------------------------ | +| endpoint_url | 是 | Amazon S3 类存储服务的 endpoint URL。 | +| access_key_id | 是 | 用于标识请求方的 access key ID。 | +| secret_access_key | 是 | 用于身份验证的 secret access key。 | +| enable_virtual_host_style | 否 | 是否使用 virtual host 风格的 URL。默认为 *false*。 | +| master_key | 否 | 用于高级数据加密的可选主密钥。 | +| region | 否 | 存储桶所在的 AWS Region。 | +| security_token | 否 | 用于临时凭证的安全令牌。 | + +> **注意:** +> +> - 如果命令中未指定 **endpoint_url** 参数,{{{ .lake }}} 默认会在 Amazon S3 上创建 stage。因此,当你在兼容 S3 的对象存储或其他对象存储解决方案上创建外部 stage 时,请务必包含 **endpoint_url** 参数。 +> +> - **region** 参数不是必需的,因为 {{{ .lake }}} 可以自动检测 Region 信息。通常你不需要手动为该参数指定值。如果自动检测失败,{{{ .lake }}} 将默认使用 `'us-east-1'` 作为 region。使用 MinIO 部署 {{{ .lake }}} 且未配置 Region 信息时,也会自动默认使用 `'us-east-1'`,并且可以正常工作。但是,如果你收到诸如 `"region is missing"` 或 `"The bucket you are trying to access requires a specific endpoint. Please direct all future requests to this particular endpoint"` 之类的错误信息,则需要确认你的 region 名称,并显式将其赋值给 **region** 参数。 + +```sql title='Examples' +-- Create a reusable connection for Amazon S3 +CREATE CONNECTION my_s3_conn + STORAGE_TYPE = 's3' + ACCESS_KEY_ID = '' + SECRET_ACCESS_KEY = ''; + +-- Use the connection when creating a stage +CREATE STAGE my_s3_stage + URL = 's3://my-bucket' + CONNECTION = (CONNECTION_NAME = 'my_s3_conn'); + +-- Create a reusable connection for an S3-compatible service such as MinIO +CREATE CONNECTION my_minio_conn + STORAGE_TYPE = 's3' + ENDPOINT_URL = 'http://localhost:9000' + ACCESS_KEY_ID = 'ROOTUSER' + SECRET_ACCESS_KEY = 'CHANGEME123'; + +CREATE STAGE my_minio_stage + URL = 's3://lake' + CONNECTION = (CONNECTION_NAME = 'my_minio_conn'); +``` + +要访问你的 Amazon S3 存储桶,也可以指定 AWS IAM role 和 external ID 进行身份验证。通过指定 AWS IAM role 和 external ID,你可以更细粒度地控制用户可以访问哪些 S3 存储桶。这意味着,如果某个 IAM role 仅被授予访问特定 S3 存储桶的权限,那么用户也只能访问这些存储桶。external ID 还可以通过提供额外的一层验证来进一步增强安全性。更多信息,请参见 + +下表列出了使用 AWS IAM role 身份验证访问 Amazon S3 存储服务的连接参数: + +| 参数 | 必填? | 描述 | +|-------------- |------- |----------------------------------------------------- | +| endpoint_url | 否 | Amazon S3 的 endpoint URL。 | +| role_arn | 是 | 用于授权访问 S3 的 AWS IAM role 的 ARN。 | +| external_id | 否 | 在承担角色时用于增强安全性的 external ID。 | + +```sql title='Examples' +-- Create the connection using IAM role authentication +CREATE CONNECTION my_iam_conn + STORAGE_TYPE = 's3' + ROLE_ARN = 'arn:aws:iam::123456789012:role/my-role' + EXTERNAL_ID = 'my-external-id'; + +-- Reference the connection when creating a stage +CREATE STAGE my_iam_stage + URL = 's3://my-bucket' + CONNECTION = (CONNECTION_NAME = 'my_iam_conn'); +``` + +
+ +
+ +下表列出了访问 Azure Blob Storage 的连接参数: + +| 参数 | 必填? | 描述 | +|----------------|--------|-------------------------------------------------------| +| endpoint_url | 是 | Azure Blob Storage 的 endpoint URL。 | +| account_key | 是 | 用于身份验证的 Azure Blob Storage account key。 | +| account_name | 是 | 用于标识的 Azure Blob Storage account name。 | + +```sql title='Examples' +-- Create a connection for Azure Blob Storage +CREATE CONNECTION my_azure_conn + STORAGE_TYPE = 'azblob' + ACCOUNT_NAME = 'myaccount' + ACCOUNT_KEY = 'myaccountkey' + ENDPOINT_URL = 'https://.blob.core.windows.net'; + +-- Create a stage that uses the connection +CREATE STAGE my_azure_stage + URL = 'azblob://my-container' + CONNECTION = (CONNECTION_NAME = 'my_azure_conn'); +``` + +
+ +
+ +下表列出了访问 Google Cloud Storage 的连接参数: + +| 参数 | 必填? | 描述 | +|----------------|--------|-------------------------------------------------------| +| credential | 是 | 用于身份验证的 Google Cloud Storage credential。 | + +要获取 `credential`,你可以参考 Google 文档中的主题 [Create a service account key](https://cloud.google.com/iam/docs/keys-create-delete#creating) 来创建并下载服务账户密钥文件。下载服务账户密钥文件后,可以通过以下命令将其转换为 base64 字符串: + +``` +base64 -i -o ~/Desktop/base64-encoded-key.txt +``` + +```sql title='Examples' +-- Create the connection with the base64-encoded credential +CREATE CONNECTION my_gcs_conn + STORAGE_TYPE = 'gcs' + CREDENTIAL = ''; + +-- Use the connection when creating a stage +CREATE STAGE my_gcs_stage + URL = 'gcs://my-bucket' + CONNECTION = (CONNECTION_NAME = 'my_gcs_conn'); +``` + +
+ +
+ +下表列出了访问 Alibaba Cloud OSS 的连接参数: + +| 参数 | 必填? | 描述 | +|---------------------- |------- |--------------------------------------------------------- | +| access_key_id | 是 | 用于身份验证的 Alibaba Cloud OSS access key ID。 | +| access_key_secret | 是 | 用于身份验证的 Alibaba Cloud OSS access key secret。 | +| endpoint_url | 是 | Alibaba Cloud OSS 的 endpoint URL。 | +| presign_endpoint_url | 否 | 用于为 Alibaba Cloud OSS URL 预签名的 endpoint URL。 | + +```sql title='Examples' +-- Create a connection for Alibaba Cloud OSS +CREATE CONNECTION my_oss_conn + STORAGE_TYPE = 'oss' + ACCESS_KEY_ID = '' + ACCESS_KEY_SECRET = '' + ENDPOINT_URL = 'https://.[-internal].aliyuncs.com'; + +-- Create a stage using the connection +CREATE STAGE my_oss_stage + URL = 'oss://my-bucket' + CONNECTION = (CONNECTION_NAME = 'my_oss_conn'); +``` + +
+ +
+ +下表列出了访问 Tencent Cloud Object Storage (COS) 的连接参数: + +| 参数 | 必填? | 描述 | +|-------------- |------- |----------------------------------------------------------- | +| endpoint_url | 是 | Tencent Cloud Object Storage 的 endpoint URL。 | +| secret_id | 是 | 用于身份验证的 Tencent Cloud Object Storage secret ID。 | +| secret_key | 是 | 用于身份验证的 Tencent Cloud Object Storage secret key。 | + +```sql title='Examples' +-- Create a connection for Tencent COS +CREATE CONNECTION my_cos_conn + STORAGE_TYPE = 'cos' + SECRET_ID = '' + SECRET_KEY = '' + ENDPOINT_URL = ''; + +-- Create a stage that uses the connection +CREATE STAGE my_cos_stage + URL = 'cos://my-bucket' + CONNECTION = (CONNECTION_NAME = 'my_cos_conn'); +``` + +
+ +
+ +下表列出了访问 Hugging Face 的连接参数: + +| 参数 | 必填? | 描述 | +|-----------|-----------------------|------------------------------------------------------------------------------------------------| +| repo_type | 否(默认值:dataset) | Hugging Face 仓库的类型。可以是 `dataset` 或 `model`。 | +| revision | 否(默认值:main) | Hugging Face URI 的 revision。可以是仓库的分支、tag 或 commit。 | +| token | 否 | Hugging Face 的 API token,在访问私有仓库或某些资源时可能需要提供。 | + +```sql title='Examples' +-- Create a connection for Hugging Face +CREATE CONNECTION my_hf_conn + STORAGE_TYPE = 'hf' + REPO_TYPE = 'dataset' + REVISION = 'main'; + +-- Create a stage that uses the connection +CREATE STAGE my_huggingface_stage + URL = 'hf://opendal/huggingface-testdata/' + CONNECTION = (CONNECTION_NAME = 'my_hf_conn'); +``` + +
+
\ No newline at end of file diff --git a/tidb-cloud-lake/sql/connection.md b/tidb-cloud-lake/sql/connection.md new file mode 100644 index 0000000000000..c290f0ec29bdf --- /dev/null +++ b/tidb-cloud-lake/sql/connection.md @@ -0,0 +1,94 @@ +--- +title: Connection +summary: {{{ .lake }}} 中的 connection 是一种指定配置,用于封装与外部存储服务交互所需的详细信息。它作为一组集中且可复用的参数集合,例如访问凭证、端点 URL 和存储类型,从而便于 {{{ .lake }}} 与各种存储服务集成。 +--- + +# Connection + +## 什么是 Connection? {#what-is-connection} + +{{{ .lake }}} 中的 connection 是一种指定配置,用于封装与外部存储服务交互所需的详细信息。它作为一组集中且可复用的参数集合,例如访问凭证、端点 URL 和存储类型,从而便于 {{{ .lake }}} 与各种存储服务集成。 + +Connection 可用于创建 external stage、external table 以及 attach table,为通过 {{{ .lake }}} 管理和访问存储在外部存储服务中的数据提供了一种更简洁、模块化的方法。 + +## Connection 管理 {#connection-management} + +| Command | Description | +|---------|-------------| +| [CREATE CONNECTION](/tidb-cloud-lake/sql/create-connection.md) | 创建到外部存储服务的新连接 | +| [DROP CONNECTION](/tidb-cloud-lake/sql/drop-connection.md) | 删除现有的连接 | + +## Connection 信息 {#connection-information} + +| Command | Description | +|---------|-------------| +| [DESCRIBE CONNECTION](/tidb-cloud-lake/sql/desc-connection.md) | 显示指定连接的详细信息 | +| [SHOW CONNECTIONS](/tidb-cloud-lake/sql/show-connections.md) | 列出当前数据库中的所有连接 | + +### 使用示例 {#usage-examples} + +本节中的示例首先创建一个包含连接 Amazon S3 所需凭证的 connection。随后,这些示例使用已建立的 connection 来创建 external stage 并 attach 一个现有表。 + +以下语句会发起到 Amazon S3 的连接,并指定必要的连接参数: + +```sql +CREATE CONNECTION toronto + STORAGE_TYPE = 's3' + ACCESS_KEY_ID = '' + SECRET_ACCESS_KEY = ''; + +``` + +#### 示例 1:使用 Connection 创建 External Stage {#example-1-creating-external-stage-with-connection} + +以下示例使用前面定义的名为 `toronto` 的 connection 创建一个 external stage: + +```sql +CREATE STAGE my_s3_stage + URL = 's3://lake-toronto' + CONNECTION = (CONNECTION_NAME = 'toronto'); + +-- Equivalent to the following statement without using a connection: + +CREATE STAGE my_s3_stage + URL = 's3://lake-toronto' + CONNECTION = ( + ACCESS_KEY_ID = '', + SECRET_ACCESS_KEY = '' + ); + +``` + +#### 示例 2:使用 Connection Attach Table {#example-2-attaching-table-with-connection} + +[ATTACH TABLE](/tidb-cloud-lake/sql/attach-table.md) 页面提供了[示例](/tidb-cloud-lake/sql/attach-table.md#examples),演示如何将 {{{ .lake }}} 中的新表与 {{{ .lake }}} 中的现有表连接,其中数据存储在名为 "lake-toronto" 的 Amazon S3 存储桶中。在每个示例中,步骤 3 都可以通过使用前面定义的名为 `toronto` 的 connection 进行简化: + +```sql title='In {{{ .lake }}}:' +ATTACH TABLE employees_backup + 's3://lake-toronto/1/216/' + CONNECTION = (CONNECTION_NAME = 'toronto'); + +``` + +```sql title='In {{{ .lake }}}:' +ATTACH TABLE population_readonly + 's3://lake-toronto/1/556/' + CONNECTION = (CONNECTION_NAME = 'toronto') + READ_ONLY; + +``` + +#### 示例 3:使用 Connection 创建 External Table {#example-3-creating-external-table-with-connection} + +本示例演示如何使用前面定义的名为 `toronto` 的 connection 创建名为 `BOOKS` 的 external table: + +```sql +CREATE TABLE BOOKS ( + id BIGINT UNSIGNED, + title VARCHAR, + genre VARCHAR DEFAULT 'General' +) +'s3://lake-toronto' +CONNECTION = (CONNECTION_NAME = 'toronto'); + +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/contains.md b/tidb-cloud-lake/sql/contains.md new file mode 100644 index 0000000000000..e8f73377e25d2 --- /dev/null +++ b/tidb-cloud-lake/sql/contains.md @@ -0,0 +1,30 @@ +--- +title: CONTAINS +summary: 检查数组是否包含特定元素。 +--- + +# CONTAINS + +检查数组是否包含特定元素。 + +## 语法 {#syntax} + +```sql +CONTAINS( , ) +``` + +## 别名 {#aliases} + +- [ARRAY_CONTAINS](/tidb-cloud-lake/sql/array-contains.md) + +## 示例 {#examples} + +```sql +SELECT ARRAY_CONTAINS([1, 2], 1), CONTAINS([1, 2], 1); + +┌─────────────────────────────────────────────────┐ +│ array_contains([1, 2], 1) │ contains([1, 2], 1) │ +├───────────────────────────┼─────────────────────┤ +│ true │ true │ +└─────────────────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/context-functions.md b/tidb-cloud-lake/sql/context-functions.md new file mode 100644 index 0000000000000..043824695a797 --- /dev/null +++ b/tidb-cloud-lake/sql/context-functions.md @@ -0,0 +1,29 @@ +--- +title: 上下文函数 +summary: 本页提供 {{{ .lake }}} 中与上下文相关的函数参考信息。这些函数返回当前会话、数据库或系统上下文的信息。 +--- + +# 上下文函数 + +本页提供 {{{ .lake }}} 中与上下文相关的函数参考信息。这些函数返回当前会话、数据库或系统上下文的信息。 + +## 会话信息函数 {#session-information-functions} + +| 函数 | 描述 | 示例 | +|----------|-------------|--------| +| [CONNECTION_ID](/tidb-cloud-lake/sql/connection-id.md) | 返回当前连接的连接 ID | `CONNECTION_ID()` → `42` | +| [CURRENT_USER](/tidb-cloud-lake/sql/current-user.md) | 返回当前连接的用户名和主机 | `CURRENT_USER()` → `'root'@'%'` | +| [LAST_QUERY_ID](/tidb-cloud-lake/sql/last-query-id.md) | 返回上一次执行的查询的查询 ID | `LAST_QUERY_ID()` → `'01890a5d-ac96-7cc6-8128-01d71ab8b93e'` | + +## 数据库上下文函数 {#database-context-functions} + +| 函数 | 描述 | 示例 | +|----------|-------------|--------| +| [CURRENT_CATALOG](/tidb-cloud-lake/sql/current-catalog.md) | 返回当前 catalog 的名称 | `CURRENT_CATALOG()` → `'default'` | +| [DATABASE](/tidb-cloud-lake/sql/database-function.md) | 返回当前数据库的名称 | `DATABASE()` → `'default'` | + +## 系统信息函数 {#system-information-functions} + +| 函数 | 描述 | 示例 | +|----------|-------------|--------| +| [VERSION](/tidb-cloud-lake/sql/version.md) | 返回 {{{ .lake }}} 的当前版本 | `VERSION()` → `'LakeQuery v1.2.252-nightly-193ed56304'` | \ No newline at end of file diff --git a/tidb-cloud-lake/sql/conversion-functions.md b/tidb-cloud-lake/sql/conversion-functions.md new file mode 100644 index 0000000000000..468aeb0a45b0e --- /dev/null +++ b/tidb-cloud-lake/sql/conversion-functions.md @@ -0,0 +1,82 @@ +--- +title: 转换函数 +summary: 本页按功能分类,全面概述了 {{{ .lake }}} 中的转换函数,便于参考。 +--- + +# 转换函数 + +本页按功能分类,全面概述了 {{{ .lake }}} 中的转换函数,便于参考。 + +## 类型转换函数 {#type-conversion-functions} + +| Function | 描述 | 示例 | +|----------|-------------|---------| +| [CAST](/tidb-cloud-lake/sql/cast.md) | 将值转换为指定的数据类型 | `CAST('123' AS INT)` → `123` | +| [TRY_CAST](/tidb-cloud-lake/sql/try-cast.md) | 安全地将值转换为指定的数据类型,失败时返回 NULL | `TRY_CAST('abc' AS INT)` → `NULL` | +| [TO_BOOLEAN](/tidb-cloud-lake/sql/to-boolean.md) | 将值转换为 BOOLEAN 类型 | `TO_BOOLEAN('true')` → `true` | +| [TO_STRING](/tidb-cloud-lake/sql/to-string.md) | 将值转换为 STRING 类型 | `TO_STRING(123)` → `'123'` | +| [TO_VARCHAR](/tidb-cloud-lake/sql/to-varchar.md) | 将值转换为 VARCHAR 类型 | `TO_VARCHAR(123)` → `'123'` | +| [TO_TEXT](/tidb-cloud-lake/sql/to-text.md) | 将值转换为 TEXT 类型 | `TO_TEXT(123)` → `'123'` | + +## 数值转换函数 {#numeric-conversion-functions} + +| Function | 描述 | 示例 | +|----------|-------------|---------| +| [TO_INT8](/tidb-cloud-lake/sql/to-int8.md) | 将值转换为 INT8 类型 | `TO_INT8('123')` → `123` | +| [TO_INT16](/tidb-cloud-lake/sql/to-int16.md) | 将值转换为 INT16 类型 | `TO_INT16('123')` → `123` | +| [TO_INT32](/tidb-cloud-lake/sql/to-int32.md) | 将值转换为 INT32 类型 | `TO_INT32('123')` → `123` | +| [TO_INT64](/tidb-cloud-lake/sql/to-int64.md) | 将值转换为 INT64 类型 | `TO_INT64('123')` → `123` | +| [TO_UINT8](/tidb-cloud-lake/sql/to-uint8.md) | 将值转换为 UINT8 类型 | `TO_UINT8('123')` → `123` | +| [TO_UINT16](/tidb-cloud-lake/sql/to-uint16.md) | 将值转换为 UINT16 类型 | `TO_UINT16('123')` → `123` | +| [TO_UINT32](/tidb-cloud-lake/sql/to-uint32.md) | 将值转换为 UINT32 类型 | `TO_UINT32('123')` → `123` | +| [TO_UINT64](/tidb-cloud-lake/sql/to-uint64.md) | 将值转换为 UINT64 类型 | `TO_UINT64('123')` → `123` | +| [TO_FLOAT32](/tidb-cloud-lake/sql/to-float32.md) | 将值转换为 FLOAT32 类型 | `TO_FLOAT32('123.45')` → `123.45` | +| [TO_FLOAT64](/tidb-cloud-lake/sql/to-float64.md) | 将值转换为 FLOAT64 类型 | `TO_FLOAT64('123.45')` → `123.45` | + +## 二进制和专用转换函数 {#binary-and-specialized-conversion-functions} + +| Function | 描述 | 示例 | +|----------|-------------|---------| +| [TO_BINARY](/tidb-cloud-lake/sql/to-binary.md) | 将值转换为 BINARY 类型 | `TO_BINARY('abc')` → `binary value` | +| [TRY_TO_BINARY](/tidb-cloud-lake/sql/try-to-binary.md) | 安全地将值转换为 BINARY 类型,失败时返回 NULL | `TRY_TO_BINARY('abc')` → `binary value` | +| [TO_HEX](/tidb-cloud-lake/sql/to-hex.md) | 将值转换为十六进制字符串 | `TO_HEX(255)` → `'FF'` | +| [TO_VARIANT](/tidb-cloud-lake/sql/to-variant.md) | 将值转换为 VARIANT 类型 | `TO_VARIANT('{"a": 1}')` → `{"a": 1}` | +| [BUILD_BITMAP](/tidb-cloud-lake/sql/build-bitmap.md) | 从整数数组构建位图 | `BUILD_BITMAP([1,2,3])` → `bitmap value` | +| [TO_BITMAP](/tidb-cloud-lake/sql/to-bitmap.md) | 将值转换为 BITMAP 类型 | `TO_BITMAP([1,2,3])` → `bitmap value` | + +将值从一种类型转换为另一种类型时,请注意以下事项: + +- 当从浮点数、小数或字符串转换为整数,或转换为带小数部分的小数时,{{{ .lake }}} 会将值四舍五入到最接近的整数。这由设置 `numeric_cast_option` 决定(默认值为 `'rounding'`),该设置控制数值类型转换操作的行为。当 `numeric_cast_option` 显式设置为 `'truncating'` 时,{{{ .lake }}} 会截断小数部分,丢弃所有小数值。 + + ```sql title='Example:' + SELECT CAST('0.6' AS DECIMAL(10, 0)), CAST(0.6 AS DECIMAL(10, 0)), CAST(1.5 AS INT); + + ┌──────────────────────────────────────────────────────────────────────────────────┐ + │ cast('0.6' as decimal(10, 0)) │ cast(0.6 as decimal(10, 0)) │ cast(1.5 as int32) │ + ├───────────────────────────────┼─────────────────────────────┼────────────────────┤ + │ 1 │ 1 │ 2 │ + └──────────────────────────────────────────────────────────────────────────────────┘ + + SET numeric_cast_option = 'truncating'; + + SELECT CAST('0.6' AS DECIMAL(10, 0)), CAST(0.6 AS DECIMAL(10, 0)), CAST(1.5 AS INT); + + ┌──────────────────────────────────────────────────────────────────────────────────┐ + │ cast('0.6' as decimal(10, 0)) │ cast(0.6 as decimal(10, 0)) │ cast(1.5 as int32) │ + ├───────────────────────────────┼─────────────────────────────┼────────────────────┤ + │ 0 │ 0 │ 1 │ + └──────────────────────────────────────────────────────────────────────────────────┘ + ``` + + 下表汇总了数值类型转换操作,展示了不同源数值数据类型与目标数值数据类型之间的转换可能性。请注意,其中还说明了从 String 转换为 Integer 的要求,即源字符串必须包含一个整数值。 + + | 源类型 | 目标类型 | + |----------------|-------------| + | 字符串 | Decimal | + | float | Decimal | + | Decimal | Decimal | + | float | Int | + | Decimal | Int | + | 字符串 (整数型) | Int | + +- {{{ .lake }}} 还提供了多种函数,用于将表达式转换为不同的日期和时间格式。更多信息,请参见 [日期与时间函数](/tidb-cloud-lake/sql/date-time-functions.md)。 \ No newline at end of file diff --git a/tidb-cloud-lake/sql/convert-timezone.md b/tidb-cloud-lake/sql/convert-timezone.md new file mode 100644 index 0000000000000..a01e6d576b63a --- /dev/null +++ b/tidb-cloud-lake/sql/convert-timezone.md @@ -0,0 +1,93 @@ +--- +title: CONVERT_TIMEZONE +summary: 将时间戳从一个时区转换到另一个时区,并且要求目标时区名称是有效的 IANA 时区名称。 +--- + +# CONVERT_TIMEZONE + +`CONVERT_TIMEZONE()` 将时间戳从当前会话时区(默认 `UTC`)转换为第一个参数中提供的时区。目标时区必须是有效的 [IANA timezone name](https://docs.rs/chrono-tz/latest/chrono_tz/enum.Tz.html)。 + +## 语法 {#syntax} + +```sql +CONVERT_TIMEZONE(, ) +``` + +| 参数 | 描述 | +|----------------------|-----------------------------------------------------------------------------| +| `` | 大小写敏感的时区名称,例如 `'America/Los_Angeles'` 或 `'UTC'`。 | +| `` | TIMESTAMP 表达式(或可转换为 TIMESTAMP 的值)。使用当前会话时区进行解释。 | + +## 返回类型 {#return-type} + +返回一个 TIMESTAMP 值,表示目标时区中的同一时刻。 + +## 行为 {#behavior} + +- 源时区始终等于当前会话时区(默认 `UTC`)。请将会话或连接配置为与你要转换的数据相匹配。 +- 无效的时区名称会引发错误。如果任一参数为 `NULL`,结果为 `NULL`。 +- 夏令时缺口可能会导致某些时间戳无效。开启 `enable_dst_hour_fix = 1`(会话或租户级别)后,{{{ .lake }}} 会自动调整此类值。 + +## 示例 {#examples} + +### 转换单个时间戳(默认 UTC 会话) {#convert-a-single-timestamp-default-utc-session} + +```sql +SELECT CONVERT_TIMEZONE('America/Los_Angeles', '2024-11-01 11:36:10'); +``` + +``` +┌──────────────────────────────────────────────────────┐ +│ convert_timezone('America/Los_Angeles', '2024-11-01… │ +├──────────────────────────────────────────────────────┤ +│ 2024-11-01 04:36:10.000000 │ +└──────────────────────────────────────────────────────┘ +``` + +### 使用每个用户的时区转换行数据 {#convert-rows-using-each-user-s-timezone} + +```sql +SELECT + user_tz, + event_time, + CONVERT_TIMEZONE(user_tz, event_time) AS local_time +FROM ( + VALUES + ('America/Los_Angeles', '2024-10-31 22:21:15'::TIMESTAMP), + ('Asia/Shanghai', '2024-10-31 22:21:15'::TIMESTAMP), + (NULL, '2024-10-31 22:21:15'::TIMESTAMP) +) AS v(user_tz, event_time) +ORDER BY user_tz NULLS LAST; +``` + +``` +┌──────────────────────┬──────────────────────────────┬──────────────────────────────┐ +│ user_tz │ event_time │ local_time │ +├──────────────────────┼──────────────────────────────┼──────────────────────────────┤ +│ America/Los_Angeles │ 2024-10-31 22:21:15.000000 │ 2024-10-31 15:21:15.000000 │ +│ Asia/Shanghai │ 2024-10-31 22:21:15.000000 │ 2024-11-01 06:21:15.000000 │ +│ NULL │ 2024-10-31 22:21:15.000000 │ NULL │ +└──────────────────────┴──────────────────────────────┴──────────────────────────────┘ +``` + +### 处理 DST 缺口中的时间戳 {#handle-timestamps-inside-dst-gaps} + +在此会话中,时区配置为 Asia/Shanghai,且 `enable_dst_hour_fix = 1`。时间戳 `1947-04-15 00:00:00` 在该时区中实际上从未存在,因为时钟曾向前跳变,因此 {{{ .lake }}} 会在返回 UTC 值之前先对其进行调整。 + +```sql +SELECT CONVERT_TIMEZONE('UTC', '1947-04-15 00:00:00'); +``` + +``` +┌──────────────────────────────────────────────┐ +│ convert_timezone('UTC', '1947-04-15 00:00:00')│ +├──────────────────────────────────────────────┤ +│ 1947-04-14 15:00:00.000000 │ +└──────────────────────────────────────────────┘ +``` + +## 另请参阅 {#see-also} + +- [TIMEZONE](/tidb-cloud-lake/sql/timezone.md) +- [TO_TIMESTAMP_TZ](/tidb-cloud-lake/sql/timestamp-tz.md) +- [TO_TIMESTAMP](/tidb-cloud-lake/sql/to-timestamp.md) \ No newline at end of file diff --git a/tidb-cloud-lake/sql/copy-into-location.md b/tidb-cloud-lake/sql/copy-into-location.md new file mode 100644 index 0000000000000..20b7a2466bd1e --- /dev/null +++ b/tidb-cloud-lake/sql/copy-into-location.md @@ -0,0 +1,385 @@ +--- +title: COPY INTO +summary: COPY INTO 允许你将表或查询中的数据卸载到以下某个位置中的一个或多个文件。 +--- + +# `COPY INTO ` + +COPY INTO 允许你将表或查询中的数据卸载到以下某个位置中的一个或多个文件: + +- 用户 / Internal / External stage:参阅 [Stage 是什么?](/tidb-cloud-lake/guides/stage-overview.md) 了解 {{{ .lake }}} 中的 stage。 +- 在存储服务中创建的存储桶或容器。 + +另请参阅:[`COPY INTO
`](/tidb-cloud-lake/sql/copy-into-table.md) + +## 语法 {#syntax} + +```sql +COPY INTO { internalStage | externalStage | externalLocation } +FROM { [.] | ( ) } +[ PARTITION BY ( ) ] +[ FILE_FORMAT = ( + FORMAT_NAME = '' + | TYPE = { CSV | TSV | NDJSON | PARQUET | LANCE } [ formatTypeOptions ] + ) ] +[ copyOptions ] +[ VALIDATION_MODE = RETURN_ROWS ] +[ DETAILED_OUTPUT = true | false ] +``` + +### internalStage {#internalstage} + +```sql +internalStage ::= @[/] +``` + +### externalStage {#externalstage} + +```sql +externalStage ::= @[/] +``` + +### externalLocation {#externallocation} + + + +
+ +```sql +externalLocation ::= + 's3://[]' + CONNECTION = ( + + ) +``` + +有关访问 Amazon S3-like 存储服务时可用的连接参数,请参阅 [连接参数](/tidb-cloud-lake/sql/connection-parameters.md)。 + +
+ +
+ +```sql +externalLocation ::= + 'azblob://[]' + CONNECTION = ( + + ) +``` + +有关访问 Azure Blob Storage 时可用的连接参数,请参阅 [连接参数](/tidb-cloud-lake/sql/connection-parameters.md)。 + +
+ +
+ +```sql +externalLocation ::= + 'gcs://[]' + CONNECTION = ( + + ) +``` + +有关访问 Google Cloud Storage 时可用的连接参数,请参阅 [连接参数](/tidb-cloud-lake/sql/connection-parameters.md)。 + +
+ +
+ +```sql +externalLocation ::= + 'oss://[]' + CONNECTION = ( + + ) +``` + +有关访问 Alibaba Cloud OSS 时可用的连接参数,请参阅 [连接参数](/tidb-cloud-lake/sql/connection-parameters.md)。 + +
+ +
+ +```sql +externalLocation ::= + 'cos://[]' + CONNECTION = ( + + ) +``` + +有关访问 Tencent Cloud Object Storage 时可用的连接参数,请参阅 [连接参数](/tidb-cloud-lake/sql/connection-parameters.md)。 + +
+
+ +### FILE_FORMAT {#file-format} + +详情请参阅 [输入与输出文件格式](/tidb-cloud-lake/sql/input-output-file-formats.md)。 + +`LANCE` 仅在 `COPY INTO ` 中受支持。{{{ .lake}}} 会在目标路径下写入一个 Lance 数据集目录,而不是单个独立文件。 + +### PARTITION BY {#partition-by} + +指定一个表达式,用于将卸载的数据分区到不同的文件夹中。该表达式必须计算为 `STRING` 类型。表达式生成的每个不同值都会在目标路径中创建一个子文件夹,相应的行会被写入该子文件夹下的文件中。 + +- 如果表达式计算结果为 `NULL`,这些行会被放入一个特殊的 `_NULL_` 文件夹中。 +- 该表达式可以引用源表或查询中的任意列。 +- 分区值中不允许使用路径遍历(`..`)。 + +以下选项与 `PARTITION BY` 不兼容,如果设置会导致报错: + +| 选项 | 限制 | +| ------------------- | ------------------------------------------------ | +| SINGLE | 使用 `PARTITION BY` 时不能为 `TRUE`。 | +| OVERWRITE | 使用 `PARTITION BY` 时不能为 `TRUE`。 | +| INCLUDE_QUERY_ID | 使用 `PARTITION BY` 时不能为 `FALSE`。 | + +### copyOptions {#copyoptions} + +```sql +copyOptions ::= + [ SINGLE = true | false ] + [ MAX_FILE_SIZE = ] + [ OVERWRITE = true | false ] + [ INCLUDE_QUERY_ID = true | false ] + [ USE_RAW_PATH = true | false ] +``` + +| 参数 | 默认值 | 描述 | +| ---------------- | ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| SINGLE | false | 当为 `true` 时,该命令会将数据卸载到单个文件中。 | +| MAX_FILE_SIZE | 67108864 bytes (64 MB) | 每个要创建文件的最大大小(以字节为单位)。当 `SINGLE` 为 false 时生效。 | +| OVERWRITE | false | 当为 `true` 时,目标路径下同名的现有文件将被覆盖。注意:`OVERWRITE = true` 要求 `USE_RAW_PATH = true` 且 `INCLUDE_QUERY_ID = false`。 | +| INCLUDE_QUERY_ID | true | 当为 `true` 时,导出文件名中会包含一个唯一的 UUID。 | +| USE_RAW_PATH | false | 当为 `true` 时,将使用用户提供的精确路径(包括完整文件名)来导出数据。如果设置为 `false`,用户必须提供一个目录路径。 | + +> **注意:** +> +> - 当 `TYPE = LANCE` 时,不支持 `SINGLE`。 +> - 当 `TYPE = LANCE` 时,不支持 `PARTITION BY`。 +> - 当 `TYPE = LANCE` 且你希望为下游 Lance 读取器提供稳定的数据集 URI 时,建议使用 `USE_RAW_PATH = TRUE`。 +> - 当 `TYPE = LANCE` 且 `USE_RAW_PATH = FALSE` 时,{{{ .lake}}} 会将查询 ID 追加到目标路径,并为每次导出创建一个单独的数据集根目录。 + +### DETAILED_OUTPUT {#detailed-output} + +决定是否返回数据卸载的详细结果,默认值为 `false`。更多信息,请参阅 [输出](#output)。 + +## 输出 {#output} + +COPY INTO 会通过以下列提供数据卸载结果的摘要: + +| 列 | 描述 | +| ------------- | --------------------------------------------------------------------------------------------- | +| rows_unloaded | 成功卸载到目标位置的行数。 | +| input_bytes | 卸载操作期间从源表读取的数据总大小(以字节为单位)。 | +| output_bytes | 写入目标位置的数据总大小(以字节为单位)。 | + +当 `DETAILED_OUTPUT` 设置为 `true` 时,COPY INTO 会返回包含以下列的结果。这有助于定位已卸载的文件,尤其是在使用 `MAX_FILE_SIZE` 将卸载数据拆分为多个文件时。 + +| 列 | 描述 | +| --------- | -------------------------------------------------- | +| file_name | 卸载文件的名称。 | +| file_size | 卸载文件的大小(以字节为单位)。 | +| row_count | 卸载文件中包含的行数。 | + +## 示例 {#examples} + +在本节中,以下示例使用了如下表和数据: + +```sql +-- Create sample table +CREATE TABLE canadian_city_population ( + city_name VARCHAR(50), + population INT +); + +-- Insert sample data +INSERT INTO canadian_city_population (city_name, population) +VALUES +('Toronto', 2731571), +('Montreal', 1704694), +('Vancouver', 631486), +('Calgary', 1237656), +('Ottawa', 934243), +('Edmonton', 972223), +('Quebec City', 542298), +('Winnipeg', 705244), +('Hamilton', 536917), +('Halifax', 403390); +``` + +### 示例 1:卸载到内部 stage {#example-1-unloading-to-internal-stage} + +本示例将数据卸载到内部 stage: + +```sql +-- Create an internal stage +CREATE STAGE my_internal_stage; + +-- Unload data from the table to the stage using the PARQUET file format +COPY INTO @my_internal_stage + FROM canadian_city_population + FILE_FORMAT = (TYPE = PARQUET); + +┌────────────────────────────────────────────┐ +│ rows_unloaded │ input_bytes │ output_bytes │ +├───────────────┼─────────────┼──────────────┤ +│ 10 │ 211 │ 572 │ +└────────────────────────────────────────────┘ + +LIST @my_internal_stage; + +┌────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ +│ name │ size │ md5 │ last_modified │ creator │ +├─────────────────────────────────────────────────────────────────┼────────┼──────────────────┼───────────────────────────────┼──────────────────┤ +│ data_abe520a3-ee88-488c-9221-b07c562c9a30_0000_00000000.parquet │ 572 │ NULL │ 2024-01-18 16:20:48.979 +0000 │ NULL │ +└────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ +``` + +### 示例 2:卸载到压缩文件 {#example-2-unloading-to-compressed-file} + +本示例将数据卸载到压缩文件中: + +```sql +-- Create an internal stage +CREATE STAGE my_internal_stage; + +-- Unload data from the table to the stage using the CSV file format with gzip compression +COPY INTO @my_internal_stage + FROM canadian_city_population + FILE_FORMAT = (TYPE = CSV COMPRESSION = gzip); + +┌────────────────────────────────────────────┐ +│ rows_unloaded │ input_bytes │ output_bytes │ +├───────────────┼─────────────┼──────────────┤ +│ 10 │ 182 │ 168 │ +└────────────────────────────────────────────┘ + +LIST @my_internal_stage; + +┌───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ +│ name │ size │ md5 │ last_modified │ creator │ +├────────────────────────────────────────────────────────────────┼────────┼──────────────────┼───────────────────────────────┼──────────────────┤ +│ data_7970afa5-32e3-4e7d-b793-e42a2a82a8e6_0000_00000000.csv.gz │ 168 │ NULL │ 2024-01-18 16:27:01.663 +0000 │ NULL │ +└───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ + +-- COPY INTO also works with custom file formats. See below: +-- Create a custom file format named my_csv_gzip with CSV format and gzip compression +CREATE FILE FORMAT my_csv_gzip TYPE = CSV COMPRESSION = gzip; + +-- Unload data from the table to the stage using the custom file format my_csv_gzip +COPY INTO @my_internal_stage + FROM canadian_city_population + FILE_FORMAT = (FORMAT_NAME = 'my_csv_gzip'); + +┌────────────────────────────────────────────┐ +│ rows_unloaded │ input_bytes │ output_bytes │ +├───────────────┼─────────────┼──────────────┤ +│ 10 │ 182 │ 168 │ +└────────────────────────────────────────────┘ + +LIST @my_internal_stage; + +┌───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ +│ name │ size │ md5 │ last_modified │ creator │ +├────────────────────────────────────────────────────────────────┼────────┼──────────────────┼───────────────────────────────┼──────────────────┤ +│ data_d006ba1c-0609-46d7-a67b-75c7078d86ff_0000_00000000.csv.gz │ 168 │ NULL │ 2024-01-18 16:29:29.721 +0000 │ NULL │ +│ data_7970afa5-32e3-4e7d-b793-e42a2a82a8e6_0000_00000000.csv.gz │ 168 │ NULL │ 2024-01-18 16:27:01.663 +0000 │ NULL │ +└───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ +``` + +### 示例 3:卸载到存储桶 {#example-3-unloading-to-bucket} + +本示例将数据卸载到 MinIO 上的存储桶中: + +```sql +-- Unload data from the table to a bucket named 'lake' on MinIO using the PARQUET file format +COPY INTO 's3://lake' + CONNECTION = ( + ENDPOINT_URL = 'http://localhost:9000/', + ACCESS_KEY_ID = 'ROOTUSER', + SECRET_ACCESS_KEY = 'CHANGEME123', + region = 'us-west-2' + ) + FROM canadian_city_population + FILE_FORMAT = (TYPE = PARQUET); + +┌────────────────────────────────────────────┐ +│ rows_unloaded │ input_bytes │ output_bytes │ +├───────────────┼─────────────┼──────────────┤ +│ 10 │ 211 │ 572 │ +└────────────────────────────────────────────┘ +``` + +### 示例 4:使用 PARTITION BY 卸载 {#example-4-unloading-with-partition-by} + +本示例根据派生表达式将数据卸载到分区目录中: + +```sql +-- Create a sample table +CREATE TABLE sales_data ( + sale_date DATE, + region VARCHAR, + amount INT +); + +INSERT INTO sales_data VALUES + ('2025-01-15', 'east', 100), + ('2025-01-20', 'west', 200), + ('2025-02-10', 'east', 150), + (NULL, 'west', 50); + +-- Create an internal stage +CREATE STAGE partitioned_stage; + +-- Unload data partitioned by year-month derived from sale_date +-- When sale_date is NULL, to_varchar() returns NULL, so the entire +-- concatenation evaluates to NULL and the row lands in the _NULL_ folder. +COPY INTO @partitioned_stage + FROM sales_data + PARTITION BY ('month=' || to_varchar(sale_date, 'YYYY-MM')) + FILE_FORMAT = (TYPE = PARQUET); + +-- Verify the partitioned folder layout +SELECT name FROM list_stage(location => '@partitioned_stage') ORDER BY name; + +┌──────────────────────────────────────────────────────────────────┐ +│ name │ +├──────────────────────────────────────────────────────────────────┤ +│ _NULL_/data__0000_00000000.parquet │ +│ month=2025-01/data__0000_00000000.parquet │ +│ month=2025-02/data__0000_00000000.parquet │ +└──────────────────────────────────────────────────────────────────┘ +``` + +当分区表达式计算结果为 `NULL` 时,数据会被放入 `_NULL_` 目录中。每个唯一的分区值都会创建各自的子目录,其中包含对应的数据文件。 + +### 示例 5:卸载到 Lance 数据集 {#example-5-unloading-to-a-lance-dataset} + +本示例将数据卸载为 Lance 数据集目录,而不是独立文件: + +```sql +CREATE STAGE ml_stage; + +COPY INTO @ml_stage/datasets/train +FROM ( + SELECT number, number + 1 AS label + FROM numbers(10) +) +FILE_FORMAT = (TYPE = LANCE) +USE_RAW_PATH = TRUE +OVERWRITE = TRUE +DETAILED_OUTPUT = TRUE; +``` + +输出路径将包含 Lance 数据集布局,类似如下: + +```text +datasets/train/_versions/... +datasets/train/data/... .lance +datasets/train/*.manifest +``` + +有关完整的端到端示例(包括使用 Python `lance` 进行验证),请参见[卸载 Lance 数据集](/tidb-cloud-lake/guides/unload-lance-dataset.md)。 \ No newline at end of file diff --git a/tidb-cloud-lake/sql/copy-into-table.md b/tidb-cloud-lake/sql/copy-into-table.md new file mode 100644 index 0000000000000..9894a9781c041 --- /dev/null +++ b/tidb-cloud-lake/sql/copy-into-table.md @@ -0,0 +1,788 @@ +--- +title: "COPY INTO
" +summary: COPY INTO 允许你从位于以下位置之一的文件中加载数据。 +--- + +# `COPY INTO
` + +COPY INTO 允许你从位于以下位置之一的文件中加载数据: + +- 用户 / Internal / External stage:参见 [Stage 是什么?](/tidb-cloud-lake/guides/stage-overview.md),了解 {{{ .lake }}} 中的 stage。 +- 在存储服务中创建的存储桶或容器。 +- 可通过其 URL(以 `https://` 开头)访问文件的远程服务器。 +- [IPFS](https://ipfs.tech) 和 Hugging Face 仓库。 + +另请参阅:[`COPY INTO `](/tidb-cloud-lake/sql/copy-into-location.md) + +## 语法 {#syntax} + +```sql +/* Standard data load */ +COPY INTO [.] [ ( [ , ... ] ) ] + FROM { userStage | internalStage | externalStage | externalLocation } +[ FILES = ( '' [ , '' ] [ , ... ] ) ] +[ PATTERN = '' ] +[ FILE_FORMAT = ( + FORMAT_NAME = '' + | TYPE = { CSV | TSV | NDJSON | PARQUET | ORC | AVRO } [ formatTypeOptions ] + ) ] +[ copyOptions ] + +/* Data load with transformation */ +COPY INTO [.] [ ( [ , ... ] ) ] + FROM ( + SELECT { + [.] [, [.] ...] -- Query columns by name + | [.]$ [, [.]$ ...] -- Query columns by position + | [.]$1[:] [, [.]$1[:] ...] -- Query rows as Variants + } ] + FROM {@[/] | ''} + ) +[ FILES = ( '' [ , '' ] [ , ... ] ) ] +[ PATTERN = '' ] +[ FILE_FORMAT = ( + FORMAT_NAME = '' + | TYPE = { CSV | TSV | NDJSON | PARQUET | ORC | AVRO } [ formatTypeOptions ] + ) ] +[ copyOptions ] +``` + +> **注意:** +> +> 从 {{{ .lake }}} `v1.2.890-nightly` 开始,`TEXT` 可以在 `FILE_FORMAT` 中用作 `TSV` 的别名。较旧的服务器可能会拒绝 `TYPE = TEXT`,因此为了兼容性,本页在语法和示例中仍使用 `TSV`。 + +其中: + +```sql +userStage ::= @~[/] + +internalStage ::= @[/] + +externalStage ::= @[/] + +externalLocation ::= + /* Amazon S3-like Storage */ + 's3://[/]' + CONNECTION = ( + [ CONNECTION_NAME = '' ] + | [ ENDPOINT_URL = '' ] + [ ACCESS_KEY_ID = '' ] + [ SECRET_ACCESS_KEY = '' ] + [ ENABLE_VIRTUAL_HOST_STYLE = TRUE | FALSE ] + [ MASTER_KEY = '' ] + [ REGION = '' ] + [ SECURITY_TOKEN = '' ] + [ ROLE_ARN = '' ] + [ EXTERNAL_ID = '' ] + ) + + /* Azure Blob Storage */ + | 'azblob://[/]' + CONNECTION = ( + [ CONNECTION_NAME = '' ] + | ENDPOINT_URL = '' + ACCOUNT_NAME = '' + ACCOUNT_KEY = '' + ) + + /* Google Cloud Storage */ + | 'gcs://[/]' + CONNECTION = ( + [ CONNECTION_NAME = '' ] + | CREDENTIAL = '' + ) + + /* Alibaba Cloud OSS */ + | 'oss://[/]' + CONNECTION = ( + [ CONNECTION_NAME = '' ] + | ACCESS_KEY_ID = '' + ACCESS_KEY_SECRET = '' + ENDPOINT_URL = '' + [ PRESIGN_ENDPOINT_URL = '' ] + ) + + /* Tencent Cloud Object Storage */ + | 'cos://[/]' + CONNECTION = ( + [ CONNECTION_NAME = '' ] + | SECRET_ID = '' + SECRET_KEY = '' + ENDPOINT_URL = '' + ) + + /* Remote Files */ + | 'https://' + + /* IPFS */ + | 'ipfs://' + CONNECTION = (ENDPOINT_URL = 'https://') + + /* Hugging Face */ + | 'hf://[/]' + CONNECTION = ( + [ REPO_TYPE = 'dataset' | 'model' ] + [ REVISION = '' ] + [ TOKEN = '' ] + ) + +formatTypeOptions ::= + /* Common options for all formats */ + [ COMPRESSION = AUTO | GZIP | BZ2 | BROTLI | ZSTD | DEFLATE | RAW_DEFLATE | XZ | NONE ] + + /* CSV specific options */ + [ RECORD_DELIMITER = '' ] + [ FIELD_DELIMITER = '' ] + [ SKIP_HEADER = ] + [ QUOTE = '' ] + [ ESCAPE = '' ] + [ NAN_DISPLAY = '' ] + [ NULL_DISPLAY = '' ] + [ ERROR_ON_COLUMN_COUNT_MISMATCH = TRUE | FALSE ] + [ EMPTY_FIELD_AS = null | string | field_default ] + [ BINARY_FORMAT = HEX | BASE64 ] + [ TRIM_SPACE = TRUE | FALSE ] + [ ENCODING = '' ] + [ ENCODING_ERROR_MODE = STRICT | REPLACE ] + + /* TSV specific options */ + [ RECORD_DELIMITER = '' ] + [ FIELD_DELIMITER = '' ] + [ TRIM_SPACE = TRUE | FALSE ] + [ ENCODING = '' ] + [ ENCODING_ERROR_MODE = STRICT | REPLACE ] + + /* NDJSON specific options */ + [ NULL_FIELD_AS = NULL | FIELD_DEFAULT ] + [ MISSING_FIELD_AS = ERROR | NULL | FIELD_DEFAULT ] + [ NULL_IF = ('value1', 'value2', ...) ] + + /* PARQUET specific options */ + [ MISSING_FIELD_AS = ERROR | FIELD_DEFAULT ] + [ NULL_IF = ('value1', 'value2', ...) ] + [ USE_LOGIC_TYPE = TRUE | FALSE ] + + /* ORC specific options */ + [ MISSING_FIELD_AS = ERROR | FIELD_DEFAULT ] + + /* AVRO specific options */ + [ MISSING_FIELD_AS = ERROR | FIELD_DEFAULT ] + [ NULL_IF = ('value1', 'value2', ...) ] + [ USE_LOGIC_TYPE = TRUE | FALSE ] + +copyOptions ::= + [ PURGE = ] + [ FORCE = ] + [ DISABLE_VARIANT_CHECK = ] + [ ON_ERROR = { continue | abort | abort_N } ] + [ MAX_FILES = ] + [ RETURN_FAILED_ONLY = ] + [ COLUMN_MATCH_MODE = { case-sensitive | case-insensitive } ] + [ SCHEMA_EVOLUTION = ( + [ SAMPLE_FILES = AUTO | ] + [ , SAMPLE_RECORDS_PER_FILE = AUTO | ] + [ , SAMPLE_TOTAL_RECORDS = AUTO | ] + ) ] +``` + +## 关键参数 {#key-parameters} + +- **FILES**:指定要加载的一个或多个文件名(用逗号分隔)。 + +- **PATTERN**:基于 [PCRE2](https://www.pcre.org/current/doc/html/) 的正则表达式模式字符串,用于指定要匹配的文件名。从 stage 加载时,该模式匹配文件路径中 `@[/]` 之后的部分。参见 [使用 PATTERN 过滤 stage 中的文件](/tidb-cloud-lake/guides/stage-overview.md#filtering-staged-files-with-pattern) 和 [示例 4:使用 Pattern 过滤文件](#example-4-filtering-files-with-pattern)。 + +## 格式类型选项 {#format-type-options} + +`FILE_FORMAT` 参数支持不同的文件类型,每种类型都有特定的格式选项。以下列出了每种受支持文件格式可用的选项。有关所有选项的完整详情,请参见[输入与输出文件格式](/tidb-cloud-lake/sql/input-output-file-formats.md)。 + + + +
+ +这些选项适用于所有文件格式: + +| 选项 | 描述 | 值 | 默认值 | +|--------|-------------|--------|--------| +| COMPRESSION | 数据文件的压缩算法 | AUTO, GZIP, BZ2, BROTLI, ZSTD, DEFLATE, RAW_DEFLATE, XZ, NONE | AUTO | + +
+ +
+ +| 选项 | 描述 | 默认值 | +|--------|-------------|--------| +| RECORD_DELIMITER | 分隔记录的字符 | newline | +| FIELD_DELIMITER | 分隔字段的字符 | comma (,) | +| SKIP_HEADER | 要跳过的表头行数 | 0 | +| QUOTE | 用于包围字段的字符 | double-quote (") | +| ESCAPE | 用于包围字段的转义字符 | NONE | +| NAN_DISPLAY | 表示 NaN 值的字符串 | NaN | +| NULL_DISPLAY | 表示 NULL 值的字符串 | \N | +| ERROR_ON_COLUMN_COUNT_MISMATCH | 当列数不匹配时是否报错 | TRUE | +| EMPTY_FIELD_AS | 如何处理空字段 | null | +| BINARY_FORMAT | 二进制数据的编码格式(HEX 或 BASE64) | HEX | +| TRIM_SPACE | 去除字段前后的 ASCII 空白字符 | FALSE | +| ENCODING | 源文件的字符集编码 | UTF-8 | +| ENCODING_ERROR_MODE | 如何处理无效字节:STRICT 或 REPLACE | STRICT | + +
+ +
+ +| 选项 | 描述 | 默认值 | +|--------|-------------|--------| +| RECORD_DELIMITER | 分隔记录的字符 | newline | +| FIELD_DELIMITER | 分隔字段的字符 | tab (\t) | +| SKIP_HEADER | 要跳过的表头行数 | 0 | +| TRIM_SPACE | 去除字段前后的 ASCII 空白字符 | FALSE | +| NAN_DISPLAY | 表示 NaN 值的字符串 | NaN | +| NULL_DISPLAY | 表示 NULL 值的字符串 | \N | +| EMPTY_FIELD_AS | 如何处理空字段 | FIELD_DEFAULT | +| ERROR_ON_COLUMN_COUNT_MISMATCH | 当列数不匹配时是否报错 | TRUE | +| ENCODING | 源文件的字符集编码 | UTF-8 | +| ENCODING_ERROR_MODE | 如何处理无效字节:STRICT 或 REPLACE | STRICT | + +
+ +
+ +| 选项 | 描述 | 默认值 | +|--------|-------------|--------| +| NULL_FIELD_AS | 如何处理空值字段 | NULL | +| MISSING_FIELD_AS | 如何处理缺失字段 | ERROR | +| NULL_IF | 视为 NULL 的字符串列表 | empty | + +
+ +
+ +| 选项 | 描述 | 默认值 | +|--------|-------------|--------| +| MISSING_FIELD_AS | 如何处理缺失字段 | ERROR | +| NULL_IF | 视为 NULL 的字符串列表 | empty | +| USE_LOGIC_TYPE | 使用 Parquet 逻辑类型进行列类型推导 | TRUE | + +
+ +
+ +| 选项 | 描述 | 默认值 | +|--------|-------------|--------| +| MISSING_FIELD_AS | 如何处理缺失字段 | ERROR | + +
+ +
+ +| 选项 | 描述 | 默认值 | +|--------|-------------|--------| +| MISSING_FIELD_AS | 如何处理缺失字段 | ERROR | +| NULL_IF | 视为 NULL 的字符串列表 | empty | +| USE_LOGIC_TYPE | 使用 Avro 逻辑类型进行列类型推导 | TRUE | + +
+
+ +## 复制选项 {#copy-options} + +| 参数 | 描述 | 默认值 | +|-----------|-------------|----------| +| PURGE | 成功加载后清除文件 | `false` | +| FORCE | 允许重新加载重复文件 | `false`(跳过重复项) | +| DISABLE_VARIANT_CHECK | 将无效 JSON 替换为空值 | `false`(遇到无效 JSON 时失败) | +| ON_ERROR | 错误处理方式:`continue`、`abort` 或 `abort_N` | `abort` | +| MAX_FILES | 要加载的最大文件数(最多 15,000) | - | +| RETURN_FAILED_ONLY | 输出中仅返回加载失败的文件 | `false` | +| COLUMN_MATCH_MODE | 对于 Parquet:列名匹配模式 | `case-insensitive` | +| SCHEMA_EVOLUTION | 对于 NDJSON:用于推导目标表中缺失列的采样选项。要求 `ENABLE_SCHEMA_EVOLUTION = true`,并且对目标表具有 `ALTER` 权限。 | `AUTO` sampling | + +### SCHEMA_EVOLUTION 选项 {#schema-evolution-options} + +`SCHEMA_EVOLUTION` 用于控制 {{{ .lake }}} 在加载前如何对 stage 中的 NDJSON 文件进行采样。当目标表启用了 `ENABLE_SCHEMA_EVOLUTION = true` 时,请将其与 `FILE_FORMAT = (TYPE = NDJSON ...)` 一起使用。 + +当针对 stage 或 location 加载执行 schema evolution 推导时,执行 `COPY INTO
` 的角色必须同时拥有目标表的 `INSERT` 和 `ALTER` 权限。基于查询的 COPY(例如 `COPY INTO
FROM (SELECT ... FROM @stage)`)仍沿用现有的权限要求。 + +| 选项 | 描述 | 值 | +|--------|-------------|--------| +| SAMPLE_FILES | 要采样的 stage 文件数量。 | `AUTO` 或正整数 | +| SAMPLE_RECORDS_PER_FILE | 从每个选中文件中采样的最大记录数。 | `AUTO` 或正整数 | +| SAMPLE_TOTAL_RECORDS | 在所有选中文件中采样的最大记录总数。 | `AUTO` 或正整数 | + +如果省略 `SCHEMA_EVOLUTION`,{{{ .lake }}} 会对这三个采样选项都使用 `AUTO`。当前 `AUTO` 的行为是最多采样 64 个文件、每个文件 1,000 条记录、总计 10,000 条记录。这些内部默认值可能会在未来版本中发生变化。如果你的加载过程对采样策略较为敏感,请显式设置 `SAMPLE_FILES`、`SAMPLE_RECORDS_PER_FILE` 和 `SAMPLE_TOTAL_RECORDS`。如果采样未覆盖某个在后续加载过程中出现的列,COPY 将失败,并报告这些额外的列名,以便你增大采样值。 + +> **提示:** +> +> 导入大量数据(例如日志)时,建议同时将 `PURGE` 和 `FORCE` 设置为 `true`。这样可以在无需与 Meta server 交互(更新 copied-files 集合)的情况下高效导入数据。不过,需要注意的是,这可能会导致重复导入数据。 + +## 输出 {#output} + +COPY INTO 会通过以下列汇总数据加载结果: + +| 列 | 类型 | 可为空 | 描述 | +| ---------------- | ------- | -------- | ----------------------------------------------- | +| FILE | VARCHAR | NO | 源文件的相对路径。 | +| ROWS_LOADED | INT | NO | 从源文件加载的行数。 | +| ERRORS_SEEN | INT | NO | 源文件中的错误行数 | +| FIRST_ERROR | VARCHAR | YES | 在源文件中发现的第一个错误。 | +| FIRST_ERROR_LINE | INT | YES | 第一个错误所在的行号。 | + +如果将 `RETURN_FAILED_ONLY` 设置为 `true`,输出将只包含加载失败的文件。 + +## 示例 {#examples} + +对于外部存储源,建议使用通过 `CONNECTION_NAME` 参数引用的预先创建连接,而不是在 COPY 语句中直接指定凭证。这种方式在安全性、可维护性和可复用性方面更好。有关如何创建连接的详细信息,请参见 [CREATE CONNECTION](/tidb-cloud-lake/sql/create-connection.md)。 + +### 示例 1:从 Stages 加载 {#example-1-loading-from-stages} + +以下示例展示了如何从不同类型的 stage 将数据加载到 {{{ .lake }}}: + + + +
+ +```sql +COPY INTO mytable + FROM @~ + PATTERN = '.*[.]parquet' + FILE_FORMAT = (TYPE = PARQUET); +``` + +
+ +
+ +```sql +COPY INTO mytable + FROM @my_internal_stage + PATTERN = '.*[.]parquet' + FILE_FORMAT = (TYPE = PARQUET); +``` + +
+ +
+ +```sql +COPY INTO mytable + FROM @my_external_stage + PATTERN = '.*[.]parquet' + FILE_FORMAT = (TYPE = PARQUET); +``` + +
+
+ +### 示例 2:从外部位置加载 {#example-2-loading-from-external-locations} + +以下示例展示了如何从不同类型的外部数据源将数据加载到 {{{ .lake }}} 中: + + + +
+ +此示例使用预先创建的连接从 Amazon S3 加载数据: + +```sql +-- First create a connection (you only need to do this once) +CREATE CONNECTION my_s3_conn + STORAGE_TYPE = 's3' + ACCESS_KEY_ID = '' + SECRET_ACCESS_KEY = ''; + +-- Use the connection to load data +COPY INTO mytable + FROM 's3://mybucket/data.csv' + CONNECTION = (CONNECTION_NAME = 'my_s3_conn') + FILE_FORMAT = ( + TYPE = CSV, + FIELD_DELIMITER = ',', + RECORD_DELIMITER = '\n', + SKIP_HEADER = 1 + ); +``` + +**使用 IAM Role(推荐用于生产环境)** + +```sql +-- Create connection using IAM role (more secure, recommended for production) +CREATE CONNECTION my_iam_conn + STORAGE_TYPE = 's3' + ROLE_ARN = 'arn:aws:iam::123456789012:role/my_iam_role'; + +-- Load CSV files using the IAM role connection +COPY INTO mytable + FROM 's3://mybucket/' + CONNECTION = (CONNECTION_NAME = 'my_iam_conn') + PATTERN = '.*[.]csv' + FILE_FORMAT = ( + TYPE = CSV, + FIELD_DELIMITER = ',', + RECORD_DELIMITER = '\n', + SKIP_HEADER = 1 + ); +``` + +
+ +
+ +此示例连接到 Azure Blob Storage,并将 `data.csv` 中的数据加载到 {{{ .lake }}} 中: + +```sql +-- Create connection for Azure Blob Storage +CREATE CONNECTION my_azure_conn + STORAGE_TYPE = 'azblob' + ENDPOINT_URL = 'https://.blob.core.windows.net' + ACCOUNT_NAME = '' + ACCOUNT_KEY = ''; + +-- Use the connection to load data +COPY INTO mytable + FROM 'azblob://mybucket/data.csv' + CONNECTION = (CONNECTION_NAME = 'my_azure_conn') + FILE_FORMAT = (type = CSV); +``` + +
+ +
+ +此示例连接到 Google Cloud Storage 并加载数据: + +```sql +-- Create connection for Google Cloud Storage +CREATE CONNECTION my_gcs_conn + STORAGE_TYPE = 'gcs' + CREDENTIAL = ''; + +-- Use the connection to load data +COPY INTO mytable + FROM 'gcs://mybucket/data.csv' + CONNECTION = (CONNECTION_NAME = 'my_gcs_conn') + FILE_FORMAT = ( + TYPE = CSV, + FIELD_DELIMITER = ',', + RECORD_DELIMITER = '\n', + SKIP_HEADER = 1 + ); +``` + +
+ +
+ +此示例从三个远程 CSV 文件加载数据,并在发生错误时跳过某个文件。 + +```sql +COPY INTO mytable + FROM 'https://lakesql-bin.tidbcloud.com/datasets/ontime_200{6,7,8}_200.csv' + FILE_FORMAT = (type = CSV) + ON_ERROR = continue; +``` + +
+ +
+ +此示例从 IPFS 上的一个 CSV 文件加载数据: + +```sql +COPY INTO mytable + FROM 'ipfs://' + CONNECTION = ( + ENDPOINT_URL = 'https://' + ) + FILE_FORMAT = ( + TYPE = CSV, + FIELD_DELIMITER = ',', + RECORD_DELIMITER = '\n', + SKIP_HEADER = 1 + ); +``` + +
+
+ +### 示例 3:加载压缩数据 {#example-3-loading-compressed-data} + +此示例将 Amazon S3 上一个经过 GZIP 压缩的 CSV 文件加载到 {{{ .lake }}} 中: + +```sql +-- Create connection for compressed data loading +CREATE CONNECTION compressed_s3_conn + STORAGE_TYPE = 's3' + ACCESS_KEY_ID = '' + SECRET_ACCESS_KEY = ''; + +-- Load GZIP-compressed CSV file using the connection +COPY INTO mytable + FROM 's3://mybucket/data.csv.gz' + CONNECTION = (CONNECTION_NAME = 'compressed_s3_conn') + FILE_FORMAT = ( + TYPE = CSV, + FIELD_DELIMITER = ',', + RECORD_DELIMITER = '\n', + SKIP_HEADER = 1, + COMPRESSION = AUTO + ); +``` + +### 示例 4:使用 Pattern 过滤文件 {#example-4-filtering-files-with-pattern} + +本示例演示如何使用 PATTERN 参数通过模式匹配从 Amazon S3 加载 CSV 文件。它会筛选文件名中包含 `sales` 且扩展名为 `.csv` 的文件: + +```sql +-- Create connection for pattern-based file loading +CREATE CONNECTION pattern_s3_conn + STORAGE_TYPE = 's3' + ACCESS_KEY_ID = '' + SECRET_ACCESS_KEY = ''; + +-- Load CSV files with 'sales' in their names using pattern matching +COPY INTO mytable + FROM 's3://mybucket/' + CONNECTION = (CONNECTION_NAME = 'pattern_s3_conn') + PATTERN = '.*sales.*[.]csv' + FILE_FORMAT = ( + TYPE = CSV, + FIELD_DELIMITER = ',', + RECORD_DELIMITER = '\n', + SKIP_HEADER = 1 + ); +``` + +其中,`.*` 表示任意字符出现零次或多次。方括号用于对文件扩展名前的句点字符 `.` 进行转义。 + +要使用连接从所有 CSV 文件中加载数据: + +```sql +COPY INTO mytable + FROM 's3://mybucket/' + CONNECTION = (CONNECTION_NAME = 'pattern_s3_conn') + PATTERN = '.*[.]csv' + FILE_FORMAT = ( + TYPE = CSV, + FIELD_DELIMITER = ',', + RECORD_DELIMITER = '\n', + SKIP_HEADER = 1 + ); +``` + +当为包含多级文件夹路径的 staged 文件指定模式时,请注意,模式只会匹配 `@[/]` 之后的路径部分。例如,对于 `FROM @sales_stage/raw/`,文件 `@sales_stage/raw/year=2025/month=01/sales_20250101.parquet` 会被匹配为 `year=2025/month=01/sales_20250101.parquet`。 + +- 如果你想匹配某个前缀之后的特定子路径,请在模式中包含该前缀(例如 `'year=2025/month=01/'`),然后再指定你希望在该子路径中匹配的模式(例如 `'sales_'`)。 + + ```sql + -- File path: raw/year=2025/month=01/sales_20250101.parquet + COPY INTO ... FROM @sales_stage/raw/ PATTERN = 'year=2025/month=01/.*sales_.*[.]parquet') ... + ``` + +- 如果你想匹配文件路径中任意位置包含目标模式的部分,请在模式前后都使用 `.*`(例如 `'.*sales_20250101.*'`),以匹配路径中任意位置出现的 `sales_20250101`。 + + ```sql + -- File path: raw/year=2025/month=01/sales_20250101.parquet + COPY INTO ... FROM @sales_stage/raw/ PATTERN = '.*sales_20250101.*') ... + ``` + +### 示例 5:加载到包含额外列的表 {#example-5-loading-to-table-with-extra-columns} + +本节演示如何将数据加载到包含额外列的表中,使用的示例文件为 [books.csv](https://lakesql-bin.tidbcloud.com/datasets/books.csv): + +```text title='books.csv' +Transaction Processing,Jim Gray,1992 +Readings in Database Systems,Michael Stonebraker,2004 +``` + +![Alt text](/media/tidb-cloud-lake/load-extra.png) + +默认情况下,COPY INTO 会按照文件中字段的顺序,将数据加载到表中对应顺序的列。因此,必须确保文件与表之间的数据能够正确对齐。例如: + +```sql +CREATE TABLE books +( + title VARCHAR, + author VARCHAR, + date VARCHAR +); + +COPY INTO books + FROM 'https://lakesql-bin.tidbcloud.com/datasets/books.csv' + FILE_FORMAT = (TYPE = CSV); +``` + +如果你的表比文件包含更多列,可以指定要将数据加载到哪些列中。例如: + +```sql +CREATE TABLE books_with_language +( + title VARCHAR, + language VARCHAR, + author VARCHAR, + date VARCHAR +); + +COPY INTO books_with_language (title, author, date) + FROM 'https://lakesql-bin.tidbcloud.com/datasets/books.csv' + FILE_FORMAT = (TYPE = CSV); +``` + +如果你的表比文件包含更多列,并且这些额外列位于表的末尾,则可以使用 [FILE_FORMAT](/tidb-cloud-lake/sql/input-output-file-formats.md) 选项 `ERROR_ON_COLUMN_COUNT_MISMATCH` 来加载数据。这样你无需逐一指定每一列。请注意,ERROR_ON_COLUMN_COUNT_MISMATCH 当前仅适用于 CSV 文件格式。 + +```sql +CREATE TABLE books_with_extra_columns +( + title VARCHAR, + author VARCHAR, + date VARCHAR, + language VARCHAR, + region VARCHAR +); + +COPY INTO books_with_extra_columns + FROM 'https://lakesql-bin.tidbcloud.com/datasets/books.csv' + FILE_FORMAT = (TYPE = CSV, ERROR_ON_COLUMN_COUNT_MISMATCH = false); +``` + +> **注意:** +> +> 表中的额外列可以通过 [CREATE TABLE](/tidb-cloud-lake/sql/create-table.md) 或 [ALTER TABLE](/tidb-cloud-lake/sql/alter-table.md#column-operations) 指定默认值。如果未为额外列显式设置默认值,则会应用其数据类型对应的默认值。例如,整数型列在未指定其他值时,默认值为 0。 + +### 示例 6:使用自定义格式加载 JSON {#example-6-loading-json-with-custom-format} + +本示例从一个名为 `"data.csv"` 的 CSV 文件中加载数据,其内容如下: + +```json +1,"U00010","{\"carPriceList\":[{\"carTypeId":10,\"distance":5860},{\"carTypeId":11,\"distance\":5861}]}" +2,"U00011","{\"carPriceList\":[{\"carTypeId":12,\"distance\":5862},{\"carTypeId":13,\"distance\":5863}]}" +``` + +每一行包含三列数据,其中第三列是一个包含 JSON 数据的字符串。为了正确加载带有 JSON 字段的 CSV 数据,我们需要设置正确的转义字符。本示例使用反斜杠 `\` 作为转义字符,因为 JSON 数据中包含双引号 `"`。 + +#### 步骤 1:创建自定义文件格式 {#step-1-create-custom-file-format} + +```sql +-- Define a custom CSV file format with the escape character set to backslash \ +CREATE FILE FORMAT my_csv_format + TYPE = CSV + ESCAPE = '\\'; +``` + +#### 步骤 2:创建目标表 {#step-2-create-target-table} + +```sql +CREATE TABLE t + ( + id INT, + seq VARCHAR, + p_detail VARCHAR + ); +``` + +#### 步骤 3:使用自定义文件格式加载 {#step-3-load-with-custom-file-format} + +```sql +COPY INTO t FROM @t_stage FILES=('data.csv') +FILE_FORMAT=(FORMAT_NAME='my_csv_format'); +``` + +### 示例 7:加载无效 JSON {#example-7-loading-invalid-json} + +将数据加载到 Variant 列时,{{{ .lake }}} 会自动检查数据的有效性;如果存在任何无效数据,则会报错。例如,如果用户 stage 中有一个名为 `invalid_json_string.parquet` 的 Parquet 文件,其中包含无效的 JSON 数据,如下所示: + +```sql +SELECT * +FROM @~/invalid_json_string.parquet; + +┌────────────────────────────────────┐ +│ a │ b │ +├─────────────────┼──────────────────┤ +│ 5 │ {"k":"v"} │ +│ 6 │ [1, │ +└────────────────────────────────────┘ + +DESC t2; + +┌──────────────────────────────────────────────┐ +│ Field │ Type │ Null │ Default │ Extra │ +├────────┼─────────┼────────┼─────────┼────────┤ +│ a │ VARCHAR │ YES │ NULL │ │ +│ b │ VARIANT │ YES │ NULL │ │ +└──────────────────────────────────────────────┘ +``` + +尝试将数据加载到表中时会发生错误: + +```sql +COPY INTO t2 FROM @~/invalid_json_string.parquet FILE_FORMAT = (TYPE = PARQUET) ON_ERROR = CONTINUE; +error: APIError: ResponseError with 1006: EOF while parsing a value, pos 3 while evaluating function `parse_json('[1,')` +``` + +如果希望在不检查 JSON 有效性的情况下进行加载,请在 COPY INTO 语句中将 `DISABLE_VARIANT_CHECK` 选项设置为 `true`: + +```sql +COPY INTO t2 FROM @~/invalid_json_string.parquet +FILE_FORMAT = (TYPE = PARQUET) +DISABLE_VARIANT_CHECK = true +ON_ERROR = CONTINUE; + +┌───────────────────────────────────────────────────────────────────────────────────────────────┐ +│ File │ Rows_loaded │ Errors_seen │ First_error │ First_error_line │ +├─────────────────────────────┼─────────────┼─────────────┼──────────────────┼──────────────────┤ +│ invalid_json_string.parquet │ 2 │ 0 │ NULL │ NULL │ +└───────────────────────────────────────────────────────────────────────────────────────────────┘ + +SELECT * FROM t2; +-- Invalid JSON is stored as null in the Variant column. +┌──────────────────────────────────────┐ +│ a │ b │ +├──────────────────┼───────────────────┤ +│ 5 │ {"k":"v"} │ +│ 6 │ null │ +└──────────────────────────────────────┘ +``` + +### 示例 8:使用 Schema Evolution 加载 {#example-8-loading-with-schema-evolution} + +当加载 Parquet 或 NDJSON 文件时,如果其 schema 中包含目标表中不存在的列,你可以使用 Schema Evolution 自动添加缺失的列。对于会运行 schema evolution 推导的 stage 或 location 加载,请确保执行加载的角色对目标表具有 `INSERT` 和 `ALTER` 权限。首先,在表上启用 schema evolution: + +```sql +CREATE OR REPLACE TABLE invoices(order_id INT); + +-- Enable schema evolution +ALTER TABLE invoices SET OPTIONS(ENABLE_SCHEMA_EVOLUTION = true); +``` + +#### Parquet {#parquet} + +然后加载具有不同 schema 的 Parquet 文件。{{{ .lake }}} 会自动添加新列,并使用 `NULL` 填充缺失值: + +```sql +-- Assume @my_stage contains Parquet files with extra columns (e.g., amount, currency) +COPY INTO invoices + FROM @my_stage/ + FILE_FORMAT = (TYPE = PARQUET MISSING_FIELD_AS = FIELD_DEFAULT); +``` + +#### NDJSON {#ndjson} + +对于 NDJSON,`COPY INTO` 会使用默认采样值来推导缺失列。只有在你想覆盖 {{{ .lake }}} 对 stage 中文件的采样方式时,才需要添加 `SCHEMA_EVOLUTION`: + +```sql +CREATE OR REPLACE TABLE events(id INT); +ALTER TABLE events SET OPTIONS(ENABLE_SCHEMA_EVOLUTION = true); + +-- Assume @events_stage contains NDJSON records such as: +-- {"id":1,"city":"SF","score":9} +COPY INTO events + FROM @events_stage/ + FILE_FORMAT = (TYPE = NDJSON MISSING_FIELD_AS = FIELD_DEFAULT) + SCHEMA_EVOLUTION = ( + SAMPLE_FILES = AUTO, + SAMPLE_RECORDS_PER_FILE = AUTO, + SAMPLE_TOTAL_RECORDS = AUTO + ); +``` + +{{{ .lake }}} 会对 stage 中的 NDJSON 文件进行采样,将推导出的 `city` 和 `score` 等字段追加为可为空的列,然后再加载数据。 + +更多详情,请参见 [Schema Evolution](/tidb-cloud-lake/guides/schema-evolution.md)。 \ No newline at end of file diff --git a/tidb-cloud-lake/sql/cos.md b/tidb-cloud-lake/sql/cos.md new file mode 100644 index 0000000000000..aaaad93dc3f28 --- /dev/null +++ b/tidb-cloud-lake/sql/cos.md @@ -0,0 +1,26 @@ +--- +title: COS +summary: 返回 `x` 的余弦值,其中 `x` 以弧度为单位给出。 +--- + +# COS + +返回 `x` 的余弦值,其中 `x` 以弧度为单位给出。 + +## 语法 {#syntax} + +```sql +COS( ) +``` + +## 示例 {#examples} + +```sql +SELECT COS(PI()); + +┌───────────┐ +│ cos(pi()) │ +├───────────┤ +│ -1 │ +└───────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/cosine-distance.md b/tidb-cloud-lake/sql/cosine-distance.md new file mode 100644 index 0000000000000..bd5ae0939932a --- /dev/null +++ b/tidb-cloud-lake/sql/cosine-distance.md @@ -0,0 +1,103 @@ +--- +title: COSINE_DISTANCE +summary: 在 {{{ .lake }}} 中使用 cosine_distance 函数衡量相似性。 +--- + +# COSINE_DISTANCE + +计算两个向量之间的余弦距离,用于衡量它们有多不相似。 + +## 语法 {#syntax} + +```sql +COSINE_DISTANCE(vector1, vector2) +``` + +## 参数 {#arguments} + +- `vector1`: 第一个向量(VECTOR 数据类型) +- `vector2`: 第二个向量(VECTOR 数据类型) + +## 返回值 {#returns} + +返回一个介于 0 和 1 之间的 FLOAT 值: + +- 0:向量相同(完全相似) +- 1:向量正交(完全不相似) + +## 描述 {#description} + +余弦距离基于两个向量之间的夹角来衡量它们的不相似程度,而与它们的大小无关。该函数会: + +1. 验证两个输入向量的长度是否相同 +2. 计算两个向量对应元素乘积之和(点积) +3. 计算每个向量平方和的平方根(向量模长) +4. 返回 `1 - (dot_product / (magnitude1 * magnitude2))` + +实现的数学公式为: + +``` +cosine_distance(v1, v2) = 1 - (Σ(v1ᵢ * v2ᵢ) / (√Σ(v1ᵢ²) * √Σ(v2ᵢ²))) +``` + +其中,v1ᵢ 和 v2ᵢ 是输入向量中的元素。 + +> **注意:** +> +> 此函数在 {{{ .lake }}} 内部执行向量计算,不依赖外部 API。 + +## 示例 {#examples} + +### 基本用法 {#basic-usage} + +```sql +-- Calculate cosine distance between two vectors +SELECT COSINE_DISTANCE([1.0, 2.0, 3.0]::vector(3), [4.0, 5.0, 6.0]::vector(3)) AS distance; +``` + +结果: + +``` +╭─────────────╮ +│ distance │ +├─────────────┤ +│ 0.025368214 │ +╰─────────────╯ +``` + +创建一个包含向量数据的表: + +```sql +CREATE OR REPLACE TABLE vectors ( + id INT, + vec VECTOR(3) +); + +INSERT INTO vectors VALUES + (1, [1.0000, 2.0000, 3.0000]), + (2, [1.0000, 2.2000, 3.0000]), + (3, [4.0000, 5.0000, 6.0000]); +``` + +查找与 [1, 2, 3] 最相似的向量: + +```sql +SELECT + id, + vec, + COSINE_DISTANCE(vec, [1.0000, 2.0000, 3.0000]::VECTOR(3)) AS distance +FROM + vectors +ORDER BY + distance ASC; +``` + +``` +╭────────────────────────────────────╮ +│ id │ vec │ distance │ +├────┼───────────┼───────────────────┤ +│ 1 │ [1,2,3] │ 0.000000059604645 │ +│ 2 │ [1,2.2,3] │ 0.00096315145 │ +│ 3 │ [4,5,6] │ 0.025368214 │ +╰────────────────────────────────────╯ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/cot.md b/tidb-cloud-lake/sql/cot.md new file mode 100644 index 0000000000000..758fca8d7c0b9 --- /dev/null +++ b/tidb-cloud-lake/sql/cot.md @@ -0,0 +1,26 @@ +--- +title: COT +summary: 返回 `x` 的余切值,其中 `x` 以弧度为单位。 +--- + +# COT + +返回 `x` 的余切值,其中 `x` 以弧度为单位。 + +## 语法 {#syntax} + +```sql +COT( ) +``` + +## 示例 {#examples} + +```sql +SELECT COT(12); + +┌─────────────────────┐ +│ cot(12) │ +├─────────────────────┤ +│ -1.5726734063976895 │ +└─────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/count-distinct.md b/tidb-cloud-lake/sql/count-distinct.md new file mode 100644 index 0000000000000..3c99bf8510352 --- /dev/null +++ b/tidb-cloud-lake/sql/count-distinct.md @@ -0,0 +1,68 @@ +--- +title: COUNT_DISTINCT +summary: 聚合函数。 +--- + +# COUNT_DISTINCT + +聚合函数。 + +`count(distinct ...)` 函数用于计算一组值中唯一值的数量。 + +如果希望在较少内存和时间开销下,从大型数据集中获得估算结果,可以考虑使用 [APPROX_COUNT_DISTINCT](/tidb-cloud-lake/sql/approx-count-distinct.md)。 + +> **注意:** +> +> 不统计 `NULL` 值。 + +## 语法 {#syntax} + +```sql +COUNT(distinct ...) +UNIQ() +``` + +## 参数 {#arguments} + +| 参数 | 描述 | +|-----------|--------------------------------------------------| +| `` | 任意表达式,参数个数范围为 [1, 32] | + +## 返回类型 {#return-type} + +UInt64 + +## 示例 {#example} + +**创建表并插入示例数据** + +```sql +CREATE TABLE products ( + id INT, + name VARCHAR, + category VARCHAR, + price FLOAT +); + +INSERT INTO products (id, name, category, price) +VALUES (1, 'Laptop', 'Electronics', 1000), + (2, 'Smartphone', 'Electronics', 800), + (3, 'Tablet', 'Electronics', 600), + (4, 'Chair', 'Furniture', 150), + (5, 'Table', 'Furniture', 300); +``` + +**查询演示:统计不同类别的数量** + +```sql +SELECT COUNT(DISTINCT category) AS unique_categories +FROM products; +``` + +**结果** + +```sql +| unique_categories | +|-------------------| +| 2 | +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/count-if.md b/tidb-cloud-lake/sql/count-if.md new file mode 100644 index 0000000000000..a2381d675cce8 --- /dev/null +++ b/tidb-cloud-lake/sql/count-if.md @@ -0,0 +1,49 @@ +--- +title: COUNT_IF +summary: 后缀 `_IF` 可以附加到任何聚合函数的名称后。在这种情况下,聚合函数会接受一个额外的参数——条件。 +--- + +# COUNT_IF + +## COUNT_IF {#count-if} + +后缀 `_IF` 可以附加到任何聚合函数的名称后。在这种情况下,聚合函数会接受一个额外的参数——条件。 + +```sql +COUNT_IF(, ) +``` + +## 示例 {#example} + +**创建表并插入示例数据** + +```sql +CREATE TABLE orders ( + id INT, + customer_id INT, + status VARCHAR, + total FLOAT +); + +INSERT INTO orders (id, customer_id, status, total) +VALUES (1, 1, 'completed', 100), + (2, 2, 'completed', 200), + (3, 1, 'pending', 150), + (4, 3, 'completed', 250), + (5, 2, 'pending', 300); +``` + +**查询示例:统计已完成订单数** + +```sql +SELECT COUNT_IF(status, status = 'completed') AS completed_orders +FROM orders; +``` + +**结果** + +```sql +| completed_orders | +|------------------| +| 3 | +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/count.md b/tidb-cloud-lake/sql/count.md new file mode 100644 index 0000000000000..1a9e657c22d63 --- /dev/null +++ b/tidb-cloud-lake/sql/count.md @@ -0,0 +1,64 @@ +--- +title: COUNT +summary: COUNT() 函数返回 SELECT 查询返回的记录数。 +--- + +# COUNT + +COUNT() 函数返回 SELECT 查询返回的记录数。 + +> **注意:** +> +> 不会统计 NULL 值。 + +## 语法 {#syntax} + +```sql +COUNT() +``` + +## 参数 {#arguments} + +| 参数 | 描述 | +|-----------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `` | 任意表达式。
可以是列名、另一个函数的结果,或数学运算。
也允许使用 `*`,表示仅统计行数。 | + +## 返回类型 {#return-type} + +整数型。 + +## 示例 {#example} + +**创建表并插入示例数据** + +```sql +CREATE TABLE students ( + id INT, + name VARCHAR, + age INT, + grade FLOAT NULL +); + +INSERT INTO students (id, name, age, grade) +VALUES (1, 'John', 21, 85), + (2, 'Emma', 22, NULL), + (3, 'Alice', 23, 90), + (4, 'Michael', 21, 88), + (5, 'Sophie', 22, 92); + +``` + +**查询示例:统计具有有效成绩的学生数量** + +```sql +SELECT COUNT(grade) AS count_valid_grades +FROM students; +``` + +**结果** + +```sql +| count_valid_grades | +|--------------------| +| 4 | +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/covar-pop.md b/tidb-cloud-lake/sql/covar-pop.md new file mode 100644 index 0000000000000..b399c9cf2d876 --- /dev/null +++ b/tidb-cloud-lake/sql/covar-pop.md @@ -0,0 +1,65 @@ +--- +title: COVAR_POP +summary: 返回一组数值对的总体协方差。 +--- + +# COVAR_POP + +返回一组数值对的总体协方差。 + +## 语法 {#syntax} + +```sql +COVAR_POP(, ) +``` + +## 参数 {#arguments} + +| 参数 | 描述 | +|-----------| ------------------------ | +| `` | 任意数值表达式 | +| `` | 任意数值表达式 | + +## 别名 {#aliases} + +- [VAR_POP](/tidb-cloud-lake/sql/var-pop.md) +- [VARIANCE_POP](/tidb-cloud-lake/sql/variance-pop.md) + +## 返回类型 {#return-type} + +float64 + +## 示例 {#example} + +**创建表并插入示例数据** + +```sql +CREATE TABLE product_sales ( + id INT, + product_id INT, + units_sold INT, + revenue FLOAT +); + +INSERT INTO product_sales (id, product_id, units_sold, revenue) +VALUES (1, 1, 10, 1000), + (2, 2, 20, 2000), + (3, 3, 30, 3000), + (4, 4, 40, 4000), + (5, 5, 50, 5000); +``` + +**查询示例:计算销量与收入之间的总体协方差** + +```sql +SELECT COVAR_POP(units_sold, revenue) AS covar_pop_units_revenue +FROM product_sales; +``` + +**结果** + +```sql +| covar_pop_units_revenue | +|-------------------------| +| 20000.0 | +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/covar-samp.md b/tidb-cloud-lake/sql/covar-samp.md new file mode 100644 index 0000000000000..9eb4bb48ec4be --- /dev/null +++ b/tidb-cloud-lake/sql/covar-samp.md @@ -0,0 +1,69 @@ +--- +title: COVAR_SAMP +summary: 返回两个数据列的样本协方差 (Σ((x - x̅)(y - y̅)) / (n - 1))。 +--- + +# COVAR_SAMP + +返回两个数据列的样本协方差 (Σ((x - x̅)(y - y̅)) / (n - 1))。 + +> **Note:** +> +> 不统计 NULL 值。 + +## 语法 {#syntax} + +```sql +COVAR_SAMP(, ) +``` + +## 参数 {#arguments} + +| 参数 | 描述 | +| --------- | ------------------------ | +| `` | 任意数值表达式 | +| `` | 任意数值表达式 | + +## 别名 {#aliases} + +- [VAR_SAMP](/tidb-cloud-lake/sql/var-samp.md) +- [VARIANCE_SAMP](/tidb-cloud-lake/sql/variance-samp.md) + +## 返回类型 {#return-type} + +float64,当 `n <= 1` 时,返回 +∞。 + +## 示例 {#example} + +**创建表并插入示例数据** + +```sql +CREATE TABLE store_sales ( + id INT, + store_id INT, + items_sold INT, + profit FLOAT +); + +INSERT INTO store_sales (id, store_id, items_sold, profit) +VALUES (1, 1, 100, 1000), + (2, 2, 200, 2000), + (3, 3, 300, 3000), + (4, 4, 400, 4000), + (5, 5, 500, 5000); +``` + +**查询示例:计算 items_sold 与 profit 之间的样本协方差** + +```sql +SELECT COVAR_SAMP(items_sold, profit) AS covar_samp_items_profit +FROM store_sales; +``` + +**结果** + +```sql +| covar_samp_items_profit | +|-------------------------| +| 250000.0 | +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/crc.md b/tidb-cloud-lake/sql/crc.md new file mode 100644 index 0000000000000..ff987bb80a44a --- /dev/null +++ b/tidb-cloud-lake/sql/crc.md @@ -0,0 +1,26 @@ +--- +title: CRC32 +summary: 返回 `x` 的 CRC32 校验和,其中 `x` 应为字符串;如果不是,则会在可能的情况下将其视为字符串处理。 +--- + +# CRC32 + +返回 `x` 的 CRC32 校验和,其中 `x` 应为字符串;如果不是,则会在可能的情况下将其视为字符串处理。 + +## 语法 {#syntax} + +```sql +CRC32( '' ) +``` + +## 示例 {#examples} + +```sql +SELECT CRC32('datalake'); + +┌───────────────────┐ +│ crc32('datalake') │ +├───────────────────┤ +│ 2878859588 │ +└───────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/create-aggregate-function.md b/tidb-cloud-lake/sql/create-aggregate-function.md new file mode 100644 index 0000000000000..e97aa5fd57b0a --- /dev/null +++ b/tidb-cloud-lake/sql/create-aggregate-function.md @@ -0,0 +1,150 @@ +--- +title: CREATE AGGREGATE FUNCTION +summary: 创建在 {{{ .lake }}} 的 JavaScript 或 Python 运行时中运行的用户定义聚合函数(UDAF)。 +--- + +# CREATE AGGREGATE FUNCTION + +创建在 {{{ .lake }}} 的 JavaScript 或 Python 运行时中运行的用户定义聚合函数(UDAF)。 + +## 支持的语言 {#supported-languages} + +- `javascript` +- `python` + +## 语法 {#syntax} + +```sql +CREATE [ OR REPLACE ] FUNCTION [ IF NOT EXISTS ] + ( [ ] ) + STATE { } + RETURNS + LANGUAGE + [ IMPORTS = () ] + [ PACKAGES = () ] +AS $$ + +$$ +[ DESC='' ] +``` + +| 参数 | 描述 | +| --- | --- | +| `` | 聚合函数的名称。 | +| `` | 可选的、以逗号分隔的输入参数及其类型列表(例如 `value DOUBLE`)。 | +| `STATE { }` | {{{ .lake }}} 在部分/最终聚合步骤之间存储的结构体定义(例如 `STATE { sum DOUBLE, count DOUBLE }`)。 | +| `` | 聚合返回的数据类型(`DOUBLE`、`INT` 等)。 | +| `LANGUAGE` | 用于执行脚本的运行时。支持的值:`javascript`、`python`。 | +| `IMPORTS` / `PACKAGES` | 可选列表,用于附带额外文件(imports)或 PyPI 包(仅 Python)。 | +| `` | 脚本主体,必须暴露 `create_state`、`accumulate`、`merge` 和 `finish` 入口点。 | +| `DESC` | 可选描述。 | + +脚本必须实现以下函数: + +- `create_state()` – 分配并返回一个初始状态对象。 +- `accumulate(state, *args)` – 针对每一行输入修改状态。 +- `merge(state1, state2)` – 合并两个部分状态。 +- `finish(state)` – 生成最终结果(对 SQL `NULL` 返回 `None`)。 + +## 访问控制要求 {#access-control-requirements} + +| 权限 | 对象类型 | 描述 | +|:----------|:--------------|:---------------| +| SUPER | 全局, Table | 操作 UDF | + +要创建用户定义函数,执行该操作的用户或 [current_role](/tidb-cloud-lake/guides/roles.md) 必须具有 SUPER [权限](/tidb-cloud-lake/guides/privileges.md)。 + +## 示例 {#examples} + +### Python average UDAF {#python-average-udaf} + +以下 Python 聚合用于计算某一列的平均值: + +```sql +CREATE OR REPLACE FUNCTION py_avg (value DOUBLE) + STATE { sum DOUBLE, count DOUBLE } + RETURNS DOUBLE + LANGUAGE python +AS $$ +class State: + def __init__(self): + self.sum = 0.0 + self.count = 0.0 + +def create_state(): + return State() + +def accumulate(state, value): + if value is not None: + state.sum += value + state.count += 1 + return state + +def merge(state1, state2): + state1.sum += state2.sum + state1.count += state2.count + return state1 + +def finish(state): + if state.count == 0: + return None + return state.sum / state.count +$$; + +SELECT py_avg(number) AS avg_val FROM numbers(5); +``` + +``` ++---------+ +| avg_val | ++---------+ +| 2 | ++---------+ +``` + +### JavaScript average UDAF {#javascript-average-udaf} + +下一个示例展示了如何用 JavaScript 实现相同的计算: + +```sql +CREATE OR REPLACE FUNCTION js_avg (value DOUBLE) + STATE { sum DOUBLE, count DOUBLE } + RETURNS DOUBLE + LANGUAGE javascript +AS $$ +export function create_state() { + return { sum: 0, count: 0 }; +} + +export function accumulate(state, value) { + if (value !== null) { + state.sum += value; + state.count += 1; + } + return state; +} + +export function merge(state1, state2) { + state1.sum += state2.sum; + state1.count += state2.count; + return state1; +} + +export function finish(state) { + if (state.count === 0) { + return null; + } + return state.sum / state.count; +} +$$; + +SELECT js_avg(number) AS avg_val FROM numbers(5); +``` + +``` ++---------+ +| avg_val | ++---------+ +| 2 | ++---------+ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/create-aggregating-index.md b/tidb-cloud-lake/sql/create-aggregating-index.md new file mode 100644 index 0000000000000..47c1f82d7ce38 --- /dev/null +++ b/tidb-cloud-lake/sql/create-aggregating-index.md @@ -0,0 +1,33 @@ +--- +title: CREATE AGGREGATING INDEX +summary: 在 {{{ .lake }}} 中创建一个新的聚合索引。 +--- + +# CREATE AGGREGATING INDEX + +在 {{{ .lake }}} 中创建一个新的聚合索引。 + +## 语法 {#syntax} + +```sql +CREATE [ OR REPLACE ] AGGREGATING INDEX AS SELECT ... +``` + +- 创建聚合索引时,其使用范围仅限于标准的[聚合函数](/tidb-cloud-lake/_index.md)(例如 AVG、SUM、MIN、MAX、COUNT 和 GROUP BY)。请注意,不支持 GROUPING SETS、[窗口函数](/tidb-cloud-lake/_index.md)、[LIMIT](/tidb-cloud-lake/sql/select.md#limit-clause) 和 [ORDER BY](/tidb-cloud-lake/sql/select.md#order-by-clause),否则会报错:`Currently create aggregating index just support simple query, like: SELECT ... FROM ... WHERE ... GROUP BY ...`。 + +- 创建聚合索引时定义的查询过滤作用域,应与实际查询的作用域一致,或覆盖实际查询的作用域。 + +- 要确认聚合索引是否对某个查询生效,可以使用 [EXPLAIN](/tidb-cloud-lake/sql/explain.md) 命令分析该查询。 + +## 示例 {#examples} + +以下示例为查询 "SELECT MIN(a), MAX(c) FROM agg" 创建了一个名为 *my_agg_index* 的聚合索引: + +```sql +-- Prepare data +CREATE TABLE agg(a int, b int, c int); +INSERT INTO agg VALUES (1,1,4), (1,2,1), (1,2,4), (2,2,5); + +-- Create an aggregating index +CREATE AGGREGATING INDEX my_agg_index AS SELECT MIN(a), MAX(c) FROM agg; +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/create-connection.md b/tidb-cloud-lake/sql/create-connection.md new file mode 100644 index 0000000000000..e412960774b3e --- /dev/null +++ b/tidb-cloud-lake/sql/create-connection.md @@ -0,0 +1,192 @@ +--- +title: CREATE CONNECTION +summary: 创建到外部存储的连接。 +--- + +# CREATE CONNECTION + +创建到外部存储的连接。 + +> **Warning:** +> +> 重要提示:当对象(stage、表等)使用某个连接时,它们会永久复制并存储该连接的参数。如果你之后使用 CREATE OR REPLACE CONNECTION 修改该连接,现有对象仍将继续使用旧参数。若要让对象使用新的连接参数,必须删除并重新创建这些对象。 + +## 语法 {#syntax} + +```sql +CREATE [ OR REPLACE ] CONNECTION [ IF NOT EXISTS ] + STORAGE_TYPE = '' + [ ] +``` + +| 参数 | 描述 | +|------------------|----------------------------------------------------------------------------------------------------------------------------------------------------| +| STORAGE_TYPE | 存储服务的类型。可能的值包括:`s3`、`azblob`、`gcs`、`oss` 和 `cos`。 | +| storage_params | 根据存储类型和认证方法而变化。完整列表请参见 [连接参数](/tidb-cloud-lake/sql/connection-parameters.md)。 | + +## 连接参数 {#connection-parameters} + +连接封装了特定存储后端的凭证和配置。创建连接时,请选择合适的 `STORAGE_TYPE` 并提供所需参数。下表列出了常见选项: + +| STORAGE_TYPE | 常见参数 | 描述 | +|--------------|-------------------|-------------| +| `s3` | `ACCESS_KEY_ID`/`SECRET_ACCESS_KEY`,或 `ROLE_ARN`/`EXTERNAL_ID`,可选 `ENDPOINT_URL`、`REGION` | Amazon S3 和兼容 S3 的服务(MinIO、Cloudflare R2 等)。 | +| `azblob` | `ACCOUNT_NAME`、`ACCOUNT_KEY`、`ENDPOINT_URL` | Azure Blob Storage。 | +| `gcs` | `CREDENTIAL`(base64 编码的服务账户密钥) | Google Cloud Storage。 | +| `oss` | `ACCESS_KEY_ID`、`ACCESS_KEY_SECRET`、`ENDPOINT_URL` | 阿里云对象存储服务。 | +| `cos` | `SECRET_ID`、`SECRET_KEY`、`ENDPOINT_URL` | 腾讯云对象存储。 | +| `hf` | `REPO_TYPE`、`REVISION`,可选 `TOKEN` | Hugging Face Hub 数据集和模型。 | + +有关参数含义、可选(命令行)标记/参数以及其他存储类型,请参见 [连接参数](/tidb-cloud-lake/sql/connection-parameters.md)。展开下面的标签页可查看各存储类型的示例: + + + +
+ +为 Amazon S3 和兼容 S3 的服务选择一种认证方法: + + + +
+ +```sql +CREATE CONNECTION + STORAGE_TYPE = 's3' + ACCESS_KEY_ID = '' + SECRET_ACCESS_KEY = ''; +``` + +| 参数 | 描述 | +|-----------|-------------| +| ACCESS_KEY_ID | 你的 AWS access key ID。 | +| SECRET_ACCESS_KEY | 你的 AWS secret access key。 | + +
+ +
+ +```sql +CREATE CONNECTION + STORAGE_TYPE = 's3' + ROLE_ARN = ''; +``` + +| 参数 | 描述 | +|-----------|-------------| +| ROLE_ARN | {{{ .lake }}} 将用于访问你的 S3 资源的 IAM 角色的 Amazon Resource Name (ARN)。 | + +
+
+ +
+ +
+ +```sql +CREATE CONNECTION + STORAGE_TYPE = 'azblob' + ACCOUNT_NAME = '' + ACCOUNT_KEY = '' + ENDPOINT_URL = 'https://.blob.core.windows.net'; +``` + +
+ +
+ +```sql +CREATE CONNECTION + STORAGE_TYPE = 'gcs' + CREDENTIAL = ''; +``` + +
+ +
+ +```sql +CREATE CONNECTION + STORAGE_TYPE = 'oss' + ACCESS_KEY_ID = '' + ACCESS_KEY_SECRET = '' + ENDPOINT_URL = 'https://[-internal].aliyuncs.com'; +``` + +
+ +
+ +```sql +CREATE CONNECTION + STORAGE_TYPE = 'cos' + SECRET_ID = '' + SECRET_KEY = '' + ENDPOINT_URL = ''; +``` + +
+ +
+ +```sql +CREATE CONNECTION + STORAGE_TYPE = 'hf' + REPO_TYPE = 'dataset' + REVISION = 'main' + TOKEN = ''; +``` + +对于公共仓库,可省略 `TOKEN`;对于私有仓库或受速率限制的资源,请包含该参数。 + +
+
+ +## 访问控制要求 {#access-control-requirements} + +| 权限 | 对象类型 | 描述 | +|:------------------|:------------|:----------------------| +| CREATE CONNECTION | 全局 | 创建连接。 | + +要创建连接,执行该操作的用户或 [current_role](/tidb-cloud-lake/guides/roles.md) 必须具有 CREATE CONNECTION [权限](/tidb-cloud-lake/guides/privileges.md)。 + +## 修改表连接 {#update-table-connections} + +要将现有表切换到新连接,请使用 [`ALTER TABLE ... CONNECTION`](/tidb-cloud-lake/sql/alter-table.md#external-table-connection)。该命令可以将外部表重新绑定到不同的连接,而无需重新创建表。 + +## 示例 {#examples} + +### 使用 Access Keys {#using-access-keys} + +本示例创建了一个名为 `toronto` 的 Amazon S3 连接,并使用该 `toronto` 连接创建了一个名为 `my_s3_stage` 的外部 stage,该 stage 关联到 `s3://lake-toronto` URL。有关连接的更多实际示例,请参见 [使用示例](/tidb-cloud-lake/sql/connection.md#usage-examples)。 + +```sql +CREATE CONNECTION toronto + STORAGE_TYPE = 's3' + ACCESS_KEY_ID = '' + SECRET_ACCESS_KEY = ''; + +CREATE STAGE my_s3_stage + URL = 's3://lake-toronto' + CONNECTION = (CONNECTION_NAME = 'toronto'); +``` + +### 使用 AWS IAM Role {#using-aws-iam-role} + +本示例使用 IAM 角色创建一个 Amazon S3 连接,然后创建一个使用该连接的 stage。这种方式更安全,因为它不需要在 {{{ .lake }}} 中存储 access keys。 + +```sql +CREATE CONNECTION lake_test + STORAGE_TYPE = 's3' + ROLE_ARN = 'arn:aws:iam::987654321987:role/lake-test'; + +CREATE STAGE lake_test + URL = 's3://test-bucket-123' + CONNECTION = (CONNECTION_NAME = 'lake_test'); + +-- You can now query data from your S3 bucket +SELECT * FROM @lake_test/test.parquet LIMIT 1; +``` + +> **Note:** +> +> 要在 {{{ .lake }}} 中使用 IAM 角色,你需要在你的 AWS 账户与 {{{ .lake }}} 之间建立信任关系。详细说明请参见 [使用 AWS IAM Role 进行认证](/tidb-cloud-lake/guides/authenticate-with-aws-iam-role.md)。 \ No newline at end of file diff --git a/tidb-cloud-lake/sql/create-database.md b/tidb-cloud-lake/sql/create-database.md new file mode 100644 index 0000000000000..21381dc70ae3c --- /dev/null +++ b/tidb-cloud-lake/sql/create-database.md @@ -0,0 +1,67 @@ +--- +title: CREATE DATABASE +summary: 创建数据库。 +--- + +# CREATE DATABASE + +创建数据库。 + +## 语法 {#syntax} + +```sql +CREATE [ OR REPLACE ] DATABASE [ IF NOT EXISTS ] + [ OPTIONS ( + DEFAULT_STORAGE_CONNECTION = '', + DEFAULT_STORAGE_PATH = '' + ) ] +``` + +## 参数 {#parameters} + +| 参数 | 描述 | +|:-----------------------------|:-------------------------------------------------------------------------------------------------------------------------------------------------| +| `DEFAULT_STORAGE_CONNECTION` | 要用作此数据库中表的默认存储连接的现有连接名称(通过 `CREATE CONNECTION` 创建)。 | +| `DEFAULT_STORAGE_PATH` | 此数据库中表的默认存储路径 URI(例如 `s3://bucket/path/`)。必须以 `/` 结尾,并且与连接的存储类型匹配。 | + +> **注意:** +> +> - `DEFAULT_STORAGE_CONNECTION` 和 `DEFAULT_STORAGE_PATH` 必须同时指定。仅指定其中一个会报错。 +> - 当同时设置这两个选项时,{{{ .lake }}} 会验证连接是否存在、路径 URI 格式是否正确,以及存储位置是否可访问。 + +## 访问控制要求 {#access-control-requirements} + +| 权限 | 对象类型 | 描述 | +|:----------------|:------------|:-------------| +| CREATE DATABASE | 全局 | 创建数据库。 | + +要创建数据库,执行该操作的用户或 [current_role](/tidb-cloud-lake/guides/roles.md) 必须具有 CREATE DATABASE [权限](/tidb-cloud-lake/guides/privileges.md)。 + +## 示例 {#examples} + +### 创建基本数据库 {#creating-a-basic-database} + +以下示例创建一个名为 `test` 的数据库: + +```sql +CREATE DATABASE test; +``` + +### 创建带默认存储连接的数据库 {#creating-a-database-with-a-default-storage-connection} + +以下示例先使用 AWS IAM role 创建一个连接,然后创建一个将该连接用作默认存储的数据库。与 access keys 相比,使用 IAM role 更安全,因为它不需要将凭证存储在 {{{ .lake }}} 中。 + +```sql +CREATE CONNECTION my_s3 + STORAGE_TYPE = 's3' + ROLE_ARN = 'arn:aws:iam::987654321987:role/lake-test'; + +CREATE DATABASE analytics OPTIONS ( + DEFAULT_STORAGE_CONNECTION = 'my_s3', + DEFAULT_STORAGE_PATH = 's3://mybucket/analytics/' +); +``` + +> **注意:** +> +> 要在 {{{ .lake }}} 中使用 IAM roles,你需要在你的 AWS account 与 {{{ .lake }}} 之间建立信任关系。详细说明请参见[使用 AWS IAM Role 进行身份验证](/tidb-cloud-lake/guides/authenticate-with-aws-iam-role.md)。 \ No newline at end of file diff --git a/tidb-cloud-lake/sql/create-dictionary.md b/tidb-cloud-lake/sql/create-dictionary.md new file mode 100644 index 0000000000000..e767c317ca6f3 --- /dev/null +++ b/tidb-cloud-lake/sql/create-dictionary.md @@ -0,0 +1,83 @@ +--- +title: CREATE DICTIONARY +summary: 创建一个字典。 +--- + +# CREATE DICTIONARY + +创建一个字典。 + +## 语法 {#syntax} + +```sql +CREATE [ OR REPLACE ] DICTIONARY [ IF NOT EXISTS ] [ . ][ . ] +( + [ , , ... ] +) +PRIMARY KEY [ , , ... ] +SOURCE( + ( + = '' [ = '' ... ] + ) +) +[ COMMENT '' ] +``` + +## 参数 {#parameters} + +| 参数 | 描述 | +|-----------|-------------| +| `OR REPLACE` | 使用相同名称替换现有字典。 | +| `IF NOT EXISTS` | 如果字典已存在,则成功返回且不做任何更改。 | +| `` | 字典名称。可以使用 catalog 和 database 名称进行限定。 | +| `( , ...)` | 声明字典的 schema。 | +| `PRIMARY KEY` | 定义一个或多个用于字典查找的键列。 | +| `SOURCE(...)` | 定义源连接器名称及其键值选项。 | +| `COMMENT` | 可选的字典注释。 | + +> **注意:** +> +> SOURCE 仅支持 `MySQL` 和 `Redis`。 + +## 示例 {#examples} + +MySQL 示例: + +```sql +CREATE DICTIONARY user_info +( + user_id UInt64, + user_name String, + user_email String +) +PRIMARY KEY user_id +SOURCE( + mysql( + host = '127.0.0.1' + port = '3306' + username = 'root' + password = 'root' + db = 'app' + table = 'users' + ) +) +COMMENT 'User dictionary from MySQL'; +``` + +Redis 示例: + +```sql +CREATE DICTIONARY cache +( + key String, + value String +) +PRIMARY KEY key +SOURCE( + redis( + host = '127.0.0.1' + port = '6379' + ) +) +COMMENT 'cache dictionary from Redis'; +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/create-external-table.md b/tidb-cloud-lake/sql/create-external-table.md new file mode 100644 index 0000000000000..3415f991d0e9a --- /dev/null +++ b/tidb-cloud-lake/sql/create-external-table.md @@ -0,0 +1,133 @@ +--- +title: CREATE EXTERNAL TABLE +summary: `CREATE TABLE... CONNECTION = (...)` 语句用于创建表,并指定一个兼容 S3 的存储桶来存储数据,而不是使用默认的本地存储。 +--- + +# CREATE EXTERNAL TABLE + +`CREATE TABLE ... CONNECTION = (...)` 语句用于创建表,并指定一个兼容 S3 的存储桶来存储数据,而不是使用默认的本地存储。 + +随后,fuse table engine 表将存储在指定的兼容 S3 的存储桶中。 + +## 优势 {#benefits} + +- 你可以自行决定表数据的存储位置。 +- 利用高性能存储(如 [Amazon S3 Express One Zone](https://aws.amazon.com/s3/storage-classes/express-one-zone/))来提升性能。 + +## 语法 {#syntax} + +```sql +CREATE TABLE [IF NOT EXISTS] [db.]table_name ( + [NOT NULL | NULL] [{ DEFAULT }], + [NOT NULL | NULL] [{ DEFAULT }], + ... +) +'s3:///[]' +CONNECTION = ( + ENDPOINT_URL = 'https://' + ACCESS_KEY_ID = '' + SECRET_ACCESS_KEY = '' + ENABLE_VIRTUAL_HOST_STYLE = 'true' | 'false' +) +| +CONNECTION = ( + CONNECTION_NAME = '' +); +``` + +连接参数: + +| 参数 | 说明 | 必填 | +|-----------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------| +| `s3:///[]` | 文件位于指定的外部位置(类 S3 存储桶) | YES | +| ENDPOINT_URL | 存储桶的 endpoint URL,必须以 `https://` 开头。 | Optional | +| ACCESS_KEY_ID | 用于连接 AWS S3 兼容对象存储的 access key ID。如果未提供,{{{ .lake }}} 将以匿名方式访问该存储桶。 | Optional | +| SECRET_ACCESS_KEY | 用于连接 AWS S3 兼容对象存储的 secret access key。 | Optional | +| ENABLE_VIRTUAL_HOST_STYLE | 如果你使用虚拟主机方式来访问存储桶,请将其设置为 `"true"`。 | Optional | + +关于 `CONNECTION_NAME` 的更多信息,请参见 [CREATE CONNECTION](/tidb-cloud-lake/sql/create-connection.md) + +## 兼容 S3 的存储桶策略要求 {#s3-compatible-bucket-policy-requirements} + +外部位置的 S3 存储桶必须通过 S3 bucket policy 授予以下权限: + +**只读访问:** + +- `s3:GetObject`:允许从存储桶中读取对象。 +- `s3:ListBucket`:允许列出存储桶中的对象。 +- `s3:ListBucketVersions`:允许列出存储桶中的对象版本。 +- `s3:GetObjectVersion`:允许获取对象的特定版本。 + +**可写访问:** + +- `s3:PutObject`:允许向存储桶写入对象。 +- `s3:DeleteObject`:允许从存储桶删除对象。 +- `s3:AbortMultipartUpload`:允许中止分段上传。 +- `s3:DeleteObjectVersion`:允许删除对象的特定版本。 + +## 示例 {#examples} + +在使用 `SHOW CREATE TABLE` 命令之前,你需要将 `hide_options_in_show_create_table` 变量设置为 `0`。 + +```sql +SET GLOBAL hide_options_in_show_create_table = 0; +``` + +### 使用外部位置创建表 {#create-a-table-with-external-location} + +创建一个表,并将数据存储在外部位置,例如 Amazon S3: + +```sql +-- Create a table named `mytable` and specify the location `s3://testbucket/admin/data/` for the data storage +CREATE TABLE mytable ( + a INT +) +'s3://testbucket/admin/data/' +CONNECTION = ( + ACCESS_KEY_ID = '', + SECRET_ACCESS_KEY = '', + ENDPOINT_URL = 'https://s3.amazonaws.com' +); + +-- Show the table schema +SHOW CREATE TABLE mytable; + +CREATE TABLE mytable ( + a INT NULL +) +ENGINE = FUSE +COMPRESSION = 'zstd' +STORAGE_FORMAT = 'parquet' +LOCATION = 's3 | bucket=testbucket,root=/admin/data/,endpoint=https://s3.amazonaws.com'; +``` + +### 使用连接创建表 {#create-a-table-using-a-connection} + +或者,你也可以先创建一个连接,再使用该连接创建表: + +```sql +-- Create a connection named `s3_connection` for the S3 credentials +CREATE CONNECTION s3_connection + STORAGE_TYPE = 's3' + ACCESS_KEY_ID = '' + SECRET_ACCESS_KEY = ''; + +CREATE TABLE mytable ( + a INT +) +'s3://testbucket/admin/data/' +CONNECTION = ( + CONNECTION_NAME = 's3_connection' +); + +-- Show the table schema +SHOW CREATE TABLE mytable; + +CREATE TABLE mytable ( + a INT NULL +) +ENGINE = FUSE +COMPRESSION = 'zstd' +STORAGE_FORMAT = 'parquet' +LOCATION = 's3 | bucket=testbucket,root=/admin/data/,endpoint=https://s3.amazonaws.com'; +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/create-file-format.md b/tidb-cloud-lake/sql/create-file-format.md new file mode 100644 index 0000000000000..5c14775a71ae3 --- /dev/null +++ b/tidb-cloud-lake/sql/create-file-format.md @@ -0,0 +1,70 @@ +--- +title: CREATE FILE FORMAT +summary: 创建命名的文件格式。 +--- + +# CREATE FILE FORMAT + +创建命名的文件格式。 + +## 语法 {#syntax} + +```sql +CREATE [ OR REPLACE ] FILE FORMAT [ IF NOT EXISTS ] FileFormatOptions +``` + +有关 `FileFormatOptions` 的详细信息,请参见[输入与输出文件格式](/tidb-cloud-lake/sql/input-output-file-formats.md)。 + +## 使用文件格式 {#use-the-file-format} + +创建一次,然后在查询和加载中复用该格式: + +```sql +-- 1) Create a reusable format +CREATE OR REPLACE FILE FORMAT my_custom_csv TYPE = CSV FIELD_DELIMITER = '\t'; + +-- 2) Query staged files (stage table function syntax uses =>) +SELECT * FROM @mystage/data.csv (FILE_FORMAT => 'my_custom_csv') LIMIT 10; + +-- 3) Load staged files with COPY INTO (copy options use =) +COPY INTO my_table +FROM @mystage/data.csv +FILE_FORMAT = (FORMAT_NAME = 'my_custom_csv'); +``` + +为什么使用不同的运算符?stage 表函数接受使用 `=>` 编写的键值参数,而 `COPY INTO` 选项使用标准赋值运算符 `=`。 + +**快速工作流:使用同一个格式进行创建、查询和加载** + +```sql +-- Create a reusable format +CREATE FILE FORMAT my_parquet TYPE = PARQUET; + +-- Query staged files with the format (stage table function syntax uses =>) +SELECT * FROM @sales_stage/2024/order.parquet (FILE_FORMAT => 'my_parquet') LIMIT 10; + +-- Load staged files with COPY INTO (copy options use =) +COPY INTO analytics.orders +FROM @sales_stage/2024/order.parquet +FILE_FORMAT = (FORMAT_NAME = 'my_parquet'); +``` + +## LANCE 格式说明 {#lance-format-note} + +你也可以创建命名的 Lance 文件格式: + +```sql +CREATE FILE FORMAT my_lance TYPE = LANCE; +``` + +与 CSV、TSV、NDJSON 或 PARQUET 不同,命名的 `LANCE` 格式只能与 `COPY INTO ` 一起复用。不支持将其用于 stage-table 读取或 `COPY INTO
`,因为 {{{ .lake}}} 写入的是 Lance 数据集目录,而不是独立文件。 + +```sql +COPY INTO @ml_stage/datasets/train +FROM my_training_table +FILE_FORMAT = (FORMAT_NAME = 'my_lance') +USE_RAW_PATH = TRUE +OVERWRITE = TRUE; +``` + +有关 Lance 特有的行为和限制,请参见[输入与输出文件格式](/tidb-cloud-lake/sql/input-output-file-formats.md#lance-options)和[`COPY INTO `](/tidb-cloud-lake/sql/copy-into-location.md)。 \ No newline at end of file diff --git a/tidb-cloud-lake/sql/create-function.md b/tidb-cloud-lake/sql/create-function.md new file mode 100644 index 0000000000000..a50d37c6c960b --- /dev/null +++ b/tidb-cloud-lake/sql/create-function.md @@ -0,0 +1,92 @@ +--- +title: CREATE FUNCTION +summary: 创建一个通过 Flight 调用远程 handler 的外部函数(通常为 Python 或其他服务)。 +--- + +# CREATE FUNCTION + +创建一个通过 Flight 调用远程 handler 的外部函数(通常为 Python 或其他服务)。 + +## 支持的语言 {#supported-languages} + +- 由远程服务器决定(通常为 Python,但只要实现了 Flight endpoint,也可以使用任何语言) + +## 语法 {#syntax} + +```sql +CREATE [ OR REPLACE ] FUNCTION [ IF NOT EXISTS ] + AS ( ) RETURNS LANGUAGE + HANDLER = '' ADDRESS = '' + [DESC=''] +``` + +| 参数 | 描述 | +|-----------------------|---------------------------------------------------------------------------------------------------| +| `` | 函数名称。 | +| `` | 定义函数行为的 lambda 表达式或代码片段。 | +| `DESC=''` | UDF 的描述。| +| `<`| 输入参数名称列表,以逗号分隔。| +| `<`| 输入参数类型列表,以逗号分隔。| +| `` | 函数的返回类型。 | +| `LANGUAGE` | 指定编写函数所使用的语言。可用值:`python`。 | +| `HANDLER = ''` | 指定函数 handler 的名称。 | +| `ADDRESS = ''` | 指定 UDF 服务器的地址。 | + +## 示例 {#examples} + +本示例将演示一个完整的端到端配置过程,用于创建一个计算两个整数最大公约数(GCD)的外部函数。 + +### 第 1 步:设置 Python UDF 服务器 {#step-1-set-up-the-python-udf-server} + +安装 `tidbcloudlake-udf` 包: + +```bash +pip install tidbcloudlake-udf +``` + +创建文件 `udf_server.py`,内容如下: + +```python +from tidbcloudlake_udf import udf, UDFServer + +@udf( + input_types=["INT", "INT"], + result_type="INT", + skip_null=True, +) +def gcd(x: int, y: int) -> int: + while y != 0: + (x, y) = (y, x % y) + return x + +if __name__ == '__main__': + server = UDFServer("0.0.0.0:8815") + server.add_function(gcd) + server.serve() +``` + +启动服务器: + +```bash +python udf_server.py +``` + +### 第 2 步:在 {{{ .lake }}} 中注册函数 {#step-2-register-the-function-in-lake} + +```sql +CREATE FUNCTION gcd AS (INT, INT) + RETURNS INT + LANGUAGE python + HANDLER = 'gcd' + ADDRESS = 'https://udf.example.com'; +``` + +### 第 3 步:调用函数 {#step-3-call-the-function} + +```sql +SELECT gcd(48, 18); +-- Returns: 6 + +SELECT gcd(100, 75); +-- Returns: 25 +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/create-inverted-index.md b/tidb-cloud-lake/sql/create-inverted-index.md new file mode 100644 index 0000000000000..a965984cb790f --- /dev/null +++ b/tidb-cloud-lake/sql/create-inverted-index.md @@ -0,0 +1,281 @@ +--- +title: CREATE INVERTED INDEX +summary: 在 {{{ .lake }}} 中创建一个新的倒排索引。 +--- + +# CREATE INVERTED INDEX + +在 {{{ .lake }}} 中创建一个新的倒排索引。 + +倒排索引通常用于 `STRING` 和 `VARIANT` 列。进行查询时,推荐优先使用 [`QUERY()`](/tidb-cloud-lake/sql/query.md) 函数,因为它支持字段感知表达式、布尔运算符和嵌套路径。你还可以将 [`score()`](/tidb-cloud-lake/sql/score.md) 与 `QUERY()` 一起使用,以返回相关性分数并对匹配的行进行排序。 + +## 语法 {#syntax} + +```sql +CREATE [ OR REPLACE ] INVERTED INDEX [IF NOT EXISTS] + ON [.]
( [, ...] ) + [ ] +``` + +| 参数 | 描述 | +|------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------| +| `[ OR REPLACE ]` | 可选参数,表示如果索引已存在,则将其替换。 | +| `[ IF NOT EXISTS ]` | 可选参数,表示仅当索引尚不存在时才创建该索引。 | +| `` | 要创建的倒排索引名称。 | +| `[.]
` | 包含待创建索引列的数据库和表名称。 | +| `` | 要包含在索引中的列名。实际使用中,这些列通常是 `STRING` 或 `VARIANT` 列。同一张表可以创建多个索引,但每个列在不同索引之间必须唯一。 | +| `` | 可选的索引选项,用于指定如何构建倒排索引。 | + +### IndexOptions {#indexoptions} + +```sql +IndexOptions ::= + TOKENIZER = 'english' | 'chinese' + FILTERS = 'english_stop' | 'english_stemmer' | 'chinese_stop' + INDEX_RECORD = 'position' | 'basic' | 'freq' +``` + +- `TOKENIZER` 指定索引时文本的分词方式。支持 `english`(默认)和 `chinese` 分词器。 +- `FILTERS` 定义词项过滤规则: + - 可以指定多个过滤器,并使用逗号分隔,例如:`FILTERS = 'english_stop,english_stemmer'`。 + - 默认会添加一个 lower case 过滤器,将单词转换为小写字母。 + +| FILTERS | 描述 | +|-------------------|------------------------------------------------------------------------------------------------| +| `english_stop` | 移除英文停用词,例如 "a"、"an"、"and" 等。 | +| `english_stemmer` | 将同一个单词的不同形式映射为一个通用词。例如,"walking" 和 "walked" 都会被映射为 "walk"。 | +| `chinese_stop` | 移除中文停用词,目前仅支持移除中文标点符号。 | + +- `INDEX_RECORD` 决定索引数据中存储的内容: + +| INDEX_RECORD | 默认? | 描述 | +|--------------|--------|------------------------------------------------------------------------------------------------| +| `position` | 是 | 存储 DocId、词频和位置信息,占用空间最多,提供更好的评分效果,并支持短语词项。 | +| `basic` | 否 | 仅存储 DocId,占用空间最小,但不支持如 "brown fox" 这样的短语搜索。 | +| `freq` | 否 | 存储 DocId 和词频,占用空间适中,不支持短语词项,但可能提供更好的评分效果。 | + +## 示例 {#examples} + +### 在单列上创建倒排索引 {#creating-an-inverted-index-on-a-single-column} + +```sql +CREATE TABLE user_comments ( + id INT, + comment_text STRING +); + +CREATE INVERTED INDEX user_comments_idx ON user_comments(comment_text); +``` + +### 使用自定义分词器和过滤器创建倒排索引 {#creating-an-inverted-index-with-custom-tokenizer-and-filters} + +```sql +CREATE TABLE product_reviews ( + id INT, + review_text STRING +); + +-- If no tokenizer is specified, the default is English. +-- Available filters include `english_stop`, `english_stemmer`, and `chinese_stop`. +CREATE INVERTED INDEX product_reviews_idx +ON product_reviews(review_text) +TOKENIZER = 'chinese' +FILTERS = 'english_stop,english_stemmer,chinese_stop' +INDEX_RECORD = 'basic'; +``` + +### 在多列上创建倒排索引 {#creating-an-inverted-index-on-multiple-columns} + +```sql +CREATE TABLE customer_feedback ( + comment_id INT, + comment_title STRING, + comment_body VARIANT +); + +CREATE INVERTED INDEX customer_feedback_idx +ON customer_feedback(comment_title, comment_body); + +SHOW CREATE TABLE customer_feedback; + +*************************** 1. row *************************** + Table: customer_feedback +Create Table: CREATE TABLE customer_feedback ( + comment_id INT NULL, + comment_title VARCHAR NULL, + comment_body VARIANT NULL, + SYNC INVERTED INDEX customer_feedback_idx (comment_title, comment_body) +) ENGINE=FUSE +``` + +### 使用 `QUERY()` 查询单个已建立索引的列 {#querying-a-single-indexed-column-with-query} + +```sql +CREATE TABLE quotes ( + id INT, + content STRING, + INVERTED INDEX idx_content(content) + FILTERS = 'english_stop,english_stemmer' +); + +INSERT INTO quotes VALUES + (1, 'The quick brown fox jumps over the lazy dog'), + (2, 'A picture is worth a thousand words'), + (3, 'Actions speak louder than words'), + (4, 'Time flies like an arrow; fruit flies like a banana'); +``` + +使用 `QUERY()` 搜索已建立索引的列,并通过 `score()` 返回相关性分数: + +```sql +SELECT id, score(), content +FROM quotes +WHERE QUERY('content:word') +ORDER BY score() DESC; +``` + +结果: + +```text +╭──────────────────────────────────────────────────────╮ +│ id │ score() │ content │ +├────┼───────────┼─────────────────────────────────────┤ +│ 2 │ 0.8025914 │ A picture is worth a thousand words │ +│ 3 │ 0.7438652 │ Actions speak louder than words │ +╰──────────────────────────────────────────────────────╯ +``` + +你也可以执行模糊搜索: + +```sql +SELECT id, score(), content +FROM quotes +WHERE QUERY('content:box', 'fuzziness=1'); +``` + +结果: + +```text +╭────────────────────────────────────────────────────────────╮ +│ id │ score() │ content │ +├────┼─────────┼─────────────────────────────────────────────┤ +│ 1 │ 1.0 │ The quick brown fox jumps over the lazy dog │ +╰────────────────────────────────────────────────────────────╯ +``` + +### 使用 `QUERY()` 查询多个已建立索引的列 {#querying-multiple-indexed-columns-with-query} + +```sql +CREATE TABLE books ( + id INT, + title STRING, + author STRING, + description STRING +); + +CREATE INVERTED INDEX idx_books +ON books(title, author, description) +TOKENIZER = 'chinese' +FILTERS = 'english_stop,english_stemmer,chinese_stop'; + +INSERT INTO books VALUES + (1, '这就是ChatGPT', '斯蒂芬·沃尔弗拉姆', 'ChatGPT 是 OpenAI 开发的人工智能聊天机器人程序。'), + (2, 'Python深度学习(第2版)', '弗朗索瓦·肖莱', '本书通过 Python 代码讲解深度学习的核心思想。'), + (3, 'Vue.js设计与实现', '霍春阳', '本书从规范和源码出发,讲解 Vue.js 框架设计与实现细节。'), + (4, '前端架构设计', '迈卡·高保特', '本书探讨前端架构原则、工作流程和工程实践。'); +``` + +使用 `QUERY()` 执行带字段感知的布尔搜索: + +```sql +SELECT id, score(), title +FROM books +WHERE QUERY('title:设计 OR title:实现') +ORDER BY score() DESC; +``` + +结果: + +```text +╭───────────────────────────────────╮ +│ id │ score() │ title │ +├────┼───────────┼──────────────────┤ +│ 3 │ 1.8571336 │ Vue.js设计与实现 │ +│ 4 │ 0.6785374 │ 前端架构设计 │ +╰───────────────────────────────────╯ +``` + +你也可以同时搜索多个字段: + +```sql +SELECT id, score(), title +FROM books +WHERE QUERY('title:ChatGPT OR description:OpenAI') +ORDER BY score() DESC; +``` + +结果: + +```text +╭───────────────────────────────────╮ +│ id │ score() │ title │ +├────┼───────────┼──────────────────┤ +│ 1 │ 2.5784383 │ 这就是ChatGPT │ +╰───────────────────────────────────╯ +``` + +### 使用 `QUERY()` 查询 `VARIANT` 列 {#querying-a-variant-column-with-query} + +也支持 `VARIANT` 列。当你希望搜索嵌套的类 JSON 文档而不先将其扁平化时,这会非常有用。 + +```sql +CREATE TABLE media_assets ( + id INT, + body VARIANT, + INVERTED INDEX idx_body(body) +); + +INSERT INTO media_assets VALUES + (1, '{"videoInfo":{"extraData":[{"name":"codecA","type":"mp4"},{"name":"codecB","type":"jpg"}]}}'), + (2, '{"videoInfo":{"extraData":[{"name":"codecA","type":"jpg"},{"name":"codecA","type":"mp4"}]}}'), + (3, '{"videoInfo":{"extraData":[{"name":"codecA","attributes":{"type":"jpg"}},{"name":"codecB","attributes":{"type":"mp4"}}]}}'), + (4, '{"videoInfo":{"extraData":[{"name":"codec foo","type":"mp4"}]}}'); +``` + +查询 `VARIANT` 文档中的嵌套路径: + +```sql +SELECT id, body +FROM media_assets +WHERE QUERY('body.videoInfo.extraData.name:codecA AND body.videoInfo.extraData.type:jpg') +ORDER BY id; +``` + +结果: + +```text +╭──────────────────────────────────────────────────────────────────────────────────────────────────╮ +│ id │ body │ +├────┼─────────────────────────────────────────────────────────────────────────────────────────────┤ +│ 2 │ {"videoInfo":{"extraData":[{"name":"codecA","type":"jpg"},{"name":"codecA","type":"mp4"}]}} │ +╰──────────────────────────────────────────────────────────────────────────────────────────────────╯ +``` + +对于包含空格的值,也可以使用带引号的词项: + +```sql +SELECT id, body +FROM media_assets +WHERE QUERY('body.videoInfo.extraData.name:"codec foo" AND body.videoInfo.extraData.type:mp4') +ORDER BY id; +``` + +结果: + +```text +╭──────────────────────────────────────────────────────────────────────╮ +│ id │ body │ +├────┼─────────────────────────────────────────────────────────────────┤ +│ 4 │ {"videoInfo":{"extraData":[{"name":"codec foo","type":"mp4"}]}} │ +╰──────────────────────────────────────────────────────────────────────╯ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/create-masking-policy.md b/tidb-cloud-lake/sql/create-masking-policy.md new file mode 100644 index 0000000000000..48b565460c552 --- /dev/null +++ b/tidb-cloud-lake/sql/create-masking-policy.md @@ -0,0 +1,97 @@ +--- +title: CREATE MASKING POLICY +summary: 在 {{{ .lake }}} 中创建新的 masking policy。 +--- + +# CREATE MASKING POLICY + +在 {{{ .lake }}} 中创建新的 masking policy。 + +## 语法 {#syntax} + +```sql +CREATE MASKING POLICY [ IF NOT EXISTS ] AS + ( [ , ... ] ) + RETURNS -> + [ COMMENT = '' ] +``` + +| 参数 | 描述 | +|------------------------|-------------| +| `policy_name` | 要创建的 masking policy 名称。 | +| `arg_name_to_mask` | 表示被脱敏列的参数。该参数必须放在第一位,并会自动绑定到 `SET MASKING POLICY` 中引用的列。 | +| `arg_type_to_mask` | 被脱敏列的数据类型。它必须与应用该策略的列的数据类型一致。 | +| `arg_1 ... arg_n` | 可选的额外参数,用于策略逻辑所依赖的其他列。附加策略时,通过 `USING` 子句提供这些列。 | +| `arg_type_1 ... arg_type_n` | 每个可选参数的数据类型。它们必须与 `USING` 子句中列出的列类型一致。 | +| `expression_on_arg_name` | 用于决定如何处理输入列以生成脱敏数据的表达式。 | +| `comment` | 可选注释,用于存储有关 masking policy 的说明。 | + +> **注意:** +> +> 请确保 *arg_type_to_mask* 与将要应用 masking policy 的列的数据类型一致。当策略定义了多个参数时,请在 `ALTER TABLE ... SET MASKING POLICY` 的 `USING` 子句中,按照相同顺序列出每个被引用的列。 + +## 访问控制要求 {#access-control-requirements} + +| 权限 | 描述 | +|:----------|:------------| +| CREATE MASKING POLICY | 创建 masking policy 所需的权限。通常授予在 `*.*` 上。 | + +{{{ .lake }}} 会自动将新 masking policy 的 OWNERSHIP 授予当前角色,以便其管理该策略并与其他人协作。 + +## 示例 {#examples} + +本示例演示了如何设置 masking policy,以便根据用户角色有选择地显示或隐藏敏感数据。 + +```sql +-- Create a table and insert sample data +CREATE TABLE user_info ( + user_id INT, + phone VARCHAR, + email VARCHAR +); + +INSERT INTO user_info (user_id, phone, email) VALUES (1, '91234567', 'sue@example.com'); +INSERT INTO user_info (user_id, phone, email) VALUES (2, '81234567', 'eric@example.com'); + +-- Create a role +CREATE ROLE 'MANAGERS'; +GRANT ALL ON *.* TO ROLE 'MANAGERS'; + +-- Create a user and grant the role to the user +CREATE USER manager_user IDENTIFIED BY 'datalake'; +GRANT ROLE 'MANAGERS' TO 'manager_user'; + +-- Create a masking policy that expects an extra column +CREATE MASKING POLICY contact_mask +AS + (contact_val nullable(string), phone_ref nullable(string)) + RETURNS nullable(string) -> + CASE + WHEN current_role() IN ('MANAGERS') THEN + contact_val + WHEN phone_ref LIKE '91%' + THEN + contact_val + ELSE + '*********' + END + COMMENT = 'mask contact data with phone check'; + +-- Associate the masking policy with the 'email' column +ALTER TABLE user_info +MODIFY COLUMN email SET MASKING POLICY contact_mask USING (email, phone); + +-- Associate the masking policy with the 'phone' column +ALTER TABLE user_info +MODIFY COLUMN phone SET MASKING POLICY contact_mask USING (phone, phone); + +-- Query with the Root user +SELECT user_id, phone, email FROM user_info ORDER BY user_id; + + user_id │ phone │ email │ + Nullable(Int32) │ Nullable(String) │ Nullable(String) │ +─────────────────┼──────────────────┼──────────────────┤ + 1 │ 91234567 │ sue@example.com │ + 2 │ ********* │ ********* │ + +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/create-network-policy.md b/tidb-cloud-lake/sql/create-network-policy.md new file mode 100644 index 0000000000000..2bf739f766991 --- /dev/null +++ b/tidb-cloud-lake/sql/create-network-policy.md @@ -0,0 +1,48 @@ +--- +title: CREATE NETWORK POLICY +summary: 在 {{{ .lake }}} 中创建新的网络策略。 +--- + +# CREATE NETWORK POLICY + +在 {{{ .lake }}} 中创建新的网络策略。 + +## 语法 {#syntax} + +```sql +CREATE [ OR REPLACE ] NETWORK POLICY [ IF NOT EXISTS ] + ALLOWED_IP_LIST = ( 'allowed_ip1', 'allowed_ip2', ... ) + [ BLOCKED_IP_LIST = ( 'blocked_ip1', 'blocked_ip2', ...) ] + [ COMMENT = 'comment' ] +``` + +| 参数 | 描述 | +|----------------- |-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| policy_name | 指定要创建的网络策略名称。 | +| ALLOWED_IP_LIST | 指定策略允许的 IP 地址范围列表,多个地址范围之间以逗号分隔。与此策略关联的用户可以使用指定的 IP 范围访问网络。 | +| BLOCKED_IP_LIST | 指定策略阻止的 IP 地址范围列表,多个地址范围之间以逗号分隔。与此策略关联的用户仍然可以从 ALLOWED_IP_LIST 中的 IP 范围访问网络,但 BLOCKED_IP_LIST 中指定的 IP 将被限制访问。 | +| COMMENT | 可选参数,用于为网络策略添加描述或注释。 | + +## 示例 {#examples} + +以下示例演示了如何创建一个包含指定允许和阻止 IP 地址的网络策略,然后将该策略与用户关联以控制网络访问。该网络策略允许从 192.168.1.0 到 192.168.1.255 的所有 IP 地址,但特定 IP 地址 192.168.1.99 除外。 + +```sql +-- Create a network policy +CREATE NETWORK POLICY sample_policy + ALLOWED_IP_LIST=('192.168.1.0/24') + BLOCKED_IP_LIST=('192.168.1.99') + COMMENT='Sample'; + +SHOW NETWORK POLICIES; + +Name |Allowed Ip List |Blocked Ip List|Comment | +-------------+-------------------------+---------------+-----------+ +sample_policy|192.168.1.0/24 |192.168.1.99 |Sample | + +-- Create a user +CREATE USER sample_user IDENTIFIED BY 'datalake'; + +-- Associate the network policy with the user +ALTER USER sample_user WITH SET NETWORK POLICY='sample_policy'; +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/create-ngram-index.md b/tidb-cloud-lake/sql/create-ngram-index.md new file mode 100644 index 0000000000000..b57325d9d9925 --- /dev/null +++ b/tidb-cloud-lake/sql/create-ngram-index.md @@ -0,0 +1,117 @@ +--- +title: CREATE NGRAM INDEX +summary: 在表的列上创建 Ngram 索引。 +--- + +# CREATE NGRAM INDEX + +在表的列上创建 Ngram 索引。 + +## 语法 {#syntax} + +```sql +-- Create an Ngram index on an existing table +CREATE [OR REPLACE] NGRAM INDEX [IF NOT EXISTS] +ON [.]() +[gram_size = ] [bloom_size = ] + +-- Create an Ngram index when creating a table +CREATE [OR REPLACE] TABLE ( + , + NGRAM INDEX () + [gram_size = ] [bloom_size = ] +)... +``` + +- `gram_size`(默认为 3)指定在为列文本建立索引时,每个基于字符的子字符串(n-gram)的长度。例如,当 `gram_size = 3` 时,文本 `"hello world"` 会被切分为如下重叠的子字符串: + + ```text + "hel", "ell", "llo", "lo ", "o w", " wo", "wor", "orl", "rld" + ``` + +- `bloom_size` 指定用于加速每个数据块内字符串匹配的布隆过滤器位图大小(以字节为单位)。它控制索引准确性与内存使用之间的权衡: + + - 较大的 `bloom_size` 会减少字符串查找中的误报,从而提高查询精度,但会占用更多内存。 + - 较小的 `bloom_size` 可以节省内存,但可能会增加误报。 + - 如果未显式设置,默认值为每个已索引列、每个数据块 1,048,576 字节(1m)。有效范围为 512 字节到 10,485,760 字节(10m)。 + +## 示例 {#examples} + +### 创建带有 NGRAM 索引的表 {#creating-a-table-with-ngram-index} + +```sql +CREATE TABLE articles ( + id INT, + title VARCHAR, + content STRING, + NGRAM INDEX idx_content (content) +); +``` + +### 在现有表上创建 NGRAM 索引 {#creating-an-ngram-index-on-an-existing-table} + +```sql +CREATE TABLE products ( + id INT, + name VARCHAR, + description STRING +); + +CREATE NGRAM INDEX idx_description +ON products(description); +``` + +### 查看索引 {#viewing-indexes} + +```sql +SHOW INDEXES; +``` + +结果: + +``` +┌─────────────────┬───────┬──────────┬─────────────────────────┬──────────────────────────┐ +│ name │ type │ original │ definition │ created_on │ +├─────────────────┼───────┼──────────┼─────────────────────────┼──────────────────────────┤ +│ idx_content │ NGRAM │ │ articles(content) │ 2025-05-13 01:22:34.123 │ +│ idx_description │ NGRAM │ │ products(description) │ 2025-05-13 01:23:45.678 │ +└─────────────────┴───────┴──────────┴─────────────────────────┴──────────────────────────┘ +``` + +### 使用 NGRAM 索引 {#using-ngram-index} + +```sql +-- Create a table with NGRAM index +CREATE TABLE phrases ( + id INT, + text STRING, + NGRAM INDEX idx_text (text) +); + +-- Insert sample data +INSERT INTO phrases VALUES +(1, 'apple banana cherry'), +(2, 'banana date fig'), +(3, 'cherry elderberry fig'), +(4, 'date grape kiwi'); + +-- Query using fuzzy matching with the NGRAM index +SELECT * FROM phrases WHERE text LIKE '%banana%'; +``` + +结果: + +``` +┌────┬─────────────────────┐ +│ id │ text │ +├────┼─────────────────────┤ +│ 1 │ apple banana cherry │ +│ 2 │ banana date fig │ +└────┴─────────────────────┘ +``` + +### 删除 NGRAM 索引 {#dropping-an-ngram-index} + +```sql +DROP NGRAM INDEX idx_text ON phrases; +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/create-notification-integration.md b/tidb-cloud-lake/sql/create-notification-integration.md new file mode 100644 index 0000000000000..f9c3081dea03d --- /dev/null +++ b/tidb-cloud-lake/sql/create-notification-integration.md @@ -0,0 +1,44 @@ +--- +title: CREATE NOTIFICATION INTEGRATION +summary: 创建一个命名的通知集成,可用于向外部消息服务发送通知。 +--- + +# CREATE NOTIFICATION INTEGRATION + +创建一个命名的通知集成,可用于向外部消息服务发送通知。 + +**NOTICE:** 此功能仅在 {{{ .lake }}} 中开箱即用。 + +## 语法 {#syntax} + +### Webhook 通知 {#webhook-notification} + +```sql +CREATE NOTIFICATION INTEGRATION [ IF NOT EXISTS ] +TYPE = +ENABLED = +[ WEBHOOK = ( url = , method = , authorization_header = ) ] +[ COMMENT = '' ] +``` + +| 必需参数 | 描述 | +|---------------------|-------------| +| name | 通知集成的名称。这是一个必填字段。 | +| type | 通知集成的类型。目前仅支持 `webhook`。 | +| enabled | 通知集成是否启用。 | + +| 可选参数 [(Webhook)](#webhook-notification) | 描述 | +|---------------------|-------------| +| url | webhook 的 URL。 | +| method | 发送 webhook 时使用的 HTTP 方法。默认值为 `GET` | +| authorization_header| 发送 webhook 时使用的授权请求头。 | + +## 示例 {#examples} + +### Webhook 通知 {#webhook-notification} + +```sql +CREATE NOTIFICATION INTEGRATION IF NOT EXISTS SampleNotification type = webhook enabled = true webhook = (url = 'https://example.com', method = 'GET', authorization_header = 'bearer auth') +``` + +此示例创建了一个名为 `SampleNotification`、类型为 `webhook` 的通知集成。该集成已启用,并使用 `GET` 方法和 `bearer auth` 授权请求头向 `https://example.com` URL 发送通知。 \ No newline at end of file diff --git a/tidb-cloud-lake/sql/create-password-policy.md b/tidb-cloud-lake/sql/create-password-policy.md new file mode 100644 index 0000000000000..92f26b6244f08 --- /dev/null +++ b/tidb-cloud-lake/sql/create-password-policy.md @@ -0,0 +1,53 @@ +--- +title: CREATE PASSWORD POLICY +summary: 在 {{{ .lake }}} 中创建新的密码策略。 +--- + +# CREATE PASSWORD POLICY + +在 {{{ .lake }}} 中创建新的密码策略。 + +## 语法 {#syntax} + +```sql +CREATE [ OR REPLACE ] PASSWORD POLICY [ IF NOT EXISTS ] + [ PASSWORD_MIN_LENGTH = ] + [ PASSWORD_MAX_LENGTH = ] + [ PASSWORD_MIN_UPPER_CASE_CHARS = ] + [ PASSWORD_MIN_LOWER_CASE_CHARS = ] + [ PASSWORD_MIN_NUMERIC_CHARS = ] + [ PASSWORD_MIN_SPECIAL_CHARS = ] + [ PASSWORD_MIN_AGE_DAYS = ] + [ PASSWORD_MAX_AGE_DAYS = ] + [ PASSWORD_MAX_RETRIES = ] + [ PASSWORD_LOCKOUT_TIME_MINS = ] + [ PASSWORD_HISTORY = ] + [ COMMENT = '' ] +``` + +### 密码策略属性 {#password-policy-attributes} + +下表汇总了密码策略的关键参数,涵盖长度、字符要求、有效期限制、重试次数限制、锁定时长以及密码历史等方面: + +| 属性 | 最小值 | 最大值 | 默认值 | 描述 | +|-------------------------------|-----|-----|---------|--------------------------------------------------------------------------------------| +| PASSWORD_MIN_LENGTH | 8 | 256 | 8 | 密码的最小长度 | +| PASSWORD_MAX_LENGTH | 8 | 256 | 256 | 密码的最大长度 | +| PASSWORD_MIN_UPPER_CASE_CHARS | 0 | 256 | 1 | 密码中大写字符的最小数量 | +| PASSWORD_MIN_LOWER_CASE_CHARS | 0 | 256 | 1 | 密码中小写字符的最小数量 | +| PASSWORD_MIN_NUMERIC_CHARS | 0 | 256 | 1 | 密码中数字字符的最小数量 | +| PASSWORD_MIN_SPECIAL_CHARS | 0 | 256 | 0 | 密码中特殊字符的最小数量 | +| PASSWORD_MIN_AGE_DAYS | 0 | 999 | 0 | 密码可被修改前所需的最少天数(0 表示无限制) | +| PASSWORD_MAX_AGE_DAYS | 0 | 999 | 90 | 密码必须修改前允许的最长天数(0 表示无限制) | +| PASSWORD_MAX_RETRIES | 1 | 10 | 5 | 触发锁定前允许的最大密码重试次数 | +| PASSWORD_LOCKOUT_TIME_MINS | 1 | 999 | 15 | 超过重试次数后锁定的持续时间,单位为分钟 | +| PASSWORD_HISTORY | 0 | 24 | 0 | 用于检查是否重复的最近密码数量(0 表示无限制) | + +## 示例 {#examples} + +以下示例创建了一个名为 `SecureLogin` 的密码策略,并将密码最小长度要求设置为 10 个字符: + +```sql +CREATE PASSWORD POLICY SecureLogin + PASSWORD_MIN_LENGTH = 10; +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/create-pipe.md b/tidb-cloud-lake/sql/create-pipe.md new file mode 100644 index 0000000000000..e980c05cefc5c --- /dev/null +++ b/tidb-cloud-lake/sql/create-pipe.md @@ -0,0 +1,38 @@ +--- +title: CREATE PIPE +summary: "了解如何在 {{{ .lake }}} 中使用 CREATE PIPE 命令创建摄取管道。" +--- + +# CREATE PIPE + +创建一个由 `COPY INTO
` 语句支持的 pipe。 + +## 语法 {#syntax} + +```sql +CREATE PIPE [ IF NOT EXISTS ] + [ AUTO_INGEST = TRUE ] + [ COMMENT = '' | COMMENTS = '' ] +AS +COPY INTO
... +``` + +## 参数 {#parameters} + +| 参数 | 描述 | +|-----------|-------------| +| `IF NOT EXISTS` | 可选。如果 pipe 已存在,则成功返回且不做任何更改。 | +| `AUTO_INGEST = TRUE` | 可选。启用自动摄取。 | +| `COMMENT` / `COMMENTS` | 可选的 pipe 注释。 | +| `AS COPY INTO ...` | 由 pipe 执行的 `COPY INTO
` 语句。 | + +## 示例 {#example} + +```sql +CREATE PIPE IF NOT EXISTS my_pipe +AUTO_INGEST = TRUE +COMMENTS = 'load staged files into target table' +AS +COPY INTO my_table +FROM @my_stage; +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/create-procedure.md b/tidb-cloud-lake/sql/create-procedure.md new file mode 100644 index 0000000000000..4be6c30e49fc3 --- /dev/null +++ b/tidb-cloud-lake/sql/create-procedure.md @@ -0,0 +1,96 @@ +--- +title: CREATE PROCEDURE +summary: 定义一个执行 SQL 操作并返回结果的存储过程。 +--- + +# CREATE PROCEDURE + +定义一个执行 SQL 操作并返回结果的存储过程。 + +## 语法 {#syntax} + +```sql +CREATE PROCEDURE ( , ...) +RETURNS [NOT NULL] +LANGUAGE +[ COMMENT '' ] +AS $$ +BEGIN + + RETURN ; -- Use to return a single value + -- OR + RETURN TABLE(); -- Use to return a table +END; +$$; +``` + +| 参数 | 描述 | +|-----------------------------------------|---------------------------------------------------------------------------------------------------------------------------| +| `` | 存储过程的名称。 | +| ` ` | 输入参数(可选),每个参数都需要指定数据类型。可以定义多个参数,并使用逗号分隔。 | +| `RETURNS [NOT NULL]` | 指定返回值的数据类型。`NOT NULL` 可确保返回的值不能为 NULL。 | +| `LANGUAGE` | 指定存储过程主体所使用的语言。目前仅支持 `SQL`。 | +| `COMMENT` | 用于描述该存储过程的可选文本。 | +| `AS ...` | 包含存储过程主体,其中可以包括 SQL 语句、变量声明、循环以及 RETURN 语句。 | + +## 访问控制要求 {#access-control-requirements} + +| 权限 | 对象类型 | 描述 | +|:-----------------|:------------|:---------------------| +| CREATE PROCEDURE | Global | 创建存储过程。 | + +要创建存储过程,执行该操作的用户或 [current_role](/tidb-cloud-lake/guides/roles.md) 必须具有 CREATE PROCEDURE [权限](/tidb-cloud-lake/guides/privileges.md)。 + +## 示例 {#examples} + +以下示例定义了一个将重量从千克(kg)转换为磅(lb)的存储过程: + +```sql +CREATE PROCEDURE convert_kg_to_lb(kg DECIMAL(4, 2)) +RETURNS DECIMAL(10, 2) +LANGUAGE SQL +COMMENT = 'Converts kilograms to pounds' +AS $$ +BEGIN + RETURN kg * 2.20462; +END; +$$; +``` + +你还可以定义一个使用循环、条件和动态变量的存储过程。 + +```sql + +CREATE OR REPLACE PROCEDURE loop_test() +RETURNS INT +LANGUAGE SQL +COMMENT = 'loop test' +AS $$ +BEGIN + LET x RESULTSET := select number n from numbers(10); + LET sum := 0; + FOR x IN x DO + FOR batch in 0 TO x.n DO + IF batch % 2 = 0 THEN + sum := sum + batch; + ELSE + sum := sum - batch; + END IF; + END FOR; + END FOR; + RETURN sum; +END; +$$; + +-- Grant ACCESS PROCEDURE Privilege TO role test +GRANT ACCESS PROCEDURE ON PROCEDURE loop_test() to role test; + +``` + +```sql +CALL PROCEDURE loop_test(); + +┌─Result─┐ +│ -5 │ +└────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/create-role.md b/tidb-cloud-lake/sql/create-role.md new file mode 100644 index 0000000000000..b0473e07a1227 --- /dev/null +++ b/tidb-cloud-lake/sql/create-role.md @@ -0,0 +1,83 @@ +--- +title: CREATE ROLE +summary: 创建一个新的角色用于访问控制。角色用于对权限进行分组,并且可以分配给用户或其他角色,从而在 {{{ .lake }}} 中提供一种灵活的权限管理方式。 +--- + +# CREATE ROLE + +创建一个新的角色用于访问控制。角色用于对权限进行分组,并且可以分配给用户或其他角色,从而在 {{{ .lake }}} 中提供一种灵活的权限管理方式。 + +## 语法 {#syntax} + +```sql +CREATE ROLE [ IF NOT EXISTS ] +``` + +**参数:** + +- `IF NOT EXISTS`:仅当角色不存在时才创建该角色(推荐使用以避免错误) +- ``:角色名称(不能包含单引号、双引号、退格符或换页符) + +## 示例 {#examples} + +```sql +-- Create a basic role +CREATE ROLE analyst; + +-- Create role only if it doesn't exist (recommended) +CREATE ROLE IF NOT EXISTS data_viewer; +``` + +## 常见用法模式 {#common-usage-patterns} + +### 只读分析师角色 {#read-only-analyst-role} + +为需要对销售数据具有读访问权限的数据分析师创建一个角色: + +```sql +-- Create the analyst role +CREATE ROLE sales_analyst; + +-- Grant read permissions +GRANT SELECT ON sales_db.* TO ROLE sales_analyst; + +-- Assign to users +GRANT ROLE sales_analyst TO 'alice'; +GRANT ROLE sales_analyst TO 'bob'; +``` + +### 数据库管理员角色 {#database-administrator-role} + +为需要完全控制权限的管理员创建一个角色: + +```sql +-- Create the admin role +CREATE ROLE sales_admin; + +-- Grant full permissions on the database +GRANT ALL ON sales_db.* TO ROLE sales_admin; + +-- Grant user management permissions +GRANT CREATE USER, CREATE ROLE ON *.* TO ROLE sales_admin; + +-- Assign to admin users +GRANT ROLE sales_admin TO 'admin_user'; +``` + +### 验证 {#verification} + +```sql +-- Check what each role can do +SHOW GRANTS FOR ROLE sales_analyst; +SHOW GRANTS FOR ROLE sales_admin; + +-- Check user permissions +SHOW GRANTS FOR 'alice'; +SHOW GRANTS FOR 'admin_user'; +``` + +## 另请参阅 {#see-also} + +- [GRANT](/tidb-cloud-lake/sql/grant.md) - 授予权限和角色 +- [SHOW GRANTS](/tidb-cloud-lake/sql/show-grants.md) - 查看已授予的权限 +- [DROP ROLE](/tidb-cloud-lake/sql/drop-role.md) - 删除角色 \ No newline at end of file diff --git a/tidb-cloud-lake/sql/create-row-access-policy.md b/tidb-cloud-lake/sql/create-row-access-policy.md new file mode 100644 index 0000000000000..8da0a2f24df62 --- /dev/null +++ b/tidb-cloud-lake/sql/create-row-access-policy.md @@ -0,0 +1,83 @@ +--- +title: CREATE ROW ACCESS POLICY +summary: "在 {{{ .lake }}} 中创建新的行访问策略。行访问策略定义了一个布尔谓词,当该策略附加到表时,{{{ .lake }}} 会将其应用到行上。" +--- + +# CREATE ROW ACCESS POLICY + +在 {{{ .lake }}} 中创建新的行访问策略。行访问策略定义了一个布尔谓词,当该策略附加到表时,{{{ .lake }}} 会将其应用到行上。 + +## 语法 {#syntax} + +```sql +CREATE ROW ACCESS POLICY [ IF NOT EXISTS ] AS + ( [ , ... ] ) + RETURNS BOOLEAN -> + [ COMMENT = '' ] +``` + +| 参数 | 描述 | +|-----------|-------------| +| `policy_name` | 要创建的行访问策略名称。策略名称与 masking policies 共享同一个命名空间。 | +| `arg_name` | 在谓词表达式内部使用的策略参数名称。参数名称不需要与表列名匹配。 | +| `arg_type` | 参数的数据类型。附加策略时,列出的每个表列都必须与对应参数的类型匹配。 | +| `predicate_expression` | 用于决定某一行是否可见的布尔表达式。仅当该表达式计算结果为 `TRUE` 时,才会返回该行。 | +| `comment` | 可选注释,用于存储有关该策略的说明。 | + +> **注意:** +> +> - 行访问策略当前仍处于实验阶段。可使用 `SET enable_experimental_row_access_policy = 1` 或 `SET GLOBAL enable_experimental_row_access_policy = 1` 启用。 +> - 该策略必须返回 `BOOLEAN`。 +> - `ALTER TABLE ... ADD ROW ACCESS POLICY ... ON (...)` 中列出的列会按位置绑定到策略参数。 +> - 行访问策略定义中不支持子查询谓词。 + +## 访问控制要求 {#access-control-requirements} + +| 权限 | 描述 | +|:----------|:------------| +| CREATE ROW ACCESS POLICY | 创建行访问策略所需的权限。通常授予在 `*.*` 上。 | + +{{{ .lake }}} 会自动将新行访问策略的 OWNERSHIP 授予当前角色,以便其能够与其他对象一样管理该策略。 + +## 示例 {#examples} + +以下示例创建了一个策略:仅暴露 `Engineering` 部门的行,除非当前角色为 `admin`。 + +```sql +SET enable_experimental_row_access_policy = 1; + +CREATE TABLE employees ( + id INT, + name STRING, + department STRING +); + +INSERT INTO employees VALUES + (1, 'Alice', 'Engineering'), + (2, 'Bob', 'Sales'), + (3, 'Charlie', 'Engineering'); + +CREATE ROW ACCESS POLICY rap_engineering +AS (dept STRING) +RETURNS BOOLEAN -> + CASE + WHEN current_role() = 'admin' THEN true + WHEN dept = 'Engineering' THEN true + ELSE false + END + COMMENT = 'show engineering rows'; + +ALTER TABLE employees +ADD ROW ACCESS POLICY rap_engineering ON (department); + +SELECT id, name, department FROM employees ORDER BY id; + +┌────┬─────────┬─────────────┐ +│ id │ name │ department │ +├────┼─────────┼─────────────┤ +│ 1 │ Alice │ Engineering │ +│ 3 │ Charlie │ Engineering │ +└────┴─────────┴─────────────┘ +``` + +`ON (department)` 子句将表列 `department` 映射到策略参数 `dept`。 \ No newline at end of file diff --git a/tidb-cloud-lake/sql/create-scalar-function.md b/tidb-cloud-lake/sql/create-scalar-function.md new file mode 100644 index 0000000000000..4ef86b7e5637e --- /dev/null +++ b/tidb-cloud-lake/sql/create-scalar-function.md @@ -0,0 +1,237 @@ +--- +title: CREATE SCALAR FUNCTION +summary: 创建标量用户定义函数(Scalar UDF)。同一个 CREATE FUNCTION 语句支持两种实现方式。 +--- + +# CREATE SCALAR FUNCTION + +创建标量用户定义函数(Scalar UDF)。同一个 `CREATE FUNCTION` 语句支持两种实现方式: + +- **SQL expression**:仅使用 SQL 表达逻辑;不需要外部运行时。 +- **Python / JavaScript**:编写代码,并使用 `HANDLER` 指定入口点。 + +如果你需要调用外部系统(HTTP/服务),请参见 External Function 命令。 + +## 语法 {#syntax} + +### SQL(expression) {#sql-expression} + +```sql +CREATE [ OR REPLACE ] FUNCTION [ IF NOT EXISTS ] + ( [] ) + RETURNS + AS $$ $$ + [ DESC='' ] +``` + +### Python / JavaScript {#python-javascript} + +```sql +CREATE [ OR REPLACE ] FUNCTION [ IF NOT EXISTS ] + ( [] ) + RETURNS + LANGUAGE + [IMPORTS = ('', ...)] + [PACKAGES = ('', ...)] + HANDLER = '' + AS $$ $$ + [ DESC='' ] +``` + +## 参数 {#parameters} + +- ``:可选的逗号分隔参数列表及其类型(例如:`x INT, y FLOAT`) +- ``:函数返回值的数据类型 +- ``:`python`、`javascript` +- ``:要导入的 stage 文件(例如:`@s_udf/your_file.zip`) +- ``:从 PyPI 安装的包(仅 Python;例如 `numpy`) +- ``:代码中要调用的函数名称 +- ``:使用指定语言编写的实现代码 + +## 访问控制要求 {#access-control-requirements} + +| 权限 | 对象类型 | 描述 | +|:----------|:--------------|:---------------| +| SUPER | 全局, Table | 操作 UDF | + +要创建用户定义函数,执行该操作的用户或 [current_role](/tidb-cloud-lake/guides/roles.md) 必须具有 SUPER [权限](/tidb-cloud-lake/guides/privileges.md)。 + +## SQL {#sql} + +```sql +-- Create a function to calculate area of a circle +CREATE OR REPLACE FUNCTION area_of_circle(radius FLOAT) +RETURNS FLOAT +AS $$ + pi() * radius * radius +$$; + +-- Create a function to calculate age in years +CREATE OR REPLACE FUNCTION calculate_age(birth_date DATE) +RETURNS INT +AS $$ + date_diff('year', birth_date, now()) +$$; + +-- Create a function with multiple parameters +CREATE OR REPLACE FUNCTION calculate_bmi(weight_kg FLOAT, height_m FLOAT) +RETURNS FLOAT +AS $$ + weight_kg / (height_m * height_m) +$$; + +-- Use the functions +SELECT area_of_circle(5.0) AS circle_area; +SELECT calculate_age(to_date('1990-05-15')) AS age; +SELECT calculate_bmi(70.0, 1.75) AS bmi; +``` + +## Python {#python} + +Python 运行时需要 {{{ .lake }}} Enterprise。你可以通过 `PACKAGES` 安装 PyPI 包,并通过 `IMPORTS` 导入 stage 文件。 + +### 数据类型映射(Python) {#data-type-mappings-python} + +| {{{ .lake }}} 类型 | Python 类型 | +|--------------|-------------| +| NULL | None | +| BOOLEAN | bool | +| INT | int | +| FLOAT/DOUBLE | float | +| DECIMAL | decimal.Decimal | +| VARCHAR | str | +| BINARY | bytes | +| LIST | list | +| MAP | dict | +| STRUCT | object | +| JSON | dict/list | + +### 示例 {#examples} + +```sql +CREATE OR REPLACE FUNCTION calculate_age_py(VARCHAR) +RETURNS INT +LANGUAGE python +HANDLER = 'calculate_age' +AS $$ +from datetime import datetime + +def calculate_age(birth_date_str): + birth_date = datetime.strptime(birth_date_str, '%Y-%m-%d') + today = datetime.now() + age = today.year - birth_date.year + if (today.month, today.day) < (birth_date.month, birth_date.day): + age -= 1 + return age +$$; + +SELECT calculate_age_py('1990-05-15') AS age; +``` + +```sql +CREATE OR REPLACE FUNCTION numpy_sqrt(FLOAT) +RETURNS FLOAT +LANGUAGE python +PACKAGES = ('numpy') +HANDLER = 'numpy_sqrt' +AS $$ +import numpy as np + +def numpy_sqrt(x): + return float(np.sqrt(x)) +$$; + +SELECT numpy_sqrt(9.0) AS sqrt_val; +``` + +## JavaScript {#javascript} + +### 数据类型映射(JavaScript) {#data-type-mappings-javascript} + +| {{{ .lake }}} 类型 | JavaScript 类型 | +|--------------|----------------| +| NULL | null | +| BOOLEAN | Boolean | +| INT | Number | +| FLOAT/DOUBLE | Number | +| DECIMAL | BigDecimal | +| VARCHAR | String | +| BINARY | Uint8Array | +| DATE/TIMESTAMP | Date | +| ARRAY | Array | +| MAP | Object | +| STRUCT | Object | +| JSON | Object/Array | + +### 示例 {#example} + +```sql +CREATE OR REPLACE FUNCTION calculate_age_js(VARCHAR) +RETURNS INT +LANGUAGE javascript +HANDLER = 'calculateAge' +AS $$ +export function calculateAge(birthDateStr) { + const birthDate = new Date(birthDateStr); + const today = new Date(); + + let age = today.getFullYear() - birthDate.getFullYear(); + const monthDiff = today.getMonth() - birthDate.getMonth(); + + if (monthDiff < 0 || (monthDiff === 0 && today.getDate() < birthDate.getDate())) { + age--; + } + + return age; +} +$$; +``` + +## UDF 的 Worker 管理 {#worker-management-for-udfs} + +在 {{{ .lake }}} 中,每个 UDF 都关联一个 **Worker**,用于在沙箱中管理其执行环境。创建 UDF 后,你可能需要管理其 worker,以获得更优的性能和资源利用率。 + +### 为你的 UDF 创建 Worker {#creating-a-worker-for-your-udf} + +```sql +-- Create a worker for your UDF (worker name should match UDF name) +CREATE WORKER calculate_age_js WITH + size='small', + auto_suspend='300', + auto_resume='true'; +``` + +### 管理 Worker 资源 {#managing-worker-resources} + +```sql +-- View all workers +SHOW WORKERS; + +-- Adjust worker settings +ALTER WORKER calculate_age_js SET size='medium', auto_suspend='600'; + +-- Add tags for organization +ALTER WORKER calculate_age_js SET TAG + environment='production', + team='analytics', + purpose='age-calculation'; +``` + +### Worker 生命周期 {#worker-lifecycle} + +```sql +-- Suspend worker when not in use +ALTER WORKER calculate_age_js SUSPEND; + +-- Resume worker when needed +ALTER WORKER calculate_age_js RESUME; + +-- Remove worker when UDF is no longer needed +DROP WORKER calculate_age_js; +``` + +### 环境变量 {#environment-variables} + +出于安全原因,UDF 的环境变量需要在云控制台中单独管理。创建 UDF 及其 worker 后,请通过 {{{ .lake }}} 接口配置所需的环境变量。 + +更多信息,请参见 [Worker 管理](/tidb-cloud-lake/sql/worker-overview.md)。 \ No newline at end of file diff --git a/tidb-cloud-lake/sql/create-sequence.md b/tidb-cloud-lake/sql/create-sequence.md new file mode 100644 index 0000000000000..52ca8bb3c51ea --- /dev/null +++ b/tidb-cloud-lake/sql/create-sequence.md @@ -0,0 +1,99 @@ +--- +title: CREATE SEQUENCE +summary: 在 {{{ .lake }}} 中创建一个新的序列。 +--- + +# CREATE SEQUENCE + +在 {{{ .lake }}} 中创建一个新的序列。 + +序列是一种能够自动生成唯一数字标识符的对象,通常用于为表中的行分配不同的值(例如用户 ID)。虽然序列能够保证值的唯一性,但**不能**保证连续性(即,可能会出现间隔)。 + +## 语法 {#syntax} + +```sql +CREATE [ OR REPLACE ] SEQUENCE [ IF NOT EXISTS ] + [ START [ = ] ] + [ INCREMENT [ = ] ] +``` + +| 参数 | 描述 | 默认值 | +|---------------------|-------------------------------------------------------|---------| +| `` | 要创建的序列名称。 | - | +| `START` | 序列的初始值。 | 1 | +| `INCREMENT` | 每次调用 NEXTVAL 时的增量值。 | 1 | + +## 访问控制要求 {#access-control-requirements} + +| 权限 | 对象类型 | 描述 | +|:----------------|:------------|:----------------------| +| CREATE SEQUENCE | Global | 创建序列。 | + +要创建序列,执行该操作的用户或 [current_role](/tidb-cloud-lake/guides/roles.md) 必须具有 CREATE SEQUENCE [权限](/tidb-cloud-lake/guides/privileges.md)。 + +> **注意:** +> +> `enable_experimental_sequence_rbac_check` 设置控制序列级别的访问控制。该设置默认禁用。 +> 创建序列时仅要求用户具有 superuser 权限,会跳过详细的 RBAC 检查。 +> 启用后,在创建序列期间会强制执行细粒度的权限验证。 +> +> 这是一个实验特性,未来可能会默认启用。 + +## 示例 {#examples} + +### 基本序列 {#basic-sequence} + +使用默认设置创建一个序列(从 1 开始,每次递增 1): + +```sql +CREATE SEQUENCE staff_id_seq; + +CREATE TABLE staff ( + staff_id INT, + name VARCHAR(50), + department VARCHAR(50) +); + +INSERT INTO staff (staff_id, name, department) +VALUES (NEXTVAL(staff_id_seq), 'John Doe', 'HR'); + +INSERT INTO staff (staff_id, name, department) +VALUES (NEXTVAL(staff_id_seq), 'Jane Smith', 'Finance'); + +SELECT * FROM staff; + +┌───────────────────────────────────────────────────────┐ +│ staff_id │ name │ department │ +├─────────────────┼──────────────────┼──────────────────┤ +│ 2 │ Jane Smith │ Finance │ +│ 1 │ John Doe │ HR │ +└───────────────────────────────────────────────────────┘ +``` + +### 自定义起始值和增量 {#custom-start-and-increment} + +创建一个从 1000 开始、每次递增 10 的序列: + +```sql +CREATE SEQUENCE order_id_seq START = 1000 INCREMENT = 10; + +CREATE TABLE orders ( + order_id BIGINT, + order_name VARCHAR(100) +); + +INSERT INTO orders (order_id, order_name) +VALUES (NEXTVAL(order_id_seq), 'Order A'); + +INSERT INTO orders (order_id, order_name) +VALUES (NEXTVAL(order_id_seq), 'Order B'); + +SELECT * FROM orders; + +┌──────────────────────────────────┐ +│ order_id │ order_name │ +├────────────────┼─────────────────┤ +│ 1000 │ Order A │ +│ 1010 │ Order B │ +└──────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/create-snapshot-tag.md b/tidb-cloud-lake/sql/create-snapshot-tag.md new file mode 100644 index 0000000000000..8f5006077e329 --- /dev/null +++ b/tidb-cloud-lake/sql/create-snapshot-tag.md @@ -0,0 +1,79 @@ +--- +title: CREATE SNAPSHOT TAG +summary: 在 FUSE 表上创建一个具名快照标签,使你能够为表历史中的特定时间点添加书签并进行查询。 +--- + +# CREATE SNAPSHOT TAG + +在 FUSE 表上创建一个具名快照标签。快照标签会为表在某个特定时间点的状态添加书签,使你之后可以通过 [AT](/tidb-cloud-lake/sql/at.md) 子句查询该状态。 + +> **Note:** +> +> - 这是一个**实验性**功能。使用前请先启用:`SET enable_experimental_table_ref = 1;`。 +> - 仅支持 FUSE engine 表。不支持 Memory engine 表和临时表。 + +## 语法 {#syntax} + +```sql +ALTER TABLE [.] CREATE TAG + [ AT ( + SNAPSHOT => '' | + TIMESTAMP => | + STREAM => | + OFFSET => | + TAG => + ) ] + [ RETAIN { DAYS | SECONDS } ] +``` + +## 参数 {#parameters} + +| 参数 | 描述 | +|-----------|-------------| +| tag_name | 标签名称。必须在表内唯一。 | +| AT | 指定标签引用哪个快照。如果省略,则标签引用当前(最新)快照。支持与 [AT](/tidb-cloud-lake/sql/at.md) 子句相同的选项,另外还支持 `TAG`,用于从现有标签复制。 | +| RETAIN | 设置自动过期时间。达到指定时长后,标签会在下一次执行 [VACUUM](/tidb-cloud-lake/sql/vacuum-table.md) 操作时被移除。不使用 `RETAIN` 时,标签会一直保留,直到被显式删除。 | + +## 示例 {#examples} + +### 为当前快照打标签 {#tag-the-current-snapshot} + +```sql +SET enable_experimental_table_ref = 1; + +CREATE TABLE t1(a INT, b STRING); +INSERT INTO t1 VALUES (1, 'a'), (2, 'b'), (3, 'c'); + +-- Create a tag at the current snapshot +ALTER TABLE t1 CREATE TAG v1_0; + +-- Insert more data +INSERT INTO t1 VALUES (4, 'd'), (5, 'e'); + +-- Query the tagged snapshot (returns 3 rows, not 5) +SELECT * FROM t1 AT (TAG => v1_0) ORDER BY a; +``` + +### 基于现有引用创建标签 {#tag-from-an-existing-reference} + +```sql +-- Copy from an existing tag +ALTER TABLE t1 CREATE TAG v1_0_copy AT (TAG => v1_0); + +-- Tag a specific snapshot +ALTER TABLE t1 CREATE TAG before_migration + AT (SNAPSHOT => 'aaa4857c5935401790db2c9f0f2818be'); + +-- Tag the state from 1 hour ago +ALTER TABLE t1 CREATE TAG hourly_checkpoint AT (OFFSET => -3600); +``` + +### 创建带自动过期时间的标签 {#tag-with-automatic-expiration} + +```sql +-- Tag expires after 7 days +ALTER TABLE t1 CREATE TAG temp_tag RETAIN 7 DAYS; + +-- Tag expires after 3600 seconds +ALTER TABLE t1 CREATE TAG debug_snapshot RETAIN 3600 SECONDS; +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/create-spatial-index.md b/tidb-cloud-lake/sql/create-spatial-index.md new file mode 100644 index 0000000000000..7c3f9f4809b64 --- /dev/null +++ b/tidb-cloud-lake/sql/create-spatial-index.md @@ -0,0 +1,157 @@ +--- +title: CREATE SPATIAL INDEX +summary: "在 {{{ .lake }}} 中创建一个新的空间索引。" +--- + +# CREATE SPATIAL INDEX + +在 {{{ .lake }}} 中创建一个新的空间索引。 + +## 语法 {#syntax} + +```sql +CREATE [ OR REPLACE ] SPATIAL INDEX [IF NOT EXISTS] + ON [.]
( [, ...] ) +``` + +| 参数 | 描述 | +|-----------|-------------| +| `[ OR REPLACE ]` | 如果索引已存在,则替换现有索引。 | +| `[ IF NOT EXISTS ]` | 仅当不存在同名索引时才创建该索引。 | +| `` | 空间索引的名称。 | +| `[.]
` | 拥有被索引列的表。 | +| `` | 索引中包含的 `GEOMETRY` 列。语句中列出的每一列都必须唯一。 | + +## 使用说明 {#usage-notes} + +- 仅 Fuse 表支持空间索引。 +- 空间索引仅支持 `GEOMETRY` 列,不支持 `GEOGRAPHY` 列。 +- 单个空间索引定义中可以为多列创建索引,但这些列都必须是 `GEOMETRY` 列。 +- 为了获得更好的裁剪效果,建议使用 `CLUSTER BY` 和 `ST_HILBERT` 对地理空间数据进行物理聚簇,这样相邻对象更有可能被写入同一个数据块。 + +## 示例 {#examples} + +创建一个包含空间列的表: + +```sql +CREATE TABLE stores ( + store_id INT, + store_name STRING, + location GEOMETRY +) CLUSTER BY ( + ST_HILBERT(location, [-180, -90, 180, 90]) +); +``` + +在 `location` 列上创建空间索引: + +```sql +CREATE SPATIAL INDEX stores_location_idx ON stores(location); +``` + +查看表定义: + +```sql +SHOW CREATE TABLE stores; + +┌──────────────────────────────────────────────────────────────────────────────────────────────┐ +│ Table │ Create Table │ +├──────────────────────────────────────────────────────────────────────────────────────────────┤ +│ stores │ CREATE TABLE stores ( │ +│ │ store_id INT NULL, │ +│ │ store_name VARCHAR NULL, │ +│ │ location GEOMETRY NULL, │ +│ │ SYNC SPATIAL INDEX stores_location_idx (location) │ +│ │ ) ENGINE=FUSE CLUSTER BY linear(st_hilbert(location, [-180, -90, 180, 90])) │ +└──────────────────────────────────────────────────────────────────────────────────────────────┘ +``` + +加载一个稍丰富一些的数据集以进行空间过滤,并运行 RECLUSTER 命令: + +```sql +INSERT INTO stores VALUES + (1, 'Starbucks', TO_GEOMETRY('POINT(10 10)')), + (2, 'Costa', TO_GEOMETRY('POINT(11 11)')), + (3, 'Gong Cha', TO_GEOMETRY('POINT(20 20)')), + (4, 'Dunkin', TO_GEOMETRY('POINT(-10 -10)')); + +ALTER TABLE stores RECLUSTER FINAL; +``` + +### 使用 `ST_WITHIN`、`ST_INTERSECTS` 和 `ST_CONTAINS` 进行过滤 {#filter-with-st-within-st-intersects-and-st-contains} + +这些谓词是常见的地理围栏式过滤条件,可以从空间索引中受益。 + +```sql +-- Rows whose locations are within a polygon +SELECT store_id, store_name +FROM stores +WHERE ST_WITHIN( + location, + TO_GEOMETRY('POLYGON((9 9, 9 12, 12 12, 12 9, 9 9))') +) +ORDER BY store_id; +``` + +```sql +-- Rows whose locations intersect a polygon +SELECT store_id, store_name +FROM stores +WHERE ST_INTERSECTS( + location, + TO_GEOMETRY('POLYGON((9 9, 9 12, 12 12, 12 9, 9 9))') +) +ORDER BY store_id; +``` + +```sql +-- Polygons that contain a point +SELECT store_id, store_name +FROM stores +WHERE ST_CONTAINS( + TO_GEOMETRY('POLYGON((9 9, 9 12, 12 12, 12 9, 9 9))'), + location +) +ORDER BY store_id; +``` + +### 使用 `ST_DWITHIN` 进行过滤 {#filter-with-st-dwithin} + +使用 `ST_DWITHIN` 执行半径式查找。这对于“查找附近位置”类查询非常有用。 + +```sql +SELECT store_id, store_name +FROM stores +WHERE ST_DWITHIN( + location, + TO_GEOMETRY('POINT(10 10)'), + 1.5 +) +ORDER BY store_id; +``` + +### 使用空间连接进行过滤 {#filter-with-spatial-joins} + +当连接条件是受支持的空间谓词时,空间索引在连接查询中同样很有用。 + +```sql +CREATE TABLE districts ( + district_id INT, + district_name STRING, + geom GEOMETRY +) CLUSTER BY ( + ST_HILBERT(geom, [-180, -90, 180, 90]) +); + +INSERT INTO districts VALUES + (1, 'Central', TO_GEOMETRY('POLYGON((8 8, 8 13, 13 13, 13 8, 8 8))')), + (2, 'West', TO_GEOMETRY('POLYGON((-2 -2, -2 2, 2 2, 2 -2, -2 -2))')); +``` + +```sql +SELECT d.district_name, s.store_name +FROM districts AS d +JOIN stores AS s + ON ST_WITHIN(s.location, d.geom) +ORDER BY d.district_name, s.store_name; +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/create-stage.md b/tidb-cloud-lake/sql/create-stage.md new file mode 100644 index 0000000000000..25b240c6891b5 --- /dev/null +++ b/tidb-cloud-lake/sql/create-stage.md @@ -0,0 +1,208 @@ +--- +title: CREATE STAGE +summary: 创建内部或外部 stage。 +--- + +# CREATE STAGE + +创建内部或外部 stage。 + +## 语法 {#syntax} + +```sql +-- Internal stage +CREATE [ OR REPLACE ] STAGE [ IF NOT EXISTS ] + [ FILE_FORMAT = ( + FORMAT_NAME = '' + | TYPE = { CSV | TSV | NDJSON | PARQUET | ORC | AVRO | LANCE } [ formatTypeOptions ] + ) ] + [ COMMENT = '' ] + +-- External stage +CREATE STAGE [ IF NOT EXISTS ] + externalStageParams + [ FILE_FORMAT = ( + FORMAT_NAME = '' + | TYPE = { CSV | TSV | NDJSON | PARQUET | ORC | AVRO | LANCE } [ formatTypeOptions ] + ) ] + [ COMMENT = '' ] +``` + +### externalStageParams {#externalstageparams} + +> **Tip:** +> +> 对于外部 stage,建议使用 `CONNECTION` 参数引用预先配置的连接对象,而不是直接内联填写凭证。这种方式可提供更好的安全性和可维护性。 + +```sql +externalStageParams ::= + '://' + CONNECTION = ( + + ) +| + CONNECTION = ( + CONNECTION_NAME = '' + ); +``` + +有关不同存储服务可用的连接参数,请参见[连接参数](/tidb-cloud-lake/sql/connection-parameters.md)。 + +有关 `CONNECTION_NAME` 的更多信息,请参见 [CREATE CONNECTION](/tidb-cloud-lake/sql/create-connection.md)。 + +### FILE_FORMAT {#file-format} + +详情请参见[输入和输出文件格式](/tidb-cloud-lake/sql/input-output-file-formats.md)。 + +## 访问控制要求 {#access-control-requirements} + +| 权限 | 对象类型 | 描述 | +|:----------|:--------------|:--------------------------------------------------------------------------| +| SUPER | 全局、表 | 对 stage(列出 stage、创建 stage、删除 stage)、catalog 或 share 执行操作。 | + +要创建 stage,执行该操作的用户或 [current_role](/tidb-cloud-lake/guides/roles.md) 必须具有 SUPER [权限](/tidb-cloud-lake/guides/privileges.md)。 + +## 示例 {#examples} + +### 示例 1:创建内部 stage {#example-1-create-internal-stage} + +以下示例创建一个名为 *my_internal_stage* 的内部 stage: + +```sql +CREATE STAGE my_internal_stage; + +DESC STAGE my_internal_stage; + +┌─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ +│ name │ stage_type │ storage_type │ url │ endpoint │ has_credentials │ has_encryption_key │ storage_params │ file_format_options │ creator │ created_on │ comment │ owner │ +├───────────────────┼────────────┼──────────────┼──────┼──────────┼─────────────────┼────────────────────┼────────────────┼─────────────────────┼──────────┼────────────────────────────┼─────────┼───────────────┤ +│ my_internal_stage │ Internal │ NULL │ NULL │ NULL │ false │ false │ NULL │ {"compression":...} │ root@% │ 2026-06-16 22:21:19.000000 │ │ account_admin │ +└─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ +``` + +### 示例 2:使用连接创建外部 stage {#example-2-create-external-stage-with-connection} + +以下示例在 Amazon S3 上使用连接创建一个名为 *my_s3_stage* 的外部 stage: + +```sql +-- First create a connection +CREATE CONNECTION my_s3_connection + STORAGE_TYPE = 's3' + ACCESS_KEY_ID = '' + SECRET_ACCESS_KEY = ''; + +-- Create stage using the connection +CREATE STAGE my_s3_stage + URL='s3://load/files/' + CONNECTION = (CONNECTION_NAME = 'my_s3_connection'); + +DESC STAGE my_s3_stage; + +┌─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ +│ name │ stage_type │ storage_type │ url │ endpoint │ has_credentials │ has_encryption_key │ storage_params │ file_format_options │ creator │ created_on │ comment │ owner │ +├─────────────┼────────────┼──────────────┼──────────────────┼──────────┼─────────────────┼────────────────────┼───────────────────────┼─────────────────────┼─────────┼────────────────────────────┼─────────┼───────────────┤ +│ my_s3_stage │ External │ s3 │ s3://load/files/ │ NULL │ true │ false │ {"bucket":"load",...} │ {"compression":...} │ root@% │ 2026-06-16 22:21:19.000000 │ │ account_admin │ +└─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ +``` + +### 示例 3:使用 AWS IAM User 创建外部 stage {#example-3-create-external-stage-with-aws-iam-user} + +以下示例在 Amazon S3 上使用 AWS Identity and Access Management (IAM) 用户创建一个名为 *iam_external_stage* 的外部 stage。 + +#### 步骤 1:为 S3 bucket 创建访问策略 {#step-1-create-access-policy-for-s3-bucket} + +以下过程会为 Amazon S3 上的 bucket *lake-toronto* 创建一个名为 *lake-access* 的访问策略: + +1. 登录 AWS Management Console,然后选择 **Services** > **Security, Identity, & Compliance** > **IAM**。 +2. 在左侧导航栏中选择 **Account settings**,然后前往右侧页面中的 **Security Token Service (STS)** 部分。确保你的账户所属 AWS 区域的状态为 **Active**。 +3. 在左侧导航栏中选择 **Policies**,然后在右侧页面选择 **Create policy**。 +4. 点击 **JSON** 选项卡,将以下代码复制并粘贴到编辑器中,然后将该策略保存为 *lake_access*。 + +```json +{ + "Version": "2012-10-17", + "Statement": [ + { + "Sid": "AllObjectActions", + "Effect": "Allow", + "Action": ["s3:*Object"], + "Resource": "arn:aws:s3:::lake-toronto/*" + }, + { + "Sid": "ListObjectsInBucket", + "Effect": "Allow", + "Action": ["s3:ListBucket"], + "Resource": "arn:aws:s3:::lake-toronto" + } + ] +} +``` + +#### 步骤 2:创建 IAM 用户 {#step-2-create-iam-user} + +以下过程会创建一个名为 *lake* 的 IAM 用户,并将访问策略 *lake-access* 附加到该用户。 + +1. 在左侧导航栏中选择 **Users**,然后在右侧页面选择 **Add users**。 +2. 配置用户: + - 将用户名设置为 *lake*。 + - 为用户设置权限时,点击 **Attach policies directly**,然后搜索并选择访问策略 *lake-access*。 +3. 创建用户后,点击用户名打开详情页面,并选择 **Security credentials** 选项卡。 +4. 在 **Access keys** 部分,点击 **Create access key**。 +5. 在 use case 中选择 **Third-party service**,并勾选下方复选框以确认创建 access key。 +6. 复制并保存生成的 access key 和 secret access key 到安全位置。 + +#### 步骤 3:创建外部 stage {#step-3-create-external-stage} + +使用 IAM role 创建外部 stage,可获得更好的安全性。 + +```sql +-- First create a connection using IAM role +CREATE CONNECTION iam_s3_connection + STORAGE_TYPE = 's3' + ROLE_ARN = 'arn:aws:iam::123456789012:role/lake-access' + EXTERNAL_ID = 'my-external-id-123'; + +-- Create stage using the connection +CREATE STAGE iam_external_stage + URL = 's3://lake-toronto' + CONNECTION = (CONNECTION_NAME = 'iam_s3_connection'); +``` + +### 示例 4:在 Cloudflare R2 上创建外部 stage {#example-4-create-external-stage-on-cloudflare-r2} + +[Cloudflare R2](https://www.cloudflare.com/en-ca/products/r2/) 是 Cloudflare 推出的一种对象存储服务,与 Amazon 的 AWS S3 服务完全兼容。以下示例在 Cloudflare R2 上创建一个名为 *r2_stage* 的外部 stage。 + +#### 步骤 1:创建 bucket {#step-1-create-bucket} + +以下过程会在 Cloudflare R2 上创建一个名为 *lake* 的 bucket。 + +1. 登录 Cloudflare dashboard,并在左侧导航栏中选择 **R2**。 +2. 点击 **Create bucket** 创建 bucket,并将 bucket 名称设置为 *lake*。bucket 创建成功后,在查看 bucket 详情页面时,你可以在 bucket 名称正下方找到 bucket endpoint。 + +#### 步骤 2:创建 R2 API Token {#step-2-create-r2-api-token} + +以下过程会创建一个 R2 API token,其中包含 Access Key ID 和 Secret Access Key。 + +1. 在 **R2** > **Overview** 中点击 **Manage R2 API Tokens**。 +2. 点击 **Create API token** 创建一个 API token。 +3. 配置 API token 时,选择所需权限,并根据需要设置 **TTL**。 +4. 点击 **Create API Token** 以获取 Access Key ID 和 Secret Access Key。复制并将其保存到安全位置。 + +#### 第 3 步:创建 External Stage {#step-3-create-external-stage} + +使用已创建的 Access Key ID 和 Secret Access Key 创建一个名为 *r2_stage* 的 external stage。 + +```sql +-- First create a connection +CREATE CONNECTION r2_connection + STORAGE_TYPE = 's3' + REGION = 'auto' + ENDPOINT_URL = '' + ACCESS_KEY_ID = '' + SECRET_ACCESS_KEY = ''; + +-- Create stage using the connection +CREATE STAGE r2_stage + URL='s3://lake/' + CONNECTION = (CONNECTION_NAME = 'r2_connection'); +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/create-stream.md b/tidb-cloud-lake/sql/create-stream.md new file mode 100644 index 0000000000000..3c70e48f6cb3a --- /dev/null +++ b/tidb-cloud-lake/sql/create-stream.md @@ -0,0 +1,112 @@ +--- +title: CREATE STREAM +summary: 创建一个 stream。 +--- + +# CREATE STREAM + +创建一个 stream。 + +## 语法 {#syntax} + +```sql +CREATE [ OR REPLACE ] STREAM [ IF NOT EXISTS ] [ . ] + ON TABLE [ . ] + [ AT ( { TIMESTAMP => | SNAPSHOT => '' | STREAM => } ) ] + [ APPEND_ONLY = true | false ] + [ COMMENT = '' ] +``` + +| 参数 | 描述 | +|---------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `< database_name >` | stream 会被视为属于某个特定数据库的对象,类似于表或视图。CREATE STREAM 允许 stream 与其关联表位于不同的数据库中。如果未显式指定数据库,则使用当前数据库作为所创建 stream 所属的数据库。 | +| AT | 当使用 `AT` 并跟随 `TIMESTAMP =>` 或 `SNAPSHOT =>` 时,可以基于时间戳或快照 ID 创建一个包含某个特定历史时间点之后数据变更的 stream;当 `AT` 跟随 `STREAM =>` 时,可以创建一个与现有 stream 相同的新 stream,并保留相同的已捕获数据变更。 | +| APPEND_ONLY | 设置为 `true` 时,stream 以 `Append-Only` 模式运行;设置为 `false` 时,stream 以 `Standard` 模式运行。默认值为 `true`。有关 stream 运行模式的更多信息,请参见 [Stream 工作原理](/tidb-cloud-lake/sql/stream.md#stream-management)。 | + +## 示例 {#examples} + +以下示例演示如何创建一个名为 'order_changes' 的 stream,用于监控 'orders' 表中的变更: + +```sql +-- Create a table named 'orders' +CREATE TABLE orders ( + order_id INT, + product_name VARCHAR, + quantity INT, + order_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP +); + +-- Create a stream named 'order_changes' for the table 'orders' +CREATE STREAM order_changes ON TABLE orders; + +-- Insert order 1001 to the table 'orders' +INSERT INTO orders (order_id, product_name, quantity) VALUES (1001, 'Product A', 10); + +-- Insert order 1002 to the table 'orders' +INSERT INTO orders (order_id, product_name, quantity) VALUES (1002, 'Product B', 20); + +-- Retrieve all records from the 'order_changes' stream +SELECT * FROM order_changes; + +┌───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ +│ order_id │ product_name │ quantity │ order_date │ change$action │ change$is_update │ change$row_id │ +├─────────────────┼──────────────────┼─────────────────┼────────────────────────────┼───────────────┼──────────────────┼────────────────────────────────────────┤ +│ 1002 │ Product B │ 20 │ 2024-03-28 03:24:16.629135 │ INSERT │ false │ acb58bd6bb4243a4bf0832bf570b38c2000000 │ +│ 1001 │ Product A │ 10 │ 2024-03-28 03:24:16.539178 │ INSERT │ false │ b93a15e694db4134ab5a23afa8c92b20000000 │ +└───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ +``` + +以下示例使用 `AT` 参数创建一个名为 'order_changes_copy' 的新 stream,其中包含与 'order_changes' 相同的数据变更: + +```sql +-- Create a stream 'order_changes_copy' on the 'orders' table, copying data changes from 'order_changes' +CREATE STREAM order_changes_copy ON TABLE orders AT (STREAM => order_changes); + +-- Retrieve all records from the 'order_changes_copy' stream +SELECT * FROM order_changes_copy; + +┌───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ +│ order_id │ product_name │ quantity │ order_date │ change$action │ change$is_update │ change$row_id │ +├─────────────────┼──────────────────┼─────────────────┼────────────────────────────┼───────────────┼──────────────────┼────────────────────────────────────────┤ +│ 1002 │ Product B │ 20 │ 2024-03-28 03:24:16.629135 │ INSERT │ false │ acb58bd6bb4243a4bf0832bf570b38c2000000 │ +│ 1001 │ Product A │ 10 │ 2024-03-28 03:24:16.539178 │ INSERT │ false │ b93a15e694db4134ab5a23afa8c92b20000000 │ +└───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ +``` + +以下示例在 'orders' 表上创建了两个 stream。每个 stream 分别使用 `AT` 参数获取某个特定快照 ID 或时间戳之后的数据变更。 + +```sql +-- Retrieve snapshot and timestamp information from the 'orders' table +SELECT snapshot_id, timestamp from FUSE_SNAPSHOT('default','orders'); + +┌───────────────────────────────────────────────────────────────┐ +│ snapshot_id │ timestamp │ +├──────────────────────────────────┼────────────────────────────┤ +│ f7f57c7d07f445a68e4aa53fa2578bbb │ 2024-03-28 03:24:16.633721 │ +│ 11b9d81eabc94c7da648908f0ba313a1 │ 2024-03-28 03:24:16.611835 │ +└───────────────────────────────────────────────────────────────┘ + +-- Create a stream 'order_changes_after_snapshot' on the 'orders' table, capturing data changes after a specific snapshot +CREATE STREAM order_changes_after_snapshot ON TABLE orders AT (SNAPSHOT => '11b9d81eabc94c7da648908f0ba313a1'); + +-- Query the 'order_changes_after_snapshot' stream to view data changes captured after the specified snapshot +SELECT * FROM order_changes_after_snapshot; + +┌───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ +│ order_id │ product_name │ quantity │ order_date │ change$action │ change$is_update │ change$row_id │ +├─────────────────┼──────────────────┼─────────────────┼────────────────────────────┼───────────────┼──────────────────┼────────────────────────────────────────┤ +│ 1002 │ Product B │ 20 │ 2024-03-28 03:24:16.629135 │ INSERT │ false │ acb58bd6bb4243a4bf0832bf570b38c2000000 │ +└───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ + +-- Create a stream 'order_changes_after_timestamp' on the 'orders' table, capturing data changes after a specific timestamp +CREATE STREAM order_changes_after_timestamp ON TABLE orders AT (TIMESTAMP => '2024-03-28 03:24:16.611835'::TIMESTAMP); + +-- Query the 'order_changes_after_timestamp' stream to view data changes captured after the specified timestamp +SELECT * FROM order_changes_after_timestamp; + +┌───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ +│ order_id │ product_name │ quantity │ order_date │ change$action │ change$is_update │ change$row_id │ +├─────────────────┼──────────────────┼─────────────────┼────────────────────────────┼───────────────┼──────────────────┼────────────────────────────────────────┤ +│ 1002 │ Product B │ 20 │ 2024-03-28 03:24:16.629135 │ INSERT │ false │ acb58bd6bb4243a4bf0832bf570b38c2000000 │ +└───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/create-table-function.md b/tidb-cloud-lake/sql/create-table-function.md new file mode 100644 index 0000000000000..dcc1684224f30 --- /dev/null +++ b/tidb-cloud-lake/sql/create-table-function.md @@ -0,0 +1,90 @@ +--- +title: CREATE TABLE FUNCTION +summary: 创建表格 SQL UDF(UDTF),将 SQL 查询封装为表函数。表函数使用 SQL 编写;不涉及外部语言。 +--- + +# CREATE TABLE FUNCTION + +创建表格 SQL UDF(UDTF),将 SQL 查询封装为表函数。表函数使用 SQL 编写;不涉及外部语言。 + +## 支持的语言 {#supported-languages} + +- 仅支持 SQL 查询(不支持外部运行时) + +## 语法 {#syntax} + +```sql +CREATE [ OR REPLACE ] FUNCTION [ IF NOT EXISTS ] + ( [] ) + RETURNS TABLE ( ) + AS $$ $$ +``` + +其中: + +- ``:可选的输入参数列表,参数之间以逗号分隔,并带有各自的类型(例如:`x INT, name VARCHAR`) +- ``:函数返回的列名及其类型列表,列之间以逗号分隔 +- ``:定义函数逻辑的 SQL 查询 + +## 统一函数语法 {#unified-function-syntax} + +{{{ .lake }}} 对标量函数和表函数统一使用 `$$` 语法: + +| 函数类型 | 返回值 | 用法 | +|---------------|---------|-------| +| **标量函数** | 单个值 | `RETURNS ` + `AS $$ $$` | +| **表函数** | 结果集 | `RETURNS TABLE(...)` + `AS $$ $$` | + +这种一致性使你能够更容易理解不同函数类型,并在它们之间切换。 + +## 示例 {#examples} + +### 基本表函数 {#basic-table-function} + +```sql +-- Create a sample table +CREATE OR REPLACE TABLE employees ( + id INT, + name VARCHAR(100), + department VARCHAR(100), + salary DECIMAL(10,2) +); + +INSERT INTO employees VALUES + (1, 'John', 'Engineering', 75000), + (2, 'Jane', 'Marketing', 65000), + (3, 'Bob', 'Engineering', 80000), + (4, 'Alice', 'Marketing', 70000); + +-- Create a simple table function to get all employees +CREATE OR REPLACE FUNCTION get_all_employees() +RETURNS TABLE (id INT, name VARCHAR(100), department VARCHAR(100), salary DECIMAL(10,2)) +AS $$ SELECT id, name, department, salary FROM employees $$; + +-- Test the function +SELECT * FROM get_all_employees(); +``` + +### 带参数的表函数 {#parameterized-table-function} + +```sql +-- Create a table function that filters employees by department +CREATE OR REPLACE FUNCTION get_employees_by_dept(dept_name VARCHAR) +RETURNS TABLE (id INT, name VARCHAR(100), department VARCHAR(100), salary DECIMAL(10,2)) +AS $$ SELECT id, name, department, salary FROM employees WHERE department = dept_name $$; + +-- Use the parameterized table function +SELECT * FROM get_employees_by_dept('Engineering'); +``` + +### 复杂表函数 {#complex-table-function} + +```sql +-- Create a table function that aggregates data +CREATE OR REPLACE FUNCTION get_department_stats() +RETURNS TABLE (department VARCHAR(100), employee_count INT, avg_salary DECIMAL(10,2)) +AS $$ SELECT department, COUNT(*) as employee_count, AVG(salary) as avg_salary FROM employees GROUP BY department $$; + +-- Use the complex table function +SELECT * FROM get_department_stats(); +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/create-table.md b/tidb-cloud-lake/sql/create-table.md new file mode 100644 index 0000000000000..6d52d4d471448 --- /dev/null +++ b/tidb-cloud-lake/sql/create-table.md @@ -0,0 +1,386 @@ +--- +title: CREATE TABLE +summary: 对于许多数据库来说,创建表是最复杂的操作之一,因为你可能需要。 +--- + +# CREATE TABLE + +对于许多数据库来说,创建表是最复杂的操作之一,因为你可能需要: + +- 手动指定引擎 +- 手动指定索引 +- 甚至指定数据分区或数据分片 + +{{{ .lake }}} 的设计目标是易于使用,因此在创建表时**不需要**执行上述任何操作。此外,CREATE TABLE 语句还提供了以下选项,使你能够在各种场景下更轻松地创建表: + +- [CREATE TABLE](#create-table):从头开始创建表。 +- [CREATE TABLE ... LIKE](#create-table--like):使用与现有表相同的列定义创建表。 +- [CREATE TABLE ... AS](#create-table--as):创建表,并将 SELECT 查询的结果插入其中。 + +另请参阅: + +- [CREATE TEMP TABLE](/tidb-cloud-lake/sql/create-temp-table.md) +- [CREATE TRANSIENT TABLE](/tidb-cloud-lake/sql/create-transient-table.md) +- [CREATE EXTERNAL TABLE](/tidb-cloud-lake/sql/create-external-table.md) + +## CREATE TABLE {#create-table} + +```sql +CREATE [ OR REPLACE ] TABLE [ IF NOT EXISTS ] [ . ] +( + [ NOT NULL | NULL ] + [ { DEFAULT + | { AUTOINCREMENT | IDENTITY } + [ { ( , ) + | START INCREMENT } ] + [ { ORDER | NOORDER } ] + } ] + [ AS () STORED | VIRTUAL ] + [ COMMENT '' ], + ... + ... +) +``` + +> **Note:** +> +> - 关于 {{{ .lake }}} 中可用的数据类型,请参阅 [数据类型](/tidb-cloud-lake/sql/data-types.md)。 +> +> - {{{ .lake }}} 建议在命名列时尽量避免使用特殊字符。不过,如果在某些情况下必须使用特殊字符,则应将别名用反引号括起来,例如:CREATE TABLE price(\`$CA\` int); +> +> - {{{ .lake }}} 会自动将列名转换为小写。例如,如果你将某列命名为 _Total_,则它会在结果中显示为 _total_。 + +## CREATE TABLE ... LIKE {#create-table-like} + +使用与现有表相同的列定义创建表。现有表的列名、数据类型及其非 NULL 约束将被复制到新表中。 + +语法: + +```sql +CREATE TABLE [IF NOT EXISTS] [db.]table_name +LIKE [db.]origin_table_name +``` + +此命令不会包含原表中的任何数据或属性(例如 `CLUSTER BY`、`TRANSIENT` 和 `COMPRESSION`),而是使用系统默认设置创建一个新表。 + +> **Note:** +> +> - 使用此命令创建新表时,可以显式指定 `TRANSIENT` 和 `COMPRESSION`。例如: +> +> ```sql +> create transient table t_new like t_old; +> +> create table t_new compression='lz4' like t_old; +> ``` + +## CREATE TABLE ... AS {#create-table-as} + +创建一个表,并使用 SELECT 命令计算得到的数据填充该表。 + +语法: + +```sql +CREATE TABLE [IF NOT EXISTS] [db.]table_name +AS SELECT query +``` + +此命令不会包含原表中的任何属性(例如 CLUSTER BY、TRANSIENT 和 COMPRESSION),而是使用系统默认设置创建一个新表。 + +> **Note:** +> +> - 使用此命令创建新表时,可以显式指定 `TRANSIENT` 和 `COMPRESSION`。例如: +> +> ```sql +> create transient table t_new as select * from t_old; +> +> create table t_new compression='lz4' as select * from t_old; +> ``` + +## Column Nullable {#column-nullable} + +默认情况下,{{{ .lake }}} 中的**所有列都允许为空(NULL)**。如果你需要某一列不允许 NULL 值,请使用 NOT NULL 约束。更多信息,请参阅 [NULL 值和 NOT NULL 约束](/tidb-cloud-lake/sql/data-types.md)。 + +## Column Default Values {#column-default-values} + +`DEFAULT ` 用于在未提供显式表达式时为列设置默认值。默认表达式可以是: + +- 固定常量,例如下面示例中 `department` 列的 `Marketing`。 +- 不带输入参数并返回标量值的表达式,例如 `1 + 1`、`NOW()` 或 `UUID()`。 +- 由序列动态生成的值,例如下面示例中 `staff_id` 列的 `NEXTVAL(staff_id_seq)`。 + - NEXTVAL 必须作为独立的默认值使用;不支持 `NEXTVAL(seq1) + 1` 之类的表达式。 + - 用户必须遵循其已授予的序列使用权限要求,包括 [NEXTVAL](/tidb-cloud-lake/sql/nextval.md#access-control-requirements) 等操作 + +## Auto-Increment Columns {#auto-increment-columns} + +`AUTOINCREMENT` 或 `IDENTITY` 可用于创建自增列,以自动生成连续的数值。这对于创建唯一标识符特别有用。 + +**语法:** + +```sql +{ AUTOINCREMENT | IDENTITY } + [ { ( , ) + | START INCREMENT } ] + [ { ORDER | NOORDER } ] +``` + +**参数:** + +- `start_num`:自增序列的初始值(默认值:1) +- `step_num`:每插入一行时的递增值(默认值:1) +- `ORDER`:保证值单调递增(可能存在间隔) +- `NOORDER`:不保证顺序(默认) + +**要点:** + +- 自增列在内部由序列支持 +- 当删除带有 AUTOINCREMENT/IDENTITY 的列时,其关联的序列也会被删除 +- 如果在插入时未提供显式值,则会自动生成下一个值 +- `AUTOINCREMENT` 和 `IDENTITY` 是同义词,行为完全一致 + +**示例:** + +```sql +-- Create a table with auto-increment columns +CREATE TABLE users ( + user_id BIGINT AUTOINCREMENT, + order_id BIGINT AUTOINCREMENT START 100 INCREMENT 10, + username VARCHAR +); + +-- Insert data without specifying auto-increment columns +INSERT INTO users (username) VALUES ('alice'), ('bob'), ('charlie'); + +-- Query the table to see auto-generated values +SELECT * FROM users; + ++----------+----------+----------+ +| user_id | order_id | username | ++----------+----------+----------+ +| 0 | 100 | alice | +| 1 | 110 | bob | +| 2 | 120 | charlie | ++----------+----------+----------+ +``` + +## 计算列 {#computed-columns} + +计算列使用标量表达式基于其他列生成。{{{ .lake }}} 支持两种类型: + +- **STORED**:值会被实际存储,并在依赖列发生变化时自动修改 +- **VIRTUAL**:值会在查询期间动态计算,从而节省存储空间 + +**语法:** + +```sql + [ NOT NULL | NULL ] AS () { STORED | VIRTUAL } + [ NOT NULL | NULL ] GENERATED ALWAYS AS () { STORED | VIRTUAL } +``` + +**示例:** + +```sql +-- Stored: physically stored, updates immediately +CREATE TABLE products ( + id INT, + price FLOAT64, + quantity INT, + total_price FLOAT64 AS (price * quantity) STORED +); + +-- Virtual: computed on query, no storage overhead +CREATE TABLE employees ( + id INT, + first_name VARCHAR, + last_name VARCHAR, + full_name VARCHAR AS (CONCAT(first_name, ' ', last_name)) VIRTUAL +); +``` + +> **Tip:** +> +> 对于经常查询且性能很重要的列,请选择 **STORED**。如果计算成本可以接受,并且希望节省存储空间,请选择 **VIRTUAL**。 + +## MySQL 兼容性 {#mysql-compatibility} + +{{{ .lake }}} 的语法与 MySQL 的差异主要体现在数据类型以及某些特定的索引提示上。 + +与 MySQL 不同,{{{ .lake }}} 默认遵循 PostgreSQL 风格的标识符大小写规则:未加引号的列名会被折叠为小写,而使用双引号的名称会保留原始大小写,并且是大小写敏感的。因此,使用带引号且保留大小写的列名(例如 `"Employee_ID"`)创建的表,执行 `SELECT *` 时可以返回行,但执行 `SELECT Employee_ID` 或 `SELECT employee_id` 时可能失败。有关标识符大小写规则、相关设置和故障排查的更多信息,请参见 [SQL 标识符](/tidb-cloud-lake/sql/sql-identifiers.md#identifier-casing-rules)。 + +## 访问控制要求 {#access-control-requirements} + +| 权限 | 对象类型 | 描述 | +|:----------|:--------------|:-----------------------| +| CREATE | 全局, Table | 创建表。 | + +要创建表,执行该操作的用户或 [current_role](/tidb-cloud-lake/guides/roles.md) 必须具有 CREATE [权限](/tidb-cloud-lake/guides/privileges.md#table-privileges)。 + +## 示例 {#examples} + +### 创建表 {#create-table} + +创建一个表,并为某列设置默认值(在本例中,`genre` 列的默认值为 `'General'`): + +```sql +CREATE TABLE books ( + id BIGINT UNSIGNED, + title VARCHAR, + genre VARCHAR DEFAULT 'General' +); +``` + +描述该表以确认表结构以及 `genre` 列的默认值: + +```sql +DESC books; ++-------+-----------------+------+---------+-------+ +| Field | Type | Null | Default | Extra | ++-------+-----------------+------+---------+-------+ +| id | BIGINT UNSIGNED | YES | 0 | | +| title | VARCHAR | YES | "" | | +| genre | VARCHAR | YES | 'General'| | ++-------+-----------------+------+---------+-------+ +``` + +插入一行数据,不指定 `genre`: + +```sql +INSERT INTO books(id, title) VALUES(1, 'Invisible Stars'); +``` + +查询该表,可以看到默认值 `'General'` 已被设置到 `genre` 列: + +```sql +SELECT * FROM books; ++----+----------------+---------+ +| id | title | genre | ++----+----------------+---------+ +| 1 | Invisible Stars| General | ++----+----------------+---------+ +``` + +### 创建表 ... Like {#create-table-like} + +创建一个新表(`books_copy`),其结构与现有表(`books`)相同: + +```sql +CREATE TABLE books_copy LIKE books; +``` + +检查新表的结构: + +```sql +DESC books_copy; ++-------+-----------------+------+---------+-------+ +| Field | Type | Null | Default | Extra | ++-------+-----------------+------+---------+-------+ +| id | BIGINT UNSIGNED | YES | 0 | | +| title | VARCHAR | YES | "" | | +| genre | VARCHAR | YES | 'General'| | ++-------+-----------------+------+---------+-------+ +``` + +向新表插入一行数据,可以看到 `genre` 列的默认值也被复制了: + +```sql +INSERT INTO books_copy(id, title) VALUES(1, 'Invisible Stars'); + +SELECT * FROM books_copy; ++----+----------------+---------+ +| id | title | genre | ++----+----------------+---------+ +| 1 | Invisible Stars| General | ++----+----------------+---------+ +``` + +### 创建表 ... As {#create-table-as} + +创建一个新表(`books_backup`),其中包含现有表(`books`)中的数据: + +```sql +CREATE TABLE books_backup AS SELECT * FROM books; +``` + +描述新表,可以看到 `genre` 列的默认值**不会**被复制: + +```sql +DESC books_backup; ++-------+-----------------+------+---------+-------+ +| Field | Type | Null | Default | Extra | ++-------+-----------------+------+---------+-------+ +| id | BIGINT UNSIGNED | NO | 0 | | +| title | VARCHAR | NO | "" | | +| genre | VARCHAR | NO | NULL | | ++-------+-----------------+------+---------+-------+ +``` + +查询新表,可以看到原表中的数据已被复制: + +```sql +SELECT * FROM books_backup; ++----+----------------+---------+ +| id | title | genre | ++----+----------------+---------+ +| 1 | Invisible Stars| General | ++----+----------------+---------+ +``` + +### Create Table ... Column As STORED | VIRTUAL {#create-table-column-as-stored-virtual} + +以下示例演示了一个包含 stored 计算列的表,该列会在 `price` 或 `quantity` 列更新时自动重新计算: + +```sql +-- Create the table with a stored computed column +CREATE TABLE IF NOT EXISTS products ( + id INT, + price FLOAT64, + quantity INT, + total_price FLOAT64 AS (price * quantity) STORED +); + +-- Insert data into the table +INSERT INTO products (id, price, quantity) +VALUES (1, 10.5, 3), + (2, 15.2, 5), + (3, 8.7, 2); + +-- Query the table to see the computed column +SELECT id, price, quantity, total_price +FROM products; + +--- ++------+-------+----------+-------------+ +| id | price | quantity | total_price | ++------+-------+----------+-------------+ +| 1 | 10.5 | 3 | 31.5 | +| 2 | 15.2 | 5 | 76.0 | +| 3 | 8.7 | 2 | 17.4 | ++------+-------+----------+-------------+ +``` + +在此示例中,我们创建了一个名为 student*profiles 的表,其中包含一个名为 profile 的 Variant 类型列,用于存储 JSON 数据。我们还添加了一个名为 \_age* 的 virtual 计算列,用于从 profile 列中提取 age 属性并将其转换为整数型。 + +```sql +-- Create the table with a virtual computed column +CREATE TABLE student_profiles ( + id STRING, + profile VARIANT, + age INT NULL AS (profile['age']::INT) VIRTUAL +); + +-- Insert data into the table +INSERT INTO student_profiles (id, profile) VALUES + ('d78236', '{"id": "d78236", "name": "Arthur Read", "age": "16", "school": "PVPHS", "credits": 120, "sports": "none"}'), + ('f98112', '{"name": "Buster Bunny", "age": "15", "id": "f98112", "school": "TEO", "credits": 67, "clubs": "MUN"}'), + ('t63512', '{"name": "Ernie Narayan", "school" : "Brooklyn Tech", "id": "t63512", "sports": "Track and Field", "clubs": "Chess"}'); + +-- Query the table to see the computed column +SELECT * FROM student_profiles; + ++--------+------------------------------------------------------------------------------------------------------------+------+ +| id | profile | age | ++--------+------------------------------------------------------------------------------------------------------------+------+ +| d78236 | `{"age":"16","credits":120,"id":"d78236","name":"Arthur Read","school":"PVPHS","sports":"none"}` | 16 | +| f98112 | `{"age":"15","clubs":"MUN","credits":67,"id":"f98112","name":"Buster Bunny","school":"TEO"}` | 15 | +| t63512 | `{"clubs":"Chess","id":"t63512","name":"Ernie Narayan","school":"Brooklyn Tech","sports":"Track and Field"}` | NULL | ++--------+------------------------------------------------------------------------------------------------------------+------+ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/create-tag.md b/tidb-cloud-lake/sql/create-tag.md new file mode 100644 index 0000000000000..1037a4a312c6d --- /dev/null +++ b/tidb-cloud-lake/sql/create-tag.md @@ -0,0 +1,58 @@ +--- +title: CREATE TAG +summary: 创建一个新标签,并可选择指定允许的值和注释。 +--- + +# CREATE TAG + +创建一个新标签。标签是租户级别的元信息对象,可分配给数据库对象以进行治理和分类。 + +另请参阅:[DROP TAG](/tidb-cloud-lake/sql/drop-tag.md)、[SHOW TAGS](/tidb-cloud-lake/sql/show-tags.md)、[SET TAG / UNSET TAG](/tidb-cloud-lake/sql/set-tag.md)。 + +## 语法 {#syntax} + +```sql +CREATE TAG [ IF NOT EXISTS ] + [ ALLOWED_VALUES = ( '' [, '', ... ] ) ] + [ COMMENT = '' ] +``` + +| 参数 | 描述 | +|------------------|----------------------------------------------------------| +| `tag_name` | 要创建的标签名称。 | +| `ALLOWED_VALUES` | 可选的允许值列表。设置后,在 SET TAG 中只能使用这些值。重复值会被自动移除。 | +| `COMMENT` | 标签的可选描述。 | + +## 示例 {#examples} + +创建一个带有允许值和注释的标签: + +```sql +CREATE TAG env ALLOWED_VALUES = ('dev', 'staging', 'prod') COMMENT = 'Environment classification'; +``` + +创建一个接受任意值的标签: + +```sql +CREATE TAG owner COMMENT = 'Data owner'; +``` + +创建一个没有限制的标签: + +```sql +CREATE TAG cost_center; +``` + +验证标签定义: + +```sql +SELECT name, allowed_values, comment FROM system.tags ORDER BY name; + +┌──────────────────────────────────────────────────────────────────────┐ +│ name │ allowed_values │ comment │ +├────────────────┼────────────────────────────┼────────────────────────┤ +│ cost_center │ NULL │ │ +│ env │ ['dev', 'staging', 'prod'] │ Environment classific… │ +│ owner │ NULL │ Data owner │ +└──────────────────────────────────────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/create-task.md b/tidb-cloud-lake/sql/create-task.md new file mode 100644 index 0000000000000..7908a7ac33163 --- /dev/null +++ b/tidb-cloud-lake/sql/create-task.md @@ -0,0 +1,272 @@ +--- +title: CREATE TASK +summary: CREATE TASK 语句用于定义一个新任务,该任务按调度周期或基于 dag 的任务图来执行指定的 SQL 语句。 +--- + +# CREATE TASK + +CREATE TASK 语句用于定义一个新任务,该任务按调度周期或基于 dag 的任务图来执行指定的 SQL 语句。 + +**NOTICE:** 此功能仅在 {{{ .lake }}} 中开箱即用。 + +## 语法 {#syntax} + +```sql +CREATE [ OR REPLACE ] TASK [ IF NOT EXISTS ] + WAREHOUSE = + SCHEDULE = { MINUTE | SECOND | USING CRON } + [ AFTER + [ WHEN ] + [ SUSPEND_TASK_AFTER_NUM_FAILURES = ] + [ ERROR_INTEGRATION = ] + [ COMMENT = '' ] + [ = [ , = ... ] ] +AS +{ +| BEGIN + ; + [ ; ... ] + END; +} +``` + +将多个 SQL 语句包装在 `BEGIN ... END;` 块中,以便任务按顺序将它们作为脚本执行。 + +| 参数 | 描述 | +| ------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| IF NOT EXISTS | 可选。如果指定,只有在不存在同名任务时才会创建该任务。 | +| name | 任务名称。这是必填字段。 | +| WAREHOUSE | 必填。指定任务使用的虚拟计算集群。 | +| SCHEDULE | 必填。定义任务的运行调度。可以按分钟指定,也可以结合时区使用 CRON 表达式指定。 | +| SUSPEND_TASK_AFTER_NUM_FAILURES | 可选。任务在连续失败达到该次数后会被自动挂起。 | +| AFTER | 必须在此任务启动前完成的前置任务列表。 | +| WHEN boolean_expr | 任务运行前必须满足的条件。 | +| [ERROR_INTEGRATION](/tidb-cloud-lake/sql/notification.md) | 可选。用于任务错误通知的通知集成名称,并应用特定的 [任务错误载荷](/tidb-cloud-lake/sql/task-error-notification-payload.md) | +| COMMENT | 可选。作为任务注释或描述的字符串字面量。 | +| session_parameter | 可选。指定任务运行期间使用的会话参数。注意,在 CREATE TASK 语句中,会话参数必须放在所有其他任务参数之后。 | +| sql | 任务将执行的 SQL 语句。可以是单条语句,也可以是包装在 `BEGIN ... END;` 中的脚本。这是必填字段。 | + +### 使用说明 {#usage-notes} + +- 独立任务或任务 DAG 中的根任务必须定义调度;否则,该任务只会在使用 EXECUTE TASK 手动执行时运行。 +- 任务 DAG 中的子任务不能指定调度。 +- 创建任务后,必须先执行 ALTER TASK … RESUME,任务才会根据任务定义中指定的参数开始运行。 +- 当 Condition 时,仅支持 `` 的一个子集。 + + 以下内容可在任务的 WHEN 子句中使用: + + - 支持在 SQL 表达式中使用 [STREAM_STATUS](/tidb-cloud-lake/sql/stream-status.md) 进行求值。该函数用于指示指定 stream 是否包含变更跟踪数据。你可以在启动当前运行前,使用该函数判断指定 stream 是否包含变更数据。如果结果为 FALSE,则任务不会运行。 + - 布尔运算符,例如 AND、OR、NOT 等。 + - 数值、字符串和布尔类型之间的类型转换。 + - 比较运算符,例如等于、不等于、大于、小于等。 + +> **Note:** +> +> 警告:在任务中使用 STREAM_STATUS 时,引用 stream 必须包含数据库名(例如,`STREAM_STATUS('mydb.stream_name')`)。 + +- 多个任务如果消费同一个表 stream 中的变更数据,将会获取不同的增量数据。当某个任务使用 DML 语句消费 stream 中的变更数据时,stream 会推进偏移量。这样一来,这些变更数据将不再可供下一个任务消费。目前,我们建议仅由单个任务消费一个 stream 中的变更数据。你可以为同一张表创建多个 stream,并由不同任务分别消费。 +- 任务在每次执行时不会重试;每次执行都是串行的。脚本中的每条 SQL 都会逐条执行,不会并行执行。这可以确保任务执行的顺序和依赖关系得到维护。 +- 基于间隔的任务会严格遵循固定的间隔点。这意味着,如果当前任务的执行时间超过间隔单位,则下一个任务会立即执行;否则,下一个任务会等待直到下一个间隔点触发。例如,如果某个任务定义为 1 秒间隔,而一次任务执行耗时 1.5 秒,则下一个任务会立即执行。如果一次任务执行耗时 0.5 秒,则下一个任务会等待直到下一个 1 秒间隔开始。 +- 虽然可以在创建任务时指定会话参数,但你也可以稍后使用 ALTER TASK 语句修改它们。例如: + + ```sql + ALTER TASK simple_task SET + enable_query_result_cache = 1, + query_result_cache_min_execute_secs = 5; + ``` + +### 关于 Cron 表达式的重要说明 {#important-notes-on-cron-expressions} + +- `SCHEDULE` 参数中使用的 cron 表达式必须**恰好包含 6 个字段**。 +- 这些字段分别表示: + 1. **秒** (0-59) + 2. **分** (0-59) + 3. **小时** (0-23) + 4. **每月第几天** (1-31) + 5. **月份** (1-12 或 JAN-DEC) + 6. **星期几** (0-6,其中 0 表示星期日,或 SUN-SAT) + +#### Cron 表达式示例 {#example-cron-expressions} + +- **太平洋时间每天上午 9:00:00:** + - `USING CRON '0 0 9 * * *' 'America/Los_Angeles'` + +- **每分钟:** + - `USING CRON '0 * * * * *' 'UTC'` + - 这表示任务会在每分钟开始时运行一次。 + +- **每小时的第 15 分钟:** + - `USING CRON '0 15 * * * *' 'UTC'` + - 这表示任务会在每小时过 15 分钟时运行一次。 + +- **每周一中午 12:00:00:** + - `USING CRON '0 0 12 * * 1' 'UTC'` + - 这表示任务会在每周一中午运行一次。 + +- **每月第一天的午夜:** + - `USING CRON '0 0 0 1 * *' 'UTC'` + - 这表示任务会在每个月第一天的午夜运行。 + +- **每个工作日上午 8:30:00:** + - `USING CRON '0 30 8 * * 1-5' 'UTC'` + - 这表示任务会在每个工作日(周一到周五)上午 8:30 运行。 + +## 使用示例 {#usage-examples} + +### CRON 调度 {#cron-schedule} + +```sql +CREATE TASK my_daily_task + WAREHOUSE = 'compute_wh' + SCHEDULE = USING CRON '0 0 9 * * *' 'America/Los_Angeles' + COMMENT = 'Daily summary task' +AS + INSERT INTO summary_table SELECT * FROM source_table; +``` + +在此示例中,创建了一个名为 `my_daily_task` 的任务。它使用 **compute_wh** warehouse 来运行一条 SQL 语句,将 `source_table` 中的数据插入到 `summary_table`。该任务使用 **CRON expression** 进行调度,在**太平洋时间每天上午 9 点**执行。 + +### 多条语句 {#multiple-statements} + +```sql +CREATE TASK IF NOT EXISTS nightly_refresh + WAREHOUSE = 'etl' + SCHEDULE = USING CRON '0 0 2 * * *' 'UTC' +AS +BEGIN + DELETE FROM staging.events WHERE event_time < DATEADD(DAY, -1, CURRENT_TIMESTAMP()); + INSERT INTO mart.events SELECT * FROM staging.events; +END; +``` + +此示例创建了一个名为 `nightly_refresh` 的任务,用于执行包含多条语句的脚本。该脚本被包装在 `BEGIN ... END;` 中,因此每次任务执行时,都会先运行 DELETE,再运行 INSERT。 + +### 动态 SQL(EXECUTE IMMEDIATE) {#dynamic-sql-execute-immediate} + +```sql +CREATE OR REPLACE TASK log_ingestion + WAREHOUSE = 'default' + SCHEDULE = 1 MINUTE +AS +EXECUTE IMMEDIATE $$ +BEGIN + LET path := CONCAT('@mylog/', DATE_FORMAT(CURRENT_DATE - INTERVAL 3 DAY, '%m/%d/')); + + LET sql := CONCAT( + 'COPY INTO logs.web_logs FROM ', path, + ' PATTERN = ''.*[.]gz'' FILE_FORMAT = (type = NDJSON compression = AUTO) MAX_FILES = 10000' + ); + + EXECUTE IMMEDIATE :sql; +END; +$$; +``` + +此示例创建了一个每分钟运行一次的任务。它会动态计算 **3 天前**的 stage 路径(例如,`@mylog/12/15/`),构造一条 `COPY INTO` 语句,并通过 `EXECUTE IMMEDIATE` 执行它。 + +### 自动挂起 {#automatic-suspension} + +```sql +CREATE TASK IF NOT EXISTS mytask + WAREHOUSE = 'system' + SCHEDULE = 2 MINUTE + SUSPEND_TASK_AFTER_NUM_FAILURES = 3 +AS + INSERT INTO compaction_test.test VALUES((1)); +``` + +此示例创建了一个名为 `mytask` 的任务(如果它尚不存在)。该任务被分配到 **system** warehouse,并被调度为**每 2 分钟**运行一次。如果它**连续失败三次**,将会被**自动挂起**。该任务会向 `compaction_test.test` 表执行 INSERT 操作。 + +### 秒级调度 {#second-level-scheduling} + +```sql +CREATE TASK IF NOT EXISTS daily_sales_summary + WAREHOUSE = 'analytics' + SCHEDULE = 30 SECOND +AS + SELECT sales_date, SUM(amount) AS daily_total + FROM sales_data + GROUP BY sales_date; +``` + +在此示例中,创建了一个名为 `daily_sales_summary` 的任务,并使用**秒级调度**。它被设置为**每 30 秒**运行一次。该任务使用 **analytics** warehouse,并通过聚合 `sales_data` 表中的数据来计算每日销售汇总。 + +### 任务依赖 {#task-dependencies} + +```sql +CREATE TASK IF NOT EXISTS process_orders + WAREHOUSE = 'etl' + AFTER task1 +AS + INSERT INTO data_warehouse.orders SELECT * FROM staging.orders; +``` + +在此示例中,创建了一个名为 `process_orders` 的任务,并将其定义为在 **task1** 和 **task2** **成功完成之后**运行。这对于在任务的**有向无环图(DAG)**中创建**依赖关系**非常有用。该任务使用 **etl** 计算集群,并将数据从暂存区传输到数据仓库。 + +> 提示:使用 AFLTER 参数时,无需设置 SCHEDULE 参数。 + +### 条件执行 {#conditional-execution} + +```sql +CREATE TASK IF NOT EXISTS hourly_data_cleanup + WAREHOUSE = 'maintenance' + SCHEDULE = USING CRON '0 0 9 * * *' 'America/Los_Angeles' + WHEN STREAM_STATUS('db1.change_stream') = TRUE +AS + DELETE FROM archived_data + WHERE archived_date < DATEADD(HOUR, -24, CURRENT_TIMESTAMP()); + +``` + +在此示例中,创建了一个名为 `hourly_data_cleanup` 的任务。它使用 **maintenance** 计算集群,并被调度为**每小时**运行一次。该任务会删除 `archived_data` 表中超过 24 小时的数据。该任务仅会在**满足条件时**运行,即使用 **STREAM_STATUS** 函数检查 `db1.change_stream` 是否包含变更数据。 + +### 错误集成 {#error-integration} + +```sql +CREATE TASK IF NOT EXISTS mytask + WAREHOUSE = 'mywh' + SCHEDULE = 30 SECOND + ERROR_INTEGRATION = 'myerror' +AS + BEGIN + BEGIN; + INSERT INTO mytable(ts) VALUES(CURRENT_TIMESTAMP); + DELETE FROM mytable WHERE ts < DATEADD(MINUTE, -5, CURRENT_TIMESTAMP()); + COMMIT; + END; +``` + +在此示例中,创建了一个名为 `mytask` 的任务。它使用 **mywh** 计算集群,并被调度为**每 30 秒**运行一次。该任务执行一个 **BEGIN 块**,其中包含一条 INSERT 语句和一条 DELETE 语句。在两条语句都执行后,任务会提交事务。当任务失败时,它将触发名为 **myerror** 的**错误集成**。 + +### 会话参数 {#session-parameters} + +```sql +CREATE TASK IF NOT EXISTS cache_enabled_task + WAREHOUSE = 'analytics' + SCHEDULE = 5 MINUTE + COMMENT = 'Task with query result cache enabled' + enable_query_result_cache = 1, + query_result_cache_min_execute_secs = 5 +AS + SELECT SUM(amount) AS total_sales + FROM sales_data + WHERE transaction_date >= DATEADD(DAY, -7, CURRENT_DATE()) + GROUP BY product_category; +``` + +在此示例中,创建了一个名为 `cache_enabled_task` 的任务,并配置了用于启用查询结果缓存的**会话参数**。该任务被调度为**每 5 分钟**运行一次,并使用 **analytics** 计算集群。会话参数 **`enable_query_result_cache = 1`** 和 **`query_result_cache_min_execute_secs = 5`** 被指定在**所有其他任务参数之后**,从而为执行时间至少为 5 秒的查询启用查询结果缓存。如果底层数据没有变化,这可以在后续执行相同任务时**提升性能**。 + +### 查看任务运行历史 {#view-task-run-history} + +使用 `TASK_HISTORY()` 表函数查看任务何时运行以及如何运行: + +```sql +SELECT * +FROM TASK_HISTORY( + TASK_NAME => 'daily_sales_summary', + RESULT_LIMIT => 20 +) +ORDER BY scheduled_time DESC; +``` + +有关所有可用选项,请参见 [TASK HISTORY](/tidb-cloud-lake/sql/table-functions.md),包括按时间范围或 DAG 中的根任务 ID 进行过滤。 \ No newline at end of file diff --git a/tidb-cloud-lake/sql/create-temp-table.md b/tidb-cloud-lake/sql/create-temp-table.md new file mode 100644 index 0000000000000..3364480c165ae --- /dev/null +++ b/tidb-cloud-lake/sql/create-temp-table.md @@ -0,0 +1,85 @@ +--- +title: CREATE TEMP TABLE +summary: 创建一个在会话结束时自动删除的临时表。 +--- + +# CREATE TEMP TABLE + +创建一个在会话结束时自动删除的临时表。 + +- 临时表仅在创建它的会话内可见,并会在会话结束时自动删除,同时清理其中的所有数据。 + - 如果临时表的自动清理失败——例如由于查询节点崩溃——你可以使用 [FUSE_VACUUM_TEMPORARY_TABLE](/tidb-cloud-lake/sql/fuse-vacuum-temporary-table.md) 函数手动清理临时表遗留的文件。 +- 要显示当前会话中已有的临时表,请查询 [system.temporary_tables](/tidb-cloud-lake/sql/system-tables.md) 系统表。参见 [Example-1](#example-1)。 +- 如果临时表与普通表同名,则临时表优先生效,在其被删除之前会隐藏普通表。参见 [Example-2](#example-2)。 +- 创建或操作临时表不需要任何权限。 +- {{{ .lake }}} 支持使用 [Fuse Engine](/tidb-cloud-lake/sql/table-engines.md) 创建临时表。 +- 要使用 LakeSQL 创建临时表,请确保你使用的是最新版本的 LakeSQL。 + +## 语法 {#syntax} + +```sql +CREATE [ OR REPLACE ] { TEMPORARY | TEMP } TABLE + [ IF NOT EXISTS ] + [ . ] + ... +``` + +省略的部分遵循 [CREATE TABLE](/tidb-cloud-lake/sql/create-table.md) 的语法。 + +## 示例 {#examples} + +### Example-1 {#example-1} + +本示例演示如何创建临时表,并通过查询 [system.temporary_tables](/tidb-cloud-lake/sql/system-tables.md) 系统表来验证其是否存在: + +```sql +CREATE TEMP TABLE my_table (id INT, description STRING); + +SELECT * FROM system.temporary_tables; + +┌────────────────────────────────────────────────────┐ +│ database │ name │ table_id │ engine │ +├──────────┼──────────┼─────────────────────┼────────┤ +│ default │ my_table │ 4611686018427407904 │ FUSE │ +└────────────────────────────────────────────────────┘ +``` + +### Example-2 {#example-2} + +本示例演示同名临时表如何优先生效。当两张表同时存在时,操作会作用于临时表,从而有效隐藏普通表。临时表删除后,普通表将再次可访问: + +```sql +-- Create a normal table +CREATE TABLE my_table (id INT, name STRING); + +-- Insert data into the normal table +INSERT INTO my_table VALUES (1, 'Alice'), (2, 'Bob'); + +-- Create a temporary table with the same name +CREATE TEMP TABLE my_table (id INT, description STRING); + +-- Insert data into the temporary table +INSERT INTO my_table VALUES (1, 'Temp Data'); + +-- Query the table: This will access the temporary table, hiding the normal table +SELECT * FROM my_table; + +┌────────────────────────────────────┐ +│ id │ description │ +├─────────────────┼──────────────────┤ +│ 1 │ Temp Data │ +└────────────────────────────────────┘ + +-- Drop the temporary table +DROP TABLE my_table; + +-- Query the table again: Now the normal table is accessible +SELECT * FROM my_table; + +┌────────────────────────────────────┐ +│ id │ name │ +├─────────────────┼──────────────────┤ +│ 1 │ Alice │ +│ 2 │ Bob │ +└────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/create-transient-table.md b/tidb-cloud-lake/sql/create-transient-table.md new file mode 100644 index 0000000000000..2e9a724b21938 --- /dev/null +++ b/tidb-cloud-lake/sql/create-transient-table.md @@ -0,0 +1,35 @@ +--- +title: CREATE TRANSIENT TABLE +summary: 创建一个不为 Time Travel 存储历史数据的表。 +--- + +# CREATE TRANSIENT TABLE + +创建一个不为 Time Travel 存储历史数据的表。 + +Transient table 用于保存临时性数据,这类数据不需要数据保护或恢复机制。Dataebend 不会为 transient table 保存历史数据,因此你无法使用 Time Travel 功能查询 transient table 的先前版本。例如,SELECT 语句中的 [AT](/tidb-cloud-lake/sql/at.md) 子句不适用于 transient table。请注意,你仍然可以 [删除](/tidb-cloud-lake/sql/drop-table.md) 和 [恢复删除](/tidb-cloud-lake/sql/undrop-table.md) transient table。 + +> **Note:** +> +> 对 transient table 的并发修改(包括写操作)可能会导致数据损坏,使数据无法读取。该缺陷正在修复中。在问题修复之前,请避免对 transient table 进行并发修改。 + +## 语法 {#syntax} + +```sql +CREATE [ OR REPLACE ] TRANSIENT TABLE + [ IF NOT EXISTS ] + [ . ] + ... +``` + +省略的部分遵循 [CREATE TABLE](/tidb-cloud-lake/sql/create-table.md) 的语法。 + +## 示例 {#examples} + +以下示例创建了一个名为 `visits` 的 transient table: + +```sql +CREATE TRANSIENT TABLE visits ( + visitor_id BIGINT +); +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/create-user.md b/tidb-cloud-lake/sql/create-user.md new file mode 100644 index 0000000000000..5e11688c1965c --- /dev/null +++ b/tidb-cloud-lake/sql/create-user.md @@ -0,0 +1,98 @@ +--- +title: CREATE USER +summary: 创建一个用于连接到 {{{ .lake }}} 的 SQL 用户。必须为用户授予适当的权限,才能访问数据库并执行操作。 +--- + +# CREATE USER + +创建一个用于连接到 {{{ .lake }}} 的 SQL 用户。必须为用户授予适当的权限,才能访问数据库并执行操作。 + +另请参阅: + +- [GRANT](/tidb-cloud-lake/sql/grant.md) +- [ALTER USER](/tidb-cloud-lake/sql/alter-user.md) +- [DROP USER](/tidb-cloud-lake/sql/drop-user.md) + +## 语法 {#syntax} + +```sql +CREATE [ OR REPLACE ] USER IDENTIFIED [ WITH ] BY '' +[ WITH MUST_CHANGE_PASSWORD = true | false ] +[ WITH SET PASSWORD POLICY = '' ] +[ WITH SET NETWORK POLICY = '' ] +[ WITH DEFAULT_ROLE = '' ] +[ WITH DISABLED = true | false ] +``` + +**参数:** + +- ``:用户名(不能包含单引号、双引号、退格符或换页符) +- ``:认证类型 - `double_sha1_password`(默认)、`sha256_password` 或 `no_password` +- `MUST_CHANGE_PASSWORD`:当为 `true` 时,用户必须在首次登录时修改密码 +- `DEFAULT_ROLE`:设置默认角色(角色必须被显式授予后才会生效) +- `DISABLED`:当为 `true` 时,用户将以禁用状态创建,且无法登录 + +## 示例 {#examples} + +### 示例 1:跨所有数据库的完全访问权限 {#example-1-full-access-across-all-databases} + +创建一个在所有数据库上都具有完整读写权限的用户: + +```sql +-- Create a role with global access +CREATE ROLE full_access_role; +GRANT ALL ON *.* TO ROLE full_access_role; + +-- Create the user and assign the role +CREATE USER admin_user IDENTIFIED BY 'SecurePass456!' WITH DEFAULT_ROLE = 'full_access_role'; +GRANT ROLE full_access_role TO admin_user; +``` + +### 示例 2:跨所有数据库的只读访问权限 {#example-2-read-only-access-across-all-databases} + +创建一个只能查询数据的用户,适用于仪表板或 BI 工具: + +```sql +-- Create a read-only role +CREATE ROLE readonly_role; +GRANT SELECT ON *.* TO ROLE readonly_role; + +-- Create the user +CREATE USER readonly_user IDENTIFIED BY 'ReadOnly789!' WITH DEFAULT_ROLE = 'readonly_role'; +GRANT ROLE readonly_role TO readonly_user; +``` + +### 示例 3:单个数据库访问权限 {#example-3-single-database-access} + +创建一个角色,授予数据库权限,并将该角色分配给用户: + +```sql +-- Create a role and grant database privileges +CREATE ROLE data_analyst_role; +GRANT SELECT, INSERT ON default.* TO ROLE data_analyst_role; + +-- Create a new user and assign the role +CREATE USER data_analyst IDENTIFIED BY 'secure_password123' WITH DEFAULT_ROLE = 'data_analyst_role'; +GRANT ROLE data_analyst_role TO data_analyst; +``` + +验证角色和权限: + +```sql +SHOW GRANTS FOR ROLE data_analyst_role; ++-----------------------------------------------------------------+ +| Grants | ++-----------------------------------------------------------------+ +| GRANT SELECT,INSERT ON 'default'.* TO ROLE 'data_analyst_role' | ++-----------------------------------------------------------------+ +``` + +### 示例 4:使用不同认证类型创建用户 {#example-4-create-users-with-different-authentication-types} + +```sql +-- Create user with default authentication +CREATE USER user1 IDENTIFIED BY 'abc123'; + +-- Create user with SHA256 authentication +CREATE USER user2 IDENTIFIED WITH sha256_password BY 'abc123'; +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/create-vector-index.md b/tidb-cloud-lake/sql/create-vector-index.md new file mode 100644 index 0000000000000..34c1faf5a47df --- /dev/null +++ b/tidb-cloud-lake/sql/create-vector-index.md @@ -0,0 +1,197 @@ +--- +title: CREATE VECTOR INDEX +summary: 在表的 VECTOR 列上创建 Vector 索引,以使用 HNSW(Hierarchical Navigable Small World)算法实现高效的相似性搜索。 +--- + +# CREATE VECTOR INDEX + +在表的 [VECTOR](/tidb-cloud-lake/sql/vector.md) 列上创建 Vector 索引,以使用 HNSW(Hierarchical Navigable Small World)算法实现高效的相似性搜索。 + +## 语法 {#syntax} + +```sql +-- Create a Vector index on an existing table +CREATE [OR REPLACE] VECTOR INDEX [IF NOT EXISTS] +ON [.]() +distance = '' [m = ] [ef_construct = ] + +-- Create a Vector index when creating a table +CREATE [OR REPLACE] TABLE ( + , + VECTOR INDEX () + distance = '' [m = ] [ef_construct = ] +)... +``` + +### 参数 {#parameters} + +- **`distance`**(必需)- 指定用于相似性搜索的距离度量。可以使用逗号组合多个度量: + - `'cosine'` - 余弦距离(最适合语义相似性、文本嵌入) + - `'l1'` - L1 距离 / 曼哈顿距离(适合特征比较、稀疏数据) + - `'l2'` - L2 距离 / 欧几里得距离(最适合几何相似性、图像特征) + - 示例:`distance = 'cosine,l1,l2'` 支持这三种度量 + +- **`m`**(可选,默认值:16)- 控制 HNSW 图中每个节点拥有的双向连接数: + - 更高的值会增加内存使用,但可以提高搜索准确性 + - 必须大于 0 + - 典型范围:8-64 + +- **`ef_construct`**(可选,默认值:100)- 控制索引构建期间动态候选列表的大小: + - 更高的值会提高索引质量,但会增加构建时间和内存消耗 + - 必须 >= 40 + - 典型范围:40-500 + +## Vector 索引的工作原理 {#how-vector-index-works} + +{{{ .lake }}} 中的 Vector 索引使用 HNSW 算法构建多层图结构: + +1. **图结构**:每个向量都是一个节点,并与其最近邻建立连接 +2. **搜索过程**:查询会在图的各层之间导航,从粗到细快速找到近似最近邻 +3. **量化**:对原始向量进行量化,以减少存储并提升查询性能(准确性损失可忽略不计) +4. **自动构建**:索引会在数据写入时自动构建。每次 INSERT、COPY 或数据加载操作都会自动为新行生成索引,无需手动维护 + +## 示例 {#examples} + +### 创建带有 Vector 索引的表 {#creating-a-table-with-vector-index} + +```sql +-- Simple vector index for embeddings +CREATE TABLE documents ( + id INT, + title VARCHAR, + content TEXT, + embedding VECTOR(1024), + VECTOR INDEX idx_embedding(embedding) distance = 'cosine' +); +``` + +### 使用自定义参数创建 Vector 索引 {#creating-a-vector-index-with-custom-parameters} + +```sql +-- Vector index with multiple distance metrics and tuned parameters +CREATE TABLE images ( + id INT, + filename VARCHAR, + feature_vector VECTOR(512), + VECTOR INDEX idx_features(feature_vector) + distance = 'cosine,l2' + m = 32 + ef_construct = 200 +); +``` + +### 在现有表上创建 Vector 索引 {#creating-a-vector-index-on-an-existing-table} + +```sql +CREATE TABLE products ( + id INT, + name VARCHAR, + description TEXT, + embedding VECTOR(768) +); + +-- Add vector index after table creation +CREATE VECTOR INDEX idx_product_embedding +ON products(embedding) +distance = 'cosine,l1,l2' +m = 20 +ef_construct = 150; +``` + +### 在不同列上创建多个 Vector 索引 {#multiple-vector-indexes-on-different-columns} + +```sql +CREATE TABLE multimodal_data ( + id INT, + text_embedding VECTOR(384), + image_embedding VECTOR(512), + VECTOR INDEX idx_text(text_embedding) distance = 'cosine', + VECTOR INDEX idx_image(image_embedding) distance = 'l2' +); +``` + +### 查看索引 {#viewing-indexes} + +使用 [SHOW INDEXES](/tidb-cloud-lake/sql/show-indexes.md) 查看所有索引: + +```sql +SHOW INDEXES; +``` + +结果: + +``` +┌──────────────────────┬────────┬──────────┬────────────────────────────┬──────────────────────────┐ +│ name │ type │ original │ definition │ created_on │ +├──────────────────────┼────────┼──────────┼────────────────────────────┼──────────────────────────┤ +│ idx_embedding │ VECTOR │ │ documents(embedding) │ 2025-05-13 01:22:34.123 │ +│ idx_product_embedding│ VECTOR │ │ products(embedding) │ 2025-05-13 01:23:45.678 │ +└──────────────────────┴────────┴──────────┴────────────────────────────┴──────────────────────────┘ +``` + +### 使用 Vector 索引进行相似性搜索 {#using-vector-index-for-similarity-search} + +```sql +-- Create a table with vector index +CREATE TABLE wiki_articles ( + id INT, + title VARCHAR, + embedding VECTOR(8), + VECTOR INDEX idx_embedding(embedding) distance = 'cosine' +); + +-- Insert sample data (8-dimensional vectors for demonstration) +INSERT INTO wiki_articles VALUES +(1, 'Machine Learning', [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8]), +(2, 'Deep Learning', [0.15, 0.25, 0.35, 0.45, 0.55, 0.65, 0.75, 0.85]), +(3, 'Natural Language Processing', [0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9]), +(4, 'Computer Vision', [0.8, 0.7, 0.6, 0.5, 0.4, 0.3, 0.2, 0.1]); + +-- Find the 2 most similar articles to a query vector using cosine distance +SELECT id, title, cosine_distance(embedding, [0.12, 0.22, 0.32, 0.42, 0.52, 0.62, 0.72, 0.82]) AS distance +FROM wiki_articles +ORDER BY distance ASC +LIMIT 2; +``` + +结果: + +``` +┌────┬─────────────────┬──────────────┐ +│ id │ title │ distance │ +├────┼─────────────────┼──────────────┤ +│ 1 │ Machine Learning│ 0.00012345 │ +│ 2 │ Deep Learning │ 0.00023456 │ +└────┴─────────────────┴──────────────┘ +``` + +## 性能调优 {#performance-tuning} + +### 选择距离度量 {#choosing-distance-metrics} + +请根据你的使用场景选择合适的距离度量。有关如何使用距离函数进行查询,请参见 [向量函数](/tidb-cloud-lake/sql/vector-functions.md)。 + +- **余弦距离**:最适合来自 BERT、GPT 等模型的文本嵌入,此时向量的模长并不重要 +- **L2(欧几里得)距离**:最适合图像特征、空间数据等绝对差异很重要的场景 +- **L1(曼哈顿)距离**:适合稀疏向量,以及希望强调各个维度差异的场景 + +### 调优 HNSW 参数 {#tuning-hnsw-parameters} + +| 参数 | 较低值 | 较高值 | +|----------------|--------------------------------------|--------------------------------------| +| `m` | 更少内存,更快构建 | 更高准确性,更多内存 | +| `ef_construct` | 构建更快,质量较低 | 质量更高,构建更慢 | + +**推荐配置:** + +- **小型数据集(< 100K 个向量)**:默认设置(`m=16`,`ef_construct=100`) +- **中型数据集(100K - 1M 个向量)**:`m=24`,`ef_construct=150` +- **大型数据集(> 1M 个向量)**:`m=32`,`ef_construct=200` +- **高准确性要求**:`m=48`,`ef_construct=300` + +## 限制 {#limitations} + +- Vector 索引仅支持 [VECTOR](/tidb-cloud-lake/sql/vector.md) 数据类型的列 +- `distance` 参数是必需的;如果索引未指定该参数,将被忽略 +- 量化可能会在距离计算中引入可忽略不计的误差(通常 < 0.01%) +- 更高的 `m` 值会增加索引大小(每个向量大约增加 `m * vector_dimension * 4 bytes`) \ No newline at end of file diff --git a/tidb-cloud-lake/sql/create-view.md b/tidb-cloud-lake/sql/create-view.md new file mode 100644 index 0000000000000..552d4cab21eb3 --- /dev/null +++ b/tidb-cloud-lake/sql/create-view.md @@ -0,0 +1,55 @@ +--- +title: CREATE VIEW +summary: 基于查询创建一个新的视图;逻辑视图不存储任何物理数据,当我们访问逻辑视图时,它会将 sql 转换为子查询格式来完成查询。 +--- + +# CREATE VIEW + +基于查询创建一个新的视图;逻辑视图不存储任何物理数据,当我们访问逻辑视图时,它会将 sql 转换为子查询格式来完成查询。 + +例如,如果你创建了一个逻辑视图: + +```sql +CREATE VIEW view_t1 AS SELECT a, b FROM t1; +``` + +然后执行如下查询: + +```sql +SELECT a FROM view_t1; +``` + +其结果等价于下面的查询: + +```sql +SELECT a FROM (SELECT a, b FROM t1); +``` + +因此,如果你删除了该视图所依赖的表,就会报错,提示原始表不存在。此时,你可能需要删除旧视图并重新创建所需的新视图。 + +## 语法 {#syntax} + +```sql +CREATE [ OR REPLACE ] VIEW [ IF NOT EXISTS ] [ db. ]view_name [ (, ...) ] AS SELECT query +``` + +## 访问控制要求 {#access-control-requirements} + +要访问视图,用户只需要拥有该视图本身的 SELECT 权限。 + +不需要对视图的底层表单独授予权限。该机制简化了访问控制并增强了数据安全性。 + +## 示例 {#examples} + +```sql +CREATE VIEW tmp_view(c1, c2) AS SELECT number % 3 AS a, avg(number) FROM numbers(1000) GROUP BY a ORDER BY a; + +SELECT * FROM tmp_view; ++------+-------+ +| c1 | c2 | ++------+-------+ +| 0 | 499.5 | +| 1 | 499.0 | +| 2 | 500.0 | ++------+-------+ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/create-warehouse.md b/tidb-cloud-lake/sql/create-warehouse.md new file mode 100644 index 0000000000000..48d3f8edec267 --- /dev/null +++ b/tidb-cloud-lake/sql/create-warehouse.md @@ -0,0 +1,66 @@ +--- +title: CREATE WAREHOUSE +summary: 为计算资源创建一个新的计算集群。 +--- + +# CREATE WAREHOUSE + +为计算资源创建一个新的计算集群。 + +## 语法 {#syntax} + +```sql +CREATE WAREHOUSE [ IF NOT EXISTS ] + [ WITH ] warehouse_size = + [ WITH ] auto_suspend = + [ WITH ] initially_suspended = + [ WITH ] auto_resume = + [ WITH ] max_cluster_count = + [ WITH ] min_cluster_count = + [ WITH ] comment = '' + [ WITH ] TAG ( = '' [ , = '' , ... ] ) +``` + +| 参数 | 描述 | +| --------------- | ------------------------------------------------------------------------------------- | +| `IF NOT EXISTS` | 可选。如果指定了该选项,当计算集群已存在时,命令会成功返回且不做任何更改。 | +| warehouse_name | 3–63 个字符,只能包含 `A-Z`、`a-z`、`0-9` 和 `-`。 | + +## 选项 {#options} + +| 选项 | 类型 / 值 | 默认值 | 描述 | +| --------------------- | --------------------------------------------------------------------------------------- | ------------- | --------------------------------------------------------------------------------------------------------------------------------------------- | +| `WAREHOUSE_SIZE` | `XSmall`, `Small`, `Medium`, `Large`, `XLarge`, `2XLarge`–`6XLarge`(不区分大小写) | `Small` | 控制计算规模。 | +| `AUTO_SUSPEND` | `NULL`、`0` 或 ≥300 秒 | `600` 秒 | 自动挂起前的空闲超时时间。`0`/`NULL` 表示永不挂起;小于 300 的值会被拒绝。 | +| `INITIALLY_SUSPENDED` | 布尔值 | `FALSE` | 如果为 `TRUE`,则计算集群在创建后会保持挂起状态,直到被显式恢复。 | +| `AUTO_RESUME` | 布尔值 | `TRUE` | 控制传入查询是否会自动唤醒计算集群。 | +| `MAX_CLUSTER_COUNT` | `NULL` 或非负整数 | `0` | 自动扩展集群数的上限。`0` 表示禁用自动扩展。 | +| `MIN_CLUSTER_COUNT` | `NULL` 或非负整数 | `0` | 自动扩展集群数的下限;应当 ≤ `MAX_CLUSTER_COUNT`。 | +| `COMMENT` | 字符串 | 空 | 由 `SHOW WAREHOUSES` 展示的自由文本。 | +| `TAG` | 键值对:`TAG ( key1 = 'value1', key2 = 'value2' )` | 无 | 用于分类和组织的资源标签(类似 AWS tags)。可用于成本分摊、环境标识或团队归属。 | + +- 选项可以按任意顺序出现,也可以重复出现(以后面的值为准)。 +- `AUTO_SUSPEND`、`MAX_CLUSTER_COUNT` 和 `MIN_CLUSTER_COUNT` 接受 `= NULL`,以将其重置为 `0`。 + +## 示例 {#examples} + +以下示例创建了一个启用自动扩展并带有自定义设置的 XLarge 计算集群 (Warehouse): + +```sql +CREATE WAREHOUSE IF NOT EXISTS 'etl-wh' + WITH warehouse_size = XLarge + auto_suspend = 600 + initially_suspended = TRUE + auto_resume = FALSE + max_cluster_count = 4 + min_cluster_count = 2 + comment = 'Nightly ETL warehouse' + TAG (environment = 'production', team = 'data-engineering', cost_center = 'analytics'); +``` + +以下示例创建了一个基础的 Small 计算集群: + +```sql +CREATE WAREHOUSE 'my-warehouse' + WITH warehouse_size = Small; +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/create-worker.md b/tidb-cloud-lake/sql/create-worker.md new file mode 100644 index 0000000000000..e5b47f7ef8d8d --- /dev/null +++ b/tidb-cloud-lake/sql/create-worker.md @@ -0,0 +1,81 @@ +--- +title: CREATE WORKER +summary: 使用可选的键值选项列表创建一个 worker。 +--- + +# CREATE WORKER + +> **注意:** +> +> 于 v1.3.0 中引入。 + +创建一个 worker。 + +> **注意:** +> +> 此命令要求启用 cloud control。 + +## 语法 {#syntax} + +```sql +CREATE WORKER [ IF NOT EXISTS ] + [ WITH = [ , = ... ] ] +``` + +## 参数 {#parameters} + +| 参数 | 描述 | +|-----------|-------------| +| `IF NOT EXISTS` | 可选。如果 worker 已存在,则成功返回且不做任何更改。 | +| `` | worker 名称。 | +| `` | worker 选项键。 | +| `` | worker 选项值。 | + +## 选项 {#options} + +{{{ .lake }}} 接受单个 `WITH` 子句,后跟一个以逗号分隔的选项列表。常见的 worker 选项包括: + +| 选项 | 示例值 | 描述 | +|--------|---------------|-------------| +| `size` | `'small'` | 控制 worker 的计算规模。 | +| `auto_suspend` | `'300'` | 自动挂起前的空闲超时时间。 | +| `auto_resume` | `'true'` | 控制 worker 是否自动恢复。 | +| `max_cluster_count` | `'3'` | 自动扩缩容集群数量的上限。 | +| `min_cluster_count` | `'1'` | 自动扩缩容集群数量的下限。 | + +- `WITH` 最多只能出现一次。 +- 选项之间使用逗号分隔。 +- 在发送请求之前,选项名称会被规范化为小写。 +- `option_value` 可以写为字符串字面量、裸标识符、无符号整数或布尔值。 +- `CREATE WORKER` 不支持 `TAG` 子句。 + +## 示例 {#examples} + +创建一个不带选项的 worker: + +```sql +CREATE WORKER read_env; +``` + +使用 `IF NOT EXISTS` 创建一个 worker: + +```sql +CREATE WORKER IF NOT EXISTS read_env; +``` + +使用自定义选项创建一个 worker: + +```sql +CREATE WORKER IF NOT EXISTS read_env +WITH size = 'small', + auto_suspend = '300', + auto_resume = 'true', + max_cluster_count = '3', + min_cluster_count = '1'; +``` + +## 相关主题 {#related-topics} + +- [ALTER WORKER](/tidb-cloud-lake/sql/alter-worker.md) - 修改 worker 的标签、选项或状态 +- [SHOW WORKERS](/tidb-cloud-lake/sql/show-workers.md) - 列出 workers 及其元信息 +- [DROP WORKER](/tidb-cloud-lake/sql/drop-worker.md) - 删除一个 worker \ No newline at end of file diff --git a/tidb-cloud-lake/sql/create-workload-group.md b/tidb-cloud-lake/sql/create-workload-group.md new file mode 100644 index 0000000000000..3331c1118f68e --- /dev/null +++ b/tidb-cloud-lake/sql/create-workload-group.md @@ -0,0 +1,97 @@ +--- +title: CREATE WORKLOAD GROUP +summary: 使用指定的配额设置创建 workload group。workload group 通过绑定到用户来控制资源分配和查询并发。当用户提交查询时,系统会根据该用户所属的组应用 workload group 的限制。 +--- + +# CREATE WORKLOAD GROUP + +使用指定的配额设置创建 workload group。workload group 通过绑定到用户来控制资源分配和查询并发。当用户提交查询时,系统会根据该用户所属的组应用 workload group 的限制。 + +## 语法 {#syntax} + +```sql +CREATE WORKLOAD GROUP [IF NOT EXISTS] +[WITH cpu_quota = '', query_timeout = ''] +``` + +## 参数 {#parameters} + +| 参数 | 类型 | 必需 | 默认值 | 描述 | +|------------------------|----------|----------|--------------|-----------------------------------------------------------------------------| +| `cpu_quota` | string | 否 | (无限制) | 以百分比字符串表示的 CPU 资源配额(例如 `"20%"`) | +| `query_timeout` | duration | 否 | (无限制) | 查询超时时长(单位:`s`/`sec`=秒,`m`/`min`=分钟,`h`/`hour`=小时,`d`/`day`=天,`ms`=毫秒,无单位=秒) | +| `memory_quota` | string or integer | 否 | (无限制) | workload group 的最大内存使用限制(百分比或绝对值) | +| `max_concurrency` | integer | 否 | (无限制) | workload group 的最大并发数 | +| `query_queued_timeout` | duration | 否 | (无限制) | 当 workload group 超过最大并发时,排队等待的最长时间(单位:`s`/`sec`=秒,`m`/`min`=分钟,`h`/`hour`=小时,`d`/`day`=天,`ms`=毫秒,无单位=秒) | + +## 示例 {#examples} + +### 基本示例 {#basic-example} + +```sql +-- Create workload groups +CREATE WORKLOAD GROUP IF NOT EXISTS interactive_queries +WITH cpu_quota = '30%', memory_quota = '20%', max_concurrency = 2; + +CREATE WORKLOAD GROUP IF NOT EXISTS batch_processing +WITH cpu_quota = '70%', memory_quota = '80%', max_concurrency = 10; +``` + +### 用户分配 {#user-assignment} + +必须先将用户分配到 workload group,才能启用资源限制。当用户执行查询时,系统会自动应用该 workload group 的限制。 + +```sql +-- Create role and grant permissions +CREATE ROLE analytics_role; +GRANT ALL ON *.* TO ROLE analytics_role; +CREATE USER analytics_user IDENTIFIED BY 'password123' WITH DEFAULT_ROLE = 'analytics_role'; +GRANT ROLE analytics_role TO analytics_user; + +-- Assign user to workload group +ALTER USER analytics_user WITH SET WORKLOAD GROUP = 'interactive_queries'; + +-- Reassign to different workload group +ALTER USER analytics_user WITH SET WORKLOAD GROUP = 'batch_processing'; + +-- Remove from workload group (user will use default unlimited resources) +ALTER USER analytics_user WITH UNSET WORKLOAD GROUP; + +-- Check user's workload group +DESC USER analytics_user; +``` + +## 资源配额归一化 {#resource-quota-normalization} + +### 配额限制 {#quota-limits} + +- 每个 workload group 的 `cpu_quota` 和 `memory_quota` 最多可设置为 `100%`(1.0) +- 所有 workload group 的配额总和可以超过 100% +- 实际资源分配会根据相对比例进行**归一化** + +### 配额归一化的工作方式 {#how-quota-normalization-works} + +资源会根据每个组的配额占总配额的比例按比例分配: + +``` +实际分配 = (组配额)/(所有组配额之和)× 100% +``` + +**示例 1:总配额 = 100%** + +- 组 A:30% 配额 → 获得 30% 的资源(30/100) +- 组 B:70% 配额 → 获得 70% 的资源(70/100) + +**示例 2:总配额 > 100%** + +- 组 A:60% 配额 → 获得 40% 的资源(60/150) +- 组 B:90% 配额 → 获得 60% 的资源(90/150) +- 总配额:150% + +**示例 3:总配额 < 100%** + +- 组 A:20% 配额 → 获得 67% 的资源(20/30) +- 组 B:10% 配额 → 获得 33% 的资源(10/30) +- 总配额:30% + +**特殊情况:**当只存在一个 workload group 时,无论其配置的配额是多少,它都会获得计算集群 (Warehouse) 100% 的资源。 \ No newline at end of file diff --git a/tidb-cloud-lake/sql/cume-dist.md b/tidb-cloud-lake/sql/cume-dist.md new file mode 100644 index 0000000000000..abb75981b90af --- /dev/null +++ b/tidb-cloud-lake/sql/cume-dist.md @@ -0,0 +1,76 @@ +--- +title: CUME_DIST +summary: 计算每一行值的累积分布。返回值小于或等于当前行值的行所占的比例。 +--- + +# CUME_DIST + +> **注意:** +> +> 于 v1.2.7 引入。 + +计算每一行值的累积分布。返回值小于或等于当前行值的行所占的比例。 + +另请参阅:[PERCENT_RANK](/tidb-cloud-lake/sql/percent-rank.md) + +## 语法 {#syntax} + +```sql +CUME_DIST() +OVER ( + [ PARTITION BY partition_expression ] + ORDER BY sort_expression [ ASC | DESC ] +) +``` + +**参数:** + +- `PARTITION BY`:可选。将行划分为分区 +- `ORDER BY`:必需。确定分布的排序顺序 +- `ASC | DESC`:可选。排序方向(默认值:ASC) + +**说明:** + +- 返回介于 0 和 1 之间的值(不包括 0,包括 1) +- 公式:(小于或等于当前值的行数)/(总行数) +- 对于最大值,始终返回 1.0 +- 适用于计算百分位数和累计百分比 + +## 示例 {#examples} + +```sql +-- Create sample data +CREATE TABLE scores ( + student VARCHAR(20), + score INT +); + +INSERT INTO scores VALUES + ('Alice', 95), + ('Bob', 87), + ('Charlie', 87), + ('David', 82), + ('Eve', 78); +``` + +**计算累积分布(显示每个分数及以下分数的学生所占百分比):** + +```sql +SELECT student, score, + CUME_DIST() OVER (ORDER BY score) AS cume_dist, + ROUND(CUME_DIST() OVER (ORDER BY score) * 100) AS cumulative_percent +FROM scores +ORDER BY score; +``` + +结果: + +``` +student | score | cume_dist | cumulative_percent +--------+-------+-----------+------------------- +Eve | 78 | 0.2 | 20 +David | 82 | 0.4 | 40 +Bob | 87 | 0.8 | 80 +Charlie | 87 | 0.8 | 80 +Alice | 95 | 1.0 | 100 +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/current-catalog.md b/tidb-cloud-lake/sql/current-catalog.md new file mode 100644 index 0000000000000..ea8a7b0f72a38 --- /dev/null +++ b/tidb-cloud-lake/sql/current-catalog.md @@ -0,0 +1,26 @@ +--- +title: CURRENT_CATALOG +summary: 返回当前会话正在使用的 catalog 名称。 +--- + +# CURRENT_CATALOG + +返回当前会话正在使用的 catalog 名称。 + +## 语法 {#syntax} + +```sql +CURRENT_CATALOG() +``` + +## 示例 {#examples} + +```sql +SELECT CURRENT_CATALOG(); + +┌───────────────────┐ +│ current_catalog() │ +├───────────────────┤ +│ default │ +└───────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/current-timestamp.md b/tidb-cloud-lake/sql/current-timestamp.md new file mode 100644 index 0000000000000..d03b9e528d329 --- /dev/null +++ b/tidb-cloud-lake/sql/current-timestamp.md @@ -0,0 +1,8 @@ +--- +title: CURRENT_TIMESTAMP +summary: [NOW](/tidb-cloud-lake/sql/now.md) 的别名。 +--- + +# CURRENT_TIMESTAMP + +[NOW](/tidb-cloud-lake/sql/now.md) 的别名。 \ No newline at end of file diff --git a/tidb-cloud-lake/sql/current-user.md b/tidb-cloud-lake/sql/current-user.md new file mode 100644 index 0000000000000..ffa2544f0f914 --- /dev/null +++ b/tidb-cloud-lake/sql/current-user.md @@ -0,0 +1,26 @@ +--- +title: CURRENT_USER +summary: 返回服务器用于对当前客户端进行身份验证的账户的用户名和主机名组合。该账户决定了你的访问权限。返回值是 utf8 字符集中的字符串。 +--- + +# CURRENT_USER + +返回服务器用于对当前客户端进行身份验证的账户的用户名和主机名组合。该账户决定了你的访问权限。返回值是 utf8 字符集中的字符串。 + +## 语法 {#syntax} + +```sql +CURRENT_USER() +``` + +## 示例 {#examples} + +```sql +SELECT CURRENT_USER(); + +┌────────────────┐ +│ current_user() │ +├────────────────┤ +│ 'root'@'%' │ +└────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/data-anonymization-functions.md b/tidb-cloud-lake/sql/data-anonymization-functions.md new file mode 100644 index 0000000000000..c703c1cc1ffd4 --- /dev/null +++ b/tidb-cloud-lake/sql/data-anonymization-functions.md @@ -0,0 +1,30 @@ +--- +title: 数据匿名化函数 +summary: 数据匿名化是指对数据集中的个人身份识别信息(PII)进行修改或移除,以保护个人隐私。其目标是在保留数据用于分析、研究和测试的可用性的同时,将数据转换为无法追溯到特定个人的形式。 +--- + +# 数据匿名化函数 + +数据匿名化是指对数据集中的个人身份识别信息(PII)进行修改或移除,以保护个人隐私。其目标是在保留数据用于分析、研究和测试的可用性的同时,将数据转换为无法追溯到特定个人的形式。 + +## 常见的匿名化数据类别 {#common-data-categories-for-anonymization} + +有效的匿名化策略通常针对以下几类敏感数据: + +* **直接标识符(PII)**:能够明确识别个人身份的信息,例如姓名全称、电子邮件地址、电话号码和政府签发的身份证件号码。 +* **间接标识符(准标识符)**:与其他数据源结合后可用于识别个人的属性,例如出生日期、性别、邮政编码或职位名称。 +* **敏感业务数据**:如财务事务、薪资明细或专有内部记录等机密信息,这些数据在非生产环境中也需要受到保护。 + +### {{{ .lake }}} 匿名化技术 {#lake-anonymization-techniques} + +{{{ .lake }}} 提供了一组函数,用于实现多种匿名化技术,包括数据脱敏、假名化和合成数据生成: + +- **数据脱敏**:使用 [`OBFUSCATE` 表函数](/tidb-cloud-lake/sql/obfuscate.md) 自动对列应用脱敏规则,用看似真实的人工值替换原始值。 +- **假名化**:使用 [FEISTEL_OBFUSCATE](/tidb-cloud-lake/sql/feistel-obfuscate.md) 将标识符替换为确定性的替代值。这可以保留数据完整性和基数,因此适合用于保留 join key。 +- **合成数据**:使用 [MARKOV_TRAIN](/tidb-cloud-lake/sql/markov-train.md) 和 [MARKOV_GENERATE](/tidb-cloud-lake/sql/markov-generate.md) 生成由机器创建的数据,这些数据在统计特征上类似于原始数据集,但与真实记录没有直接关联。 + +| 函数 | 描述 | +|----------|-------------| +| [MARKOV_GENERATE](/tidb-cloud-lake/sql/markov-generate.md) | 基于 Markov 模型生成匿名化字符串 | +| [FEISTEL_OBFUSCATE](/tidb-cloud-lake/sql/feistel-obfuscate.md) | 使用 Feistel 密码对数字进行混淆 | +| [OBFUSCATE](/tidb-cloud-lake/sql/obfuscate.md) | 使用内置规则进行表级脱敏 | \ No newline at end of file diff --git a/tidb-cloud-lake/sql/data-types.md b/tidb-cloud-lake/sql/data-types.md new file mode 100644 index 0000000000000..2aa4d4333d58c --- /dev/null +++ b/tidb-cloud-lake/sql/data-types.md @@ -0,0 +1,103 @@ +--- +title: 数据类型 +summary: "{{{ .lake }}} 将数据存储在强类型列中。本页概述支持的数据类型、自动/显式转换的工作方式,以及 NULL 或默认值的处理行为。" +--- + +# 数据类型 + +{{{ .lake }}} 将数据存储在强类型列中。本页概述支持的数据类型、自动/显式转换的工作方式,以及 NULL 或默认值的处理行为。 + +## 基础类型 {#foundational-types} + +| 数据类型 | 别名 | 存储 / 精度 | 最小值 | 最大值 | +|--------------------------------------------|------------|-----------------------------------|--------------------------|--------------------------------| +| [BOOLEAN](/tidb-cloud-lake/sql/boolean.md) | BOOL | 1 字节 | – | – | +| [BINARY](/tidb-cloud-lake/sql/binary.md) | VARBINARY | 可变 | – | – | +| [VARCHAR](/tidb-cloud-lake/sql/string.md) | STRING | 可变 | – | – | +| [TINYINT](/tidb-cloud-lake/sql/numeric.md#integer-data-types) | INT8 | 1 字节 | -128 | 127 | +| [SMALLINT](/tidb-cloud-lake/sql/numeric.md#integer-data-types) | INT16 | 2 字节 | -32768 | 32767 | +| [INT](/tidb-cloud-lake/sql/numeric.md#integer-data-types) | INT32 | 4 字节 | -2147483648 | 2147483647 | +| [BIGINT](/tidb-cloud-lake/sql/numeric.md#integer-data-types) | INT64 | 8 字节 | -9223372036854775808 | 9223372036854775807 | +| [FLOAT](/tidb-cloud-lake/sql/numeric.md#floating-point-data-types) | – | 4 字节 (Float32) | -3.40e38 | 3.40e38 | +| [DOUBLE](/tidb-cloud-lake/sql/numeric.md#floating-point-data-types) | – | 8 字节 (Float64) | -1.79e308 | 1.79e308 | +| [DECIMAL](/tidb-cloud-lake/sql/decimal.md) | – | 16/32 字节 (精度 ≤38/76) | `-(10^P-1)/10^S` | `(10^P-1)/10^S` | + +## 日期和时间类型 {#date-time-types} + +| 数据类型 | 别名 | 精度 / 说明 | +|---------------------------|-----------|--------------------------------------| +| [DATE](/tidb-cloud-lake/sql/datetime.md) | – | 天级精度 | +| [TIMESTAMP](/tidb-cloud-lake/sql/datetime.md) | DATETIME | 微秒,按会话时区输出 | +| [TIMESTAMP_TZ](/tidb-cloud-lake/sql/datetime.md) | – | 微秒 + 存储偏移 | +| [INTERVAL](/tidb-cloud-lake/sql/interval.md) | – | 微秒,支持负时间跨度 | + +## 结构化与半结构化类型 {#structured-semi-structured-types} + +| 数据类型 | 示例 | 说明 | +|-----------------------|----------------------------------------|-------------| +| [ARRAY](/tidb-cloud-lake/sql/array.md) | `[1, 2, 3]` | 具有相同内部类型的有序值列表。 | +| [TUPLE](/tidb-cloud-lake/sql/tuple.md) | `('2023-02-14','Valentine's Day')` | 具有已声明元素类型的定长有序列表。 | +| [MAP](/tidb-cloud-lake/sql/map.md) | `{'a': 1, 'b': 2}` | 键值集合(内部表示为键类型和值类型的元组)。 | +| [VARIANT](/tidb-cloud-lake/sql/variant.md) | `[1, {"name":"datalake"}]` | 类似 JSON 的容器,可混合原语、数组和对象。 | +| [BITMAP](/tidb-cloud-lake/sql/bitmap.md) | `` | 针对成员关系和集合运算优化的压缩位图。 | + +## 领域特定类型 {#domain-specific-types} + +| 数据类型 | 说明 | +|------------------------------------|-------------| +| [VECTOR](/tidb-cloud-lake/sql/vector.md) | 用于相似度搜索 / ML 工作负载的 Float32 向量嵌入。 | +| [GEOMETRY](/tidb-cloud-lake/sql/geospatial.md) / GEOGRAPHY | 以 WKB/EWKB 格式存储的空间对象。 | + +## 类型转换与转换规则 {#casting-and-conversion} + +### 显式类型转换 {#explicit-casting} + +- `CAST(expr AS TYPE)` 使用 ANSI 语法,在转换无效时会失败。 +- `expr::TYPE` 是 PostgreSQL 风格的简写。 +- `TRY_CAST(expr AS TYPE)` 在转换失败时返回 NULL,而不是抛出错误。 + +### 隐式类型转换(Coercion) {#implicit-casting-coercion} + +{{{ .lake }}} 会在定义明确的场景下执行自动转换: + +1. 整数型会向上提升为 `INT64`。例如:`UInt8 -> INT64`。 +2. 数值类型在必要时会向上提升为 `FLOAT64`。 +3. 如果表达式中出现 NULL,任意类型 `T` 都可以变为 `Nullable(T)`。 +4. 所有类型都可以向上提升为 `VARIANT`。 +5. 复杂类型按元素进行强制转换(当 `T -> U` 时,`Array -> Array`;元组和映射同理)。 + +当目标列为 `NOT NULL` 时,如果数据中可能包含 NULL,请显式转换为 `Nullable` 或使用 `TRY_CAST`。 + +```sql +SELECT CONCAT('1', col); -- safe (strings) +SELECT CONCAT(1, col); -- may fail if `col` can't coerce to number +``` + +## NULL 处理与默认值 {#null-handling-and-defaults} + +除非声明为 `NOT NULL`,否则列允许 NULL 值。当在 INSERT 时省略 `NOT NULL` 列,{{{ .lake }}} 会写入该类型对应的默认值: + +| 类型类别 | 默认值 | +|--------------------------|---------| +| 整数型 | `0` | +| 浮点型 | `0.0` | +| 字符串 / 二进制 | 空字符串 / 空二进制 | +| 日期 | `1970-01-01` | +| 时间戳 | `1970-01-01 00:00:00` | +| 布尔型 | `FALSE` | + +示例: + +```sql +CREATE TABLE test ( + id INT64, + name STRING NOT NULL, + age INT32 +); + +INSERT INTO test (id, name, age) VALUES (2, 'Alice', NULL); -- allowed +INSERT INTO test (id, name) VALUES (1, 'John'); -- age becomes NULL +INSERT INTO test (id, age) VALUES (3, 45); -- name uses default '' +``` + +你可以随时使用 `DESC test` 或 `SHOW CREATE TABLE test` 查看列的默认值和可空性。 \ No newline at end of file diff --git a/tidb-cloud-lake/sql/database-function.md b/tidb-cloud-lake/sql/database-function.md new file mode 100644 index 0000000000000..fd06728ba27d6 --- /dev/null +++ b/tidb-cloud-lake/sql/database-function.md @@ -0,0 +1,26 @@ +--- +title: DATABASE +summary: 返回当前已选择数据库的名称。如果未选择数据库,则此函数返回 default。 +--- + +# DATABASE + +返回当前已选择数据库的名称。如果未选择数据库,则此函数返回 `default`。 + +## 语法 {#syntax} + +```sql +DATABASE() +``` + +## 示例 {#examples} + +```sql +SELECT DATABASE(); + +┌────────────┐ +│ database() │ +├────────────┤ +│ default │ +└────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/date-add.md b/tidb-cloud-lake/sql/date-add.md new file mode 100644 index 0000000000000..5e638bd7d2ffc --- /dev/null +++ b/tidb-cloud-lake/sql/date-add.md @@ -0,0 +1,96 @@ +--- +title: DATE_ADD +summary: 向 DATE 或 TIMESTAMP 值添加指定的时间间隔。 +--- + +# DATE_ADD + +向 DATE 或 TIMESTAMP 值添加指定的时间间隔。 + +## 语法 {#syntax} + +```sql +DATE_ADD(, , ) +``` + +| 参数 | 描述 | +|-----------------------|----------------------------------------------------------------------------------------------------| +| `` | 指定时间单位:`YEAR`、`QUARTER`、`MONTH`、`WEEK`、`DAY`、`HOUR`、`MINUTE` 和 `SECOND`。 | +| `` | 要添加的间隔,例如,当单位为 `DAY` 时,2 表示 2 天。 | +| `` | `DATE` 或 `TIMESTAMP` 类型的值。 | + +## 返回类型 {#return-type} + +DATE 或 TIMESTAMP(取决于 `` 的类型)。 + +## 示例 {#examples} + +以下示例向当前日期添加不同的时间间隔(年、季度、月、周和天): + +```sql +SELECT + TODAY(), + DATE_ADD(YEAR, 1, TODAY()), + DATE_ADD(QUARTER, 1, TODAY()), + DATE_ADD(MONTH, 1, TODAY()), + DATE_ADD(WEEK, 1, TODAY()), + DATE_ADD(DAY, 1, TODAY()); + +-[ RECORD 1 ]----------------------------------- + today(): 2024-10-10 + DATE_ADD(YEAR, 1, today()): 2025-10-10 +DATE_ADD(QUARTER, 1, today()): 2025-01-10 + DATE_ADD(MONTH, 1, today()): 2024-11-10 + DATE_ADD(WEEK, 1, today()): 2024-10-17 + DATE_ADD(DAY, 1, today()): 2024-10-11 +``` + +以下示例向当前时间戳添加不同的时间间隔(小时、分钟和秒): + +```sql +SELECT + NOW(), + DATE_ADD(HOUR, 1, NOW()), + DATE_ADD(MINUTE, 1, NOW()), + DATE_ADD(SECOND, 1, NOW()); + +-[ RECORD 1 ]----------------------------------- + now(): 2024-10-10 01:35:33.601312 + DATE_ADD(HOUR, 1, now()): 2024-10-10 02:35:33.601312 +DATE_ADD(MINUTE, 1, now()): 2024-10-10 01:36:33.601312 +DATE_ADD(SECOND, 1, now()): 2024-10-10 01:35:34.601312 +``` + +- 当单位为 MONTH 时,如果日期是该月的最后一天,或者结果月份的天数少于原日期中的“日”部分, +- 则结果为结果月份的最后一天。否则,结果中的“日”部分与原日期相同。 + +当向某个日期加一个月后会得到无效日期时(例如,1 月 31 日 → 2 月 31 日),将返回结果月份中最后一个有效日期: + +```sql +SELECT DATE_ADD(month, 1, '2023-01-31'::DATE) ; +╭────────────────────────────────────────╮ +│ DATE_ADD(MONTH, 1, '2023-01-31'::DATE) │ +│ Date │ +├────────────────────────────────────────┤ +│ 2023-02-28 │ +╰────────────────────────────────────────╯ + +``` + +当向某个日期加一个月后,结果月份有足够的天数时,将执行简单的月份运算: + +```sql +SELECT DATE_ADD(month, 1, '2023-02-28'::DATE); +╭────────────────────────────────────────╮ +│ DATE_ADD(MONTH, 1, '2023-02-28'::DATE) │ +│ Date │ +├────────────────────────────────────────┤ +│ 2023-03-28 │ +╰────────────────────────────────────────╯ + +``` + +## 另请参阅 {#see-also} + +- [ADD_MONTH](/tidb-cloud-lake/sql/add-months.md): 用于添加月份的函数 +- [DATE_SUB](/tidb-cloud-lake/sql/date-sub.md): 用于减去时间间隔的函数 \ No newline at end of file diff --git a/tidb-cloud-lake/sql/date-between.md b/tidb-cloud-lake/sql/date-between.md new file mode 100644 index 0000000000000..5bde9fae1b7e7 --- /dev/null +++ b/tidb-cloud-lake/sql/date-between.md @@ -0,0 +1,72 @@ +--- +title: DATE_BETWEEN +summary: 计算两个日期或时间戳之间的时间间隔,并以指定单位的整数型差值返回。正值表示第一个时间早于第二个时间,负值则表示相反。 +--- + +# DATE_BETWEEN + +计算两个日期或时间戳之间的时间间隔,并以指定单位的整数型差值返回。正值表示第一个时间早于第二个时间,负值则表示相反。 + +另请参阅:[DATE_DIFF](/tidb-cloud-lake/sql/date-diff.md) + +## 语法 {#syntax} + +```sql +DATE_BETWEEN( + YEAR | QUARTER | MONTH | WEEK | DAY | HOUR | MINUTE | SECOND | + DOW | DOY | EPOCH | ISODOW | YEARWEEK | MILLENNIUM, + , + +) +``` + +| 关键字 | 描述 | +|--------------|-------------------------------------------------------------------------| +| `DOW` | 一周中的第几天。星期日 (0) 到星期六 (6)。 | +| `DOY` | 一年中的第几天。1 到 366。 | +| `EPOCH` | 自 1970-01-01 00:00:00 以来的秒数。 | +| `ISODOW` | ISO 一周中的第几天。星期一 (1) 到星期日 (7)。 | +| `YEARWEEK` | 年份与周数组合,遵循 ISO 8601(例如,202415)。 | +| `MILLENNIUM` | 日期所属的千年(1 表示 1–1000 年,2 表示 1001–2000 年,依此类推)。 | + +## DATE_DIFF 与 DATE_BETWEEN 的区别 {#date-diff-vs-date-between} + +`DATE_DIFF` 函数用于计算两个日期之间跨越了多少个用户指定单位的边界(例如天、月或年),而 `DATE_BETWEEN` 用于计算它们之间严格包含了多少个完整单位。例如: + +```sql +SELECT + DATE_DIFF(month, '2025-07-31', '2025-10-01'), -- returns 3 + DATE_BETWEEN(month, '2025-07-31', '2025-10-01'); -- returns 2 +``` + +在这个示例中,`DATE_DIFF` 返回 `3`,因为该时间范围跨越了 3 个月边界(July → August → September → October);而 `DATE_BETWEEN` 返回 `2`,因为这两个日期之间有 2 个完整的月份:August 和 September。 + +## 示例 {#examples} + +以下示例计算固定时间戳(`2020-01-01 00:00:00`)与当前时间戳(`NOW()`)之间在多种单位下的差值,例如年、ISO 工作日、年周和千年: + +```sql +SELECT + DATE_BETWEEN(YEAR, TIMESTAMP '2020-01-01 00:00:00', NOW()) AS diff_year, + DATE_BETWEEN(QUARTER, TIMESTAMP '2020-01-01 00:00:00', NOW()) AS diff_quarter, + DATE_BETWEEN(MONTH, TIMESTAMP '2020-01-01 00:00:00', NOW()) AS diff_month, + DATE_BETWEEN(WEEK, TIMESTAMP '2020-01-01 00:00:00', NOW()) AS diff_week, + DATE_BETWEEN(DAY, TIMESTAMP '2020-01-01 00:00:00', NOW()) AS diff_day, + DATE_BETWEEN(HOUR, TIMESTAMP '2020-01-01 00:00:00', NOW()) AS diff_hour, + DATE_BETWEEN(MINUTE, TIMESTAMP '2020-01-01 00:00:00', NOW()) AS diff_minute, + DATE_BETWEEN(SECOND, TIMESTAMP '2020-01-01 00:00:00', NOW()) AS diff_second, + DATE_BETWEEN(DOW, TIMESTAMP '2020-01-01 00:00:00', NOW()) AS diff_dow, + DATE_BETWEEN(DOY, TIMESTAMP '2020-01-01 00:00:00', NOW()) AS diff_doy, + DATE_BETWEEN(EPOCH, TIMESTAMP '2020-01-01 00:00:00', NOW()) AS diff_epoch, + DATE_BETWEEN(ISODOW, TIMESTAMP '2020-01-01 00:00:00', NOW()) AS diff_isodow, + DATE_BETWEEN(YEARWEEK, TIMESTAMP '2020-01-01 00:00:00', NOW()) AS diff_yearweek, + DATE_BETWEEN(MILLENNIUM, TIMESTAMP '2020-01-01 00:00:00', NOW()) AS diff_millennium; +``` + +```sql +┌─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ +│ diff_year │ diff_quarter │ diff_month │ diff_week │ diff_day │ diff_hour │ diff_minute │ diff_second │ diff_dow │ diff_doy │ diff_epoch │ diff_isodow │ diff_yearweek │ diff_millennium │ +├───────────┼──────────────┼────────────┼───────────┼──────────┼───────────┼─────────────┼─────────────┼──────────┼──────────┼────────────┼─────────────┼───────────────┼─────────────────┤ +│ 5 │ 21 │ 63 │ 276 │ 1933 │ 46414 │ 2784887 │ 167093234 │ 1933 │ 1933 │ 167093234 │ 1933 │ 276 │ 0 │ +└─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/date-diff.md b/tidb-cloud-lake/sql/date-diff.md new file mode 100644 index 0000000000000..4f67e9d9ece4c --- /dev/null +++ b/tidb-cloud-lake/sql/date-diff.md @@ -0,0 +1,72 @@ +--- +title: DATE_DIFF +summary: 根据指定的时间单位,计算两个日期或时间戳之间的差值。如果 `` 晚于 ``,结果为正;如果早于 ``,结果为负。 +--- + +# DATE_DIFF + +根据指定的时间单位,计算两个日期或时间戳之间的差值。如果 `` 晚于 ``,结果为正;如果早于 ``,结果为负。 + +另请参阅:[DATE_BETWEEN](/tidb-cloud-lake/sql/date-between.md) + +## 语法 {#syntax} + +```sql +DATE_DIFF( + YEAR | QUARTER | MONTH | WEEK | DAY | HOUR | MINUTE | SECOND | + DOW | DOY | EPOCH | ISODOW | YEARWEEK | MILLENNIUM, + , + +) +``` + +| 关键字 | 描述 | +|--------------|-------------------------------------------------------------------------| +| `DOW` | 一周中的第几天。星期日 (0) 到星期六 (6)。 | +| `DOY` | 一年中的第几天。1 到 366。 | +| `EPOCH` | 自 1970-01-01 00:00:00 以来的秒数。 | +| `ISODOW` | ISO 一周中的第几天。星期一 (1) 到星期日 (7)。 | +| `YEARWEEK` | 年份与周数组合后的值,遵循 ISO 8601(例如,202415)。 | +| `MILLENNIUM` | 日期所属的千年(1 表示 1–1000 年,2 表示 1001–2000 年,依此类推)。 | + +## DATE_DIFF 与 DATE_BETWEEN 的区别 {#date-diff-vs-date-between} + +`DATE_DIFF` 函数用于统计两个日期之间跨越了多少个用户指定单位的边界(例如天、月或年),而 `DATE_BETWEEN` 用于统计两个日期之间严格包含了多少个完整单位。例如: + +```sql +SELECT + DATE_DIFF(month, '2025-07-31', '2025-10-01'), -- returns 3 + DATE_BETWEEN(month, '2025-07-31', '2025-10-01'); -- returns 2 +``` + +在这个示例中,`DATE_DIFF` 返回 `3`,因为该时间范围跨越了 3 个月边界(July → August → September → October);而 `DATE_BETWEEN` 返回 `2`,因为这两个日期之间有 2 个完整的月份:August 和 September。 + +## 示例 {#examples} + +以下示例计算固定时间戳(`2020-01-01 00:00:00`)与当前时间戳(`NOW()`)之间在多个单位下的差值,例如年、ISO 星期几、年周以及千年: + +```sql +SELECT + DATE_DIFF(YEAR, TIMESTAMP '2020-01-01 00:00:00', NOW()) AS diff_year, + DATE_DIFF(QUARTER, TIMESTAMP '2020-01-01 00:00:00', NOW()) AS diff_quarter, + DATE_DIFF(MONTH, TIMESTAMP '2020-01-01 00:00:00', NOW()) AS diff_month, + DATE_DIFF(WEEK, TIMESTAMP '2020-01-01 00:00:00', NOW()) AS diff_week, + DATE_DIFF(DAY, TIMESTAMP '2020-01-01 00:00:00', NOW()) AS diff_day, + DATE_DIFF(HOUR, TIMESTAMP '2020-01-01 00:00:00', NOW()) AS diff_hour, + DATE_DIFF(MINUTE, TIMESTAMP '2020-01-01 00:00:00', NOW()) AS diff_minute, + DATE_DIFF(SECOND, TIMESTAMP '2020-01-01 00:00:00', NOW()) AS diff_second, + DATE_DIFF(DOW, TIMESTAMP '2020-01-01 00:00:00', NOW()) AS diff_dow, + DATE_DIFF(DOY, TIMESTAMP '2020-01-01 00:00:00', NOW()) AS diff_doy, + DATE_DIFF(EPOCH, TIMESTAMP '2020-01-01 00:00:00', NOW()) AS diff_epoch, + DATE_DIFF(ISODOW, TIMESTAMP '2020-01-01 00:00:00', NOW()) AS diff_isodow, + DATE_DIFF(YEARWEEK, TIMESTAMP '2020-01-01 00:00:00', NOW()) AS diff_yearweek, + DATE_DIFF(MILLENNIUM, TIMESTAMP '2020-01-01 00:00:00', NOW()) AS diff_millennium; +``` + +```sql +┌─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ +│ diff_year │ diff_quarter │ diff_month │ diff_week │ diff_day │ diff_hour │ diff_minute │ diff_second │ diff_dow │ diff_doy │ diff_epoch │ diff_isodow │ diff_yearweek │ diff_millennium │ +├───────────┼──────────────┼────────────┼───────────┼──────────┼───────────┼─────────────┼─────────────┼──────────┼──────────┼────────────┼─────────────┼───────────────┼─────────────────┤ +│ 5 │ 21 │ 63 │ 276 │ 1932 │ 46386 │ 2783184 │ 166991069 │ 1932 │ 1932 │ 166991069 │ 1932 │ 515 │ 0 │ +└─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/date-format.md b/tidb-cloud-lake/sql/date-format.md new file mode 100644 index 0000000000000..3cf9b5be8ecb7 --- /dev/null +++ b/tidb-cloud-lake/sql/date-format.md @@ -0,0 +1,8 @@ +--- +title: DATE_FORMAT +summary: TO_STRING 的别名。 +--- + +# DATE_FORMAT + +[TO_STRING](/tidb-cloud-lake/sql/to-string.md) 的别名。 \ No newline at end of file diff --git a/tidb-cloud-lake/sql/date-part.md b/tidb-cloud-lake/sql/date-part.md new file mode 100644 index 0000000000000..38d37ee53efa1 --- /dev/null +++ b/tidb-cloud-lake/sql/date-part.md @@ -0,0 +1,63 @@ +--- +title: DATE_PART +summary: 返回日期或时间戳中指定的部分。 +--- + +# DATE_PART + +返回日期或时间戳中指定的部分。 + +另请参阅:[EXTRACT](/tidb-cloud-lake/sql/extract.md) + +## 语法 {#syntax} + +```sql +DATE_PART( + YEAR | QUARTER | MONTH | WEEK | DAY | HOUR | MINUTE | SECOND | + DOW | DOY | EPOCH | ISODOW | YEARWEEK | MILLENNIUM, + +) +``` + +| 关键字 | 描述 | +|--------------|-------------------------------------------------------------------------| +| `DOW` | 一周中的第几天。星期日 (0) 到星期六 (6)。 | +| `DOY` | 一年中的第几天。1 到 366。 | +| `EPOCH` | 自 1970-01-01 00:00:00 以来的秒数。 | +| `ISODOW` | ISO 一周中的第几天。星期一 (1) 到星期日 (7)。 | +| `YEARWEEK` | 年份和周数组合,遵循 ISO 8601(例如,202415)。 | +| `MILLENNIUM` | 日期所属的千年(1 表示 1–1000 年,2 表示 1001–2000 年,依此类推)。 | + +## 返回类型 {#return-type} + +整数型。 + +## 示例 {#examples} + +以下示例演示了如何使用 DATE_PART 从当前时间戳中提取多个组成部分,例如年份、月份、ISO 周内日、年周组合以及千年: + +```sql +SELECT + DATE_PART(YEAR, NOW()) AS year_part, + DATE_PART(QUARTER, NOW()) AS quarter_part, + DATE_PART(MONTH, NOW()) AS month_part, + DATE_PART(WEEK, NOW()) AS week_part, + DATE_PART(DAY, NOW()) AS day_part, + DATE_PART(HOUR, NOW()) AS hour_part, + DATE_PART(MINUTE, NOW()) AS minute_part, + DATE_PART(SECOND, NOW()) AS second_part, + DATE_PART(DOW, NOW()) AS dow_part, + DATE_PART(DOY, NOW()) AS doy_part, + DATE_PART(EPOCH, NOW()) AS epoch_part, + DATE_PART(ISODOW, NOW()) AS isodow_part, + DATE_PART(YEARWEEK, NOW()) AS yearweek_part, + DATE_PART(MILLENNIUM, NOW()) AS millennium_part; +``` + +```sql +┌────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ +│ year_part │ quarter_part │ month_part │ week_part │ day_part │ hour_part │ minute_part │ second_part │ dow_part │ doy_part │ epoch_part │ isodow_part │ yearweek_part │ millennium_part │ +├───────────┼──────────────┼────────────┼───────────┼──────────┼───────────┼─────────────┼─────────────┼──────────┼──────────┼───────────────────┼─────────────┼───────────────┼─────────────────┤ +│ 2025 │ 2 │ 4 │ 16 │ 16 │ 18 │ 10 │ 10 │ 3 │ 106 │ 1744827010.257671 │ 3 │ 202516 │ 3 │ +└────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/date-sub.md b/tidb-cloud-lake/sql/date-sub.md new file mode 100644 index 0000000000000..eec6f7ed7adda --- /dev/null +++ b/tidb-cloud-lake/sql/date-sub.md @@ -0,0 +1,38 @@ +--- +title: DATE_SUB +summary: 从提供的日期或带时间的日期(timestamp/datetime)中减去时间间隔或日期间隔。 +--- + +# DATE_SUB + +从提供的日期或带时间的日期(timestamp/datetime)中减去时间间隔或日期间隔。 + +## 语法 {#syntax} + +```sql +DATE_SUB(, , ) +``` + +## 参数 {#arguments} + +| 参数 | 描述 | +|-----------------------|----------------------------------------------------------------------| +| `` | 必须是以下值之一:`YEAR`、`QUARTER`、`MONTH`、`DAY`、`HOUR`、`MINUTE` 和 `SECOND` | +| `` | 表示要增加的时间单位数量。例如,如果要增加 2 天,则该值为 2。 | +| `` | `DATE` 或 `TIMESTAMP` 类型的值 | + +## 返回类型 {#return-type} + +该函数返回与 `` 参数相同类型的值。 + +## 示例 {#examples} + +```sql +SELECT date_sub(YEAR, 1, to_date('2018-01-02')); + +┌──────────────────────────────────────────┐ +│ date_sub(year, 1, to_date('2018-01-02')) │ +├──────────────────────────────────────────┤ +│ 2017-01-02 │ +└──────────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/date-time-functions.md b/tidb-cloud-lake/sql/date-time-functions.md new file mode 100644 index 0000000000000..947c5f9065e24 --- /dev/null +++ b/tidb-cloud-lake/sql/date-time-functions.md @@ -0,0 +1,92 @@ +--- +title: 日期与时间函数 +summary: 本页按功能分类,全面概述了 {{{ .lake }}} 中的日期与时间函数,便于快速查阅。 +--- + +# 日期与时间函数 + +本页按功能分类,全面概述了 {{{ .lake }}} 中的日期与时间函数,便于快速查阅。 + +## 当前日期与时间函数 {#current-date-time-functions} + +| Function | 描述 | 示例 | +|-------------------------------------------|------------------------|------------------------------------------------------| +| [NOW](/tidb-cloud-lake/sql/now.md) | 返回当前日期和时间 | `NOW()` → `2024-06-04 17:42:31.123456` | +| [CURRENT_TIMESTAMP](/tidb-cloud-lake/sql/current-timestamp.md) | 返回当前日期和时间 | `CURRENT_TIMESTAMP()` → `2024-06-04 17:42:31.123456` | +| [TODAY](/tidb-cloud-lake/sql/today.md) | 返回当前日期 | `TODAY()` → `2024-06-04` | +| [TOMORROW](/tidb-cloud-lake/sql/tomorrow.md) | 返回明天的日期 | `TOMORROW()` → `2024-06-05` | +| [YESTERDAY](/tidb-cloud-lake/sql/yesterday.md) | 返回昨天的日期 | `YESTERDAY()` → `2024-06-03` | + +## 日期与时间提取函数 {#date-time-extraction-functions} + +| Function | 描述 | 示例 | +|-----------------------------------------------|------------------------------|------------------------------------------| +| [YEAR](/tidb-cloud-lake/sql/year.md) | 从日期中提取年份 | `YEAR('2024-06-04')` → `2024` | +| [MONTH](/tidb-cloud-lake/sql/month.md) | 从日期中提取月份 | `MONTH('2024-06-04')` → `6` | +| [DAY](/tidb-cloud-lake/sql/day.md) | 从日期中提取日 | `DAY('2024-06-04')` → `4` | +| [QUARTER](/tidb-cloud-lake/sql/quarter.md) | 从日期中提取季度 | `QUARTER('2024-06-04')` → `2` | +| [WEEK](/tidb-cloud-lake/sql/week.md) / [WEEKOFYEAR](/tidb-cloud-lake/sql/weekofyear.md) | 从日期中提取周序号 | `WEEK('2024-06-04')` → `23` | +| [EXTRACT](/tidb-cloud-lake/sql/extract.md) | 从日期中提取指定部分 | `EXTRACT(MONTH FROM '2024-06-04')` → `6` | +| [DATE_PART](/tidb-cloud-lake/sql/date-part.md) | 从日期中提取指定部分 | `DATE_PART('month', '2024-06-04')` → `6` | +| [YEARWEEK](/tidb-cloud-lake/sql/yearweek.md) | 返回年份和周序号 | `YEARWEEK('2024-06-04')` → `202423` | +| [MILLENNIUM](/tidb-cloud-lake/sql/millennium.md) | 返回日期所属的千年 | `MILLENNIUM('2024-06-04')` → `3` | + +## 日期与时间转换函数 {#date-time-conversion-functions} + +| Function | 描述 | 示例 | +|-------------------------------------------|---------------------------------------------|---------------------------------------------------------------| +| [DATE](/tidb-cloud-lake/sql/date.md) | 将值转换为 DATE 类型 | `DATE('2024-06-04')` → `2024-06-04` | +| [TO_DATE](/tidb-cloud-lake/sql/to-date.md) | 将字符串转换为 DATE 类型 | `TO_DATE('2024-06-04')` → `2024-06-04` | +| [TO_DATETIME](/tidb-cloud-lake/sql/datetime.md) | 将字符串转换为 DATETIME 类型 | `TO_DATETIME('2024-06-04 12:30:45')` → `2024-06-04 12:30:45` | +| [TO_TIMESTAMP](/tidb-cloud-lake/sql/to-timestamp.md) | 将字符串转换为 TIMESTAMP 类型 | `TO_TIMESTAMP('2024-06-04 12:30:45')` → `2024-06-04 12:30:45` | +| [TO_UNIX_TIMESTAMP](/tidb-cloud-lake/sql/unix-timestamp.md) | 将日期转换为 Unix 时间戳 | `TO_UNIX_TIMESTAMP('2024-06-04')` → `1717516800` | +| [TO_YYYYMM](/tidb-cloud-lake/sql/yyyymm.md) | 将日期格式化为 YYYYMM | `TO_YYYYMM('2024-06-04')` → `202406` | +| [TO_YYYYMMDD](/tidb-cloud-lake/sql/yyyymmdd.md) | 将日期格式化为 YYYYMMDD | `TO_YYYYMMDD('2024-06-04')` → `20240604` | +| [TO_YYYYMMDDHH](/tidb-cloud-lake/sql/yyyymmddhh.md) | 将日期格式化为 YYYYMMDDHH | `TO_YYYYMMDDHH('2024-06-04 12:30:45')` → `2024060412` | +| [TO_YYYYMMDDHHMMSS](/tidb-cloud-lake/sql/yyyymmddhhmmss.md) | 将日期格式化为 YYYYMMDDHHMMSS | `TO_YYYYMMDDHHMMSS('2024-06-04 12:30:45')` → `20240604123045` | +| [DATE_FORMAT](/tidb-cloud-lake/sql/date-format.md) | 按格式字符串格式化日期 | `DATE_FORMAT('2024-06-04', '%Y-%m-%d')` → `'2024-06-04'` | +| [CONVERT_TIMEZONE](/tidb-cloud-lake/sql/convert-timezone.md) | 将时间戳转换为目标时区 | `CONVERT_TIMEZONE('America/Los_Angeles', '2024-11-01 11:36:10')` → `2024-10-31 20:36:10` | + +## 日期与时间算术函数 {#date-time-arithmetic-functions} + +| Function | 描述 | 示例 | +|------------------------------------------|----------------------------------------------------------------------|--------------------------------------------------------------------------------------| +| [DATE_ADD](/tidb-cloud-lake/sql/date-add.md) | 为日期增加一个时间间隔 | `DATE_ADD(DAY, 7, '2024-06-04')` → `2024-06-11` | +| [DATE_SUB](/tidb-cloud-lake/sql/date-sub.md) | 从日期中减去一个时间间隔 | `DATE_SUB(MONTH, 1, '2024-06-04')` → `2024-05-04` | +| [ADD INTERVAL](/tidb-cloud-lake/sql/add-interval.md) | 为日期增加一个间隔 | `'2024-06-04' + INTERVAL 1 DAY` → `2024-06-05` | +| [SUBTRACT INTERVAL](/tidb-cloud-lake/sql/subtract-interval.md) | 从日期中减去一个间隔 | `'2024-06-04' - INTERVAL 1 MONTH` → `2024-05-04` | +| [DATE_DIFF](/tidb-cloud-lake/sql/date-diff.md) | 返回两个日期之间的差值 | `DATE_DIFF(DAY, '2024-06-01', '2024-06-04')` → `3` | +| [TIMESTAMP_DIFF](/tidb-cloud-lake/sql/timestamp-diff.md) | 返回两个时间戳之间的差值 | `TIMESTAMP_DIFF(HOUR, '2024-06-04 10:00:00', '2024-06-04 15:00:00')` → `5` | +| [MONTHS_BETWEEN](/tidb-cloud-lake/sql/months-between.md) | 返回两个日期之间相差的月数 | `MONTHS_BETWEEN('2024-06-04', '2024-01-04')` → `5` | +| [DATE_BETWEEN](/tidb-cloud-lake/sql/date-between.md) | 检查某个日期是否位于另外两个日期之间 | `DATE_BETWEEN('2024-06-04', '2024-06-01', '2024-06-10')` → `true` | +| [AGE](/tidb-cloud-lake/sql/age.md) | 计算两个时间戳之间,或某个时间戳与当前日期/时间之间的差值 | `AGE('2000-01-01'::TIMESTAMP, '1990-05-15'::TIMESTAMP)` → `9 years 7 months 17 days` | +| [ADD_MONTHS](/tidb-cloud-lake/sql/add-months.md) | 在保留月末日期的情况下为日期增加月数。 | `ADD_MONTHS('2025-04-30',1)` → `2025-05-31` | + +## 日期与时间截断函数 {#date-time-truncation-functions} + +| Function | 描述 | 示例 | +|-----------------------------------------------|----------------------------------------------------------|---------------------------------------------------------------------| +| [DATE_TRUNC](/tidb-cloud-lake/sql/date-trunc.md) | 将时间戳截断到指定精度 | `DATE_TRUNC('month', '2024-06-04')` → `2024-06-01` | +| [TIME_SLICE](/tidb-cloud-lake/sql/time-slice.md) | 将单个日期/时间戳值映射到按日历对齐的时间区间 | `TIME_SLICE('2024-06-04', 4, 'MONTH', 'START')` → `2024-05-01` | +| [TO_START_OF_DAY](/tidb-cloud-lake/sql/to-start-of-day.md) | 返回当天的开始时间 | `TO_START_OF_DAY('2024-06-04 12:30:45')` → `2024-06-04 00:00:00` | +| [TO_START_OF_HOUR](/tidb-cloud-lake/sql/to-start-of-hour.md) | 返回当前小时的开始时间 | `TO_START_OF_HOUR('2024-06-04 12:30:45')` → `2024-06-04 12:00:00` | +| [TO_START_OF_MINUTE](/tidb-cloud-lake/sql/to-start-of-minute.md) | 返回当前分钟的开始时间 | `TO_START_OF_MINUTE('2024-06-04 12:30:45')` → `2024-06-04 12:30:00` | +| [TO_START_OF_MONTH](/tidb-cloud-lake/sql/to-start-of-month.md) | 返回当月的开始日期 | `TO_START_OF_MONTH('2024-06-04')` → `2024-06-01` | +| [TO_START_OF_QUARTER](/tidb-cloud-lake/sql/to-start-of-quarter.md) | 返回当季度的开始日期 | `TO_START_OF_QUARTER('2024-06-04')` → `2024-04-01` | +| [TO_START_OF_YEAR](/tidb-cloud-lake/sql/to-start-of-year.md) | 返回当年的开始日期 | `TO_START_OF_YEAR('2024-06-04')` → `2024-01-01` | +| [TO_START_OF_WEEK](/tidb-cloud-lake/sql/to-start-of-week.md) | 返回当周的开始日期 | `TO_START_OF_WEEK('2024-06-04')` → `2024-06-03` | + +## 日期与时间导航函数 {#date-time-navigation-functions} + +| Function | 描述 | 示例 | +|---------------------------------|--------------------------------------------|-------------------------------------------------------| +| [LAST_DAY](/tidb-cloud-lake/sql/last-day.md) | 返回当月的最后一天 | `LAST_DAY('2024-06-04')` → `2024-06-30` | +| [NEXT_DAY](/tidb-cloud-lake/sql/next-day.md) | 返回下一个指定星期几的日期 | `NEXT_DAY('2024-06-04', 'SUNDAY')` → `2024-06-09` | +| [PREVIOUS_DAY](/tidb-cloud-lake/sql/previous-day.md) | 返回上一个指定星期几的日期 | `PREVIOUS_DAY('2024-06-04', 'MONDAY')` → `2024-06-03` | + +## 其他日期与时间函数 {#other-date-time-functions} + +| Function | 描述 | 示例 | +|---------------------------|----------------------|--------------------------------------------------------------------------| +| [TIMEZONE](/tidb-cloud-lake/sql/timezone.md) | 返回当前时区 | `TIMEZONE()` → `'UTC'` | +| [TIME_SLOT](/tidb-cloud-lake/sql/time-slot.md) | 返回时间槽 | `TIME_SLOT('2024-06-04 12:30:45', 15, 'MINUTE')` → `2024-06-04 12:30:00` | \ No newline at end of file diff --git a/tidb-cloud-lake/sql/date-time.md b/tidb-cloud-lake/sql/date-time.md new file mode 100644 index 0000000000000..1620943996d35 --- /dev/null +++ b/tidb-cloud-lake/sql/date-time.md @@ -0,0 +1,396 @@ +--- +title: 日期与时间 +summary: "{{{ .lake }}} 的日期和时间数据类型支持标准化,并兼容多种 SQL 标准,使从其他数据库系统迁移的用户更加容易上手。" +--- + +# 日期与时间 + +## 概述 {#overview} + +| 名称 | 别名 | 存储大小 | 精度 | 最小值 | 最大值 | 格式 | +|--------------|---------------------------|--------------|-------------|----------------------------|--------------------------------|--------------------------------------------------------------------------------| +| DATE | | 4 bytes | 天 | 0001-01-01 | 9999-12-31 | `YYYY-MM-DD` | +| TIMESTAMP | DATETIME | 8 bytes | 微秒 | 0001-01-01 00:00:00.000000 | 9999-12-31 23:59:59.999999 UTC | `YYYY-MM-DD hh:mm:ss[.fraction]`,显示时使用会话时区 | +| TIMESTAMP_TZ | TIMESTAMP WITH TIME ZONE | 8 bytes | 微秒 | 0001-01-01 00:00:00.000000 | 9999-12-31 23:59:59.999999 UTC | `YYYY-MM-DD hh:mm:ss[.fraction]±hh:mm`,存储 UTC 值和偏移 | + +`DATE` 仅保留日历日期值,`TIMESTAMP` 在内部以 UTC 存储,但会通过当前会话时区进行显示,而 `TIMESTAMP_TZ` 会保留原始偏移,适用于审计或副本场景。 + +## 示例 {#examples} + +### DATE {#date} + +```sql +CREATE TABLE events (event_date DATE); +INSERT INTO events VALUES ('2024-01-15'), ('2024-12-31'); +SELECT * FROM events; +``` + +结果: + +``` +┌────────────┐ +│ event_date │ +├────────────┤ +│ 2024-01-15 │ +│ 2024-12-31 │ +└────────────┘ +``` + +### TIMESTAMP {#timestamp} + +```sql +CREATE TABLE meetings ( + meeting_id INT, + meeting_time TIMESTAMP +); + +INSERT INTO meetings VALUES (1, '2024-01-15 14:00:00+08:00'); + +SETTINGS (timezone = 'UTC') +SELECT meeting_id, meeting_time FROM meetings; + +SETTINGS (timezone = 'America/New_York') +SELECT meeting_id, meeting_time FROM meetings; +``` + +结果(timezone = 'UTC'): + +``` +┌────────────┬──────────────────────┐ +│ meeting_id │ meeting_time │ +├────────────┼──────────────────────┤ +│ 1 │ 2024-01-15T06:00:00 │ +└────────────┴──────────────────────┘ +``` + +结果(timezone = 'America/New_York'): + +``` +┌────────────┬──────────────────────┐ +│ meeting_id │ meeting_time │ +├────────────┼──────────────────────┤ +│ 1 │ 2024-01-15T01:00:00 │ +└────────────┴──────────────────────┘ +``` + +### TIMESTAMP_TZ {#timestamp-tz} + +```sql +CREATE TABLE system_logs ( + log_id INT, + log_time TIMESTAMP_TZ +); + +INSERT INTO system_logs VALUES + (1, '2024-01-15 14:00:00+08:00'), + (2, '2024-01-15 06:00:00+00:00'), + (3, '2024-01-15 01:00:00-05:00'); + +SETTINGS (timezone = 'UTC') +SELECT log_id, TO_STRING(log_time) AS log_time FROM system_logs; + +SETTINGS (timezone = 'Asia/Shanghai') +SELECT log_id, TO_STRING(log_time) AS log_time FROM system_logs; +``` + +结果(timezone = 'UTC'): + +``` +┌────────┬────────────────────────────────────────────┐ +│ log_id │ log_time │ +├────────┼────────────────────────────────────────────┤ +│ 1 │ 2024-01-15 14:00:00.000000 +0800 │ +│ 2 │ 2024-01-15 06:00:00.000000 +0000 │ +│ 3 │ 2024-01-15 01:00:00.000000 -0500 │ +└────────┴────────────────────────────────────────────┘ +``` + +结果(timezone = 'Asia/Shanghai'): + +``` +┌────────┬────────────────────────────────────────────┐ +│ log_id │ log_time │ +├────────┼────────────────────────────────────────────┤ +│ 1 │ 2024-01-15 14:00:00.000000 +0800 │ +│ 2 │ 2024-01-15 06:00:00.000000 +0000 │ +│ 3 │ 2024-01-15 01:00:00.000000 -0500 │ +└────────┴────────────────────────────────────────────┘ +``` + +偏移是存储值的一部分,因此显示结果不会发生变化。 + +## 选择合适的类型 {#choosing-the-right-type} + +- 如果只需要日历日期而不包含一天中的具体时间,请使用 `DATE`。 +- 如果希望不同会话以各自本地时区显示同一时刻,请使用 `TIMESTAMP`。 +- 如果必须保留输入时的偏移以满足合规或调试需求,请使用 `TIMESTAMP_TZ`。 + +## 夏令时调整 {#daylight-saving-time-adjustments} + +启用 `enable_dst_hour_fix` 后,当夏令时导致一天中的某些小时被跳过时,{{{ .lake }}} 会自动将缺失的小时向后滚动到下一个有效时间。 + +```sql +SET enable_dst_hour_fix = 1; + +SETTINGS (timezone = 'America/Toronto') +SELECT to_datetime('2024-03-10 02:01:00'); +``` + +结果: + +``` +┌────────────────────────────────────┐ +│ to_datetime('2024-03-10 02:01:00') │ +├────────────────────────────────────┤ +│ 2024-03-10T03:01:00 │ +└────────────────────────────────────┘ +``` + +如果你更希望对缺失的小时直接报错,可以使用 `SET enable_dst_hour_fix = 0` 恢复默认行为。 + +## 处理无效值 {#handling-invalid-values} + +超出支持范围的日期会自动钳制到其最小值。 + +```sql +SELECT + ADD_DAYS(TO_DATE('9999-12-31'), 1) AS overflow_date, + SUBTRACT_MINUTES(TO_DATE('1000-01-01'), 1) AS underflow_timestamp; +``` + +结果: + +``` +┌───────────────┬──────────────────────────┐ +│ overflow_date │ underflow_timestamp │ +├───────────────┼──────────────────────────┤ +│ 0001-01-01 │ 0999-12-31T18:41:28 │ +└───────────────┴──────────────────────────┘ +``` + +这些值会回绕到可表示的最小日期或时间戳,而不是报错。 + +## 格式化日期和时间 {#formatting-date-and-time} + +[TO_DATE](/tidb-cloud-lake/sql/to-date.md) 和 [TO_TIMESTAMP](/tidb-cloud-lake/sql/to-timestamp.md) 等函数支持显式格式字符串。你可以通过调整 `date_format_style` 和 `week_start` 来控制它们如何解析或渲染值。 + +### Date Format Styles {#date-format-styles} + +使用 `date_format_style` 可以在两种格式词汇体系之间切换: + +- **MySQL**(默认)使用 `%Y`、`%m`、`%d` 这类说明符。 +- **Oracle** 使用 `YYYY`、`MM`、`DD` 这类说明符,以匹配 ANSI 风格的掩码。 + +```sql +-- Oracle-style mask +SETTINGS (date_format_style = 'Oracle') +SELECT to_string('2024-04-05'::DATE, 'YYYY-MM-DD'); +``` + +结果(Oracle): + +``` +┌──────────────────────────────────────┐ +│ to_string('2024-04-05'::DATE, 'YYYY-MM-DD') │ +├──────────────────────────────────────┤ +│ 2024-04-05 │ +└──────────────────────────────────────┘ +``` + +```sql +-- Back to MySQL-style mask +SETTINGS (date_format_style = 'MySQL') +SELECT to_string('2024-04-05'::DATE, '%Y-%m-%d'); +``` + +结果(MySQL): + +``` +┌──────────────────────────────────────┐ +│ to_string('2024-04-05'::DATE, '%Y-%m-%d') │ +├──────────────────────────────────────┤ +│ 2024-04-05 │ +└──────────────────────────────────────┘ +``` + +### Week Start Configuration {#week-start-configuration} + +`week_start` 用于定义一周从星期几开始,适用于使用 `WEEK` 精度时的 `DATE_TRUNC` 或 `TRUNC` 等函数。 + +```sql +SETTINGS (week_start = 0) SELECT DATE_TRUNC(WEEK, to_date('2024-04-05')); -- Sunday +SETTINGS (week_start = 1) SELECT DATE_TRUNC(WEEK, to_date('2024-04-05')); -- Monday +``` + +结果(week_start = 0): + +``` +┌────────────────────────────────┐ +│ DATE_TRUNC(WEEK, TO_DATE('2024-04-05')) │ +├────────────────────────────────┤ +│ 2024-03-31 │ +└────────────────────────────────┘ +``` + +结果(week_start = 1): + +``` +┌────────────────────────────────┐ +│ DATE_TRUNC(WEEK, TO_DATE('2024-04-05')) │ +├────────────────────────────────┤ +│ 2024-04-01 │ +└────────────────────────────────┘ +``` + +### MySQL Format Specifiers {#mysql-format-specifiers} + +为了处理日期和时间格式化,{{{ .lake }}} 使用 chrono::format::strftime 模块,这是 Rust 中 chrono 库提供的标准模块。该模块可以对日期和时间的格式进行精确控制。以下内容摘自 [https://docs.rs/chrono/latest/chrono/format/strftime/index.html](https://docs.rs/chrono/latest/chrono/format/strftime/index.html): + +| 说明符 | 示例 | 描述 | +| ----- | -------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| | | 日期说明符: | +| %Y | 2001 | 完整的前推公历年份,左侧补零至 4 位。chrono 支持从 -262144 到 262143 的年份。注意:对于公元前 1 年之前或公元 9999 年之后的年份,需要带前导符号(+/-)。 | +| %C | 20 | 前推公历年份除以 100 的结果,左侧补零至 2 位。 | +| %y | 01 | 前推公历年份对 100 取模的结果,左侧补零至 2 位。 | +| %m | 07 | 月份编号(01–12),左侧补零至 2 位。 | +| %b | Jul | 月份简称。始终为 3 个字母。 | +| %B | July | 月份全称。解析时也接受对应的简称。 | +| %h | Jul | 与 %b 相同。 | +| %d | 08 | 日期编号(01–31),左侧补零至 2 位。 | +| %e | 8 | 与 %d 相同,但使用空格填充。等同于 %\_d。 | +| %a | Sun | 星期简称。始终为 3 个字母。 | +| %A | Sunday | 星期全称。解析时也接受对应的简称。 | +| %w | 0 | 星期日 = 0,星期一 = 1,…,星期六 = 6。 | +| %u | 7 | 星期一 = 1,星期二 = 2,…,星期日 = 7。(ISO 8601) | +| %U | 28 | 以星期日为一周起始日的周编号(00–53),左侧补零至 2 位。 | +| %W | 27 | 与 %U 相同,但第 1 周改为从该年的第一个星期一开始。 | +| %G | 2001 | 与 %Y 相同,但使用 ISO 8601 周日期中的年份编号。 | +| %g | 01 | 与 %y 相同,但使用 ISO 8601 周日期中的年份编号。 | +| %V | 27 | 与 %U 相同,但使用 ISO 8601 周日期中的周编号(01–53)。 | +| %j | 189 | 一年中的第几天(001–366),左侧补零至 3 位。 | +| %D | 07/08/01 | 月-日-年格式。等同于 %m/%d/%y。 | +| %x | 07/08/01 | 区域设置的日期表示形式(例如 12/31/99)。 | +| %F | 2001-07-08 | 年-月-日格式(ISO 8601)。等同于 %Y-%m-%d。 | +| %v | 8-Jul-2001 | 日-月-年格式。等同于 %e-%b-%Y。 | +| | | 时间说明符: | +| %H | 00 | 小时编号(00–23),左侧补零至 2 位。 | +| %k | 0 | 与 %H 相同,但使用空格填充。等同于 %\_H。 | +| %I | 12 | 12 小时制中的小时编号(01–12),左侧补零至 2 位。 | +| %l | 12 | 与 %I 相同,但使用空格填充。等同于 %\_I。 | +| %P | am | 12 小时制中的 am 或 pm。 | +| %p | AM | 12 小时制中的 AM 或 PM。 | +| %M | 34 | 分钟编号(00–59),左侧补零至 2 位。 | +| %S | 60 | 秒编号(00–60),左侧补零至 2 位。 | +| %f | 026490000 | 自上一整秒以来的小数秒部分(以纳秒计)。{{{ .lake }}} 建议优先将 Integer 字符串转换为 Integer,而不是使用此说明符。示例请参见 [将整数转换为时间戳](/tidb-cloud-lake/sql/to-timestamp.md#example-2-converting-integer-to-timestamp)。 | +| %.f | .026490 | 与 .%f 类似,但左对齐。这些格式都会消耗前导点号。 | +| %.3f | .026 | 与 .%f 类似,但左对齐,并固定长度为 3。 | +| %.6f | .026490 | 与 .%f 类似,但左对齐,并固定长度为 6。 | +| %.9f | .026490000 | 与 .%f 类似,但左对齐,并固定长度为 9。 | +| %3f | 026 | 与 %.3f 类似,但不带前导点号。 | +| %6f | 026490 | 与 %.6f 类似,但不带前导点号。 | +| %9f | 026490000 | 与 %.9f 类似,但不带前导点号。 | +| %R | 00:34 | 时:分格式。等同于 %H:%M。 | +| %T | 00:34:60 | 时:分:秒格式。等同于 %H:%M:%S。 | +| %X | 00:34:60 | 区域设置的时间表示形式(例如 23:13:48)。 | +| %r | 12:34:60 AM | 12 小时制的时:分:秒格式。等同于 %I:%M:%S %p。 | +| | | 时区说明符: | +| %Z | ACST | 本地时区名称。解析时会跳过所有非空白字符。 | +| %z | +0930 | 本地时间相对于 UTC 的偏移(其中 UTC 为 +0000)。 | +| %:z | +09:30 | 与 %z 相同,但带冒号。 | +| %::z | +09:30:00 | 本地时间相对于 UTC 的偏移,包含秒。 | +| %:::z | +09 | 本地时间相对于 UTC 的偏移,不包含分钟。 | +| %#z | +09 | 仅用于解析:与 %z 相同,但允许分钟部分缺失或存在。 | +| | | 日期和时间说明符: | +| %c | Sun Jul 8 00:34:60 2001 | 区域设置的日期和时间表示形式(例如 Thu Mar 3 23:05:25 2005)。 | +| %+ | 2001-07-08T00:34:60.026490+09:30 | ISO 8601 / RFC 3339 日期和时间格式。 | +| %s | 994518299 | UNIX 时间戳,即自 1970-01-01 00:00 UTC 以来的秒数。{{{ .lake }}} 建议优先将 Integer 字符串转换为 Integer,而不是使用此说明符。示例请参见 [将整数转换为时间戳](/tidb-cloud-lake/sql/to-timestamp.md#example-2-converting-integer-to-timestamp)。 | +| | | 特殊说明符: | +| %t | | 字面量制表符(\t)。 | +| %n | | 字面量换行符(\n)。 | +| %% | | 字面量百分号。 | + +可以覆盖数值说明符 %? 的默认填充行为。其他说明符不允许这样做,否则会导致 BAD_FORMAT 错误。 + +| 修饰符 | 描述 | +| -------- | ----------------------------------------------------------------------------- | +| %-? | 禁用任何填充,包括空格和零。(例如 %j = 012,%-j = 12) | +| %\_? | 使用空格作为填充。(例如 %j = 012,%\_j = 12) | +| %0? | 使用零作为填充。(例如 %e = 9,%0e = 09) | + +- %C, %y:这里使用向下取整除法,因此公元前 100 年(年份编号 -99)将分别输出 -1 和 99。 + +- %U:第 1 周从该年的第一个星期日开始。在第一个星期日之前的日期可能属于第 0 周。 + +- %G, %g, %V:第 1 周是该年中至少包含 4 天的第一周。不存在第 0 周,因此应与 %G 或 %g 搭配使用。 + +- %S:它会考虑闰秒,因此 60 是可能的。 + +- %f, %.f, %.3f, %.6f, %.9f, %3f, %6f, %9f: + + 默认的 %f 是右对齐,并且始终左侧补零到 9 位,以兼容 glibc 等实现,因此它始终表示自上一整秒以来的纳秒数。例如,距离上一秒过去 7ms 时会输出 007000000,而解析 7000000 也会得到相同结果。 + + 变体 %.f 是左对齐,并根据精度输出 0、3、6 或 9 位小数。例如,距离上一秒过去 70ms 时,使用 %.f 会输出 .070(注意:不是 .07);解析 .07、.070000 等也会得到相同结果。注意,如果小数部分为零,或者下一个字符不是 .,则它们可能不会输出或读取任何内容。 + + 变体 %.3f、%.6f 和 %.9f 是左对齐,并根据 f 前面的数字输出 3、6 或 9 位小数。例如,距离上一秒过去 70ms 时,使用 %.3f 会输出 .070(注意:不是 .07);解析 .07、.070000 等也会得到相同结果。注意,如果小数部分为零,或者下一个字符不是 .,则它们在读取时可能不会读取任何内容;但在输出时会按指定长度输出。 + + 变体 %3f、%6f 和 %9f 是左对齐,并根据 f 前面的数字输出 3、6 或 9 位小数,但不带前导点号。例如,距离上一秒过去 70ms 时,使用 %3f 会输出 070(注意:不是 07);解析 07、070000 等也会得到相同结果。注意,如果小数部分为零,则它们在读取时可能不会读取任何内容。 + +- %Z:不会根据解析出的数据来填充偏移,也不会对其进行校验。时区会被完全忽略。这与 glibc 的 strptime 对该格式代码的处理方式类似。 + + 无法可靠地将缩写转换为偏移,例如 CDT 既可能表示 Central Daylight Time(北美中部夏令时),也可能表示 China Daylight Time(中国夏令时)。 + +- %+:等同于 %Y-%m-%dT%H:%M:%S%.f%:z,也就是说,秒的小数部分会输出 0、3、6 或 9 位,时区偏移中带有冒号。 + + 该格式还支持使用 Z 或 UTC 替代 %:z。它们都等价于 +00:00。 + + 注意,所有的 T、Z 和 UTC 在解析时都不区分大小写。 + + 典型的 strftime 实现对该说明符的格式定义各不相同(并且依赖区域设置)。虽然 Chrono 对 %+ 的格式更稳定,但如果你希望精确控制输出,最好避免使用该说明符。 + +- %s:该说明符不进行填充,并且可以为负数。对于 Chrono 而言,它只考虑非闰秒,因此与 ISO C strftime 的行为略有不同。 + +### Oracle 格式说明符 {#oracle-format-specifiers} + +当 `date_format_style` 设置为 'Oracle' 时,支持以下格式说明符: + +| Oracle 格式 | 描述 | 示例输出(对应 '2024-04-05 14:30:45.123456') | +|---------------|----------------------------------------------|---------------------------------------------------| +| YYYY | 4 位年份 | 2024 | +| YY | 2 位年份 | 24 | +| MMMM | 完整月份名称 | April | +| MON | 缩写月份名称 | Apr | +| MM | 月份数字 (01-12) | 04 | +| DD | 月中的日期 (01-31) | 05 | +| DY | 缩写星期名称 | Fri | +| HH24 | 一天中的小时 (00-23) | 14 | +| HH12 | 一天中的小时 (01-12) | 02 | +| AM/PM | 上下午指示符 | PM | +| MI | 分钟 (00-59) | 30 | +| SS | 秒 (00-59) | 45 | +| FF | 小数秒 | 123456 | +| UUUU | ISO 周编号年份 | 2024 | +| TZH:TZM | 带冒号的时区小时和分钟 | +08:00 | +| TZH | 时区小时 | +08 | + +以下示例使用相同的数据对比 MySQL 和 Oracle 格式风格: + +```sql +-- MySQL format style (default) +SELECT to_string('2022-12-25'::DATE, '%m/%d/%Y'); + +┌────────────────────────────────┐ +│ to_string('2022-12-25', '%m/%d/%Y') │ +├────────────────────────────────┤ +│ 12/25/2022 │ +└────────────────────────────────┘ + +-- Oracle format style (same data as MySQL example above) +SETTINGS (date_format_style = 'Oracle') +SELECT to_string('2022-12-25'::DATE, 'MM/DD/YYYY'); + +┌────────────────────────────────┐ +│ to_string('2022-12-25', 'MM/DD/YYYY') │ +├────────────────────────────────┤ +│ 12/25/2022 │ +└────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/date-trunc.md b/tidb-cloud-lake/sql/date-trunc.md new file mode 100644 index 0000000000000..37b9db0e328b8 --- /dev/null +++ b/tidb-cloud-lake/sql/date-trunc.md @@ -0,0 +1,71 @@ +--- +title: DATE_TRUNC +summary: 将日期或时间戳截断到指定精度,提供一种标准化的方式来处理日期和时间戳。该函数旨在与多种数据库系统兼容,从而让用户更容易进行迁移并使用不同的数据库。 +--- + +# DATE_TRUNC + +将日期或时间戳截断到指定精度,提供一种标准化的方式来处理日期和时间戳。该函数旨在与多种数据库系统兼容,从而让用户更容易进行迁移并使用不同的数据库。 + +## 语法 {#syntax} + +```sql +DATE_TRUNC(, ) +``` + +| 参数 | 描述 | +|-----------------------|------------------------------------------------------------------------------------------------------------| +| `` | 必须是以下值之一:`YEAR`、`QUARTER`、`MONTH`、`WEEK`、`DAY`、`HOUR`、`MINUTE` 和 `SECOND`。 | +| `` | `DATE` 或 `TIMESTAMP` 类型的值。 | + +## Week Start 配置 {#week-start-configuration} + +当使用 `WEEK` 作为精度参数时,结果取决于 `week_start` 设置,该设置定义了一周的第一天: + +- `week_start = 1`(默认):星期一被视为一周的第一天 +- `week_start = 0`:星期日被视为一周的第一天 + +你可以使用 `SETTINGS` 子句为特定查询更改此设置: + +```sql +-- Set Sunday as the first day of the week +SETTINGS (week_start = 0) SELECT DATE_TRUNC(WEEK, to_date('2024-04-05')); + +-- Set Monday as the first day of the week (default) +SETTINGS (week_start = 1) SELECT DATE_TRUNC(WEEK, to_date('2024-04-05')); +``` + +## 返回类型 {#return-type} + +与 `` 相同。 + +## 示例 {#examples} + +```sql +SELECT + DATE_TRUNC(MONTH, to_date('2022-07-07')), + DATE_TRUNC(WEEK, to_date('2022-07-07')); + +┌────────────────────────────────────────────────────────────────────────────────────┐ +│ DATE_TRUNC(MONTH, to_date('2022-07-07')) │ DATE_TRUNC(WEEK, to_date('2022-07-07')) │ +├──────────────────────────────────────────┼─────────────────────────────────────────┤ +│ 2022-07-01 │ 2022-07-04 │ +└────────────────────────────────────────────────────────────────────────────────────┘ +``` + +```sql +SELECT + DATE_TRUNC(HOUR, to_timestamp('2022-07-07 01:01:01.123456')), + DATE_TRUNC(SECOND, to_timestamp('2022-07-07 01:01:01.123456')); + +┌────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ +│ DATE_TRUNC(HOUR, to_timestamp('2022-07-07 01:01:01.123456')) │ DATE_TRUNC(SECOND, to_timestamp('2022-07-07 01:01:01.123456')) │ +├─────────────────────────────────────────────────────────────┼────────────────────────────────────────────────────────────────┤ +│ 2022-07-07 01:00:00.000000 │ 2022-07-07 01:01:01.000000 │ +└────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ +``` + +## 另请参阅 {#see-also} + +- [TRUNC](/tidb-cloud-lake/sql/trunc.md):提供类似功能,但使用不同的语法,以获得更好的 SQL 标准兼容性。 +- [TIME_SLICE](/tidb-cloud-lake/sql/time-slice.md):将单个日期/时间戳值映射到与日历对齐的时间区间。 \ No newline at end of file diff --git a/tidb-cloud-lake/sql/date.md b/tidb-cloud-lake/sql/date.md new file mode 100644 index 0000000000000..0c1e4a02b721e --- /dev/null +++ b/tidb-cloud-lake/sql/date.md @@ -0,0 +1,8 @@ +--- +title: DATE +summary: TO_DATE 的别名。 +--- + +# DATE + +[TO_DATE](/tidb-cloud-lake/sql/to-date.md) 的别名。 \ No newline at end of file diff --git a/tidb-cloud-lake/sql/datetime.md b/tidb-cloud-lake/sql/datetime.md new file mode 100644 index 0000000000000..cf77a9748e996 --- /dev/null +++ b/tidb-cloud-lake/sql/datetime.md @@ -0,0 +1,8 @@ +--- +title: TO_DATETIME +summary: TO_TIMESTAMP 的别名。 +--- + +# TO_DATETIME + +[TO_TIMESTAMP](/tidb-cloud-lake/sql/to-timestamp.md) 的别名。 \ No newline at end of file diff --git a/tidb-cloud-lake/sql/day-week.md b/tidb-cloud-lake/sql/day-week.md new file mode 100644 index 0000000000000..cf67edefc9720 --- /dev/null +++ b/tidb-cloud-lake/sql/day-week.md @@ -0,0 +1,38 @@ +--- +title: TO_DAY_OF_WEEK +summary: 将日期或带时间的日期(timestamp/datetime)转换为一个 UInt8 数字,表示一周中的第几天(星期一为 1,星期日为 7)。 +--- + +# TO_DAY_OF_WEEK + +将日期或带时间的日期(timestamp/datetime)转换为一个 UInt8 数字,表示一周中的第几天(星期一为 1,星期日为 7)。 + +## 语法 {#syntax} + +```sql +TO_DAY_OF_WEEK() +``` + +## 参数 {#arguments} + +| 参数 | 描述 | +|-----------|----------------| +| `` | 日期/时间戳 | + +## 返回类型 {#return-type} + +`TINYINT` + +## 示例 {#examples} + +```sql + +SELECT + to_day_of_week('2023-11-12 09:38:18.165575'); + +┌──────────────────────────────────────────────┐ +│ to_day_of_week('2023-11-12 09:38:18.165575') │ +├──────────────────────────────────────────────┤ +│ 7 │ +└──────────────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/day-year.md b/tidb-cloud-lake/sql/day-year.md new file mode 100644 index 0000000000000..dc46c180a6734 --- /dev/null +++ b/tidb-cloud-lake/sql/day-year.md @@ -0,0 +1,37 @@ +--- +title: TO_DAY_OF_YEAR +summary: 将日期或带时间的日期(timestamp/datetime)转换为一个 UInt16 数字,表示该日期是一年中的第几天(1-366)。 +--- + +# TO_DAY_OF_YEAR + +将日期或带时间的日期(timestamp/datetime)转换为一个 UInt16 数字,表示该日期是一年中的第几天(1-366)。 + +## 语法 {#syntax} + +```sql +TO_DAY_OF_YEAR() +``` + +## 参数 {#arguments} + +| 参数 | 描述 | +| ----------- | ----------- | +| `` | 日期/时间戳 | + +## 返回类型 {#return-type} + +`SMALLINT` + +## 示例 {#examples} + +```sql +SELECT + to_day_of_year('2023-11-12 09:38:18.165575'); + +┌──────────────────────────────────────────────┐ +│ to_day_of_year('2023-11-12 09:38:18.165575') │ +├──────────────────────────────────────────────┤ +│ 316 │ +└──────────────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/day.md b/tidb-cloud-lake/sql/day.md new file mode 100644 index 0000000000000..1657cb243f0fd --- /dev/null +++ b/tidb-cloud-lake/sql/day.md @@ -0,0 +1,8 @@ +--- +title: DAY +summary: TO_DAY_OF_MONTH 的别名。 +--- + +# DAY + +[TO_DAY_OF_MONTH](/tidb-cloud-lake/sql/to-day-of-month.md) 的别名。 \ No newline at end of file diff --git a/tidb-cloud-lake/sql/days.md b/tidb-cloud-lake/sql/days.md new file mode 100644 index 0000000000000..c414862f048a6 --- /dev/null +++ b/tidb-cloud-lake/sql/days.md @@ -0,0 +1,32 @@ +--- +title: TO_DAYS +summary: 将指定的天数转换为 Interval 类型。 +--- + +# TO_DAYS + +将指定的天数转换为 Interval 类型。 + +- 接受正整数、零和负整数作为输入。 + +## 语法 {#syntax} + +```sql +TO_DAYS() +``` + +## 返回类型 {#return-type} + +Interval(以天表示)。 + +## 示例 {#examples} + +```sql +SELECT TO_DAYS(2), TO_DAYS(0), TO_DAYS(-2); + +┌────────────────────────────────────────┐ +│ to_days(2) │ to_days(0) │ to_days(- 2) │ +├────────────┼────────────┼──────────────┤ +│ 2 days │ 00:00:00 │ -2 days │ +└────────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/ddl-database-overview.md b/tidb-cloud-lake/sql/ddl-database-overview.md new file mode 100644 index 0000000000000..45e673650d361 --- /dev/null +++ b/tidb-cloud-lake/sql/ddl-database-overview.md @@ -0,0 +1,30 @@ +--- +title: 数据库 +summary: 本页按功能组织,全面概述了 {{{ .lake }}} 中的数据库操作,便于参考。 +--- + +# 数据库 + +本页按功能组织,全面概述了 {{{ .lake }}} 中的数据库操作,便于参考。 + +## 数据库创建与管理 {#database-creation-management} + +| 命令 | 描述 | +|---------|-------------| +| [CREATE DATABASE](/tidb-cloud-lake/sql/create-database.md) | 创建新数据库 | +| [ALTER DATABASE](/tidb-cloud-lake/sql/alter-database.md) | 修改数据库 | +| [DROP DATABASE](/tidb-cloud-lake/sql/drop-database.md) | 删除数据库 | +| [USE DATABASE](/tidb-cloud-lake/sql/use-database.md) | 设置当前工作数据库 | +| [UNDROP DATABASE](/tidb-cloud-lake/sql/undrop-database.md) | 恢复已删除的数据库 | + +## 数据库信息 {#database-information} + +| 命令 | 描述 | +|---------|-------------| +| [SHOW DATABASES](/tidb-cloud-lake/sql/show-databases.md) | 列出所有数据库 | +| [SHOW CREATE DATABASE](/tidb-cloud-lake/sql/show-create-database.md) | 显示某个数据库的 CREATE DATABASE 语句 | +| [SHOW DROP DATABASES](/tidb-cloud-lake/sql/show-drop-databases.md) | 列出可恢复的已删除数据库 | + +> **注意:** +> +> 数据库操作是你在 {{{ .lake }}} 中组织数据的基础。在执行这些命令之前,请确保你具有适当的权限。 \ No newline at end of file diff --git a/tidb-cloud-lake/sql/ddl-table-overview.md b/tidb-cloud-lake/sql/ddl-table-overview.md new file mode 100644 index 0000000000000..337a85891de73 --- /dev/null +++ b/tidb-cloud-lake/sql/ddl-table-overview.md @@ -0,0 +1,57 @@ +--- +title: 表 +summary: 本页按功能分类,全面概述了 {{{ .lake }}} 中的表操作,便于快速查阅。 +--- + +# 表 + +本页按功能分类,全面概述了 {{{ .lake }}} 中的表操作,便于快速查阅。 + +## 表创建 {#table-creation} + +| 命令 | 描述 | +|---------|-------------| +| [CREATE TABLE](/tidb-cloud-lake/sql/create-table.md) | 使用指定的列和选项创建新表 | +| [CREATE TABLE ... LIKE](/tidb-cloud-lake/sql/create-table.md#create-table--like) | 使用与现有表相同的列定义创建表 | +| [CREATE TABLE ... AS](/tidb-cloud-lake/sql/create-table.md#create-table--as) | 创建表,并基于 SELECT 查询结果插入数据 | +| [CREATE TRANSIENT TABLE](/tidb-cloud-lake/sql/create-transient-table.md) | 创建不支持 Time Travel 的表 | +| [CREATE EXTERNAL TABLE](/tidb-cloud-lake/sql/create-external-table.md) | 创建一个表,其数据存储在指定的外部位置 | +| [ATTACH TABLE](/tidb-cloud-lake/sql/attach-table.md) | 通过将表与现有表关联来创建表 | + +## 表修改 {#table-modification} + +| 命令 | 描述 | +|---------|-------------| +| [ALTER TABLE](/tidb-cloud-lake/sql/alter-table.md) | 修改表列、注释、Fuse 选项、外部连接,或与另一张表交换元信息 | +| [RENAME TABLE](/tidb-cloud-lake/sql/rename-table.md) | 更改表名 | + +## 表信息 {#table-information} + +| 命令 | 描述 | +|---------|-------------| +| [DESCRIBE TABLE](/tidb-cloud-lake/sql/describe-table.md) / [SHOW FIELDS](/tidb-cloud-lake/sql/show-fields.md) | 显示指定表中列的信息 | +| [SHOW FULL COLUMNS](/tidb-cloud-lake/sql/show-columns.md) | 获取指定表中列的完整详细信息 | +| [SHOW CREATE TABLE](/tidb-cloud-lake/sql/show-create-table.md) | 显示用于创建指定表的 CREATE TABLE 语句 | +| [SHOW TABLES](/tidb-cloud-lake/sql/show-tables.md) | 列出当前数据库或指定数据库中的表 | +| [SHOW TABLE STATUS](/tidb-cloud-lake/sql/show-table-status.md) | 显示数据库中各表的状态 | +| [SHOW DROP TABLES](/tidb-cloud-lake/sql/show-drop-tables.md) | 列出当前数据库或指定数据库中已删除的表 | + +## 表删除与恢复 {#table-deletion-recovery} + +| 命令 | 描述 | 恢复选项 | +|---------|-------------|----------------| +| [TRUNCATE TABLE](/tidb-cloud-lake/sql/truncate-table.md) | 删除表中的所有数据,同时保留表结构 | [FLASHBACK TABLE](/tidb-cloud-lake/sql/flashback-table.md) | +| [DROP TABLE](/tidb-cloud-lake/sql/drop-table.md) | 删除表 | [UNDROP TABLE](/tidb-cloud-lake/sql/undrop-table.md) | +| [VACUUM TABLE](/tidb-cloud-lake/sql/vacuum-table.md) | 永久删除表的历史数据文件(企业版) | 不可恢复 | +| [VACUUM DROP TABLE](/tidb-cloud-lake/sql/vacuum-drop-table.md) | 永久删除已删除表的数据文件(企业版) | 不可恢复 | + +## 表优化 {#table-optimization} + +| 命令 | 描述 | +|---------|-------------| +| [OPTIMIZE TABLE](/tidb-cloud-lake/sql/optimize-table.md) | 压缩或清理历史数据以节省存储空间并提升查询性能 | +| [SET CLUSTER KEY](/tidb-cloud-lake/sql/set-cluster-key.md) | 配置 cluster key,以提升大表的查询性能 | + +> **注意:** +> +> 表优化属于高级操作。请在执行前仔细阅读相关文档,以避免潜在的数据丢失。 \ No newline at end of file diff --git a/tidb-cloud-lake/sql/ddl-view-overview.md b/tidb-cloud-lake/sql/ddl-view-overview.md new file mode 100644 index 0000000000000..f1f1406f3c0d2 --- /dev/null +++ b/tidb-cloud-lake/sql/ddl-view-overview.md @@ -0,0 +1,29 @@ +--- +title: 视图 +summary: 本页按功能分类,全面概述了 {{{ .lake }}} 中的视图操作,便于快速查阅。 +--- + +# 视图 + +本页按功能分类,全面概述了 {{{ .lake }}} 中的视图操作,便于快速查阅。 + +## 视图管理 {#view-management} + +| 命令 | 描述 | +|---------|-------------| +| [CREATE VIEW](/tidb-cloud-lake/sql/create-view.md) | 基于查询创建一个新视图 | +| [ALTER VIEW](/tidb-cloud-lake/sql/alter-view.md) | 为现有视图分配或移除标签 | +| [DROP VIEW](/tidb-cloud-lake/sql/drop-view.md) | 删除一个视图 | +| [物化视图](/tidb-cloud-lake/sql/materialized-view.md) | 创建并维护由物理存储支持的物化视图 | +| [REFRESH LINEAGE](/tidb-cloud-lake/sql/refresh-lineage.md) | 为现有视图回填或校正血缘关系 | + +## 视图信息 {#view-information} + +| 命令 | 描述 | +|---------|-------------| +| [DESC VIEW](/tidb-cloud-lake/sql/desc-view.md) | 显示视图的详细信息 | +| [SHOW VIEWS](/tidb-cloud-lake/sql/show-views.md) | 列出当前或指定数据库中的所有视图 | + +> **Note:** +> +> {{{ .lake }}} 中的视图是存储在数据库中的命名查询,可以像表一样被引用。它们可用于简化复杂查询,并控制对底层数据的访问。 \ No newline at end of file diff --git a/tidb-cloud-lake/sql/ddl.md b/tidb-cloud-lake/sql/ddl.md new file mode 100644 index 0000000000000..d75219b311c88 --- /dev/null +++ b/tidb-cloud-lake/sql/ddl.md @@ -0,0 +1,73 @@ +--- +title: DDL(数据定义语言)命令 +summary: 本主题提供 {{{ .lake }}} 中 DDL(数据定义语言)命令的参考信息。 +--- + +# DDL(数据定义语言)命令 + +本主题提供 {{{ .lake }}} 中 DDL(数据定义语言)命令的参考信息。 + +## 数据库和表管理 {#database-table-management} + +| 组件 | 描述 | +|-----------|-------------| +| **[Catalog](/tidb-cloud-lake/sql/catalog.md)** | 创建、删除和列出 catalog | +| **[数据库](/tidb-cloud-lake/sql/ddl-database-overview.md)** | 创建、修改和删除数据库 | +| **[表](/tidb-cloud-lake/sql/ddl-table-overview.md)** | 创建、修改和管理表 | +| **[表版本控制](/tidb-cloud-lake/sql/table-versioning.md)** | 创建用于时间旅行的命名快照标签 | +| **[视图](/tidb-cloud-lake/sql/ddl-view-overview.md)** | 基于查询创建和管理虚拟表 | + +## 性能和索引 {#performance-indexing} + +| 组件 | 描述 | +|-----------|-------------| +| **[Cluster Key](/tidb-cloud-lake/sql/cluster-key.md)** | 定义数据聚簇以优化查询 | +| **[聚合索引](/tidb-cloud-lake/sql/aggregating-index-sql.md)** | 预计算聚合以加快查询 | +| **[倒排索引](/tidb-cloud-lake/sql/inverted-index.md)** | 用于文本列的全文搜索索引 | +| **[Ngram 索引](/tidb-cloud-lake/sql/ngram-index-sql.md)** | 用于 LIKE 模式的子字符串搜索索引 | +| **[空间索引](/tidb-cloud-lake/sql/spatial-index-overview.md)** | 用于 GEOMETRY 列的空间裁剪索引 | +| **[向量索引](/tidb-cloud-lake/sql/vector-index.md)** | 用于向量嵌入的相似度搜索索引 | +| **[虚拟列](/tidb-cloud-lake/sql/virtual-column-overview.md)** | 将 JSON 字段提取并索引为虚拟列 | + +## 安全和访问控制 {#security-access-control} + +| 组件 | 描述 | +|-----------|-------------| +| **[用户](/tidb-cloud-lake/sql/user-role.md)** | 创建和管理数据库用户 | +| **[标签](/tidb-cloud-lake/sql/tag-overview.md)** | 将键值元信息附加到对象上,用于治理和分类 | +| **[网络策略](/tidb-cloud-lake/sql/network-policy-sql.md)** | 控制对数据库的网络访问 | +| **[脱敏策略](/tidb-cloud-lake/sql/masking-policy-sql.md)** | 对敏感信息应用数据脱敏 | +| **[密码策略](/tidb-cloud-lake/sql/password-policy-sql.md)** | 强制执行密码要求和轮换 | +| **[行访问策略](/tidb-cloud-lake/sql/row-access-policy-overview.md)** | 使用集中式行级谓词过滤表中的行 | + +## 数据集成和处理 {#data-integration-processing} + +| 组件 | 描述 | +|-----------|-------------| +| **[Stage](/tidb-cloud-lake/sql/stage.md)** | 定义用于数据加载的存储位置 | +| **[Pipe](/tidb-cloud-lake/sql/pipe.md)** | 管理摄取管道 | +| **[Stream](/tidb-cloud-lake/sql/stream.md)** | 捕获并处理数据变更 | +| **[任务](/tidb-cloud-lake/sql/task.md)** | 调度并自动化 SQL 操作 | +| **[序列](/tidb-cloud-lake/sql/sequence.md)** | 生成唯一的顺序编号 | +| **[Connection](/tidb-cloud-lake/sql/connection.md)** | 配置外部数据源连接 | +| **[文件格式](/tidb-cloud-lake/sql/file-format.md)** | 定义数据导入/导出的格式 | +| **[字典](/tidb-cloud-lake/sql/dictionary.md)** | 定义由外部源支持的字典 | + +## 函数和过程 {#functions-procedures} + +| 组件 | 描述 | +|-----------|-------------| +| **[UDF](/tidb-cloud-lake/sql/user-defined-function.md)** | 使用 Python 或 JavaScript 创建自定义函数 | +| **[外部函数](/tidb-cloud-lake/sql/external-function.md)** | 将外部 API 集成为 SQL 函数 | +| **[存储过程](/tidb-cloud-lake/sql/stored-procedure.md)** | 创建用于复杂逻辑的存储过程 | +| **[通知](/tidb-cloud-lake/sql/notification.md)** | 设置事件通知和 webhook | + +## 资源管理 {#resource-management} + +| 组件 | 描述 | +|-----------|-------------| +| **[计算集群 (Warehouse)](/tidb-cloud-lake/sql/warehouse-overview.md)** | 管理用于查询执行的计算资源 | +| **[Worker](/tidb-cloud-lake/sql/worker-overview.md)** | 通过云控制管理沙箱 UDF 执行环境 | +| **[Workload Group](/tidb-cloud-lake/sql/workload-group.md)** | 控制资源分配和优先级 | +| **[事务](/tidb-cloud-lake/sql/transaction.md)** | 管理数据库事务 | +| **[变量](/tidb-cloud-lake/sql/sql-variables.md)** | 设置和使用会话/全局变量 | \ No newline at end of file diff --git a/tidb-cloud-lake/sql/decades.md b/tidb-cloud-lake/sql/decades.md new file mode 100644 index 0000000000000..0e5e543188052 --- /dev/null +++ b/tidb-cloud-lake/sql/decades.md @@ -0,0 +1,32 @@ +--- +title: TO_DECADES +summary: 将指定的 decade 数转换为 Interval 类型。 +--- + +# TO_DECADES + +将指定的 decade 数转换为 Interval 类型。 + +- 接受正整数、零和负整数作为输入。 + +## 语法 {#syntax} + +```sql +TO_DECADES() +``` + +## 返回类型 {#return-type} + +Interval(以年表示)。 + +## 示例 {#examples} + +```sql +SELECT TO_DECADES(2), TO_DECADES(0), TO_DECADES((- 2)); + +┌─────────────────────────────────────────────────┐ +│ to_decades(2) │ to_decades(0) │ to_decades(- 2) │ +├───────────────┼───────────────┼─────────────────┤ +│ 20 years │ 00:00:00 │ -20 years │ +└─────────────────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/decimal.md b/tidb-cloud-lake/sql/decimal.md new file mode 100644 index 0000000000000..afeae420b866c --- /dev/null +++ b/tidb-cloud-lake/sql/decimal.md @@ -0,0 +1,66 @@ +--- +title: Decimal +summary: Decimal 类型是用于存储和处理的高精度数值。 +--- + +# Decimal + +## 概述 {#overview} + +`DECIMAL(P, S)` 用于存储精确数值,其中精度 `P` 表示总位数(1–76),扩展 `S` 表示小数点右侧的位数(0–P)。取值必须位于 ±`(10^P - 1) / 10^S` 范围内。精度不超过 38 的值使用 `DECIMAL128`,更大的值使用 `DECIMAL256`。 + +## 示例 {#examples} + +```sql +CREATE TABLE invoices ( + description STRING, + amount DECIMAL(10, 2), + tax_rate DECIMAL(5, 4) +); + +INSERT INTO invoices VALUES + ('Laptop', 1299.99, 0.1300), + ('Monitor', 399.50, 0.0750); + +SELECT + description, + amount, + tax_rate, + amount * tax_rate AS tax_value, + amount + amount * tax_rate AS total_due +FROM invoices; +``` + +结果: + +``` +┌─────────────┬──────────┬──────────┬────────────┬────────────┐ +│ description │ amount │ tax_rate │ tax_value │ total_due │ +├─────────────┼──────────┼──────────┼────────────┼────────────┤ +│ Laptop │ 1299.99 │ 0.1300 │ 168.998700 │ 1468.988700 │ +│ Monitor │ 399.50 │ 0.0750 │ 29.962500 │ 429.462500 │ +└─────────────┴──────────┴──────────┴────────────┴────────────┘ +``` + +算术运算会自动保持精度:加法会保留最宽的整数部分和小数部分,乘法会累加精度,除法会保留左操作数的扩展。如果你需要特定的结果格式,请使用显式类型转换。 + +```sql +SELECT + SUM(amount) AS sum_default, + CAST(SUM(amount) AS DECIMAL(12, 2)) AS sum_cast, + AVG(amount) AS avg_default, + CAST(AVG(amount) AS DECIMAL(12, 4)) AS avg_cast +FROM invoices; +``` + +结果: + +``` +┌─────────────┬───────────┬────────────────┬──────────┐ +│ sum_default │ sum_cast │ avg_default │ avg_cast │ +├─────────────┼───────────┼────────────────┼──────────┤ +│ 1699.49 │ 1699.49 │ 849.74500000 │ 849.7450 │ +└─────────────┴───────────┴────────────────┴──────────┘ +``` + +如果某个运算会导致整数部分溢出,{{{ .lake }}} 会报错;多余的小数位会被截断而不是四舍五入。你可以通过调整 `P`/`S` 或对结果进行类型转换来控制这两种行为。 \ No newline at end of file diff --git a/tidb-cloud-lake/sql/decode.md b/tidb-cloud-lake/sql/decode.md new file mode 100644 index 0000000000000..fb6f264deac3e --- /dev/null +++ b/tidb-cloud-lake/sql/decode.md @@ -0,0 +1,60 @@ +--- +title: DECODE +summary: DECODE 函数按顺序将选择表达式与每个搜索表达式进行比较。一旦某个搜索表达式与选择表达式匹配,就返回对应的结果表达式。如果未找到匹配项且提供了默认值,则返回默认值。 +--- + +# DECODE + +DECODE 函数按顺序将选择表达式与每个搜索表达式进行比较。一旦某个搜索表达式与选择表达式匹配,就返回对应的结果表达式。如果未找到匹配项且提供了默认值,则返回默认值。 + +## 语法 {#syntax} + +```sql +DECODE( , , [, , ... ] [, ] ) +``` + +## 参数 {#arguments} + +- `expr`:与每个搜索表达式进行比较的“选择表达式”。通常这是一个列,但也可以是子查询、字面量或其他表达式。 +- `searchN`:要与选择表达式进行比较的搜索表达式。如果找到匹配项,则返回对应的结果。 +- `resultN`:当对应的搜索表达式与选择表达式匹配时将返回的值。 +- `default`:可选。如果提供了该参数且没有任何搜索表达式匹配,则返回此默认值。 + +## 使用说明 {#usage-notes} + +- 与 `CASE` 不同,选择表达式中的 `NULL` 值会与搜索表达式中的 `NULL` 值匹配。 +- 如果有多个搜索表达式都能匹配,则只返回第一个匹配项的结果。 + +## 示例 {#examples} + +```sql +CREATE TABLE t (a VARCHAR); +INSERT INTO t (a) VALUES + ('1'), + ('2'), + (NULL), + ('4'); +``` + +带默认值 `'other'` 的示例(注意,`NULL` 等于 `NULL`): + +```sql +SELECT a, decode(a, + 1, 'one', + 2, 'two', + NULL, '-NULL-', + 'other' + ) AS decode_result + FROM t; +``` + +结果: + +``` +┌─a─┬─decode_result─┐ +│ 1 │ one │ +│ 2 │ two │ +│ │ -NULL- │ +│ 4 │ other │ +└───┴───────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/degrees.md b/tidb-cloud-lake/sql/degrees.md new file mode 100644 index 0000000000000..e4459b8944a5c --- /dev/null +++ b/tidb-cloud-lake/sql/degrees.md @@ -0,0 +1,26 @@ +--- +title: DEGREES +summary: 返回参数 `x` 从弧度转换为角度后的值,其中 `x` 以弧度给出。 +--- + +# DEGREES + +返回参数 `x` 从弧度转换为角度后的值,其中 `x` 以弧度给出。 + +## 语法 {#syntax} + +```sql +DEGREES( ) +``` + +## 示例 {#examples} + +```sql +SELECT DEGREES(PI()); + +┌───────────────┐ +│ degrees(pi()) │ +├───────────────┤ +│ 180 │ +└───────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/delete.md b/tidb-cloud-lake/sql/delete.md new file mode 100644 index 0000000000000..aaa7068f3a59c --- /dev/null +++ b/tidb-cloud-lake/sql/delete.md @@ -0,0 +1,156 @@ +--- +title: DELETE +summary: 从表中删除一行或多行。 +--- + +# DELETE + +从表中删除一行或多行。 + +> **Tip:** +> +> {{{ .lake }}} 通过原子操作确保数据完整性。插入、修改、替换和删除要么全部成功,要么全部失败。 + +## 语法 {#syntax} + +```sql +DELETE FROM [AS ] +[WHERE ] +``` + +- `AS `:允许你为表设置别名,从而更方便地在查询中引用该表。这有助于简化并缩短 SQL 代码,尤其是在处理涉及多个表的复杂查询时。参见[使用 EXISTS / NOT EXISTS 子句和子查询删除](#deleting-with-subquery-using-exists--not-exists-clause)中的示例。 + +- DELETE 目前还不支持 USING 子句。如果你需要使用子查询来识别要删除的行,请直接将其包含在 WHERE 子句中。参见[基于子查询的删除](#example-2-subquery-based-deletions)中的示例。 + +## 示例 {#examples} + +### 示例 1:直接删除行 {#example-1-direct-row-deletion} + +本示例演示如何使用 DELETE 命令,直接从 `bookstore` 表中删除 ID 为 103 的图书记录。 + +```sql +-- Create a table and insert 5 book records +CREATE TABLE bookstore ( + book_id INT, + book_name VARCHAR +); + +INSERT INTO bookstore VALUES (101, 'After the death of Don Juan'); +INSERT INTO bookstore VALUES (102, 'Grown ups'); +INSERT INTO bookstore VALUES (103, 'The long answer'); +INSERT INTO bookstore VALUES (104, 'Wartime friends'); +INSERT INTO bookstore VALUES (105, 'Deconstructed'); + +-- Delete a book (Id: 103) +DELETE FROM bookstore WHERE book_id = 103; + +-- Show all records after deletion +SELECT * FROM bookstore; + +101|After the death of Don Juan +102|Grown ups +104|Wartime friends +105|Deconstructed +``` + +### 示例 2:基于子查询的删除 {#example-2-subquery-based-deletions} + +当使用子查询来识别要删除的行时,可以使用[子查询运算符](/tidb-cloud-lake/sql/query-operators.md)和[比较运算符](/tidb-cloud-lake/sql/query-operators.md)来实现所需的删除操作。 + +本节中的示例基于以下两个表: + +```sql +-- Create the 'employees' table +CREATE TABLE employees ( + id INT, + name VARCHAR, + department VARCHAR +); + +-- Insert values into the 'employees' table +INSERT INTO employees VALUES (1, 'John', 'HR'); +INSERT INTO employees VALUES (2, 'Mary', 'Sales'); +INSERT INTO employees VALUES (3, 'David', 'IT'); +INSERT INTO employees VALUES (4, 'Jessica', 'Finance'); + +-- Create the 'departments' table +CREATE TABLE departments ( + id INT, + department VARCHAR +); + +-- Insert values into the 'departments' table +INSERT INTO departments VALUES (1, 'Sales'); +INSERT INTO departments VALUES (2, 'IT'); +``` + +#### 使用 IN / NOT IN 子句和子查询删除 {#deleting-with-subquery-using-in-not-in-clause} + +```sql +DELETE FROM EMPLOYEES +WHERE DEPARTMENT IN ( + SELECT DEPARTMENT + FROM DEPARTMENTS +); +``` + +这会删除 `employees` 表中 `department` 与 `departments` 表中任一部门匹配的员工。在此情况下,将删除 ID 为 2 和 3 的员工。 + +#### 使用 EXISTS / NOT EXISTS 子句和子查询删除 {#deleting-with-subquery-using-exists-not-exists-clause} + +```sql +DELETE FROM EMPLOYEES +WHERE EXISTS ( + SELECT * + FROM DEPARTMENTS + WHERE EMPLOYEES.DEPARTMENT = DEPARTMENTS.DEPARTMENT +); + +-- Alternatively, you can delete employees using the alias 'e' for the 'EMPLOYEES' table and 'd' for the 'DEPARTMENTS' table when their department matches. +DELETE FROM EMPLOYEES AS e +WHERE EXISTS ( + SELECT * + FROM DEPARTMENTS AS d + WHERE e.DEPARTMENT = d.DEPARTMENT +); +``` + +这会删除所属部门存在于 `departments` 表中的员工。在此情况下,将删除 ID 为 2 和 3 的员工。 + +#### 使用 ALL 子句和子查询删除 {#deleting-with-subquery-using-all-clause} + +```sql +DELETE FROM EMPLOYEES +WHERE DEPARTMENT = ALL ( + SELECT DEPARTMENT + FROM DEPARTMENTS +); +``` + +这会删除 `department` 与 `departments` 表中所有部门都匹配的员工。在此情况下,不会删除任何员工。 + +#### 使用 ANY 子句和子查询删除 {#deleting-with-subquery-using-any-clause} + +```sql +DELETE FROM EMPLOYEES +WHERE DEPARTMENT = ANY ( + SELECT DEPARTMENT + FROM DEPARTMENTS +); +``` + +这会删除 `department` 与 `departments` 表中任一部门匹配的员工。在此情况下,将删除 ID 为 2 和 3 的员工。 + +#### 结合多个条件使用子查询删除 {#deleting-with-subquery-combining-multiple-conditions} + +```sql +DELETE FROM EMPLOYEES +WHERE DEPARTMENT = ANY ( + SELECT DEPARTMENT + FROM DEPARTMENTS + WHERE EMPLOYEES.DEPARTMENT = DEPARTMENTS.DEPARTMENT +) + OR ID > 2; +``` + +这会在以下任一条件满足时,从 `employees` 表中删除员工:`department` 列的值与 `departments` 表中 `department` 列的任一值匹配,或者 `id` 列的值大于 2。在此情况下,将删除 `id` 为 2、3 和 4 的行,因为 Mary 的部门是 `"Sales"`,该部门存在于 `departments` 表中,并且 ID 为 3 和 4 的行都大于 2。 \ No newline at end of file diff --git a/tidb-cloud-lake/sql/delta-lake-engine.md b/tidb-cloud-lake/sql/delta-lake-engine.md new file mode 100644 index 0000000000000..f502a715e40f8 --- /dev/null +++ b/tidb-cloud-lake/sql/delta-lake-engine.md @@ -0,0 +1,38 @@ +--- +title: Delta Lake Engine +summary: "{{{ .lake }}} 的 Delta Lake engine 允许你无缝查询和分析存储在对象存储中的 Delta Lake 表数据。在 {{{ .lake }}} 中使用 Delta Lake engine 创建表时,你需要指定 Delta Lake 表数据文件的存储位置。通过这种方式,你可以直接访问该表,并在 {{{ .lake }}} 内无缝执行查询。" +--- + +# Delta Lake Engine + +{{{ .lake }}} 的 [Delta Lake](https://delta.io/) engine 允许你无缝查询和分析存储在对象存储中的 Delta Lake 表数据。在 {{{ .lake }}} 中使用 Delta Lake engine 创建表时,你需要指定 Delta Lake 表数据文件的存储位置。通过这种方式,你可以直接访问该表,并在 {{{ .lake }}} 内无缝执行查询。 + +- {{{ .lake }}} 的 Delta Lake engine 当前仅支持只读操作。这意味着支持从 Delta Lake 表中查询数据,但不支持向表中写入数据。 +- 使用 Delta Lake engine 创建的表,其 schema 会在创建时确定。若原始 Delta Lake 表的 schema 发生任何修改,则需要在 {{{ .lake }}} 中重新创建对应的表,以确保两者保持同步。 +- {{{ .lake }}} 中的 Delta Lake engine 基于官方 [delta-rs](https://github.com/delta-io/delta-rs) 库构建。需要注意的是,delta-protocol 中定义的某些特性(包括 Deletion Vector、Change Data Feed、Generated Columns 和 Identity Columns)当前**不**受该 engine 支持。 + +## 语法 {#syntax} + +```sql +CREATE TABLE +ENGINE = Delta +LOCATION = 's3://' +CONNECTION_NAME = '' +``` + +在使用 Delta Lake engine 创建表之前,你需要先创建一个 connection 对象,用于与 S3 存储建立连接。要在 {{{ .lake }}} 中创建 connection,请使用 [CREATE CONNECTION](/tidb-cloud-lake/sql/create-connection.md) 命令。 + +## 示例 {#examples} + +```sql +--Set up connection +CREATE CONNECTION my_s3_conn +STORAGE_TYPE = 's3' +ACCESS_KEY_ID ='your-ak' SECRET_ACCESS_KEY ='your-sk'; + +-- Create table with Delta Lake engine +CREATE TABLE test_delta +ENGINE = Delta +LOCATION = 's3://testbucket/admin/data/delta/delta-table/' +CONNECTION_NAME = 'my_s3_conn'; +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/dense-rank.md b/tidb-cloud-lake/sql/dense-rank.md new file mode 100644 index 0000000000000..4169508625731 --- /dev/null +++ b/tidb-cloud-lake/sql/dense-rank.md @@ -0,0 +1,103 @@ +--- +title: DENSE_RANK +summary: 为分区内的每一行分配一个排名。值相等的行会获得相同的排名,后续排名中不会出现间隔。 +--- + +# DENSE_RANK + +为分区内的每一行分配一个排名。值相等的行会获得相同的排名,后续排名中不会出现间隔。 + +## 语法 {#syntax} + +```sql +DENSE_RANK() +OVER ( + [ PARTITION BY partition_expression ] + ORDER BY sort_expression [ ASC | DESC ] +) +``` + +**参数:** + +- `PARTITION BY`:可选。将行划分为多个分区 +- `ORDER BY`:必需。确定排名顺序 +- `ASC | DESC`:可选。排序方向(默认值:ASC) + +**说明:** + +- 排名从 1 开始 +- 相等的值会获得相同的排名 +- 并列之后的排名序列中不会出现间隔 +- 示例:1, 2, 2, 3, 4(而不是像 RANK 那样为 1, 2, 2, 4, 5) + +## 示例 {#examples} + +```sql +-- Create sample data +CREATE TABLE scores ( + student VARCHAR(20), + subject VARCHAR(20), + score INT +); + +INSERT INTO scores VALUES + ('Alice', 'Math', 95), + ('Alice', 'English', 87), + ('Alice', 'Science', 92), + ('Bob', 'Math', 85), + ('Bob', 'English', 85), + ('Bob', 'Science', 80), + ('Charlie', 'Math', 88), + ('Charlie', 'English', 85), + ('Charlie', 'Science', 85); +``` + +**对所有分数进行稠密排名(展示并列后无间隔):** + +```sql +SELECT student, subject, score, + DENSE_RANK() OVER (ORDER BY score DESC) AS dense_rank +FROM scores +ORDER BY score DESC, student, subject; +``` + +结果: + +``` +student | subject | score | dense_rank +--------+---------+-------+----------- +Alice | Math | 95 | 1 +Alice | Science | 92 | 2 +Charlie | Math | 88 | 3 +Alice | English | 87 | 4 +Bob | English | 85 | 5 +Bob | Math | 85 | 5 +Charlie | English | 85 | 5 +Charlie | Science | 85 | 5 +Bob | Science | 80 | 6 +``` + +**在每个学生内部对分数进行稠密排名:** + +```sql +SELECT student, subject, score, + DENSE_RANK() OVER (PARTITION BY student ORDER BY score DESC) AS subject_dense_rank +FROM scores +ORDER BY student, score DESC, subject; +``` + +结果: + +``` +student | subject | score | subject_dense_rank +--------+---------+-------+------------------- +Alice | Math | 95 | 1 +Alice | Science | 92 | 2 +Alice | English | 87 | 3 +Bob | English | 85 | 1 +Bob | Math | 85 | 1 +Bob | Science | 80 | 2 +Charlie | Math | 88 | 1 +Charlie | English | 85 | 2 +Charlie | Science | 85 | 2 +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/desc-connection.md b/tidb-cloud-lake/sql/desc-connection.md new file mode 100644 index 0000000000000..901c4c3a57776 --- /dev/null +++ b/tidb-cloud-lake/sql/desc-connection.md @@ -0,0 +1,26 @@ +--- +title: DESC CONNECTION +summary: 描述特定连接的详细信息,提供其类型和配置相关的信息。 +--- + +# DESC CONNECTION + +描述特定连接的详细信息,提供其类型和配置相关的信息。 + +## 语法 {#syntax} + +```sql +DESC CONNECTION +``` + +## 示例 {#examples} + +```sql +DESC CONNECTION toronto; + +┌────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ +│ name │ storage_type │ storage_params │ +├─────────┼──────────────┼───────────────────────────────────────────────────────────────────────────────────┤ +│ toronto │ s3 │ access_key_id= secret_access_key= │ +└────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/desc-masking-policy.md b/tidb-cloud-lake/sql/desc-masking-policy.md new file mode 100644 index 0000000000000..5fdadd68f4bb5 --- /dev/null +++ b/tidb-cloud-lake/sql/desc-masking-policy.md @@ -0,0 +1,49 @@ +--- +title: DESC MASKING POLICY +summary: 显示 {{{ .lake }}} 中特定 masking policy 的详细信息。 +--- + +# DESC MASKING POLICY + +显示 {{{ .lake }}} 中特定 masking policy 的详细信息。 + +## 语法 {#syntax} + +```sql +DESC MASKING POLICY +``` + +## 访问控制要求 {#access-control-requirements} + +| 权限 | 描述 | +|:----------|:------------| +| APPLY MASKING POLICY | 描述 masking policy 所必需的权限,除非你是该 policy 的所有者。 | + +满足此要求的条件包括:拥有全局 `APPLY MASKING POLICY` 权限,或者对特定 masking policy 拥有 APPLY/OWNERSHIP。 + +## 示例 {#examples} + +```sql +CREATE MASKING POLICY email_mask +AS + (val string) + RETURNS string -> + CASE + WHEN current_role() IN ('MANAGERS') THEN + val + ELSE + '*********' + END + COMMENT = 'hide_email'; + +DESC MASKING POLICY email_mask; + +Name |Value | +-----------+---------------------------------------------------------------------+ +Name |email_mask | +Created On |2023-08-09 02:29:16.177898 UTC | +Signature |(val STRING) | +Return Type|STRING | +Body |CASE WHEN current_role() IN('MANAGERS') THEN VAL ELSE '*********' END| +Comment |hide_email | +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/desc-network-policy.md b/tidb-cloud-lake/sql/desc-network-policy.md new file mode 100644 index 0000000000000..f87056aa55e4d --- /dev/null +++ b/tidb-cloud-lake/sql/desc-network-policy.md @@ -0,0 +1,24 @@ +--- +title: DESC NETWORK POLICY +summary: 显示 {{{ .lake }}} 中特定网络策略的详细信息。它会提供与该策略关联的允许和阻止 IP 地址列表,以及用于描述该策略用途或函数的注释(如果有)。 +--- + +# DESC NETWORK POLICY + +显示 {{{ .lake }}} 中特定网络策略的详细信息。它会提供与该策略关联的允许和阻止 IP 地址列表,以及用于描述该策略用途或函数的注释(如果有)。 + +## 语法 {#syntax} + +```sql +DESC NETWORK POLICY +``` + +## 示例 {#examples} + +```sql +DESC NETWORK POLICY test_policy; + +Name |Allowed Ip List |Blocked Ip List|Comment | +-----------+-------------------------+---------------+-----------+ +test_policy|192.168.10.0,192.168.20.0| |new comment| +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/desc-password-policy.md b/tidb-cloud-lake/sql/desc-password-policy.md new file mode 100644 index 0000000000000..9b0aee30a8c0e --- /dev/null +++ b/tidb-cloud-lake/sql/desc-password-policy.md @@ -0,0 +1,41 @@ +--- +title: DESC PASSWORD POLICY +summary: 显示 {{{ .lake }}} 中特定密码策略的详细信息。有关密码策略属性的详细说明,请参见 Password Policy Attributes。 +--- + +# DESC PASSWORD POLICY + +显示 {{{ .lake }}} 中特定密码策略的详细信息。有关密码策略属性的详细说明,请参见 [密码策略属性](/tidb-cloud-lake/sql/create-password-policy.md#password-policy-attributes)。 + +## 语法 {#syntax} + +```sql +DESC PASSWORD POLICY +``` + +## 示例 {#examples} + +```sql +CREATE PASSWORD POLICY SecureLogin + PASSWORD_MIN_LENGTH = 10; + +DESC PASSWORD POLICY SecureLogin; + +┌─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ +│ Property │ Value │ Default │ Description │ +├───────────────────────────────┼─────────────┼──────────────────┼────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤ +│ NAME │ SecureLogin │ NULL │ Name of password policy. │ +│ COMMENT │ │ NULL │ Comment of password policy. │ +│ PASSWORD_MIN_LENGTH │ 10 │ 8 │ Minimum length of new password. │ +│ PASSWORD_MAX_LENGTH │ 256 │ 256 │ Maximum length of new password. │ +│ PASSWORD_MIN_UPPER_CASE_CHARS │ 1 │ 1 │ Minimum number of uppercase characters in new password. │ +│ PASSWORD_MIN_LOWER_CASE_CHARS │ 1 │ 1 │ Minimum number of lowercase characters in new password. │ +│ PASSWORD_MIN_NUMERIC_CHARS │ 1 │ 1 │ Minimum number of numeric characters in new password. │ +│ PASSWORD_MIN_SPECIAL_CHARS │ 0 │ 0 │ Minimum number of special characters in new password. │ +│ PASSWORD_MIN_AGE_DAYS │ 0 │ 0 │ Period after a password is changed during which a password cannot be changed again, in days. │ +│ PASSWORD_MAX_AGE_DAYS │ 90 │ 90 │ Period after which password must be changed, in days. │ +│ PASSWORD_MAX_RETRIES │ 5 │ 5 │ Number of attempts users have to enter the correct password before their account is locked. │ +│ PASSWORD_LOCKOUT_TIME_MINS │ 15 │ 15 │ Period of time for which users will be locked after entering their password incorrectly many times (specified by MAX_RETRIES), in minutes. │ +│ PASSWORD_HISTORY │ 0 │ 0 │ Number of most recent passwords that may not be repeated by the user. │ +└─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/desc-procedure.md b/tidb-cloud-lake/sql/desc-procedure.md new file mode 100644 index 0000000000000..2c51042dd79bd --- /dev/null +++ b/tidb-cloud-lake/sql/desc-procedure.md @@ -0,0 +1,51 @@ +--- +title: DESC PROCEDURE +summary: 显示特定存储过程的详细信息。 +--- + +# DESC PROCEDURE + +显示特定存储过程的详细信息。 + +## 语法 {#syntax} + +```sql +DESC | DESCRIBE PROCEDURE ([, , ...]) +``` + +- 如果过程没有参数,请使用空括号:`DESC PROCEDURE ()`; +- 对于带参数的过程,请指定精确的类型以避免错误。 + +## 示例 {#examples} + +以下示例创建了一个名为 `sum_even_numbers` 的存储过程,然后显示其详细信息。 + +```sql +CREATE PROCEDURE sum_even_numbers(start_val UInt8, end_val UInt8) +RETURNS UInt8 NOT NULL +LANGUAGE SQL +COMMENT='Calculate the sum of all even numbers' +AS $$ +BEGIN + LET sum := 0; + FOR i IN start_val TO end_val DO + IF i % 2 = 0 THEN + sum := sum + i; + END IF; + END FOR; + + RETURN sum; +END; +$$; + +DESC PROCEDURE sum_even_numbers(Uint8, Uint8); + +┌────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ +│ Property │ Value │ +├───────────┼────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤ +│ signature │ (start_val,end_val) │ +│ returns │ (UInt8) │ +│ language │ SQL │ +│ body │ BEGIN\n LET sum := 0;\n FOR i IN start_val TO end_val DO\n IF i % 2 = 0 THEN\n sum := sum + i;\n END IF;\n END FOR;\n \n RETURN sum;\nEND; │ +└────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/desc-row-access-policy.md b/tidb-cloud-lake/sql/desc-row-access-policy.md new file mode 100644 index 0000000000000..fb5d152579f89 --- /dev/null +++ b/tidb-cloud-lake/sql/desc-row-access-policy.md @@ -0,0 +1,46 @@ +--- +title: DESC ROW ACCESS POLICY +summary: "显示 {{{ .lake }}} 中特定行访问策略的详细信息。" +--- + +# DESC ROW ACCESS POLICY + +显示 {{{ .lake }}} 中特定行访问策略的详细信息。 + +## 语法 {#syntax} + +```sql +DESC ROW ACCESS POLICY +``` + +也支持 `DESCRIBE ROW ACCESS POLICY`。 + +## 访问控制要求 {#access-control-requirements} + +| 权限 | 描述 | +|:----------|:------------| +| APPLY ROW ACCESS POLICY | 描述行访问策略时需要此权限,除非你是该策略的所有者。 | + +满足以下任一条件即可:具有全局 `APPLY ROW ACCESS POLICY` 权限,或对特定行访问策略具有 APPLY/OWNERSHIP。 + +## 示例 {#examples} + +```sql +SET enable_experimental_row_access_policy = 1; + +CREATE ROW ACCESS POLICY rap_engineering +AS (dept STRING) +RETURNS BOOLEAN -> + CASE + WHEN current_role() = 'admin' THEN true + WHEN dept = 'Engineering' THEN true + ELSE false + END + COMMENT = 'show engineering rows'; + +DESC ROW ACCESS POLICY rap_engineering; + +Name | Created On | Signature | Return Type | Body | Comment +----------------+-----------------------------+---------------+-------------+------------------------------------------------------------+---------------------- +rap_engineering | 2026-05-15 08:42:10.949 UTC | (dept STRING) | BOOLEAN | CASE WHEN current_role() = 'admin' THEN true WHEN... | show engineering rows +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/desc-sequence.md b/tidb-cloud-lake/sql/desc-sequence.md new file mode 100644 index 0000000000000..06a961d804352 --- /dev/null +++ b/tidb-cloud-lake/sql/desc-sequence.md @@ -0,0 +1,38 @@ +--- +title: DESC SEQUENCE +summary: 描述序列的属性。 +--- + +# DESC SEQUENCE + +描述序列的属性。 + +## 语法 {#syntax} + +```sql +DESC SEQUENCE +``` + +| 参数 | 描述 | +|----------------|-----------------------------------------------------------------------------------------------------------------------------| +| sequence_name | 要描述的序列名称。该命令会显示该序列的所有属性,包括起始值、间隔、当前值、创建时间戳、最后修改时间戳以及注释。 | + +## 示例 {#examples} + +```sql +-- Create a sequence +CREATE SEQUENCE seq; + +-- Use the sequence in an INSERT statement +CREATE TABLE tmp(a int, b uint64, c int); +INSERT INTO tmp select 10,nextval(seq),20 from numbers(3); + +-- Describe the sequence +DESC SEQUENCE seq; + +╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ +│ name │ start │ interval │ current │ created_on │ updated_on │ comment │ +├────────┼────────┼──────────┼─────────┼────────────────────────────┼────────────────────────────┼──────────────────┤ +│ seq │ 1 │ 1 │ 4 │ 2025-05-20 02:48:49.749338 │ 2025-05-20 02:49:14.302917 │ NULL │ +╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/desc-stage.md b/tidb-cloud-lake/sql/desc-stage.md new file mode 100644 index 0000000000000..462773ddf9090 --- /dev/null +++ b/tidb-cloud-lake/sql/desc-stage.md @@ -0,0 +1,30 @@ +--- +title: DESC STAGE +summary: 描述 stage 的属性。 +--- + +# DESC STAGE + +描述 stage 的属性。 + +## 语法 {#syntax} + +```sql +DESC STAGE +``` + +## 示例 {#examples} + +```sql +CREATE STAGE my_int_stage; +``` + +```sql +DESC STAGE my_int_stage; + +┌───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ +│ name │ stage_type │ storage_type │ url │ endpoint │ has_credentials │ has_encryption_key │ storage_params │ file_format_options │ creator │ created_on │ comment │ owner │ +├──────────────┼────────────┼──────────────┼──────┼──────────┼─────────────────┼────────────────────┼────────────────┼─────────────────────┼─────────┼────────────────────────────┼─────────┼───────────────┤ +│ my_int_stage │ Internal │ NULL │ NULL │ NULL │ false │ false │ NULL │ {"compression":...} │ root@% │ 2026-06-16 22:21:19.000000 │ │ account_admin │ +└───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/desc-stream.md b/tidb-cloud-lake/sql/desc-stream.md new file mode 100644 index 0000000000000..293a48b9a5a02 --- /dev/null +++ b/tidb-cloud-lake/sql/desc-stream.md @@ -0,0 +1,26 @@ +--- +title: DESC STREAM +summary: 描述特定 stream 的详细信息。 +--- + +# DESC STREAM + +描述特定 stream 的详细信息。 + +## 语法 {#syntax} + +```sql +DESC|DESCRIBE STREAM [ . ] +``` + +## 示例 {#examples} + +```sql +DESC STREAM books_stream_2023; + +┌───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ +│ created_on │ name │ database │ catalog │ table_on │ owner │ comment │ mode │ invalid_reason │ +├────────────────────────────┼───────────────────┼──────────┼─────────┼─────────────────────┼──────────────────┼─────────┼─────────────┼────────────────┤ +│ 2023-11-29 02:38:29.588518 │ books_stream_2023 │ default │ default │ default.books_total │ NULL │ │ append_only │ │ +└───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/desc-user.md b/tidb-cloud-lake/sql/desc-user.md new file mode 100644 index 0000000000000..67946eda01338 --- /dev/null +++ b/tidb-cloud-lake/sql/desc-user.md @@ -0,0 +1,44 @@ +--- +title: DESC USER +summary: 显示特定 SQL 用户的详细信息,包括认证类型、角色、网络策略、密码策略以及其他与用户相关的设置。 +--- + +# DESC USER + +显示特定 SQL 用户的详细信息,包括认证类型、角色、网络策略、密码策略以及其他与用户相关的设置。 + +## 语法 {#syntax} + +```sql +DESC[RIBE] USER +``` + +## 示例 {#examples} + +```sql +CREATE NETWORK POLICY my_network_policy ALLOWED_IP_LIST=('192.168.100.0/24'); + +CREATE PASSWORD POLICY my_password_policy + PASSWORD_MIN_LENGTH = 12 + PASSWORD_MAX_LENGTH = 24 + PASSWORD_MIN_UPPER_CASE_CHARS = 2 + PASSWORD_MIN_LOWER_CASE_CHARS = 2 + PASSWORD_MIN_NUMERIC_CHARS = 2 + PASSWORD_MIN_SPECIAL_CHARS = 2 + PASSWORD_MIN_AGE_DAYS = 1 + PASSWORD_MAX_AGE_DAYS = 30 + PASSWORD_MAX_RETRIES = 3 + PASSWORD_LOCKOUT_TIME_MINS = 30 + PASSWORD_HISTORY = 5 + COMMENT = 'test comment'; + +CREATE USER eric IDENTIFIED BY '123ABCabc$$123' WITH SET PASSWORD POLICY='my_password_policy', SET NETWORK POLICY='my_network_policy'; + +DESC USER eric; + +┌─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ +│ name │ hostname │ auth_type │ default_role │ roles │ disabled │ network_policy │ password_policy │ must_change_password │ +├────────┼──────────┼──────────────────────┼──────────────┼────────┼──────────┼───────────────────┼────────────────────┼──────────────────────┤ +│ eric │ % │ double_sha1_password │ │ │ false │ my_network_policy │ my_password_policy │ NULL │ +└─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/desc-view.md b/tidb-cloud-lake/sql/desc-view.md new file mode 100644 index 0000000000000..445c90aea07fa --- /dev/null +++ b/tidb-cloud-lake/sql/desc-view.md @@ -0,0 +1,65 @@ +--- +title: DESC VIEW +summary: 返回视图的列列表。 +--- + +# DESC VIEW + +返回视图的列列表。 + +## 语法 {#syntax} + +```sql +DESC[RIBE] VIEW [.] +``` + +## 输出 {#output} + +该命令会输出一个包含以下列的表: + +| 列名 | 描述 | +|---------|-------------------------------------------------------------------------------------------------------------------------| +| Field | 视图中列的名称。 | +| Type | 列的数据类型。 | +| Null | 指示该列是否允许 NULL 值(YES 表示允许 NULL,NO 表示不允许 NULL)。 | +| Default | 指定列的默认值。 | +| Extra | 提供有关该列的附加信息,例如它是否为计算列,或其他特殊属性。 | + +## 示例 {#examples} + +```sql +-- Create the employees table +CREATE TABLE employees ( + employee_id INT, + first_name VARCHAR(50), + last_name VARCHAR(50), + email VARCHAR(100), + hire_date DATE, + department_id INT +); + +-- Insert data into the employees table +INSERT INTO employees (employee_id, first_name, last_name, email, hire_date, department_id) +VALUES +(1, 'John', 'Doe', 'john@example.com', '2020-01-01', 101), +(2, 'Jane', 'Smith', 'jane@example.com', '2020-02-01', 102), +(3, 'Alice', 'Johnson', 'alice@example.com', '2020-03-01', 103); + +-- Create the employee_info view +CREATE VIEW employee_info AS +SELECT employee_id, CONCAT(first_name, ' ', last_name) AS full_name, email, hire_date, department_id +FROM employees; + +-- Describe the structure of the employee_info view +DESC employee_info; + +┌─────────────────────────────────────────────────────┐ +│ Field │ Type │ Null │ Default │ Extra │ +├───────────────┼─────────┼────────┼─────────┼────────┤ +│ employee_id │ INT │ YES │ NULL │ │ +│ full_name │ VARCHAR │ YES │ NULL │ │ +│ email │ VARCHAR │ YES │ NULL │ │ +│ hire_date │ DATE │ YES │ NULL │ │ +│ department_id │ INT │ YES │ NULL │ │ +└─────────────────────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/describe-notification-integration.md b/tidb-cloud-lake/sql/describe-notification-integration.md new file mode 100644 index 0000000000000..253142e9a7cb3 --- /dev/null +++ b/tidb-cloud-lake/sql/describe-notification-integration.md @@ -0,0 +1,30 @@ +--- +title: DESCRIBE NOTIFICATION INTEGRATION +summary: 显示通知集成的属性。 +--- + +# DESCRIBE NOTIFICATION INTEGRATION + +显示通知集成的属性。 + +> **Note:** +> +> 此命令要求启用 cloud control。 + +## 语法 {#syntax} + +```sql +DESCRIBE NOTIFICATION INTEGRATION +``` + +`DESC NOTIFICATION INTEGRATION ` 也可作为同义语法使用。 + +## 输出 {#output} + +结果包括通知的创建时间、名称、标识符、类型、启用状态、webhook 选项和注释。 + +## 示例 {#example} + +```sql +DESCRIBE NOTIFICATION INTEGRATION SampleNotification; +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/describe-pipe.md b/tidb-cloud-lake/sql/describe-pipe.md new file mode 100644 index 0000000000000..7a368cc320c2e --- /dev/null +++ b/tidb-cloud-lake/sql/describe-pipe.md @@ -0,0 +1,22 @@ +--- +title: DESCRIBE PIPE +summary: "了解如何使用 DESCRIBE PIPE 命令查看 {{{ .lake }}} 中摄取管道的属性。" +--- + +# DESCRIBE PIPE + +显示 pipe 的属性。 + +## 语法 {#syntax} + +```sql +DESCRIBE PIPE +``` + +`DESC PIPE ` 可作为同义写法。 + +## 示例 {#example} + +```sql +DESCRIBE PIPE my_pipe; +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/describe-table.md b/tidb-cloud-lake/sql/describe-table.md new file mode 100644 index 0000000000000..7493fb9237175 --- /dev/null +++ b/tidb-cloud-lake/sql/describe-table.md @@ -0,0 +1,37 @@ +--- +title: DESCRIBE TABLE +summary: 显示给定表中列的信息。等同于 SHOW FIELDS。 +--- + +# DESCRIBE TABLE + +显示给定表中列的信息。等同于 [SHOW FIELDS](/tidb-cloud-lake/sql/show-fields.md)。 + +> **Tip:** +> +> [SHOW COLUMNS](/tidb-cloud-lake/sql/show-columns.md) 提供类似功能,但会返回关于表列的更多信息。 + +## 语法 {#syntax} + +```sql +DESC|DESCRIBE [TABLE] [ . ] +``` + +## 示例 {#examples} + +```sql +CREATE TABLE books + ( + price FLOAT Default 0.00, + pub_time DATETIME Default '1900-01-01', + author VARCHAR + ); + +DESC books; + +Field |Type |Null|Default |Extra| +--------+---------+----+----------------------------+-----+ +price |FLOAT |YES |0 | | +pub_time|TIMESTAMP|YES |'1900-01-01 00:00:00.000000'| | +author |VARCHAR |YES |NULL | | +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/dictionary.md b/tidb-cloud-lake/sql/dictionary.md new file mode 100644 index 0000000000000..45f68c0d20684 --- /dev/null +++ b/tidb-cloud-lake/sql/dictionary.md @@ -0,0 +1,23 @@ +--- +title: 字典 +summary: 字典管理和信息命令概述。 +--- + +# 字典 + +字典提供了一种键值方式,用于从各种外部数据源(包括 MySQL 和 Redis)中读数据。 + +## 字典管理 {#dictionary-management} + +| 命令 | 描述 | +|---------|-------------| +| [CREATE DICTIONARY](/tidb-cloud-lake/sql/create-dictionary.md) | 创建字典 | +| [DROP DICTIONARY](/tidb-cloud-lake/sql/drop-dictionary.md) | 删除字典 | +| [RENAME DICTIONARY](/tidb-cloud-lake/sql/rename-dictionary.md) | 重命名字典 | + +## 字典信息 {#dictionary-information} + +| 命令 | 描述 | +|---------|-------------| +| [SHOW CREATE DICTIONARY](/tidb-cloud-lake/sql/show-create-dictionary.md) | 显示字典的 CREATE 语句 | +| [SHOW DICTIONARIES](/tidb-cloud-lake/sql/show-dictionaries.md) | 列出字典 | \ No newline at end of file diff --git a/tidb-cloud-lake/sql/div.md b/tidb-cloud-lake/sql/div.md new file mode 100644 index 0000000000000..3907820552d88 --- /dev/null +++ b/tidb-cloud-lake/sql/div.md @@ -0,0 +1,48 @@ +--- +title: DIV +summary: 返回将第一个数字除以第二个数字所得的商,并向下取整到最接近且更小的整数。等价于除法运算符 //。 +--- + +# DIV + +返回将第一个数字除以第二个数字所得的商,并向下取整到最接近且更小的整数。等价于除法运算符 `//`。 + +另请参阅: + +- [DIV0](/tidb-cloud-lake/sql/div0.md) +- [DIVNULL](/tidb-cloud-lake/sql/divnull.md) + +## 语法 {#syntax} + +```sql + DIV +``` + +## 别名 {#aliases} + +- [INTDIV](/tidb-cloud-lake/sql/intdiv.md) + +## 示例 {#examples} + +```sql +-- Equivalent to the division operator "//" +SELECT 6.1 DIV 2, 6.1//2; + +┌──────────────────────────┐ +│ (6.1 div 2) │ (6.1 // 2) │ +├─────────────┼────────────┤ +│ 3 │ 3 │ +└──────────────────────────┘ + +SELECT 6.1 DIV 2, INTDIV(6.1, 2), 6.1 DIV NULL; + +┌───────────────────────────────────────────────┐ +│ (6.1 div 2) │ intdiv(6.1, 2) │ (6.1 div null) │ +├─────────────┼────────────────┼────────────────┤ +│ 3 │ 3 │ NULL │ +└───────────────────────────────────────────────┘ + +-- Error when divided by 0 +root@localhost:8000/default> SELECT 6.1 DIV 0; +error: APIError: ResponseError with 1006: divided by zero while evaluating function `div(6.1, 0)` +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/div0.md b/tidb-cloud-lake/sql/div0.md new file mode 100644 index 0000000000000..8b9574d49ed28 --- /dev/null +++ b/tidb-cloud-lake/sql/div0.md @@ -0,0 +1,34 @@ +--- +title: DIV0 +summary: 返回将第一个数字除以第二个数字所得的商。如果第二个数字为 0,则返回 0。 +--- + +# DIV0 + +返回将第一个数字除以第二个数字所得的商。如果第二个数字为 0,则返回 0。 + +另请参阅: + +- [DIV](/tidb-cloud-lake/sql/div.md) +- [DIVNULL](/tidb-cloud-lake/sql/divnull.md) + +## 语法 {#syntax} + +```sql +DIV0(, ) +``` + +## 示例 {#examples} + +```sql +SELECT + DIV0(20, 6), + DIV0(20, 0), + DIV0(20, NULL); + +┌───────────────────────────────────────────────────┐ +│ div0(20, 6) │ div0(20, 0) │ div0(20, null) │ +├────────────────────┼─────────────┼────────────────┤ +│ 3.3333333333333335 │ 0 │ NULL │ +└───────────────────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/divnull.md b/tidb-cloud-lake/sql/divnull.md new file mode 100644 index 0000000000000..d007290bed712 --- /dev/null +++ b/tidb-cloud-lake/sql/divnull.md @@ -0,0 +1,34 @@ +--- +title: DIVNULL +summary: 将第一个数字除以第二个数字并返回商。如果第二个数字为 0 或 NULL,则返回 NULL。 +--- + +# DIVNULL + +将第一个数字除以第二个数字并返回商。如果第二个数字为 0 或 NULL,则返回 NULL。 + +另请参阅: + +- [DIV](/tidb-cloud-lake/sql/div.md) +- [DIV0](/tidb-cloud-lake/sql/div0.md) + +## 语法 {#syntax} + +```sql +DIVNULL(, ) +``` + +## 示例 {#examples} + +```sql +SELECT + DIVNULL(20, 6), + DIVNULL(20, 0), + DIVNULL(20, NULL); + +┌─────────────────────────────────────────────────────────┐ +│ divnull(20, 6) │ divnull(20, 0) │ divnull(20, null) │ +├────────────────────┼────────────────┼───────────────────┤ +│ 3.3333333333333335 │ NULL │ NULL │ +└─────────────────────────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/dml.md b/tidb-cloud-lake/sql/dml.md new file mode 100644 index 0000000000000..b77b595f9d879 --- /dev/null +++ b/tidb-cloud-lake/sql/dml.md @@ -0,0 +1,26 @@ +--- +title: DML(数据操作语言)命令 +summary: 本页提供 {{{ .lake }}} 中 DML(数据操作语言)命令的参考信息。 +--- + +# DML(数据操作语言)命令 + +本页提供 {{{ .lake }}} 中 DML(数据操作语言)命令的参考信息。 + +## 数据修改 {#data-modification} + +| 命令 | 描述 | +|---------|-------------| +| **[INSERT](/tidb-cloud-lake/sql/insert.md)** | 向表中添加新行 | +| **[INSERT MULTI](/tidb-cloud-lake/sql/insert-multi-table.md)** | 在一条语句中向多个表插入数据 | +| **[UPDATE](/tidb-cloud-lake/sql/update.md)** | 修改表中的现有行 | +| **[DELETE](/tidb-cloud-lake/sql/delete.md)** | 从表中删除行 | +| **[REPLACE](/tidb-cloud-lake/sql/replace.md)** | 插入新行或修改现有行 | +| **[MERGE](/tidb-cloud-lake/sql/merge.md)** | 根据条件执行 upsert 操作 | + +## 数据加载与导出 {#data-loading-export} + +| 命令 | 描述 | +|---------|-------------| +| **[COPY INTO Table](/tidb-cloud-lake/sql/copy-into-table.md)** | 将文件中的数据加载到表中 | +| **[COPY INTO Location](/tidb-cloud-lake/sql/copy-into-location.md)** | 将表数据导出到文件 | \ No newline at end of file diff --git a/tidb-cloud-lake/sql/drop-aggregating-index.md b/tidb-cloud-lake/sql/drop-aggregating-index.md new file mode 100644 index 0000000000000..2f12dec9f4811 --- /dev/null +++ b/tidb-cloud-lake/sql/drop-aggregating-index.md @@ -0,0 +1,22 @@ +--- +title: DROP AGGREGATING INDEX +summary: 删除现有的聚合索引。请注意,删除聚合索引并不会移除关联的存储块。若要同时删除这些块,请使用 VACUUM TABLE 命令。若要禁用聚合索引功能,请将 enable_aggregating_index_scan 设置为 0。 +--- + +# DROP AGGREGATING INDEX + +删除现有的聚合索引。请注意,删除聚合索引并不会移除关联的存储块。若要同时删除这些块,请使用 [VACUUM TABLE](/tidb-cloud-lake/sql/vacuum-table.md) 命令。若要禁用聚合索引功能,请将 `enable_aggregating_index_scan` 设置为 0。 + +## 语法 {#syntax} + +```sql +DROP AGGREGATING INDEX +``` + +## 示例 {#examples} + +以下示例删除了一个名为 *my_agg_index* 的聚合索引: + +```sql +DROP AGGREGATING INDEX my_agg_index; +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/drop-cluster-key.md b/tidb-cloud-lake/sql/drop-cluster-key.md new file mode 100644 index 0000000000000..4f984fc074020 --- /dev/null +++ b/tidb-cloud-lake/sql/drop-cluster-key.md @@ -0,0 +1,24 @@ +--- +title: DROP CLUSTER KEY +summary: 删除表的 cluster key。 +--- + +# DROP CLUSTER KEY + +删除表的 cluster key。 + +另请参阅:[ALTER CLUSTER KEY](/tidb-cloud-lake/sql/alter-cluster-key.md) + +## 语法 {#syntax} + +```sql +ALTER TABLE [ IF EXISTS ] DROP CLUSTER KEY +``` + +## 示例 {#examples} + +此命令会删除表 *test* 的 cluster key: + +```sql +ALTER TABLE test DROP CLUSTER KEY +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/drop-connection.md b/tidb-cloud-lake/sql/drop-connection.md new file mode 100644 index 0000000000000..6cb7998f237de --- /dev/null +++ b/tidb-cloud-lake/sql/drop-connection.md @@ -0,0 +1,20 @@ +--- +title: DROP CONNECTION +summary: 删除一个现有连接。 +--- + +# DROP CONNECTION + +删除一个现有连接。 + +## 语法 {#syntax} + +```sql +DROP CONNECTION [ IF EXISTS ] +``` + +## 示例 {#examples} + +```sql +DROP CONNECTION toronto; +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/drop-database.md b/tidb-cloud-lake/sql/drop-database.md new file mode 100644 index 0000000000000..9e57aff586947 --- /dev/null +++ b/tidb-cloud-lake/sql/drop-database.md @@ -0,0 +1,36 @@ +--- +title: DROP DATABASE +summary: 删除一个数据库。 +--- + +# DROP DATABASE + +删除一个数据库。 + +另请参阅:[UNDROP DATABASE](/tidb-cloud-lake/sql/undrop-database.md) + +## 语法 {#syntax} + +```sql +DROP { DATABASE | SCHEMA } [ IF EXISTS ] +``` + +`DROP SCHEMA` 是 `DROP DATABASE` 的同义词。 + +## 示例 {#examples} + +以下示例先创建一个名为 "orders_2024" 的数据库,然后将其删除: + +```sql +root@localhost:8000/default> CREATE DATABASE orders_2024; + +CREATE DATABASE orders_2024 + +0 row written in 0.014 sec. Processed 0 row, 0 B (0 row/s, 0 B/s) + +root@localhost:8000/default> DROP DATABASE orders_2024; + +DROP DATABASE orders_2024 + +0 row written in 0.012 sec. Processed 0 row, 0 B (0 row/s, 0 B/s) +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/drop-dictionary.md b/tidb-cloud-lake/sql/drop-dictionary.md new file mode 100644 index 0000000000000..5bd75330bae26 --- /dev/null +++ b/tidb-cloud-lake/sql/drop-dictionary.md @@ -0,0 +1,31 @@ +--- +title: DROP DICTIONARY +summary: 删除一个字典。 +--- + +# DROP DICTIONARY + +删除一个字典。 + +## 语法 {#syntax} + +```sql +DROP DICTIONARY [ IF EXISTS ] [ . ][ . ] +``` + +## 参数 {#parameters} + +| 参数 | 描述 | +|-----------|-------------| +| `IF EXISTS` | 可选。如果字典不存在,则抑制报错。 | +| `` | 字典名称。你可以使用 catalog 和 database 名称对其进行限定。 | + +## 示例 {#examples} + +```sql +DROP DICTIONARY user_info; +``` + +```sql +DROP DICTIONARY IF EXISTS default.user_info; +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/drop-file-format.md b/tidb-cloud-lake/sql/drop-file-format.md new file mode 100644 index 0000000000000..336a0754bcd1a --- /dev/null +++ b/tidb-cloud-lake/sql/drop-file-format.md @@ -0,0 +1,20 @@ +--- +title: DROP FILE FORMAT +summary: 删除一个文件格式。 +--- + +# DROP FILE FORMAT + +删除一个文件格式。 + +## 语法 {#syntax} + +```sql +DROP FILE FORMAT [ IF EXISTS ] ; +``` + +## 示例 {#examples} + +```sql +DROP FILE FORMAT IF EXISTS my_custom_csv; +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/drop-function-sql.md b/tidb-cloud-lake/sql/drop-function-sql.md new file mode 100644 index 0000000000000..e6dd117ee9ecf --- /dev/null +++ b/tidb-cloud-lake/sql/drop-function-sql.md @@ -0,0 +1,23 @@ +--- +title: DROP FUNCTION +summary: 删除一个外部函数。 +--- + +# DROP FUNCTION + +删除一个外部函数。 + +## 语法 {#syntax} + +```sql +DROP FUNCTION [ IF EXISTS ] +``` + +## 示例 {#examples} + +```sql +DROP FUNCTION a_plus_3; + +SELECT a_plus_3(2); +ERROR 1105 (HY000): Code: 2602, Text = Unknown Function a_plus_3 (while in analyze select projection). +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/drop-function.md b/tidb-cloud-lake/sql/drop-function.md new file mode 100644 index 0000000000000..ca90228911484 --- /dev/null +++ b/tidb-cloud-lake/sql/drop-function.md @@ -0,0 +1,67 @@ +--- +title: DROP FUNCTION +summary: 删除用户定义函数。适用于所有函数类型:Scalar SQL、Tabular SQL 和 Embedded functions。 +--- + +# DROP FUNCTION + +删除用户定义函数。适用于所有函数类型:Scalar SQL、Tabular SQL 和 Embedded functions。 + +## 语法 {#syntax} + +```sql +DROP FUNCTION [ IF EXISTS ] +``` + +## 示例 {#examples} + +### 删除 Scalar SQL 函数 {#dropping-scalar-sql-function} + +```sql +-- Create a scalar function +CREATE FUNCTION calculate_bmi(weight FLOAT, height FLOAT) +RETURNS FLOAT +AS $$ weight / (height * height) $$; + +-- Drop the function +DROP FUNCTION calculate_bmi; +``` + +### 删除 Tabular SQL 函数 {#dropping-tabular-sql-function} + +```sql +-- Create a table function +CREATE FUNCTION get_employees_by_dept(dept_name VARCHAR) +RETURNS TABLE (id INT, name VARCHAR, department VARCHAR) +AS $$ SELECT id, name, department FROM employees WHERE department = dept_name $$; + +-- Drop the function +DROP FUNCTION get_employees_by_dept; +``` + +### 删除 Embedded 函数 {#dropping-embedded-function} + +```sql +-- Create a Python function +CREATE FUNCTION custom_hash(input_str VARCHAR) +RETURNS VARCHAR +LANGUAGE python +HANDLER = 'hash_func' +AS $$ +import hashlib +def hash_func(s): + return hashlib.md5(s.encode()).hexdigest() +$$; + +-- Drop the function +DROP FUNCTION custom_hash; +``` + +### 使用 IF EXISTS {#using-if-exists} + +```sql +-- Safe drop - won't error if function doesn't exist +DROP FUNCTION IF EXISTS non_existent_function; + +-- This will succeed without error even if the function doesn't exist +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/drop-inverted-index.md b/tidb-cloud-lake/sql/drop-inverted-index.md new file mode 100644 index 0000000000000..82a1b13012eaa --- /dev/null +++ b/tidb-cloud-lake/sql/drop-inverted-index.md @@ -0,0 +1,21 @@ +--- +title: DROP INVERTED INDEX +summary: 删除 {{{ .lake }}} 中的倒排索引。 +--- + +# DROP INVERTED INDEX + +删除 {{{ .lake }}} 中的倒排索引。 + +## 语法 {#syntax} + +```sql +DROP INVERTED INDEX [IF EXISTS] ON [.]
+``` + +## 示例 {#examples} + +```sql +-- Drop the inverted index 'customer_feedback_idx' on the 'customer_feedback' table +DROP INVERTED INDEX customer_feedback_idx ON customer_feedback; +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/drop-masking-policy.md b/tidb-cloud-lake/sql/drop-masking-policy.md new file mode 100644 index 0000000000000..a9ca818082151 --- /dev/null +++ b/tidb-cloud-lake/sql/drop-masking-policy.md @@ -0,0 +1,40 @@ +--- +title: DROP MASKING POLICY +summary: 从 {{{ .lake }}} 中删除现有的 masking policy。删除 masking policy 后,它会从 {{{ .lake }}} 中移除,并且与其关联的 masking 规则将不再生效。请注意,在删除 masking policy 之前,请确保该策略未与任何列关联。 +--- + +# DROP MASKING POLICY + +从 {{{ .lake }}} 中删除现有的 masking policy。删除 masking policy 后,它会从 {{{ .lake }}} 中移除,并且与其关联的 masking 规则将不再生效。请注意,在删除 masking policy 之前,请确保该策略未与任何列关联。 + +## 语法 {#syntax} + +```sql +DROP MASKING POLICY [ IF EXISTS ] +``` + +## 访问控制要求 {#access-control-requirements} + +| 权限 | 描述 | +|:----------|:------------| +| APPLY MASKING POLICY | 删除 masking policy 所需的权限,除非你拥有该策略。 | + +你必须具有全局 `APPLY MASKING POLICY` 权限,或者对目标策略具有 APPLY/OWNERSHIP。删除策略后,{{{ .lake }}} 会自动从创建者角色回收 OWNERSHIP。 + +## 示例 {#examples} + +```sql +CREATE MASKING POLICY email_mask +AS + (val string) + RETURNS string -> + CASE + WHEN current_role() IN ('MANAGERS') THEN + val + ELSE + '*********' + END + COMMENT = 'hide_email'; + +DROP MASKING POLICY email_mask; +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/drop-network-policy.md b/tidb-cloud-lake/sql/drop-network-policy.md new file mode 100644 index 0000000000000..55d073ccac8c1 --- /dev/null +++ b/tidb-cloud-lake/sql/drop-network-policy.md @@ -0,0 +1,20 @@ +--- +title: DROP NETWORK POLICY +summary: 从 {{{ .lake }}} 中删除现有的网络策略。删除网络策略后,该策略会从 {{{ .lake }}} 中移除,其关联的允许和阻止 IP 地址列表规则也将不再生效。请注意,在删除网络策略之前,请确保该策略未与任何用户关联。 +--- + +# DROP NETWORK POLICY + +从 {{{ .lake }}} 中删除现有的网络策略。删除网络策略后,该策略会从 {{{ .lake }}} 中移除,其关联的允许和阻止 IP 地址列表规则也将不再生效。请注意,在删除网络策略之前,请确保该策略未与任何用户关联。 + +## 语法 {#syntax} + +```sql +DROP NETWORK POLICY [ IF EXISTS ] +``` + +## 示例 {#examples} + +```sql +DROP NETWORK POLICY test_policy +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/drop-ngram-index.md b/tidb-cloud-lake/sql/drop-ngram-index.md new file mode 100644 index 0000000000000..f8e46dce3dfc7 --- /dev/null +++ b/tidb-cloud-lake/sql/drop-ngram-index.md @@ -0,0 +1,23 @@ +--- +title: DROP NGRAM INDEX +summary: 从表中删除现有的 NGRAM 索引。 +--- + +# DROP NGRAM INDEX + +从表中删除现有的 NGRAM 索引。 + +## 语法 {#syntax} + +```sql +DROP NGRAM INDEX [IF EXISTS] +ON [.]; +``` + +## 示例 {#examples} + +以下示例从 `amazon_reviews_ngram` 表中删除 `idx1` 索引: + +```sql +DROP NGRAM INDEX idx1 ON amazon_reviews_ngram; +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/drop-notification-integration.md b/tidb-cloud-lake/sql/drop-notification-integration.md new file mode 100644 index 0000000000000..e5b0fee899080 --- /dev/null +++ b/tidb-cloud-lake/sql/drop-notification-integration.md @@ -0,0 +1,29 @@ +--- +title: DROP NOTIFICATION INTEGRATION +summary: DROP NOTIFICATION INTEGRATION 语句用于删除现有通知。 +--- + +# DROP NOTIFICATION INTEGRATION + +`DROP NOTIFICATION INTEGRATION` 语句用于删除现有通知。 + +**注意:** 此功能开箱即用仅适用于 {{{ .lake }}}。 + +## 语法 {#syntax} + +```sql +DROP NOTIFICATION INTEGRATION [ IF EXISTS ] +``` + +| 参数 | 描述 | +|----------------------------------|------------------------------------------------------------------------------------------------------| +| IF EXISTS | 可选。如果指定,只有在已存在同名通知时,才会删除该通知。 | +| name | 通知的名称。这是必填字段。 | + +## 使用示例 {#usage-examples} + +```sql +DROP NOTIFICATION INTEGRATION IF EXISTS error_notification; +``` + +此命令会在 `error_notification` 存在时删除名为 `error_notification` 的通知集成。 \ No newline at end of file diff --git a/tidb-cloud-lake/sql/drop-password-policy.md b/tidb-cloud-lake/sql/drop-password-policy.md new file mode 100644 index 0000000000000..3c13afbbe2737 --- /dev/null +++ b/tidb-cloud-lake/sql/drop-password-policy.md @@ -0,0 +1,23 @@ +--- +title: DROP PASSWORD POLICY +summary: 从 {{{ .lake }}} 中删除现有的密码策略。请注意,在删除密码策略之前,请确保该策略未与任何用户关联。 +--- + +# DROP PASSWORD POLICY + +从 {{{ .lake }}} 中删除现有的密码策略。请注意,在删除密码策略之前,请确保该策略未与任何用户关联。 + +## 语法 {#syntax} + +```sql +DROP PASSWORD POLICY [ IF EXISTS ] +``` + +## 示例 {#examples} + +```sql +CREATE PASSWORD POLICY SecureLogin + PASSWORD_MIN_LENGTH = 10; + +DROP PASSWORD POLICY SecureLogin; +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/drop-pipe.md b/tidb-cloud-lake/sql/drop-pipe.md new file mode 100644 index 0000000000000..57e95c0ae72c2 --- /dev/null +++ b/tidb-cloud-lake/sql/drop-pipe.md @@ -0,0 +1,20 @@ +--- +title: DROP PIPE +summary: "了解如何使用 DROP PIPE 命令删除 {{{ .lake }}} 中的数据摄取管道。" +--- + +# DROP PIPE + +删除一个管道。 + +## 语法 {#syntax} + +```sql +DROP PIPE [ IF EXISTS ] +``` + +## 示例 {#example} + +```sql +DROP PIPE IF EXISTS my_pipe; +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/drop-procedure.md b/tidb-cloud-lake/sql/drop-procedure.md new file mode 100644 index 0000000000000..40349757c124b --- /dev/null +++ b/tidb-cloud-lake/sql/drop-procedure.md @@ -0,0 +1,35 @@ +--- +title: DROP PROCEDURE +summary: 删除现有的存储过程。 +--- + +# DROP PROCEDURE + +删除现有的存储过程。 + +## 语法 {#syntax} + +```sql +DROP PROCEDURE ([, , ...]) +``` + +- 如果存储过程没有参数,请使用空括号:`DROP PROCEDURE ()`; +- 对于带参数的存储过程,请指定精确的类型以避免错误。 + +## 示例 {#examples} + +以下示例先创建一个存储过程,然后将其删除: + +```sql +CREATE PROCEDURE convert_kg_to_lb(kg DECIMAL(4, 2)) +RETURNS DECIMAL(10, 2) +LANGUAGE SQL +COMMENT = 'Converts kilograms to pounds' +AS $$ +BEGIN + RETURN kg * 2.20462; +END; +$$; + +DROP PROCEDURE convert_kg_to_lb(Decimal(4, 2)); +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/drop-role.md b/tidb-cloud-lake/sql/drop-role.md new file mode 100644 index 0000000000000..9f4df5347253e --- /dev/null +++ b/tidb-cloud-lake/sql/drop-role.md @@ -0,0 +1,24 @@ +--- +title: DROP ROLE +summary: 从系统中移除指定的角色。 +--- + +# DROP ROLE + +从系统中移除指定的角色。 + +## 语法 {#syntax} + +```sql +DROP ROLE [ IF EXISTS ] +``` + +## 使用说明 {#usage-notes} + +* 如果某个角色已授予给用户,{{{ .lake }}} 无法自动删除该角色上的授权。 + +## 示例 {#examples} + +```sql +DROP ROLE role1; +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/drop-row-access-policy.md b/tidb-cloud-lake/sql/drop-row-access-policy.md new file mode 100644 index 0000000000000..4d554a59ad204 --- /dev/null +++ b/tidb-cloud-lake/sql/drop-row-access-policy.md @@ -0,0 +1,40 @@ +--- +title: DROP ROW ACCESS POLICY +summary: "从 {{{ .lake }}} 中删除现有的行访问策略。在删除策略之前,请先将其从所有引用该策略的表中解绑。" +--- + +# DROP ROW ACCESS POLICY + +从 {{{ .lake }}} 中删除现有的行访问策略。在删除策略之前,请先将其从所有引用该策略的表中解绑。 + +## 语法 {#syntax} + +```sql +DROP ROW ACCESS POLICY [ IF EXISTS ] +``` + +## 访问控制要求 {#access-control-requirements} + +| 权限 | 说明 | +|:----------|:------------| +| APPLY ROW ACCESS POLICY | 删除行访问策略所需的权限,除非你拥有该策略。 | + +你必须具有全局 `APPLY ROW ACCESS POLICY` 权限,或者对目标策略具有 APPLY/OWNERSHIP。策略被删除后,{{{ .lake }}} 会自动从创建者角色回收 OWNERSHIP。 + +## 示例 {#examples} + +```sql +SET enable_experimental_row_access_policy = 1; + +CREATE ROW ACCESS POLICY rap_engineering +AS (dept STRING) +RETURNS BOOLEAN -> dept = 'Engineering'; + +CREATE TABLE employees(id INT, department STRING); +ALTER TABLE employees ADD ROW ACCESS POLICY rap_engineering ON (department); + +-- Detach the policy before dropping it. +ALTER TABLE employees DROP ROW ACCESS POLICY rap_engineering; + +DROP ROW ACCESS POLICY rap_engineering; +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/drop-sequence.md b/tidb-cloud-lake/sql/drop-sequence.md new file mode 100644 index 0000000000000..a52839f18cd47 --- /dev/null +++ b/tidb-cloud-lake/sql/drop-sequence.md @@ -0,0 +1,25 @@ +--- +title: DROP SEQUENCE +summary: 从 {{{ .lake }}} 中删除现有的 sequence。 +--- + +# DROP SEQUENCE + +从 {{{ .lake }}} 中删除现有的 sequence。 + +## 语法 {#syntax} + +```sql +DROP SEQUENCE [IF EXISTS] +``` + +| 参数 | 描述 | +|--------------|-----------------------------------------| +| `` | 要删除的 sequence 的名称。 | + +## 示例 {#examples} + +```sql +-- Delete a sequence named staff_id_seq +DROP SEQUENCE staff_id_seq; +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/drop-snapshot-tag.md b/tidb-cloud-lake/sql/drop-snapshot-tag.md new file mode 100644 index 0000000000000..6f14a70c369da --- /dev/null +++ b/tidb-cloud-lake/sql/drop-snapshot-tag.md @@ -0,0 +1,42 @@ +--- +title: DROP SNAPSHOT TAG +summary: 从 FUSE 表中删除一个已命名的快照标签;如果没有其他标签或保留策略对其进行保护,则该标签引用的快照可以被垃圾回收。 +--- + +# DROP SNAPSHOT TAG + +从 FUSE 表中删除一个已命名的快照标签。删除后,如果没有其他标签或保留策略对其进行保护,则该标签引用的快照将可以被垃圾回收。 + +> **Note:** +> +> - 这是一个**实验性**功能。使用前请先启用:`SET enable_experimental_table_ref = 1;`。 +> - 仅支持 FUSE 引擎表。 + +## 语法 {#syntax} + +```sql +ALTER TABLE [.] DROP TAG +``` + +## 参数 {#parameters} + +| 参数 | 描述 | +|-----------|-------------| +| tag_name | 要删除的快照标签名称。如果该标签不存在,则会返回错误。 | + +## 示例 {#examples} + +```sql +SET enable_experimental_table_ref = 1; + +CREATE TABLE t1(a INT, b STRING); +INSERT INTO t1 VALUES (1, 'a'), (2, 'b'); + +-- Create and then drop a tag +ALTER TABLE t1 CREATE TAG v1_0; +ALTER TABLE t1 DROP TAG v1_0; + +-- Querying a dropped tag returns an error +SELECT * FROM t1 AT (TAG => v1_0); +-- Error: tag 'v1_0' not found +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/drop-spatial-index.md b/tidb-cloud-lake/sql/drop-spatial-index.md new file mode 100644 index 0000000000000..47454efd78afc --- /dev/null +++ b/tidb-cloud-lake/sql/drop-spatial-index.md @@ -0,0 +1,27 @@ +--- +title: DROP SPATIAL INDEX +summary: "删除 {{{ .lake }}} 中的空间索引。" +--- + +# DROP SPATIAL INDEX + +删除 {{{ .lake }}} 中的空间索引。 + +## 语法 {#syntax} + +```sql +DROP SPATIAL INDEX [IF EXISTS] ON [.]
+``` + +## 示例 {#examples} + +```sql +CREATE TABLE stores ( + store_id INT, + store_name STRING, + location GEOMETRY, + SPATIAL INDEX location_idx (location) +) ENGINE = FUSE; + +DROP SPATIAL INDEX location_idx ON stores; +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/drop-stage.md b/tidb-cloud-lake/sql/drop-stage.md new file mode 100644 index 0000000000000..8f201efbbab32 --- /dev/null +++ b/tidb-cloud-lake/sql/drop-stage.md @@ -0,0 +1,20 @@ +--- +title: DROP STAGE +summary: 删除一个 stage。 +--- + +# DROP STAGE + +删除一个 stage。 + +## 语法 {#syntax} + +```sql +DROP STAGE [ IF EXISTS ] ; +``` + +## 示例 {#examples} + +```sql +DROP STAGE IF EXISTS test_stage; +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/drop-stream.md b/tidb-cloud-lake/sql/drop-stream.md new file mode 100644 index 0000000000000..50dcb5b5398d7 --- /dev/null +++ b/tidb-cloud-lake/sql/drop-stream.md @@ -0,0 +1,20 @@ +--- +title: DROP STREAM +summary: 删除现有的 stream。 +--- + +# DROP STREAM + +删除现有的 stream。 + +## 语法 {#syntax} + +```sql +DROP STREAM [ IF EXISTS ] [ . ] +``` + +## 示例 {#examples} + +```sql +DROP STREAM books_stream_2023; +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/drop-table.md b/tidb-cloud-lake/sql/drop-table.md new file mode 100644 index 0000000000000..7d50215f7ba6b --- /dev/null +++ b/tidb-cloud-lake/sql/drop-table.md @@ -0,0 +1,57 @@ +--- +title: DROP TABLE +summary: 删除表。 +--- + +# DROP TABLE + +删除表。 + +**另请参阅:** + +- [CREATE TABLE](/tidb-cloud-lake/sql/create-table.md) +- [UNDROP TABLE](/tidb-cloud-lake/sql/undrop-table.md) +- [TRUNCATE TABLE](/tidb-cloud-lake/sql/truncate-table.md) + +## 语法 {#syntax} + +```sql +DROP TABLE [ IF EXISTS ] [ . ] +``` + +此命令仅在元信息服务中将表结构标记为已删除,以确保实际数据保持不变。如果你需要恢复已删除的表结构,可以使用 [UNDROP TABLE](/tidb-cloud-lake/sql/undrop-table.md) 命令。 + +如果要连同数据文件一起彻底删除表,请考虑使用 [VACUUM DROP TABLE](/tidb-cloud-lake/sql/vacuum-drop-table.md) 命令。 + +## 示例 {#examples} + +### 删除表 {#deleting-a-table} + +本示例展示了如何使用 DROP TABLE 命令删除 `"test"` 表。删除该表后,任何对其执行 SELECT 的尝试都会返回 `"Unknown table"` 错误。该示例还演示了如何使用 UNDROP TABLE 命令恢复已删除的 `"test"` 表,从而可以再次对其执行 SELECT 查询。 + +```sql +CREATE TABLE test(a INT, b VARCHAR); +INSERT INTO test (a, b) VALUES (1, 'example'); +SELECT * FROM test; + +a|b | +-+-------+ +1|example| + +-- Delete the table +DROP TABLE test; +SELECT * FROM test; +>> SQL Error [1105] [HY000]: UnknownTable. Code: 1025, Text = error: + --> SQL:1:80 + | +1 | /* ApplicationName=DBeaver 23.2.0 - SQLEditor */ SELECT * FROM test + | ^^^^ Unknown table `default`.`test` in catalog 'default' + +-- Recover the table +UNDROP TABLE test; +SELECT * FROM test; + +a|b | +-+-------+ +1|example| +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/drop-tag.md b/tidb-cloud-lake/sql/drop-tag.md new file mode 100644 index 0000000000000..04e858f09a030 --- /dev/null +++ b/tidb-cloud-lake/sql/drop-tag.md @@ -0,0 +1,36 @@ +--- +title: DROP TAG +summary: 删除一个标签。如果某个对象仍在引用该标签,则无法删除。 +--- + +# DROP TAG + +删除一个标签。如果某个对象仍在引用该标签,则无法删除——你必须先从所有对象中取消设置该标签,或删除这些对象。 + +另请参阅:[CREATE TAG](/tidb-cloud-lake/sql/create-tag.md)、[SET TAG / UNSET TAG](/tidb-cloud-lake/sql/set-tag.md)。 + +## 语法 {#syntax} + +```sql +DROP TAG [ IF EXISTS ] +``` + +## 示例 {#examples} + +```sql +-- Fails if the tag is still in use +DROP TAG env; +-- Error: Tag 'env' still has references + +-- Remove the tag reference first +ALTER TABLE my_table UNSET TAG env; + +-- Now it succeeds +DROP TAG env; +``` + +仅当标签存在时才删除该标签: + +```sql +DROP TAG IF EXISTS env; +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/drop-task.md b/tidb-cloud-lake/sql/drop-task.md new file mode 100644 index 0000000000000..73455a6a39284 --- /dev/null +++ b/tidb-cloud-lake/sql/drop-task.md @@ -0,0 +1,34 @@ +--- +title: DROP TASK +summary: DROP TASK 语句用于删除现有任务。 +--- + +# DROP TASK + +`DROP TASK` 语句用于删除现有任务。 + +**注意:** 此功能默认仅在 {{{ .lake }}} 中开箱即用。 + +## 语法 {#syntax} + +```sql +DROP TASK [ IF EXISTS ] +``` + +| 参数 | 描述 | +|----------------------------------|----------------------------------------------------------------------------------------------| +| IF EXISTS | 可选。如果指定了该参数,则仅当已存在同名任务时才会删除该任务。 | +| name | 任务名称。这是必填字段。 | + +## 使用说明 {#usage-notes} + +- 如果删除了 DAG 中的前驱任务,则所有将该任务标识为前驱任务的原子任务会变为独立任务或根任务,具体取决于是否还有其他任务将这些原子任务标识为其前驱任务。这些原子任务默认会被挂起,必须手动恢复。 +- 在执行 DROP 之前,必须先挂起 Root Task。 + +## 使用示例 {#usage-examples} + +```sql +DROP TASK IF EXISTS mytask; +``` + +如果任务 `mytask` 存在,此命令会将其删除。 \ No newline at end of file diff --git a/tidb-cloud-lake/sql/drop-user.md b/tidb-cloud-lake/sql/drop-user.md new file mode 100644 index 0000000000000..c581cec57a8e4 --- /dev/null +++ b/tidb-cloud-lake/sql/drop-user.md @@ -0,0 +1,20 @@ +--- +title: DROP USER +summary: 从系统中删除指定的用户。 +--- + +# DROP USER + +从系统中删除指定的用户。 + +## 语法 {#syntax} + +```sql +DROP USER [ IF EXISTS ] +``` + +## 示例 {#examples} + +```sql +DROP USER user1; +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/drop-vector-index.md b/tidb-cloud-lake/sql/drop-vector-index.md new file mode 100644 index 0000000000000..fcbba8b2eed95 --- /dev/null +++ b/tidb-cloud-lake/sql/drop-vector-index.md @@ -0,0 +1,32 @@ +--- +title: DROP VECTOR INDEX +summary: 从表中移除一个 Vector 索引。 +--- + +# DROP VECTOR INDEX + +从表中移除一个 Vector 索引。 + +## 语法 {#syntax} + +```sql +DROP VECTOR INDEX [IF EXISTS] ON [.] +``` + +## 示例 {#examples} + +```sql +-- Create a table with a vector index +CREATE TABLE articles ( + id INT, + title VARCHAR, + embedding VECTOR(768), + VECTOR INDEX idx_embedding(embedding) distance = 'cosine' +); + +-- Drop the vector index +DROP VECTOR INDEX idx_embedding ON articles; + +-- Drop with IF EXISTS to avoid errors if index doesn't exist +DROP VECTOR INDEX IF EXISTS idx_embedding ON articles; +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/drop-view.md b/tidb-cloud-lake/sql/drop-view.md new file mode 100644 index 0000000000000..9e11d179c30b1 --- /dev/null +++ b/tidb-cloud-lake/sql/drop-view.md @@ -0,0 +1,23 @@ +--- +title: DROP VIEW +summary: 删除视图。 +--- + +# DROP VIEW + +删除视图。 + +## 语法 {#syntax} + +```sql +DROP VIEW [ IF EXISTS ] [ . ]view_name +``` + +## 示例 {#examples} + +```sql +DROP VIEW IF EXISTS tmp_view; + +SELECT * FROM tmp_view; +ERROR 1105 (HY000): Code: 1025, Text = Unknown table 'tmp_view'. +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/drop-warehouse.md b/tidb-cloud-lake/sql/drop-warehouse.md new file mode 100644 index 0000000000000..c66ea051ff42a --- /dev/null +++ b/tidb-cloud-lake/sql/drop-warehouse.md @@ -0,0 +1,33 @@ +--- +title: DROP WAREHOUSE +summary: 删除一个 warehouse,并释放与其关联的资源。 +--- + +# DROP WAREHOUSE + +删除一个 warehouse,并释放与其关联的资源。 + +## 语法 {#syntax} + +```sql +DROP WAREHOUSE [ IF EXISTS ] +``` + +| 参数 | 描述 | +| -------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- | +| `IF EXISTS` | 可选。如果指定了该选项,当计算集群 (Warehouse) 不存在时,命令会静默成功。如果未指定,当计算集群不存在时,命令会失败。 | +| warehouse_name | 要删除的计算集群名称。 | + +## 示例 {#examples} + +删除一个 warehouse: + +```sql +DROP WAREHOUSE my_warehouse; +``` + +仅当 warehouse 存在时才删除: + +```sql +DROP WAREHOUSE IF EXISTS my_warehouse; +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/drop-worker.md b/tidb-cloud-lake/sql/drop-worker.md new file mode 100644 index 0000000000000..91815a5914813 --- /dev/null +++ b/tidb-cloud-lake/sql/drop-worker.md @@ -0,0 +1,45 @@ +--- +title: DROP WORKER +summary: 使用 DROP WORKER 移除 worker。 +--- + +# DROP WORKER + +> **注意:** +> +> 于 v1.3.0 中引入。 + +移除一个 worker。 + +> **注意:** +> +> 此命令要求启用 cloud control。 + +## 语法 {#syntax} + +```sql +DROP WORKER [ IF EXISTS ] +``` + +## 参数 {#parameters} + +| 参数 | 描述 | +|-----------|-------------| +| `IF EXISTS` | 可选。如果 worker 不存在,则抑制报错。 | +| `` | worker 名称。 | + +## 示例 {#examples} + +```sql +DROP WORKER read_env; +``` + +```sql +DROP WORKER IF EXISTS read_env; +``` + +## 相关主题 {#related-topics} + +- [CREATE WORKER](/tidb-cloud-lake/sql/create-worker.md) - 创建 worker +- [ALTER WORKER](/tidb-cloud-lake/sql/alter-worker.md) - 修改 worker 的标签、选项或状态 +- [SHOW WORKERS](/tidb-cloud-lake/sql/show-workers.md) - 列出 workers 及其元信息 \ No newline at end of file diff --git a/tidb-cloud-lake/sql/drop-workload-group.md b/tidb-cloud-lake/sql/drop-workload-group.md new file mode 100644 index 0000000000000..1cea6a22b5ea5 --- /dev/null +++ b/tidb-cloud-lake/sql/drop-workload-group.md @@ -0,0 +1,22 @@ +--- +title: DROP WORKLOAD GROUP +summary: 删除指定的 workload group。 +--- + +# DROP WORKLOAD GROUP + +删除指定的 workload group。 + +## 语法 {#syntax} + +```sql +DROP WORKLOAD GROUP [IF EXISTS] +``` + +## 示例 {#examples} + +以下示例删除 `test_workload_group` workload group: + +```sql +DROP WORKLOAD GROUP test_workload_group; +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/epoch.md b/tidb-cloud-lake/sql/epoch.md new file mode 100644 index 0000000000000..7b08d4a499ca5 --- /dev/null +++ b/tidb-cloud-lake/sql/epoch.md @@ -0,0 +1,8 @@ +--- +title: EPOCH +summary: TO_SECONDS 的别名。 +--- + +# EPOCH + +[TO_SECONDS](/tidb-cloud-lake/sql/seconds.md) 的别名。 \ No newline at end of file diff --git a/tidb-cloud-lake/sql/error-or.md b/tidb-cloud-lake/sql/error-or.md new file mode 100644 index 0000000000000..43ab999ce72e5 --- /dev/null +++ b/tidb-cloud-lake/sql/error-or.md @@ -0,0 +1,37 @@ +--- +title: ERROR_OR +summary: 返回其输入中第一个不报错的表达式。如果所有表达式都产生错误,则返回 NULL。 +--- + +# ERROR_OR + +返回其输入中第一个不报错的表达式。如果所有表达式都产生错误,则返回 NULL。 + +## 语法 {#syntax} + +```sql +ERROR_OR(expr1, expr2, ...) +``` + +## 示例 {#examples} + +```sql +-- 如果没有发生错误,则返回有效日期 +-- 如果转换产生错误,则返回当前日期 +SELECT NOW(), ERROR_OR('2024-12-25'::DATE, NOW()::DATE); + +┌────────────────────────────────────────────────────────────────────────┐ +│ now() │ error_or('2024-12-25'::date, now()::date) │ +├────────────────────────────┼───────────────────────────────────────────┤ +│ 2024-03-18 01:22:39.460320 │ 2024-12-25 │ +└────────────────────────────────────────────────────────────────────────┘ + +-- 由于转换产生错误,因此返回 NULL +SELECT ERROR_OR('2024-1234'::DATE); + +┌─────────────────────────────┐ +│ error_or('2024-1234'::date) │ +├─────────────────────────────┤ +│ NULL │ +└─────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/execute-immediate.md b/tidb-cloud-lake/sql/execute-immediate.md new file mode 100644 index 0000000000000..6cf1c163dd218 --- /dev/null +++ b/tidb-cloud-lake/sql/execute-immediate.md @@ -0,0 +1,68 @@ +--- +title: EXECUTE IMMEDIATE +summary: 执行 SQL 脚本。有关如何为 {{{ .lake }}} 编写 SQL 脚本,请参见 Stored Procedure & SQL Scripting。 +--- + +# EXECUTE IMMEDIATE + +执行 SQL 脚本。有关如何为 {{{ .lake }}} 编写 SQL 脚本,请参见 [存储过程与 SQL 脚本](/tidb-cloud-lake/sql/stored-procedure-scripting.md)。 + +## 语法 {#syntax} + +```sql +EXECUTE IMMEDIATE $$ +BEGIN + + RETURN ; -- Use to return a single value + -- OR + RETURN TABLE(); -- Use to return a table +END; +$$; +``` + +## 示例 {#examples} + +以下示例使用循环从 -1 迭代到 2,对 sum 进行累加,结果为总和 (2): + +```sql +EXECUTE IMMEDIATE $$ +BEGIN + LET x := -1; + LET sum := 0; + FOR x IN x TO x + 3 DO + sum := sum + x; + END FOR; + RETURN sum; +END; +$$; + +┌────────┐ +│ Result │ +│ String │ +├────────┤ +│ 2 │ +└────────┘ +``` + +以下示例返回一个表,其中包含一列 `1 + 1`,其值为 2: + +```sql +EXECUTE IMMEDIATE $$ +BEGIN + LET x := 1; + RETURN TABLE(SELECT :x + 1); +END; +$$; + +┌───────────┐ +│ Result │ +│ String │ +├───────────┤ +│ ┌───────┐ │ +│ │ 1 + 1 │ │ +│ │ UInt8 │ │ +│ ├───────┤ │ +│ │ 2 │ │ +│ └───────┘ │ +└───────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/execute-task.md b/tidb-cloud-lake/sql/execute-task.md new file mode 100644 index 0000000000000..b6700336d91d1 --- /dev/null +++ b/tidb-cloud-lake/sql/execute-task.md @@ -0,0 +1,32 @@ +--- +title: EXECUTE TASK +summary: `EXECUTE TASK` 语句用于手动执行一个现有任务。 +--- + +# EXECUTE TASK + +`EXECUTE TASK` 语句用于手动执行一个现有任务。 + +**NOTICE:** 此功能仅在 {{{ .lake }}} 中开箱即用。 + +## 语法 {#syntax} + +```sql +EXECUTE TASK +``` + +| 参数 | 描述 | +|----------------------------------|------------------------------------------------------------------------------------------------------| +| name | 任务的名称。这是一个必填字段。 | + +## 使用说明 {#usage-notes} + +- 该 SQL 命令只能执行独立任务或 DAG 中的根任务。如果输入的是子任务,该命令会返回用户错误。 + +## 使用示例 {#usage-examples} + +```sql +EXECUTE TASK mytask; +``` + +该命令会执行名为 mytask 的任务。 \ No newline at end of file diff --git a/tidb-cloud-lake/sql/exists.md b/tidb-cloud-lake/sql/exists.md new file mode 100644 index 0000000000000..bd2165212f293 --- /dev/null +++ b/tidb-cloud-lake/sql/exists.md @@ -0,0 +1,29 @@ +--- +title: EXISTS +summary: exists 条件与子查询结合使用;如果子查询至少返回一行,则认为该条件“成立”。 +--- + +# EXISTS + +exists 条件与子查询结合使用;如果子查询至少返回一行,则认为该条件“成立”。 + +## 语法 {#syntax} + +```sql +WHERE EXISTS ( ); +``` + +## 示例 {#examples} + +```sql +SELECT number FROM numbers(5) AS A WHERE exists (SELECT * FROM numbers(3) WHERE number=1); ++--------+ +| number | ++--------+ +| 0 | +| 1 | +| 2 | +| 3 | +| 4 | ++--------+ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/exp.md b/tidb-cloud-lake/sql/exp.md new file mode 100644 index 0000000000000..15b7efe05d6d2 --- /dev/null +++ b/tidb-cloud-lake/sql/exp.md @@ -0,0 +1,26 @@ +--- +title: EXP +summary: 返回自然对数的底数 e 的 `x` 次幂值。 +--- + +# EXP + +返回自然对数的底数 e 的 `x` 次幂值。 + +## 语法 {#syntax} + +```sql +EXP( ) +``` + +## 示例 {#examples} + +```sql +SELECT EXP(2); + +┌──────────────────┐ +│ exp(2) │ +├──────────────────┤ +│ 7.38905609893065 │ +└──────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/explain-analyze-graphical.md b/tidb-cloud-lake/sql/explain-analyze-graphical.md new file mode 100644 index 0000000000000..96f93b9297f63 --- /dev/null +++ b/tidb-cloud-lake/sql/explain-analyze-graphical.md @@ -0,0 +1,43 @@ +--- +title: EXPLAIN ANALYZE GRAPHICAL +summary: 在浏览器中通过交互式可视化表示分析查询性能。仅在 LakeSQL v0.22.2+ 中可用。 +--- + +# EXPLAIN ANALYZE GRAPHICAL + +在浏览器中通过交互式可视化表示分析查询性能。仅在 LakeSQL v0.22.2+ 中可用。 + +## 语法 {#syntax} + +```sql +EXPLAIN ANALYZE GRAPHICAL +``` + +## 配置 {#configuration} + +将以下内容添加到你的 LakeSQL 配置文件 `~/.config/lakesql/config.toml` 中: + +```toml +[server] +bind_address = "127.0.0.1" +auto_open_browser = true +``` + +## 示例 {#example} + +```sql +EXPLAIN ANALYZE GRAPHICAL SELECT l_returnflag, COUNT(*) +FROM lineitem +WHERE l_shipdate <= '1998-09-01' +GROUP BY l_returnflag; +``` + +输出: + +```bash +View graphical online: http://127.0.0.1:8080?perf_id=1 +``` + +这会打开一个交互式视图,显示执行计划、operator 运行时和数据流。 + +![Graphical Analysis](/media/tidb-cloud-lake/explain-graphical.png) \ No newline at end of file diff --git a/tidb-cloud-lake/sql/explain-analyze.md b/tidb-cloud-lake/sql/explain-analyze.md new file mode 100644 index 0000000000000..94c9a25678505 --- /dev/null +++ b/tidb-cloud-lake/sql/explain-analyze.md @@ -0,0 +1,185 @@ +--- +title: EXPLAIN ANALYZE +summary: EXPLAIN ANALYZE 用于显示查询执行计划以及实际运行时性能统计信息。 +--- + +# EXPLAIN ANALYZE + +`EXPLAIN ANALYZE` 用于显示查询执行计划以及实际运行时性能统计信息。 + +这对于分析查询性能以及识别查询中的瓶颈非常有用。 + +## 语法 {#syntax} + +```sql +EXPLAIN ANALYZE +``` + +## 示例 {#examples} + +TPC-H Q21: + +```sql +EXPLAIN ANALYZE SELECT s_name, + -> Count(*) AS numwait + -> FROM supplier, + -> lineitem l1, + -> orders, + -> nation + -> WHERE s_suppkey = l1.l_suppkey + -> AND o_orderkey = l1.l_orderkey + -> AND o_orderstatus = 'F' + -> AND l1.l_receiptdate > l1.l_commitdate + -> AND EXISTS (SELECT * + -> FROM lineitem l2 + -> WHERE l2.l_orderkey = l1.l_orderkey + -> AND l2.l_suppkey <> l1.l_suppkey) + -> AND NOT EXISTS (SELECT * + -> FROM lineitem l3 + -> WHERE l3.l_orderkey = l1.l_orderkey + -> AND l3.l_suppkey <> l1.l_suppkey + -> AND l3.l_receiptdate > l3.l_commitdate) + -> AND s_nationkey = n_nationkey + -> AND n_name = 'EGYPT' + -> GROUP BY s_name + -> ORDER BY numwait DESC, + -> s_name + -> LIMIT 100; ++------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| explain | ++------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| Limit | +| ├── limit: 100 | +| ├── offset: 0 | +| ├── estimated rows: 100.00 | +| ├── total process time: 0ms | +| └── Sort | +| ├── sort keys: [numwait DESC NULLS LAST, s_name ASC NULLS LAST] | +| ├── estimated rows: 11000.00 | +| ├── total process time: 0ms | +| └── EvalScalar | +| ├── expressions: [COUNT(*) (#70)] | +| ├── estimated rows: 11000.00 | +| ├── total process time: 0ms | +| └── AggregateFinal | +| ├── group by: [s_name] | +| ├── aggregate functions: [count()] | +| ├── estimated rows: 11000.00 | +| └── AggregatePartial | +| ├── group by: [s_name] | +| ├── aggregate functions: [count()] | +| ├── estimated rows: 11000.00 | +| ├── total process time: 1ms | +| └── HashJoin | +| ├── join type: LEFT ANTI | +| ├── build keys: [l3.l_orderkey (#52)] | +| ├── probe keys: [l1.l_orderkey (#7)] | +| ├── filters: [noteq(l3.l_suppkey (#54), l1.l_suppkey (#9))] | +| ├── estimated rows: 1633696.00 | +| ├── total process time: 788ms | +| ├── Filter(Build) | +| │ ├── filters: [gt(l3.l_receiptdate (#64), l3.l_commitdate (#63))] | +| │ ├── estimated rows: 2400786.33 | +| │ ├── total process time: 85ms | +| │ └── TableScan | +| │ ├── table: default.tpch.lineitem | +| │ ├── read rows: 7202359 | +| │ ├── read bytes: 42731029 | +| │ ├── partitions total: 9 | +| │ ├── partitions scanned: 9 | +| │ ├── pruning stats: [segments: , blocks: ] | +| │ ├── push downs: [filters: [gt(l3.l_receiptdate (#64), l3.l_commitdate (#63))], limit: NONE] | +| │ ├── output columns: [l_orderkey, l_suppkey, l_commitdate, l_receiptdate] | +| │ └── estimated rows: 7202359.00 | +| └── HashJoin(Probe) | +| ├── join type: LEFT SEMI | +| ├── build keys: [l2.l_orderkey (#36)] | +| ├── probe keys: [l1.l_orderkey (#7)] | +| ├── filters: [noteq(l2.l_suppkey (#38), l1.l_suppkey (#9))] | +| ├── estimated rows: 1633696.00 | +| ├── total process time: 905ms | +| ├── TableScan(Build) | +| │ ├── table: default.tpch.lineitem | +| │ ├── read rows: 7202359 | +| │ ├── read bytes: 17507468 | +| │ ├── partitions total: 9 | +| │ ├── partitions scanned: 9 | +| │ ├── pruning stats: [segments: , blocks: ] | +| │ ├── push downs: [filters: [], limit: NONE] | +| │ ├── output columns: [l_orderkey, l_suppkey] | +| │ └── estimated rows: 7202359.00 | +| └── HashJoin(Probe) | +| ├── join type: INNER | +| ├── build keys: [orders.o_orderkey (#23)] | +| ├── probe keys: [l1.l_orderkey (#7)] | +| ├── filters: [] | +| ├── estimated rows: 1633696.00 | +| ├── total process time: 338ms | +| ├── Filter(Build) | +| │ ├── filters: [eq(orders.o_orderstatus (#25), "F")] | +| │ ├── estimated rows: 550000.00 | +| │ ├── total process time: 42ms | +| │ └── TableScan | +| │ ├── table: default.tpch.orders | +| │ ├── read rows: 1650000 | +| │ ├── read bytes: 5173599 | +| │ ├── partitions total: 3 | +| │ ├── partitions scanned: 3 | +| │ ├── pruning stats: [segments: , blocks: ] | +| │ ├── push downs: [filters: [eq(orders.o_orderstatus (#25), "F")], limit: NONE] | +| │ ├── output columns: [o_orderkey, o_orderstatus] | +| │ └── estimated rows: 1650000.00 | +| └── HashJoin(Probe) | +| ├── join type: INNER | +| ├── build keys: [nation.n_nationkey (#32)] | +| ├── probe keys: [supplier.s_nationkey (#3)] | +| ├── filters: [] | +| ├── estimated rows: 184766.67 | +| ├── total process time: 93ms | +| ├── Filter(Build) | +| │ ├── filters: [eq(nation.n_name (#33), "EGYPT")] | +| │ ├── estimated rows: 16.67 | +| │ ├── total process time: 0ms | +| │ └── TableScan | +| │ ├── table: default.tpch.nation | +| │ ├── read rows: 50 | +| │ ├── read bytes: 566 | +| │ ├── partitions total: 2 | +| │ ├── partitions scanned: 2 | +| │ ├── pruning stats: [segments: , blocks: ] | +| │ ├── push downs: [filters: [eq(nation.n_name (#33), "EGYPT")], limit: NONE] | +| │ ├── output columns: [n_nationkey, n_name] | +| │ └── estimated rows: 50.00 | +| └── HashJoin(Probe) | +| ├── join type: INNER | +| ├── build keys: [supplier.s_suppkey (#0)] | +| ├── probe keys: [l1.l_suppkey (#9)] | +| ├── filters: [] | +| ├── estimated rows: 11086.00 | +| ├── total process time: 447ms | +| ├── TableScan(Build) | +| │ ├── table: default.tpch.supplier | +| │ ├── read rows: 11000 | +| │ ├── read bytes: 42015 | +| │ ├── partitions total: 2 | +| │ ├── partitions scanned: 2 | +| │ ├── pruning stats: [segments: , blocks: ] | +| │ ├── push downs: [filters: [], limit: NONE] | +| │ ├── output columns: [s_suppkey, s_name, s_nationkey] | +| │ └── estimated rows: 11000.00 | +| └── Filter(Probe) | +| ├── filters: [gt(l1.l_receiptdate (#19), l1.l_commitdate (#18))] | +| ├── estimated rows: 2400786.33 | +| ├── total process time: 59ms | +| └── TableScan | +| ├── table: default.tpch.lineitem | +| ├── read rows: 7202359 | +| ├── read bytes: 42731029 | +| ├── partitions total: 9 | +| ├── partitions scanned: 9 | +| ├── pruning stats: [segments: , blocks: ] | +| ├── push downs: [filters: [gt(l1.l_receiptdate (#19), l1.l_commitdate (#18))], limit: NONE] | +| ├── output columns: [l_orderkey, l_suppkey, l_commitdate, l_receiptdate] | +| └── estimated rows: 7202359.00 | ++------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/explain-ast.md b/tidb-cloud-lake/sql/explain-ast.md new file mode 100644 index 0000000000000..852e7d63608eb --- /dev/null +++ b/tidb-cloud-lake/sql/explain-ast.md @@ -0,0 +1,67 @@ +--- +title: EXPLAIN AST +summary: 返回 SQL 语句的抽象语法树(AST)。该命令会将 SQL 语句拆分为语法组成部分,并以层次结构表示。 +--- + +# EXPLAIN AST + +返回 SQL 语句的抽象语法树(AST)。该命令会将 SQL 语句拆分为语法组成部分,并以层次结构表示。 + +## 语法 {#syntax} + +```sql +EXPLAIN AST +``` + +## 示例 {#examples} + +```sql +EXPLAIN AST create user 'test'@'localhost' identified with sha256_password by 'new_password'; + + ---- + CreateUser (children 3) + ├── User 'test'@'localhost' + ├── AuthType sha256_password + └── Password "new_password" + ``` + + ```sql +EXPLAIN AST insert into t1 (a, b) values (1, 2),(3, 4); + + ---- + Insert (children 3) + ├── TableIdentifier t1 + ├── Columns (children 2) + │ ├── Identifier a + │ └── Identifier b + └── Source (children 1) + └── ValueSource +``` + +```sql +EXPLAIN AST select * from t1 inner join t2 on t1.a = t2.a and t1.b = t2.b and t1.a > 2; + + ---- + Query (children 1) + └── QueryBody (children 1) + └── SelectQuery (children 2) + ├── SelectList (children 1) + │ └── Target * + └── TableList (children 1) + └── TableJoin (children 1) + └── Join (children 3) + ├── TableIdentifier t1 + ├── TableIdentifier t2 + └── ConditionOn (children 1) + └── Function AND (children 2) + ├── Function AND (children 2) + │ ├── Function = (children 2) + │ │ ├── ColumnIdentifier t1.a + │ │ └── ColumnIdentifier t2.a + │ └── Function = (children 2) + │ ├── ColumnIdentifier t1.b + │ └── ColumnIdentifier t2.b + └── Function > (children 2) + ├── ColumnIdentifier t1.a + └── Literal Integer(2) +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/explain-commands.md b/tidb-cloud-lake/sql/explain-commands.md new file mode 100644 index 0000000000000..c22cbd06c2f6c --- /dev/null +++ b/tidb-cloud-lake/sql/explain-commands.md @@ -0,0 +1,20 @@ +--- +title: Explain 命令 +summary: 本页提供 {{{ .lake }}} 中与 explain 相关命令的参考信息。 +--- + +# Explain 命令 + +本页提供 {{{ .lake }}} 中与 explain 相关命令的参考信息。 + +## 命令概览 {#commands-overview} + +| 命令 | 使用场景 | +|---------|----------| +| [`EXPLAIN`](/tidb-cloud-lake/sql/explain.md) | 理解查询结构和优化 | +| [`EXPLAIN ANALYZE`](/tidb-cloud-lake/sql/explain-analyze.md) | 基于运行时统计信息进行性能分析 | +| [`EXPLAIN ANALYZE GRAPHICAL`](/tidb-cloud-lake/sql/explain-analyze-graphical.md) | 可视化性能分析(仅 LakeSQL) | +| [`EXPLAIN AST`](/tidb-cloud-lake/sql/explain-ast.md) | SQL 解析和语法分析 | +| [`EXPLAIN PERF`](/tidb-cloud-lake/sql/explain-perf.md) | 查询性能剖析(仅 LakeSQL) | +| [`EXPLAIN RAW`](/tidb-cloud-lake/sql/explain-raw.md) | 内部查询处理分析 | +| [`EXPLAIN SYNTAX`](/tidb-cloud-lake/sql/explain-syntax.md) | SQL 代码格式化和标准化 | \ No newline at end of file diff --git a/tidb-cloud-lake/sql/explain-perf.md b/tidb-cloud-lake/sql/explain-perf.md new file mode 100644 index 0000000000000..9b7b30bcd05c3 --- /dev/null +++ b/tidb-cloud-lake/sql/explain-perf.md @@ -0,0 +1,26 @@ +--- +title: EXPLAIN PERF +summary: 对查询 CPU 使用情况进行性能分析,并返回一个从当前集群所有节点收集的 HTML 火焰图。 +--- + +# EXPLAIN PERF + +`EXPLAIN PERF` 通过捕获堆栈跟踪来执行 CPU 性能分析。该命令会返回一个 HTML 文件,其中包含基于从当前集群所有节点收集的数据生成的火焰图。你可以直接在浏览器中打开此 HTML 文件。 + +它有助于分析查询性能并帮助识别瓶颈。 + +## 语法 {#syntax} + +```sql +EXPLAIN PERF +``` + +## 示例 {#examples} + +```shell +lakesql --quote-style never --query="EXPLAIN PERF SELECT avg(number) FROM numbers(10000000)" > demo.html +``` + +然后,你可以在浏览器中打开 `demo.html` 文件以查看火焰图。 + +如果查询完成得非常快,可能无法收集到足够的数据,从而导致火焰图为空。 \ No newline at end of file diff --git a/tidb-cloud-lake/sql/explain-raw.md b/tidb-cloud-lake/sql/explain-raw.md new file mode 100644 index 0000000000000..7d25709635f76 --- /dev/null +++ b/tidb-cloud-lake/sql/explain-raw.md @@ -0,0 +1,36 @@ +--- +title: EXPLAIN RAW +summary: 显示 SQL 语句的逻辑执行计划,你可以使用它来分析、排查问题并提升查询效率。 +--- + +# EXPLAIN RAW + +显示 SQL 语句的逻辑执行计划,你可以使用它来分析、排查问题并提升查询效率。 + +## 语法 {#syntax} + +```sql +EXPLAIN RAW +``` + +## 示例 {#examples} + +```sql +explain raw select * from t1, t2 where (t1.a = t2.a and t1.a > 3) or (t1.a = t2.a); + +Project: [a (#0),b (#1),a (#2),b (#3)] + └── EvalScalar: [t1.a (#0), t1.b (#1), t2.a (#2), t2.b (#3)] + └── Filter: [((t1.a (#0) = t2.a (#2)) AND (t1.a (#0) > 3)) OR (t1.a (#0) = t2.a (#2))] + └── LogicalJoin: equi-conditions: [], non-equi-conditions: [] + ├── LogicalGet: default.default.t1 + └── LogicalGet: default.default.t2 + +explain raw select * from t1 inner join t2 on t1.a = t2.a and t1.b = t2.b and t1.a > 2; + + ---- + Project: [a (#0),b (#1),a (#2),b (#3)] + └── EvalScalar: [t1.a (#0), t1.b (#1), t2.a (#2), t2.b (#3)] + └── LogicalJoin: equi-conditions: [(t1.a (#0) = t2.a (#2)) AND (t1.b (#1) = t2.b (#3))], non-equi-conditions: [t1.a (#0) > 2] + ├── LogicalGet: default.default.t1 + └── LogicalGet: default.default.t2 +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/explain-syntax.md b/tidb-cloud-lake/sql/explain-syntax.md new file mode 100644 index 0000000000000..d3f5ee5484183 --- /dev/null +++ b/tidb-cloud-lake/sql/explain-syntax.md @@ -0,0 +1,48 @@ +--- +title: EXPLAIN SYNTAX +summary: 输出格式化后的 SQL 代码。该命令可用作 SQL 格式化工具,使你的代码更易于阅读。 +--- + +# EXPLAIN SYNTAX + +输出格式化后的 SQL 代码。该命令可用作 SQL 格式化工具,使你的代码更易于阅读。 + +## 语法 {#syntax} + +```sql +EXPLAIN SYNTAX +``` + +## 示例 {#examples} + +```sql +EXPLAIN SYNTAX select a, sum(b) as sum from t1 where a in (1, 2) and b > 0 and b < 100 group by a order by a; + + ---- + SELECT + a, + sum(b) AS sum + FROM + t1 + WHERE + a IN (1, 2) + AND b > 0 + AND b < 100 + GROUP BY a + ORDER BY a +``` + +```sql +EXPLAIN SYNTAX copy into 's3://mybucket/data.csv' from t1 file_format = ( type = CSV field_delimiter = ',' record_delimiter = '\n' skip_header = 1); + + ---- + COPY + INTO 's3://mybucket/data.csv' + FROM t1 + FILE_FORMAT = ( + field_delimiter = ",", + record_delimiter = "\n", + skip_header = "1", + type = "CSV" + ) +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/explain.md b/tidb-cloud-lake/sql/explain.md new file mode 100644 index 0000000000000..100906c31e4c1 --- /dev/null +++ b/tidb-cloud-lake/sql/explain.md @@ -0,0 +1,59 @@ +--- +title: EXPLAIN +summary: 显示 SQL 语句的执行计划。执行计划以由不同操作符组成的树形结构展示,你可以借此查看 {{{ .lake }}} 将如何执行该 SQL 语句。一个操作符通常包含一个或多个字段,用于描述 {{{ .lake }}} 将执行的操作或与查询相关的对象。 +--- + +# EXPLAIN + +显示 SQL 语句的执行计划。执行计划以由不同操作符组成的树形结构展示,你可以借此查看 {{{ .lake }}} 将如何执行该 SQL 语句。一个操作符通常包含一个或多个字段,用于描述 {{{ .lake }}} 将执行的操作或与查询相关的对象。 + +例如,以下由 EXPLAIN 命令返回的执行计划中包含一个名为 *TableScan* 的操作符,并带有多个字段。 + +```sql +EXPLAIN SELECT * FROM allemployees; + +--- +TableScan +├── table: default.default.allemployees +├── read rows: 5 +├── read bytes: 592 +├── partitions total: 5 +├── partitions scanned: 5 +└── push downs: [filters: [], limit: NONE] +``` + +如果你正在使用 {{{ .lake }}},可以利用 Query Profile 功能将 SQL 语句的执行计划可视化。 + +## 语法 {#syntax} + +```sql +EXPLAIN +``` + +## 示例 {#examples} + +```sql +EXPLAIN select t.number from numbers(1) as t, numbers(1) as t1 where t.number = t1.number; +---- +Project +├── columns: [number (#0)] +└── HashJoin + ├── join type: INNER + ├── build keys: [numbers.number (#1)] + ├── probe keys: [numbers.number (#0)] + ├── filters: [] + ├── TableScan(Build) + │ ├── table: default.system.numbers + │ ├── read rows: 1 + │ ├── read bytes: 8 + │ ├── partitions total: 1 + │ ├── partitions scanned: 1 + │ └── push downs: [filters: [], limit: NONE] + └── TableScan(Probe) + ├── table: default.system.numbers + ├── read rows: 1 + ├── read bytes: 8 + ├── partitions total: 1 + ├── partitions scanned: 1 + └── push downs: [filters: [], limit: NONE] +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/external-function.md b/tidb-cloud-lake/sql/external-function.md new file mode 100644 index 0000000000000..8fd5890ec1744 --- /dev/null +++ b/tidb-cloud-lake/sql/external-function.md @@ -0,0 +1,20 @@ +--- +title: 外部函数 +summary: 本页按功能分类,全面概述了 {{{ .lake }}} 中的外部函数操作,便于参考。 +--- + +# 外部函数 + +本页按功能分类,全面概述了 {{{ .lake }}} 中的外部函数操作,便于参考。 + +## 外部函数管理 {#external-function-management} + +| 命令 | 描述 | +|---------|-------------| +| [CREATE EXTERNAL FUNCTION](/tidb-cloud-lake/sql/create-function.md) | 创建新的外部函数 | +| [ALTER EXTERNAL FUNCTION](/tidb-cloud-lake/sql/alter-function-sql.md) | 修改现有的外部函数 | +| [DROP EXTERNAL FUNCTION](/tidb-cloud-lake/sql/drop-function-sql.md) | 删除外部函数 | + +> **注意:** +> +> {{{ .lake }}} 中的外部函数允许你通过 HTTP/HTTPS 端点与外部服务集成来扩展功能,从而利用外部处理能力。 \ No newline at end of file diff --git a/tidb-cloud-lake/sql/extract.md b/tidb-cloud-lake/sql/extract.md new file mode 100644 index 0000000000000..f479978491975 --- /dev/null +++ b/tidb-cloud-lake/sql/extract.md @@ -0,0 +1,83 @@ +--- +title: EXTRACT +summary: 提取日期、时间戳或间隔中指定的部分。 +--- + +# EXTRACT + +提取日期、时间戳或间隔中指定的部分。 + +另请参阅:[DATE_PART](/tidb-cloud-lake/sql/date-part.md) + +## 语法 {#syntax} + +```sql +-- Extract from a date or timestamp +EXTRACT( + YEAR | QUARTER | MONTH | WEEK | DAY | HOUR | MINUTE | SECOND | + DOW | DOY | EPOCH | ISODOW | YEARWEEK | MILLENNIUM + FROM +) + +-- Extract from an interval +EXTRACT( YEAR | MONTH | WEEK | DAY | HOUR | MINUTE | SECOND | MICROSECOND | EPOCH FROM ) +``` + +| 关键字 | 描述 | +|--------------|-------------------------------------------------------------------------| +| `DOW` | 一周中的第几天。星期日 (0) 到星期六 (6)。 | +| `DOY` | 一年中的第几天。1 到 366。 | +| `EPOCH` | 自 1970-01-01 00:00:00 以来的秒数。 | +| `ISODOW` | ISO 一周中的第几天。星期一 (1) 到星期日 (7)。 | +| `YEARWEEK` | 按照 ISO 8601 组合的年份和周数(例如,202415)。 | +| `MILLENNIUM` | 日期所属的千年(年份 1–1000 为 1,1001–2000 为 2,依此类推)。 | + +## 返回类型 {#return-type} + +返回类型取决于被提取的字段: + +- 返回整数型:提取离散的日期或时间组成部分时(例如 YEAR、MONTH、DAY、DOY、HOUR、MINUTE、SECOND),该函数返回一个整数型值。 + + ```sql + SELECT EXTRACT(DAY FROM now()); -- Returns Integer + SELECT EXTRACT(DOY FROM now()); -- Returns Integer + ``` + +- 返回 float:提取 EPOCH(自 1970-01-01 00:00:00 UTC 以来的秒数)时,该函数返回一个 float,因为结果可能包含小数秒。 + + ```sql + SELECT EXTRACT(EPOCH FROM now()); -- Returns Float + ``` + +## 示例 {#examples} + +以下示例从当前时间戳中提取多个字段: + +```sql +SELECT + NOW(), + EXTRACT(DAY FROM NOW()), + EXTRACT(DOY FROM NOW()), + EXTRACT(EPOCH FROM NOW()), + EXTRACT(ISODOW FROM NOW()), + EXTRACT(YEARWEEK FROM NOW()), + EXTRACT(MILLENNIUM FROM NOW()); + +┌─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ +│ now() │ EXTRACT(DAY FROM now()) │ EXTRACT(DOY FROM now()) │ EXTRACT(EPOCH FROM now()) │ EXTRACT(ISODOW FROM now()) │ EXTRACT(YEARWEEK FROM now()) │ EXTRACT(MILLENNIUM FROM now()) │ +├────────────────────────────┼─────────────────────────┼─────────────────────────┼───────────────────────────┼────────────────────────────┼──────────────────────────────┼────────────────────────────────┤ +│ 2025-04-16 18:04:22.773888 │ 16 │ 106 │ 1744826662.773888 │ 3 │ 202516 │ 3 │ +└─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ +``` + +以下示例从一个 interval 中提取天数: + +```sql +SELECT EXTRACT(DAY FROM '1 day 2 hours 3 minutes 4 seconds'::INTERVAL); + +┌─────────────────────────────────────────────────────────────────┐ +│ EXTRACT(DAY FROM '1 day 2 hours 3 minutes 4 seconds'::INTERVAL) │ +├─────────────────────────────────────────────────────────────────┤ +│ 1 │ +└─────────────────────────────────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/factorial.md b/tidb-cloud-lake/sql/factorial.md new file mode 100644 index 0000000000000..cf71027428763 --- /dev/null +++ b/tidb-cloud-lake/sql/factorial.md @@ -0,0 +1,26 @@ +--- +title: FACTORIAL +summary: 返回 `x` 的阶乘。如果 `x` 小于或等于 0,函数返回 0。 +--- + +# FACTORIAL + +返回 `x` 的阶乘。如果 `x` 小于或等于 0,函数返回 0。 + +## 语法 {#syntax} + +```sql +FACTORIAL( ) +``` + +## 示例 {#examples} + +```sql +SELECT FACTORIAL(5); + +┌──────────────┐ +│ factorial(5) │ +├──────────────┤ +│ 120 │ +└──────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/feistel-obfuscate.md b/tidb-cloud-lake/sql/feistel-obfuscate.md new file mode 100644 index 0000000000000..cf93f0902bc15 --- /dev/null +++ b/tidb-cloud-lake/sql/feistel-obfuscate.md @@ -0,0 +1,66 @@ +--- +title: FEISTEL_OBFUSCATE +summary: 在保持位长度和值基数不变的情况下,对整数(例如 ID 或电话号码)进行确定性混淆,从而使 JOIN 仍然可用。 +--- + +# FEISTEL_OBFUSCATE + +在保持位长度和值基数不变的情况下,对整数(例如 ID 或电话号码)进行确定性混淆,从而使 JOIN 仍然可用。 + +## 语法 {#syntax} + +```sql +FEISTEL_OBFUSCATE( , ) +``` + +## 参数 {#arguments} + +| 参数 | 描述 | +| ----------- | ----------- | +| `number` | 输入 | +| `seed` | 不同表中对应的非文本列数据将以相同方式进行转换,因此混淆后不同表中的数据仍可进行 JOIN | + +## 返回类型 {#return-type} + +与输入相同 + +## 示例 {#examples} + +```sql +SELECT feistel_obfuscate(10000,1561819567875); ++------------------------------------------+ +| feistel_obfuscate(10000, 1561819567875) | ++------------------------------------------+ +| 15669 | ++------------------------------------------+ +``` + +feistel_obfuscate 会保留原始输入的位数。如果需要映射到更大的范围,可以在原始输入上增加一个偏移,例如 feistel_obfuscate(n+10000,50) + +```sql +SELECT feistel_obfuscate(10,1561819567875); ++------------------------------------------+ +| feistel_obfuscate(10, 1561819567875) | ++------------------------------------------+ +| 13 | ++------------------------------------------+ +``` + +电话号码风格示例(seed = 4242): + +```sql +SELECT 13000000000 + number AS phone, + feistel_obfuscate(13000000000 + number, 4242) AS masked_phone +FROM numbers(5); + +-- Sample output ++-------------+--------------+ +| phone | masked_phone | ++-------------+--------------+ +| 13000000000 | 12221668677 | +| 13000000001 | 10245458699 | +| 13000000002 | 15398657780 | +| 13000000003 | 9910824758 | +| 13000000004 | 13299971128 | ++-------------+--------------+ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/file-format.md b/tidb-cloud-lake/sql/file-format.md new file mode 100644 index 0000000000000..3a373abc0b752 --- /dev/null +++ b/tidb-cloud-lake/sql/file-format.md @@ -0,0 +1,25 @@ +--- +title: 文件格式 +summary: 本页按功能组织,全面概述了 {{{ .lake }}} 中的文件格式操作,便于参考。 +--- + +# 文件格式 + +本页按功能组织,全面概述了 {{{ .lake }}} 中的文件格式操作,便于参考。 + +## 文件格式管理 {#file-format-management} + +| Command | Description | +|---------|-------------| +| [CREATE FILE FORMAT](/tidb-cloud-lake/sql/create-file-format.md) | 创建一个具名的文件格式对象,用于数据加载和卸载 | +| [DROP FILE FORMAT](/tidb-cloud-lake/sql/drop-file-format.md) | 删除一个文件格式对象 | + +## 文件格式信息 {#file-format-information} + +| 命令 | 描述 | +|---------|-------------| +| [SHOW FILE FORMATS](/tidb-cloud-lake/sql/show-file-formats.md) | 列出当前数据库中的所有文件格式 | + +> **注意:** +> +> {{{ .lake }}} 中的文件格式定义了在数据加载操作期间应如何解析数据文件,或在数据卸载操作期间应如何设置数据文件的格式。它们提供了一种可复用的方式,用于指定文件类型、字段分隔符、压缩方式以及其他格式选项。 \ No newline at end of file diff --git a/tidb-cloud-lake/sql/first-value.md b/tidb-cloud-lake/sql/first-value.md new file mode 100644 index 0000000000000..d2fdd06ee9e16 --- /dev/null +++ b/tidb-cloud-lake/sql/first-value.md @@ -0,0 +1,151 @@ +--- +title: FIRST_VALUE +summary: 返回窗口框架中的第一个值。 +--- + +# FIRST_VALUE + +返回窗口框架中的第一个值。 + +另请参阅: + +- [LAST_VALUE](/tidb-cloud-lake/sql/last-value.md) +- [NTH_VALUE](/tidb-cloud-lake/sql/nth-value.md) + +## 语法 {#syntax} + +```sql +FIRST_VALUE(expression) [ { RESPECT | IGNORE } NULLS ] +OVER ( + [ PARTITION BY partition_expression ] + ORDER BY sort_expression [ ASC | DESC ] + [ window_frame ] +) +``` + +**参数:** + +- `expression`:必需。要从中返回第一个值的列或表达式。 +- `PARTITION BY`:可选。将行划分为多个分区。 +- `ORDER BY`:必需。确定窗口内的排序顺序。 +- `window_frame`:可选。定义窗口框架。默认值为 `RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW`。 + +**说明:** + +- 返回有序窗口框架中的第一个值。 +- 支持 `IGNORE NULLS` 以跳过空值,支持 `RESPECT NULLS` 以保留默认行为。 +- 当你需要基于行的语义而不是默认的范围框架时,请显式指定窗口框架(例如,`ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW`)。 +- 适用于查找每个分组或时间窗口中的最早值或最小值。 + +## 示例 {#examples} + +```sql +-- Sample order data +CREATE OR REPLACE TABLE orders_window_demo ( + customer VARCHAR, + order_id INT, + order_time TIMESTAMP, + amount INT, + sales_rep VARCHAR +); + +INSERT INTO orders_window_demo VALUES + ('Alice', 1001, to_timestamp('2024-05-01 09:00:00'), 120, 'Erin'), + ('Alice', 1002, to_timestamp('2024-05-01 11:00:00'), 135, NULL), + ('Alice', 1003, to_timestamp('2024-05-02 14:30:00'), 125, 'Glen'), + ('Bob', 1004, to_timestamp('2024-05-01 08:30:00'), 90, NULL), + ('Bob', 1005, to_timestamp('2024-05-01 20:15:00'), 105, 'Kai'), + ('Bob', 1006, to_timestamp('2024-05-03 10:00:00'), 95, NULL), + ('Carol', 1007, to_timestamp('2024-05-04 09:45:00'), 80, 'Lily'); +``` + +**示例 1:每个客户的首次购买** + +```sql +SELECT customer, + order_id, + order_time, + amount, + FIRST_VALUE(amount) OVER ( + PARTITION BY customer + ORDER BY order_time + ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW + ) AS first_order_amount +FROM orders_window_demo +ORDER BY customer, order_time; +``` + +结果: + +``` +customer | order_id | order_time | amount | first_order_amount +---------+----------+----------------------+--------+-------------------- +Alice | 1001 | 2024-05-01 09:00:00 | 120 | 120 +Alice | 1002 | 2024-05-01 11:00:00 | 135 | 120 +Alice | 1003 | 2024-05-02 14:30:00 | 125 | 120 +Bob | 1004 | 2024-05-01 08:30:00 | 90 | 90 +Bob | 1005 | 2024-05-01 20:15:00 | 105 | 90 +Bob | 1006 | 2024-05-03 10:00:00 | 95 | 90 +Carol | 1007 | 2024-05-04 09:45:00 | 80 | 80 +``` + +**示例 2:过去 24 小时内的第一笔订单** + +```sql +SELECT customer, + order_id, + order_time, + FIRST_VALUE(order_id) OVER ( + PARTITION BY customer + ORDER BY order_time + RANGE BETWEEN INTERVAL 1 DAY PRECEDING AND CURRENT ROW + ) AS first_order_in_24h +FROM orders_window_demo +ORDER BY customer, order_time; +``` + +结果: + +``` +customer | order_id | order_time | first_order_in_24h +---------+----------+----------------------+-------------------- +Alice | 1001 | 2024-05-01 09:00:00 | 1001 +Alice | 1002 | 2024-05-01 11:00:00 | 1001 +Alice | 1003 | 2024-05-02 14:30:00 | 1003 +Bob | 1004 | 2024-05-01 08:30:00 | 1004 +Bob | 1005 | 2024-05-01 20:15:00 | 1004 +Bob | 1006 | 2024-05-03 10:00:00 | 1006 +Carol | 1007 | 2024-05-04 09:45:00 | 1007 +``` + +**示例 3:跳过空值以查找第一个有姓名的销售代表** + +```sql +SELECT customer, + order_id, + sales_rep, + FIRST_VALUE(sales_rep) RESPECT NULLS OVER ( + PARTITION BY customer + ORDER BY order_time + ) AS first_rep_respect, + FIRST_VALUE(sales_rep) IGNORE NULLS OVER ( + PARTITION BY customer + ORDER BY order_time + ) AS first_rep_ignore +FROM orders_window_demo +ORDER BY customer, order_id; +``` + +结果: + +``` +customer | order_id | sales_rep | first_rep_respect | first_rep_ignore +---------+----------+-----------+-------------------+------------------ +Alice | 1001 | Erin | Erin | Erin +Alice | 1002 | NULL | Erin | Erin +Alice | 1003 | Glen | Erin | Erin +Bob | 1004 | NULL | NULL | NULL +Bob | 1005 | Kai | NULL | Kai +Bob | 1006 | NULL | NULL | Kai +Carol | 1007 | Lily | Lily | Lily +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/first.md b/tidb-cloud-lake/sql/first.md new file mode 100644 index 0000000000000..d3f129b6c4c7d --- /dev/null +++ b/tidb-cloud-lake/sql/first.md @@ -0,0 +1,12 @@ +--- +title: FIRST +summary: FIRST_VALUE 的别名。 +--- + +# FIRST + +> **注意:** +> +> 于 v1.1.50 中引入。 + +[FIRST_VALUE](/tidb-cloud-lake/sql/first-value.md) 的别名。 \ No newline at end of file diff --git a/tidb-cloud-lake/sql/flashback-table.md b/tidb-cloud-lake/sql/flashback-table.md new file mode 100644 index 0000000000000..76291edf76fc0 --- /dev/null +++ b/tidb-cloud-lake/sql/flashback-table.md @@ -0,0 +1,165 @@ +--- +title: FLASHBACK TABLE +summary: 使用快照 ID 或时间戳将表闪回到以下版本,且仅涉及元信息操作,因此该过程非常快。 +--- + +# FLASHBACK TABLE + +使用快照 ID 或时间戳将表闪回到以下版本,且仅涉及元信息操作,因此该过程非常快。 + +通过命令中指定的快照 ID 或时间戳,{{{ .lake }}} 可以将表闪回到创建该快照时的先前状态。要获取表的快照 ID 和时间戳,请使用 [FUSE_SNAPSHOT](/tidb-cloud-lake/sql/fuse-snapshot.md)。 + +表闪回能力受以下条件限制: + +- 该命令只能将现有表恢复到其先前状态。要恢复已删除的表,请使用 [UNDROP TABLE](/tidb-cloud-lake/sql/undrop-table.md)。 + +- 表闪回是 {{{ .lake }}} 时间旅行功能的一部分。在使用该命令前,请确保要闪回的表支持时间旅行。例如,该命令不适用于 transient tables,因为 {{{ .lake }}} 不会为这类表创建或存储快照。 + +- 将表闪回到先前状态后,不能再回滚该操作,但你可以再次将表闪回到更早的状态。 + +- {{{ .lake }}} 建议仅在紧急恢复场景中使用此命令。若要查询表的历史数据,请使用 [AT](/tidb-cloud-lake/sql/at.md) 子句。 + +## 语法 {#syntax} + +```sql +-- Restore with a snapshot ID +ALTER TABLE
FLASHBACK TO (SNAPSHOT => ''); + +-- Restore with a snapshot timestamp +ALTER TABLE
FLASHBACK TO (TIMESTAMP => ''::TIMESTAMP); +``` + +## 示例 {#example} + +### 步骤 1:创建示例 users 表并插入数据 {#step-1-create-a-sample-users-table-and-insert-data} + +```sql +-- Create a sample users table +CREATE TABLE users ( + id INT, + first_name VARCHAR, + last_name VARCHAR, + email VARCHAR, + registration_date TIMESTAMP +); + +-- Insert sample data +INSERT INTO users (id, first_name, last_name, email, registration_date) +VALUES (1, 'John', 'Doe', 'john.doe@example.com', '2023-01-01 00:00:00'), + (2, 'Jane', 'Doe', 'jane.doe@example.com', '2023-01-02 00:00:00'); +``` + +数据: + +```sql +SELECT * FROM users; ++------+------------+-----------+----------------------+----------------------------+ +| id | first_name | last_name | email | registration_date | ++------+------------+-----------+----------------------+----------------------------+ +| 1 | John | Doe | john.doe@example.com | 2023-01-01 00:00:00.000000 | +| 2 | Jane | Doe | jane.doe@example.com | 2023-01-02 00:00:00.000000 | ++------+------------+-----------+----------------------+----------------------------+ +``` + +快照: + +```sql +SELECT * FROM Fuse_snapshot('default', 'users')\G; +*************************** 1. row *************************** + snapshot_id: c5c538d6b8bc42f483eefbddd000af7d + snapshot_location: 29356/44446/_ss/c5c538d6b8bc42f483eefbddd000af7d_v2.json + format_version: 2 +previous_snapshot_id: NULL + segment_count: 1 + block_count: 1 + row_count: 2 + bytes_uncompressed: 150 + bytes_compressed: 829 + index_size: 1028 + timestamp: 2023-04-19 04:20:25.062854 +``` + +### 步骤 2:模拟一次误删除操作 {#step-2-simulate-an-accidental-delete-operation} + +```sql +-- Simulate an accidental delete operation +DELETE FROM users WHERE id = 1; +``` + +数据: + +```sql ++------+------------+-----------+----------------------+----------------------------+ +| id | first_name | last_name | email | registration_date | ++------+------------+-----------+----------------------+----------------------------+ +| 2 | Jane | Doe | jane.doe@example.com | 2023-01-02 00:00:00.000000 | ++------+------------+-----------+----------------------+----------------------------+ +``` + +快照: + +```sql +SELECT * FROM Fuse_snapshot('default', 'users')\G; +*************************** 1. row *************************** + snapshot_id: 7193af51a4c9423ebd6ddbb04327b280 + snapshot_location: 29356/44446/_ss/7193af51a4c9423ebd6ddbb04327b280_v2.json + format_version: 2 +previous_snapshot_id: c5c538d6b8bc42f483eefbddd000af7d + segment_count: 1 + block_count: 1 + row_count: 1 + bytes_uncompressed: 87 + bytes_compressed: 778 + index_size: 1028 + timestamp: 2023-04-19 04:22:20.390430 +*************************** 2. row *************************** + snapshot_id: c5c538d6b8bc42f483eefbddd000af7d + snapshot_location: 29356/44446/_ss/c5c538d6b8bc42f483eefbddd000af7d_v2.json + format_version: 2 +previous_snapshot_id: NULL + segment_count: 1 + block_count: 1 + row_count: 2 + bytes_uncompressed: 150 + bytes_compressed: 829 + index_size: 1028 + timestamp: 2023-04-19 04:20:25.062854 +``` + +### 步骤 3:找到删除操作之前的快照 ID {#step-3-find-the-snapshot-id-before-the-delete-operation} + +```sql +-- Assume the snapshot_id from the previous query is 'xxxxxx' +-- Restore the table to the snapshot before the delete operation +ALTER TABLE users FLASHBACK TO (SNAPSHOT => 'c5c538d6b8bc42f483eefbddd000af7d'); +``` + +数据: + +```sql +SELECT * FROM users; ++------+------------+-----------+----------------------+----------------------------+ +| id | first_name | last_name | email | registration_date | ++------+------------+-----------+----------------------+----------------------------+ +| 1 | John | Doe | john.doe@example.com | 2023-01-01 00:00:00.000000 | +| 2 | Jane | Doe | jane.doe@example.com | 2023-01-02 00:00:00.000000 | ++------+------------+-----------+----------------------+----------------------------+ +``` + +快照: + +```sql +SELECT * FROM Fuse_snapshot('default', 'users')\G; +*************************** 1. row *************************** + snapshot_id: c5c538d6b8bc42f483eefbddd000af7d + snapshot_location: 29356/44446/_ss/c5c538d6b8bc42f483eefbddd000af7d_v2.json + format_version: 2 +previous_snapshot_id: NULL + segment_count: 1 + block_count: 1 + row_count: 2 + bytes_uncompressed: 150 + bytes_compressed: 829 + index_size: 1028 + timestamp: 2023-04-19 04:20:25.062854 +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/flatten.md b/tidb-cloud-lake/sql/flatten.md new file mode 100644 index 0000000000000..068c5626672b8 --- /dev/null +++ b/tidb-cloud-lake/sql/flatten.md @@ -0,0 +1,137 @@ +--- +title: FLATTEN +summary: 将嵌套的 JSON 或数组数据转换为表格格式,其中每个元素或字段都表示为单独的一行。 +--- + +# FLATTEN + +将嵌套的 JSON 或数组数据转换为表格格式,其中每个元素或字段都表示为单独的一行。 + +## 语法 {#syntax} + +```sql +[LATERAL] FLATTEN ( + INPUT => + [, PATH => ] + [, OUTER => TRUE | FALSE] + [, RECURSIVE => TRUE | FALSE] + [, MODE => 'OBJECT' | 'ARRAY' | 'BOTH'] +) +``` + +## 参数 {#parameters} + +| 参数 | 描述 | 默认值 | +|-----------|-------------|---------| +| `INPUT` | 要展开的 JSON 或数组数据 | 必填 | +| `PATH` | 要展开的数组/对象路径 | 无 | +| `OUTER` | 包含结果为零的行(其值为 NULL) | `FALSE` | +| `RECURSIVE` | 展开嵌套元素 | `FALSE` | +| `MODE` | 展开对象、数组或两者 | `'BOTH'` | +| `LATERAL` | 启用与前置表表达式的交叉引用 | 可选 | + +## 输出列 {#output-columns} + +| 列 | 描述 | +|--------|-------------| +| `SEQ` | 输入的序列号 | +| `KEY` | 展开后值的键(如果没有则为 NULL) | +| `PATH` | 展开元素的路径 | +| `INDEX` | 数组索引(对象为 NULL) | +| `VALUE` | 展开元素的值 | +| `THIS` | 正在展开的元素 | + +**注意:** 使用 LATERAL 时,由于动态交叉引用,输出列可能会有所不同。 + +## 示例 {#examples} + +### 基本展开 {#basic-flattening} + +```sql +-- Flatten a JSON object with nested structures +SELECT * FROM FLATTEN( + INPUT => PARSE_JSON( + '{"name": "John", "languages": ["English", "Spanish"], "address": {"city": "New York"}}' + ) +); +``` + +结果会将顶层键展开: + +```text +| seq | key | path | index | value | this | +|-----|-----------|-----------|-------|----------------------|----------------------| +| 1 | name | name | NULL | "John" | {original JSON} | +| 1 | languages | languages | NULL | ["English","Spanish"]| {original JSON} | +| 1 | address | address | NULL | {"city":"New York"} | {original JSON} | +``` + +### 使用 PATH 参数 {#using-path-parameter} + +```sql +-- Flatten only the languages array by specifying the PATH +SELECT * FROM FLATTEN( + INPUT => PARSE_JSON( + '{"name": "John", "languages": ["English", "Spanish"]}' + ), + PATH => 'languages' +); +``` + +结果会将数组元素展开: + +```text +| seq | key | path | index | value | this | +|-----|------|--------------|-------|-----------|-------------------| +| 1 | NULL | languages[0] | 0 | "English" | ["English","Spanish"] | +| 1 | NULL | languages[1] | 1 | "Spanish" | ["English","Spanish"] | +``` + +### 递归展开 {#recursive-flattening} + +```sql +-- Recursively flatten nested objects and arrays +SELECT * FROM FLATTEN( + INPUT => PARSE_JSON( + '{"name": "John", "address": {"city": "New York", "zip": 10001}}' + ), + RECURSIVE => TRUE +); +``` + +结果会将嵌套对象展开: + +```text +| seq | key | path | index | value | this | +|-----|---------|--------------|-------|-------------|-----------------| +| 1 | name | name | NULL | "John" | {original JSON} | +| 1 | address | address | NULL | {"city":...}| {original JSON} | +| 1 | city | address.city | NULL | "New York" | {"city":...} | +| 1 | zip | address.zip | NULL | 10001 | {"city":...} | +``` + +### 使用 LATERAL FLATTEN {#using-lateral-flatten} + +```sql +-- Use LATERAL FLATTEN to transform a JSON array into rows +-- This allows direct access to array elements without a table +SELECT + f.value:item::STRING AS item_name, + f.value:price::FLOAT AS price +FROM + LATERAL FLATTEN( + INPUT => PARSE_JSON('[ + {"item":"coffee", "price":2.50}, + {"item":"donut", "price":1.20} + ]') + ) f; +``` + +结果: + +```text +| item_name | price | +|-----------|-------| +| coffee | 2.5 | +| donut | 1.2 | +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/floor.md b/tidb-cloud-lake/sql/floor.md new file mode 100644 index 0000000000000..8b1365dc5d3b9 --- /dev/null +++ b/tidb-cloud-lake/sql/floor.md @@ -0,0 +1,26 @@ +--- +title: FLOOR +summary: 向下舍入该数字。 +--- + +# FLOOR + +向下舍入该数字。 + +## 语法 {#syntax} + +```sql +FLOOR( ) +``` + +## 示例 {#examples} + +```sql +SELECT FLOOR(1.23); + +┌─────────────┐ +│ floor(1.23) │ +├─────────────┤ +│ 1 │ +└─────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/from-base64.md b/tidb-cloud-lake/sql/from-base64.md new file mode 100644 index 0000000000000..660a848aa4054 --- /dev/null +++ b/tidb-cloud-lake/sql/from-base64.md @@ -0,0 +1,36 @@ +--- +title: FROM_BASE64 +summary: 接受一个按 base-64 编码规则编码的字符串,并将解码结果以二进制形式返回。如果参数为 NULL 或不是有效的 base-64 字符串,则结果为 NULL。 +--- + +# FROM_BASE64 + +接受一个按 base-64 编码规则编码的字符串,并将解码结果以二进制形式返回。如果参数为 NULL 或不是有效的 base-64 字符串,则结果为 NULL。 + +## 语法 {#syntax} + +```sql +FROM_BASE64() +``` + +## 参数 {#arguments} + +| 参数 | 描述 | +|-----------|-------------------| +| `` | 字符串值。 | + +## 返回类型 {#return-type} + +`BINARY` + +## 示例 {#examples} + +```sql +SELECT TO_BASE64('abc'), FROM_BASE64(TO_BASE64('abc')) as b, b::String; +┌───────────────────────────────────────┐ +│ to_base64('abc') │ b │ b::string │ +│ String │ Binary │ String │ +├──────────────────┼────────┼───────────┤ +│ YWJj │ 616263 │ abc │ +└───────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/from-hex.md b/tidb-cloud-lake/sql/from-hex.md new file mode 100644 index 0000000000000..a215c7d502952 --- /dev/null +++ b/tidb-cloud-lake/sql/from-hex.md @@ -0,0 +1,8 @@ +--- +title: FROM_HEX +summary: UNHEX 的别名。 +--- + +# FROM_HEX + +[UNHEX](/tidb-cloud-lake/sql/unhex.md) 的别名。 \ No newline at end of file diff --git a/tidb-cloud-lake/sql/full-text-search-functions.md b/tidb-cloud-lake/sql/full-text-search-functions.md new file mode 100644 index 0000000000000..f15cdafa8b5a1 --- /dev/null +++ b/tidb-cloud-lake/sql/full-text-search-functions.md @@ -0,0 +1,95 @@ +--- +title: 全文搜索函数 +summary: "{{{ .lake }}} 的全文搜索函数可为使用倒排索引建立索引的半结构化 `VARIANT` 数据和纯文本列提供类似搜索引擎的过滤能力。它们非常适合与资产一同存储的 AI 生成元信息,例如来自自动驾驶视频帧的感知结果。" +--- + +# 全文搜索函数 + +{{{ .lake }}} 的全文搜索函数可为使用倒排索引建立索引的半结构化 `VARIANT` 数据和纯文本列提供类似搜索引擎的过滤能力。它们非常适合与资产一同存储的 AI 生成元信息,例如来自自动驾驶视频帧的感知结果。 + +> **注意:** +> +> {{{ .lake }}} 的搜索函数受 [Elasticsearch Full-Text Search Functions](https://www.elastic.co/guide/en/elasticsearch/reference/current/sql-functions-search.html) 启发。 + +在表定义中,为你计划搜索的列包含倒排索引: + +```sql +CREATE OR REPLACE TABLE frames ( + id INT, + meta VARIANT, + INVERTED INDEX idx_meta (meta) +); +``` + +## 搜索函数 {#search-functions} + +| 函数 | 描述 | 示例 | +|----------|-------------|---------| +| [MATCH](/tidb-cloud-lake/sql/match.md) | 对列出的列执行按相关性排序的搜索。 | `MATCH('summary, tags', 'traffic light red')` | +| [QUERY](/tidb-cloud-lake/sql/query.md) | 对 Lucene 风格的查询表达式进行求值,包括嵌套的 `VARIANT` 字段。 | `QUERY('meta.signals.traffic_light:red')` | +| [SCORE](/tidb-cloud-lake/sql/score.md) | 与 `MATCH` 或 `QUERY` 一起使用时,返回当前行的相关性得分。 | `SELECT summary, SCORE() FROM frame_notes WHERE MATCH('summary, tags', 'traffic light red')` | + +## 查询语法示例 {#query-syntax-examples} + +### 示例:单个关键字 {#example-single-keyword} + +```sql +SELECT id, meta['frame']['timestamp'] AS ts +FROM frames +WHERE QUERY('meta.detections.label:pedestrian') +LIMIT 100; +``` + +### 示例:布尔 AND {#example-boolean-and} + +```sql +SELECT id, meta['frame']['timestamp'] AS ts +FROM frames +WHERE QUERY('meta.signals.traffic_light:red AND meta.vehicle.lane:center') +LIMIT 100; +``` + +### 示例:布尔 OR {#example-boolean-or} + +```sql +SELECT id, meta['frame']['timestamp'] AS ts +FROM frames +WHERE QUERY('meta.signals.traffic_light:red OR meta.detections.label:bike') +LIMIT 100; +``` + +### 示例:IN 列表 {#example-in-list} + +```sql +SELECT id, meta['frame']['timestamp'] AS ts +FROM frames +WHERE QUERY('meta.tags:IN [stop urban]') +LIMIT 100; +``` + +### 示例:包含端点的范围 {#example-inclusive-range} + +```sql +SELECT id, meta['frame']['timestamp'] AS ts +FROM frames +WHERE QUERY('meta.vehicle.speed_kmh:[0 TO 10]') +LIMIT 100; +``` + +### 示例:不包含端点的范围 {#example-exclusive-range} + +```sql +SELECT id, meta['frame']['timestamp'] AS ts +FROM frames +WHERE QUERY('meta.vehicle.speed_kmh:{0 TO 10}') +LIMIT 100; +``` + +### 示例:字段加权 {#example-boosted-fields} + +```sql +SELECT id, meta['frame']['timestamp'] AS ts, SCORE() +FROM frames +WHERE QUERY('meta.signals.traffic_light:red^1.0 AND meta.tags:urban^2.0') +LIMIT 100; +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/fuse-block.md b/tidb-cloud-lake/sql/fuse-block.md new file mode 100644 index 0000000000000..043763f27e6ce --- /dev/null +++ b/tidb-cloud-lake/sql/fuse-block.md @@ -0,0 +1,39 @@ +--- +title: FUSE_BLOCK +summary: 返回表的最新或指定快照的 block 信息。有关 {{{ .lake }}} 中 block 的更多信息,请参阅 What are Snapshot, Segment, and Block?。 +--- + +# FUSE_BLOCK + +返回表的最新或指定快照的 block 信息。有关 {{{ .lake }}} 中 block 的更多信息,请参阅 [Snapshot、Segment 和 Block 是什么?](/tidb-cloud-lake/sql/optimize-table.md#-lake--data-storage-snapshot-segment-and-block)。 + +该命令返回某个快照所引用的每个 parquet 文件的位置信息。这使下游应用能够访问并使用存储在这些文件中的数据。 + +另请参阅: + +- [FUSE_SNAPSHOT](/tidb-cloud-lake/sql/fuse-snapshot.md) +- [FUSE_SEGMENT](/tidb-cloud-lake/sql/fuse-segment.md) + +## 语法 {#syntax} + +```sql +FUSE_BLOCK('', ''[, '']) +``` + +## 示例 {#examples} + +```sql +CREATE TABLE mytable(c int); +INSERT INTO mytable values(1); +INSERT INTO mytable values(2); + +SELECT * FROM FUSE_BLOCK('default', 'mytable'); + +--- ++----------------------------------+----------------------------+----------------------------------------------------+------------+----------------------------------------------------+-------------------+ +| snapshot_id | timestamp | block_location | block_size | bloom_filter_location | bloom_filter_size | ++----------------------------------+----------------------------+----------------------------------------------------+------------+----------------------------------------------------+-------------------+ +| 51e84b56458f44269b05a059b364a659 | 2022-09-15 07:14:14.137268 | 1/7/_b/39a6dbbfd9b44ad5a8ec8ab264c93cf5_v0.parquet | 4 | 1/7/_i/39a6dbbfd9b44ad5a8ec8ab264c93cf5_v1.parquet | 221 | +| 51e84b56458f44269b05a059b364a659 | 2022-09-15 07:14:14.137268 | 1/7/_b/d0ee9688c4d24d6da86acd8b0d6f4fad_v0.parquet | 4 | 1/7/_i/d0ee9688c4d24d6da86acd8b0d6f4fad_v1.parquet | 219 | ++----------------------------------+----------------------------+----------------------------------------------------+------------+----------------------------------------------------+-------------------+ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/fuse-column.md b/tidb-cloud-lake/sql/fuse-column.md new file mode 100644 index 0000000000000..22f54ff35f3bd --- /dev/null +++ b/tidb-cloud-lake/sql/fuse-column.md @@ -0,0 +1,38 @@ +--- +title: FUSE_COLUMN +summary: 返回表的最新或指定快照的列信息。有关 {{{ .lake }}} 中 block 的更多信息,请参阅什么是 Snapshot、Segment 和 Block?。 +--- + +# FUSE_COLUMN + +返回表的最新或指定快照的列信息。有关 {{{ .lake }}} 中 block 的更多信息,请参阅[什么是 Snapshot、Segment 和 Block?](/tidb-cloud-lake/sql/optimize-table.md#-lake--data-storage-snapshot-segment-and-block)。 + +另请参阅: + +- [FUSE_SNAPSHOT](/tidb-cloud-lake/sql/fuse-snapshot.md) +- [FUSE_SEGMENT](/tidb-cloud-lake/sql/fuse-segment.md) +- [FUSE_BLOCK](/tidb-cloud-lake/sql/fuse-block.md) + +## 语法 {#syntax} + +```sql +FUSE_COLUMN('', ''[, '']) +``` + +## 示例 {#examples} + +```sql +CREATE TABLE mytable(c int); +INSERT INTO mytable values(1); +INSERT INTO mytable values(2); + +SELECT * FROM FUSE_COLUMN('default', 'mytable'); + +--- ++----------------------------------+----------------------------+---------------------------------------------------------+------------+-----------+-----------+-------------+-------------+-----------+--------------+------------------+ +| snapshot_id | timestamp | block_location | block_size | file_size | row_count | column_name | column_type | column_id | block_offset | bytes_compressed | ++----------------------------------+----------------------------+---------------------------------------------------------+------------+-----------+-----------+-------------+-------------+-----------+--------------+------------------+ +| 3faefc1a9b6a48f388a8b59228dd06c1 | 2023-07-18 03:06:30.276502 | 1/118746/_b/44df130c207745cb858928135d39c1c0_v2.parquet | 4 | 196 | 1 | c | Int32 | 0 | 8 | 14 | +| 3faefc1a9b6a48f388a8b59228dd06c1 | 2023-07-18 03:06:30.276502 | 1/118746/_b/b6f8496d7e3f4f62a89c09572840cf70_v2.parquet | 4 | 196 | 1 | c | Int32 | 0 | 8 | 14 | ++----------------------------------+----------------------------+---------------------------------------------------------+------------+-----------+-----------+-------------+-------------+-----------+--------------+------------------+ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/fuse-encoding.md b/tidb-cloud-lake/sql/fuse-encoding.md new file mode 100644 index 0000000000000..116809cfb3ffc --- /dev/null +++ b/tidb-cloud-lake/sql/fuse-encoding.md @@ -0,0 +1,57 @@ +--- +title: FUSE_ENCODING +summary: 返回应用于表中特定列的编码类型。它可帮助你了解数据在表中如何以原生格式被压缩和存储。 +--- + +# FUSE_ENCODING + +返回应用于表中特定列的编码类型。它可帮助你了解数据在表中如何以原生格式被压缩和存储。 + +## 语法 {#syntax} + +```sql +FUSE_ENCODING('', '', '') +``` + +该函数返回一个包含以下列的结果集: + +| 列名 | 数据类型 | 描述 | +|-------------------|------------------|------------------------------------------------------------------------------------------------------------------------------------------| +| VALIDITY_SIZE | Nullable(UInt32) | 位图值的大小,该位图用于指示列中每一行是否具有非空值。此位图用于跟踪该列数据中空值的存在或缺失。 | +| COMPRESSED_SIZE | UInt32 | 列数据压缩后的大小。 | +| UNCOMPRESSED_SIZE | UInt32 | 应用编码前的列数据大小。 | +| LEVEL_ONE | String | 应用于该列的主要或初始编码。 | +| LEVEL_TWO | Nullable(String) | 在初始编码之后应用于该列的次级或递归编码方法。 | + +## 示例 {#examples} + +```sql +-- Create a table with an integer column 'c' and apply 'Lz4' compression +CREATE TABLE t(c INT) STORAGE_FORMAT = 'native' COMPRESSION = 'lz4'; + +-- Insert data into the table. +INSERT INTO t SELECT number FROM numbers(2048); + +-- Analyze the encoding for column 'c' in table 't' +SELECT LEVEL_ONE, LEVEL_TWO, COUNT(*) +FROM FUSE_ENCODING('default', 't', 'c') +GROUP BY LEVEL_ONE, LEVEL_TWO; + +level_one |level_two|count(*)| +------------+---------+--------+ +DeltaBitpack| | 1| + +-- Insert 2,048 rows with the value 1 into the table 't' +INSERT INTO t (c) +SELECT 1 +FROM numbers(2048); + +SELECT LEVEL_ONE, LEVEL_TWO, COUNT(*) +FROM FUSE_ENCODING('default', 't', 'c') +GROUP BY LEVEL_ONE, LEVEL_TWO; + +level_one |level_two|count(*)| +------------+---------+--------+ +OneValue | | 1| +DeltaBitpack| | 1| +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/fuse-engine-tables.md b/tidb-cloud-lake/sql/fuse-engine-tables.md new file mode 100644 index 0000000000000..87c8031ed690e --- /dev/null +++ b/tidb-cloud-lake/sql/fuse-engine-tables.md @@ -0,0 +1,207 @@ +--- +title: Fuse Engine 表 +summary: "{{{ .lake }}} 使用 Fuse Engine 作为其默认存储引擎,提供类似 Git 的数据管理系统。" +--- + +# Fuse Engine 表 + +## 概述 {#overview} + +{{{ .lake }}} 使用 Fuse Engine 作为其默认存储引擎,提供类似 Git 的数据管理系统,具备以下特性: + +- **基于快照的架构**:可以查询和恢复任意时间点的数据,并保留数据变更历史以便恢复 +- **高性能**:针对分析型负载进行了优化,支持自动索引和布隆过滤器 +- **高效存储**:使用 Parquet 格式和高压缩率,以获得最佳存储效率 +- **灵活配置**:支持自定义压缩、索引和存储选项 +- **数据维护**:支持自动数据保留、快照管理和变更跟踪能力 + +## 何时使用 Fuse Engine {#when-to-use-fuse-engine} + +适用于以下场景: + +- **分析**:使用列式存储的 OLAP 查询 +- **数据仓库**:大规模历史数据 +- **时间旅行**:访问历史版本数据 +- **云存储**:针对对象存储进行了优化 + +## 语法 {#syntax} + +```sql +CREATE TABLE ( + +) [ENGINE = FUSE] +[CLUSTER BY ( [, , ...] )] +[]; +``` + +有关 `CREATE TABLE` 语法的更多详细信息,请参见 [CREATE TABLE](/tidb-cloud-lake/sql/create-table.md)。 + +## 参数 {#parameters} + +以下是创建 Fuse Engine 表时的主要参数: + +### `ENGINE` {#engine} + +**说明:** 如果未显式指定引擎,{{{ .lake }}} 会默认使用 Fuse Engine 创建表,这等同于 `ENGINE = FUSE`。 + +### `CLUSTER BY` {#cluster-by} + +**说明:** 指定由多个表达式组成的数据的排序方法。更多信息,请参见 [Cluster Key](/tidb-cloud-lake/sql/cluster-key.md)。 + +### `` + +**说明:** Fuse Engine 提供了多种选项(不区分大小写),可用于自定义表属性。 + +- 详细信息请参见 [Fuse Engine 选项](#fuse-engine-options)。 +- 多个选项之间使用空格分隔。 +- 使用 [ALTER TABLE](/tidb-cloud-lake/sql/alter-table.md#fuse-engine-options) 修改表选项。 +- 使用 [SHOW CREATE TABLE](/tidb-cloud-lake/sql/show-create-table.md) 查看表选项。 + +## Fuse Engine 选项 {#fuse-engine-options} + +以下是可用的 Fuse Engine 选项,按用途分组: + +### `compression` {#compression} + +- **语法:** `compression = ''` +- **说明:** 指定引擎的压缩方法。可选压缩方式包括 lz4、zstd、snappy 或 none。在对象存储中默认使用 zstd,在文件系统(fs)存储中默认使用 lz4。 + +### `snapshot_loc` {#snapshot-loc} + +- **语法:** `snapshot_loc = ''` +- **说明:** 以字符串格式指定位置参数,从而可以在不复制数据的情况下轻松共享表。 + +### `block_size_threshold` {#block-size-threshold} + +- **语法:** `block_size_threshold = ` +- **说明:** 指定最大 block 大小(单位为字节)。默认值为 104,857,600 字节。 + +### `block_per_segment` {#block-per-segment} + +- **语法:** `block_per_segment = ` +- **说明:** 指定一个 segment 中的最大 block 数量。默认值为 1,000。 + +### `row_per_block` {#row-per-block} + +- **语法:** `row_per_block = ` +- **说明:** 指定一个文件中的最大行数。默认值为 1,000,000。 + +### `bloom_index_columns` {#bloom-index-columns} + +- **语法:** `bloom_index_columns = ' [, ...]'` +- **说明:** 指定用于 bloom index 的列。这些列的数据类型可以是 Map、Number、String、Date 或 Timestamp。如果未指定具体列,则默认会在所有受支持的列上创建 bloom index。`bloom_index_columns=''` 会禁用 bloom index。 + +### `bloom_index_type` {#bloom-index-type} + +- **语法:** `bloom_index_type = 'xor8' | 'binary_fuse32'` +- **说明:** 指定 bloom index 使用的过滤算法。默认值为 `xor8`。对于点查负载较重的表,建议使用 `binary_fuse32`——它能提供更低的误判率,但代价是更大的索引大小(约为 `xor8` 的 4 倍)。 + + 请注意,`ALTER TABLE ... SET OPTIONS(bloom_index_type = ...)` 仅影响新写入的数据和重建后的 bloom index。现有的 `xor8` 索引文件和新的 `binary_fuse32` 索引文件可以在同一张表中共存。 + + **示例:** + + ```sql + -- Set bloom_index_type at table creation + CREATE TABLE t (a INT) bloom_index_type = 'binary_fuse32'; + + -- Change bloom_index_type for an existing table (affects new writes only) + ALTER TABLE t SET OPTIONS(bloom_index_type = 'binary_fuse32'); + + -- Revert to xor8 + ALTER TABLE t SET OPTIONS(bloom_index_type = 'xor8'); + ``` + +### `change_tracking` {#change-tracking} + +- **语法:** `change_tracking = True / False` +- **说明:** 在 Fuse Engine 中将此选项设置为 `True` 后,可以为表跟踪变更。为表创建 stream 时,会自动将 `change_tracking` 设置为 `True`,并向表中引入额外的隐藏列作为变更跟踪元信息。更多信息,请参见 [Stream 工作原理](/tidb-cloud-lake/guides/track-and-transform-data-via-streams.md)。 + +### `data_retention_period_in_hours` {#data-retention-period-in-hours} + +- **语法:** `data_retention_period_in_hours = ` +- **说明:** 指定表数据的保留小时数。最小值为 1 小时。最大值由 {{{ .lake }}} 服务配置决定;如果未指定,则默认值为 2,160 小时(90 天 x 24 小时)。 + +### `enable_auto_vacuum` {#enable-auto-vacuum} + +- **语法:** `enable_auto_vacuum = 0 / 1` +- **说明:** 控制表是否在发生变异时自动触发 vacuum 操作。该选项既可以作为适用于所有表的全局设置,也可以在表级别进行配置。表级选项的优先级高于同名的会话/全局设置。启用后(设置为 1),在 INSERT 或 ALTER TABLE 等变异操作之后会自动触发 vacuum,并根据配置的数据保留策略清理表数据。 + +**示例:** + +```sql +-- Set enable_auto_vacuum globally for all tables across all sessions +SET GLOBAL enable_auto_vacuum = 1; + +-- Create a table with auto vacuum disabled (overrides global setting) +CREATE OR REPLACE TABLE t1 (id INT) ENABLE_AUTO_VACUUM = 0; +INSERT INTO t1 VALUES(1); -- Won't trigger vacuum despite global setting + +-- Create another table that inherits the global setting +CREATE OR REPLACE TABLE t2 (id INT); +INSERT INTO t2 VALUES(1); -- Will trigger vacuum due to global setting + +-- Enable auto vacuum for an existing table +ALTER TABLE t1 SET OPTIONS(ENABLE_AUTO_VACUUM = 1); +INSERT INTO t1 VALUES(2); -- Now will trigger vacuum + +-- Table option takes precedence over global settings +SET GLOBAL enable_auto_vacuum = 0; -- Turn off globally +-- t1 will still vacuum because table setting overrides global +INSERT INTO t1 VALUES(3); -- Will still trigger vacuum +INSERT INTO t2 VALUES(2); -- Won't trigger vacuum anymore +``` + +### `data_retention_num_snapshots_to_keep` {#data-retention-num-snapshots-to-keep} + +- **语法:** `data_retention_num_snapshots_to_keep = ` +- **说明:** 指定在 vacuum 操作期间要保留的快照数量。该选项既可以作为适用于所有表的全局设置,也可以在表级别进行配置。表级选项的优先级高于同名的会话/全局设置。设置后,vacuum 操作完成后只会保留指定数量的最新快照。该选项会覆盖 `data_retention_time_in_days` 设置。如果设置为 0,则会忽略此设置。此选项与 `enable_auto_vacuum` 设置配合使用,可对快照保留策略进行更细粒度的控制。 + +**示例:** + +```sql +-- Set global retention to 10 snapshots for all tables across all sessions +SET GLOBAL data_retention_num_snapshots_to_keep = 10; + +-- Create a table with custom snapshot retention (overrides global setting) +CREATE OR REPLACE TABLE t1 (id INT) + enable_auto_vacuum = 1 + data_retention_num_snapshots_to_keep = 5; + +-- Create another table that inherits the global setting +CREATE OR REPLACE TABLE t2 (id INT) enable_auto_vacuum = 1; + +-- When vacuum is triggered: +-- t1 will keep 5 snapshots (table setting) +-- t2 will keep 10 snapshots (global setting) + +-- Change global setting +SET GLOBAL data_retention_num_snapshots_to_keep = 20; + +-- Table options still take precedence: +-- t1 will still keep only 5 snapshots +-- t2 will now keep 20 snapshots + +-- Modify snapshot retention for an existing table +ALTER TABLE t1 SET OPTIONS(data_retention_num_snapshots_to_keep = 3); +-- Now t1 will keep 3 snapshots when vacuum is triggered +``` + +### `enable_schema_evolution` {#enable-schema-evolution} + +- **语法:** + + `enable_schema_evolution = True / False` + +- **说明:** + + 控制在执行 `COPY INTO` 操作期间是否可以自动进行表结构演进。启用后(设置为 `True`),当负载 Parquet 文件且其 schema 中包含目标表中不存在的列时,{{{ .lake }}} 会自动将缺失的列添加到表中。现有行中缺失的值会填充为 `NULL`。更多信息,请参见 [Schema Evolution](/tidb-cloud-lake/guides/schema-evolution.md)。 + +**示例:** + +```sql +-- Enable schema evolution for an existing table +ALTER TABLE invoices SET OPTIONS(ENABLE_SCHEMA_EVOLUTION = true); + +-- Create a new table with schema evolution enabled +CREATE OR REPLACE TABLE invoices (order_id INT) ENABLE_SCHEMA_EVOLUTION = true; +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/fuse-segment.md b/tidb-cloud-lake/sql/fuse-segment.md new file mode 100644 index 0000000000000..4a04a1c46f408 --- /dev/null +++ b/tidb-cloud-lake/sql/fuse-segment.md @@ -0,0 +1,47 @@ +--- +title: FUSE_SEGMENT +summary: 返回指定表快照的 segment 信息。有关 {{{ .lake }}} 中 segment 的更多信息,请参阅什么是 Snapshot、Segment 和 Block?。 +--- + +# FUSE_SEGMENT + +返回指定表快照的 segment 信息。有关 {{{ .lake }}} 中 segment 的更多信息,请参阅 [什么是 Snapshot、Segment 和 Block?](/tidb-cloud-lake/sql/optimize-table.md#-lake--data-storage-snapshot-segment-and-block)。 + +另请参阅: + +- [FUSE_SNAPSHOT](/tidb-cloud-lake/sql/fuse-snapshot.md) +- [FUSE_BLOCK](/tidb-cloud-lake/sql/fuse-block.md) + +## 语法 {#syntax} + +```sql +FUSE_SEGMENT('', '','') +``` + +## 示例 {#examples} + +```sql +CREATE TABLE mytable(c int); +INSERT INTO mytable values(1); +INSERT INTO mytable values(2); + +-- Obtain a snapshot ID +SELECT snapshot_id FROM FUSE_SNAPSHOT('default', 'mytable') limit 1; + +--- ++----------------------------------+ +| snapshot_id | ++----------------------------------+ +| 82c572947efa476892bd7c0635158ba2 | ++----------------------------------+ + +SELECT * FROM FUSE_SEGMENT('default', 'mytable', '82c572947efa476892bd7c0635158ba2'); + +--- ++----------------------------------------------------+----------------+-------------+-----------+--------------------+------------------+ +| file_location | format_version | block_count | row_count | bytes_uncompressed | bytes_compressed | ++----------------------------------------------------+----------------+-------------+-----------+--------------------+------------------+ +| 1/319/_sg/d35fe7bf99584301b22e8f6a8a9c97f9_v1.json | 1 | 1 | 1 | 4 | 184 | +| 1/319/_sg/c261059d47c840e1b749222dabb4b2bb_v1.json | 1 | 1 | 1 | 4 | 184 | ++----------------------------------------------------+----------------+-------------+-----------+--------------------+------------------+ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/fuse-snapshot.md b/tidb-cloud-lake/sql/fuse-snapshot.md new file mode 100644 index 0000000000000..a65e2520f72eb --- /dev/null +++ b/tidb-cloud-lake/sql/fuse-snapshot.md @@ -0,0 +1,38 @@ +--- +title: FUSE_SNAPSHOT +summary: 返回表的快照信息。有关 {{{ .lake }}} 中快照的更多信息,请参阅什么是 Snapshot、Segment 和 Block?。 +--- + +# FUSE_SNAPSHOT + +返回表的快照信息。有关 {{{ .lake }}} 中快照的更多信息,请参阅[什么是 Snapshot、Segment 和 Block?](/tidb-cloud-lake/sql/optimize-table.md#-lake--data-storage-snapshot-segment-and-block)。 + +另请参阅: + +- [FUSE_SEGMENT](/tidb-cloud-lake/sql/fuse-segment.md) +- [FUSE_BLOCK](/tidb-cloud-lake/sql/fuse-block.md) + +## 语法 {#syntax} + +```sql +FUSE_SNAPSHOT('', '') +``` + +## 示例 {#examples} + +```sql +CREATE TABLE mytable(a int, b int) CLUSTER BY(a+1); + +INSERT INTO mytable VALUES(1,1),(3,3); +INSERT INTO mytable VALUES(2,2),(5,5); +INSERT INTO mytable VALUES(4,4); + +SELECT * FROM FUSE_SNAPSHOT('default','mytable'); + +--- +| snapshot_id | snapshot_location | format_version | previous_snapshot_id | segment_count | block_count | row_count | bytes_uncompressed | bytes_compressed | index_size | timestamp | +|----------------------------------|------------------------------------------------------------|----------------|----------------------------------|---------------|-------------|-----------|--------------------|------------------|------------|----------------------------| +| a13d211b7421432898a3786848b8ced3 | 670655/783287/_ss/a13d211b7421432898a3786848b8ced3_v1.json | 1 | \N | 1 | 1 | 2 | 16 | 290 | 363 | 2022-09-19 14:51:52.860425 | +| cf08e6af6c134642aeb76bc81e6e7580 | 670655/783287/_ss/cf08e6af6c134642aeb76bc81e6e7580_v1.json | 1 | a13d211b7421432898a3786848b8ced3 | 2 | 2 | 4 | 32 | 580 | 726 | 2022-09-19 14:52:15.282943 | +| 1bd4f68b831a402e8c42084476461aa1 | 670655/783287/_ss/1bd4f68b831a402e8c42084476461aa1_v1.json | 1 | cf08e6af6c134642aeb76bc81e6e7580 | 3 | 3 | 5 | 40 | 862 | 1085 | 2022-09-19 14:52:20.284347 | +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/fuse-statistic.md b/tidb-cloud-lake/sql/fuse-statistic.md new file mode 100644 index 0000000000000..7d9ff508dbd0a --- /dev/null +++ b/tidb-cloud-lake/sql/fuse-statistic.md @@ -0,0 +1,10 @@ +--- +title: FUSE_STATISTIC +summary: 注意:此函数已弃用。请改用 SHOW STATISTICS 查看表统计信息。 +--- + +# FUSE_STATISTIC + +> **注意:** +> +> 此函数已弃用。请改用 [SHOW STATISTICS](/tidb-cloud-lake/sql/show-statistics.md) 查看表统计信息。 \ No newline at end of file diff --git a/tidb-cloud-lake/sql/fuse-tag.md b/tidb-cloud-lake/sql/fuse-tag.md new file mode 100644 index 0000000000000..65acdfa733f1e --- /dev/null +++ b/tidb-cloud-lake/sql/fuse-tag.md @@ -0,0 +1,48 @@ +--- +title: FUSE_TAG +summary: 返回表的快照标签。有关快照标签的更多信息,请参见 Snapshot Tags。 +--- + +# FUSE_TAG + +返回表的快照标签。有关快照标签的更多信息,请参见 [快照标签](/tidb-cloud-lake/sql/table-versioning.md#snapshot-tags)。 + +## 语法 {#syntax} + +```sql +FUSE_TAG('', '') +``` + +## 输出列 {#output-columns} + +| 列名 | 类型 | 描述 | +|---------------------|--------------------|-----------------------------------------------------------------------------| +| name | STRING | 标签名称 | +| snapshot_location | STRING | 该标签指向的快照文件 | +| expire_at | TIMESTAMP (nullable) | 过期时间戳;在 CREATE SNAPSHOT TAG 中使用 `RETAIN` 时设置 | + +## 示例 {#examples} + +```sql +SET enable_experimental_table_ref = 1; + +CREATE TABLE mytable(a INT, b INT); + +INSERT INTO mytable VALUES(1, 1),(2, 2); + +-- Create a snapshot tag +ALTER TABLE mytable CREATE TAG v1; + +INSERT INTO mytable VALUES(3, 3); + +-- Create another tag with expiration +ALTER TABLE mytable CREATE TAG temp RETAIN 2 DAYS; + +SELECT * FROM FUSE_TAG('default', 'mytable'); + +--- +| name | snapshot_location | expire_at | +|------|------------------------------------------------------------|----------------------------| +| v1 | 1/319/_ss/a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4_v4.mpk | NULL | +| temp | 1/319/_ss/f6e5d4c3b2a1f6e5d4c3b2a1f6e5d4c3_v4.mpk | 2025-06-15 10:30:00.000000 | +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/fuse-time-travel-size.md b/tidb-cloud-lake/sql/fuse-time-travel-size.md new file mode 100644 index 0000000000000..49e169e2c1085 --- /dev/null +++ b/tidb-cloud-lake/sql/fuse-time-travel-size.md @@ -0,0 +1,52 @@ +--- +title: FUSE_TIME_TRAVEL_SIZE +summary: 计算表的历史数据(用于 Time Travel)的存储大小。 +--- + +# FUSE_TIME_TRAVEL_SIZE + +计算表的历史数据(用于 Time Travel)的存储大小。 + +## 语法 {#syntax} + +```sql +-- Calculate historical data size for all tables in all databases +SELECT ... +FROM fuse_time_travel_size(); + +-- Calculate historical data size for all tables in a specified database +SELECT ... +FROM fuse_time_travel_size(''); + +-- Calculate historical data size for a specified table in a specified database +SELECT ... +FROM fuse_time_travel_size('', ''); +``` + +## 输出 {#output} + +该函数返回一个结果集,包含以下列: + +| 列 | 描述 | +|----------------------------------|-------------------------------------------------------------------------------------------------------| +| `database_name` | 表所在数据库的名称。 | +| `table_name` | 表名。 | +| `is_dropped` | 表示该表是否已被删除(已删除的表为 `true`,否则为 `false`)。 | +| `time_travel_size` | 该表历史数据(用于 Time Travel)的总存储大小,单位为字节。 | +| `latest_snapshot_size` | 该表最新快照的存储大小,单位为字节。 | +| `data_retention_period_in_hours` | Time Travel 数据的保留时间(单位为小时)(`NULL` 表示使用默认保留策略)。 | +| `error` | 检索存储大小时遇到的错误(如果未发生错误,则为 `NULL`)。 | + +## 示例 {#examples} + +以下示例计算 `default` 数据库中所有表的历史数据大小: + +```sql +SELECT * FROM fuse_time_travel_size('default') + +┌───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ +│ database_name │ table_name │ is_dropped │ time_travel_size │ latest_snapshot_size │ data_retention_period_in_hours │ error │ +├───────────────┼────────────┼────────────┼──────────────────┼──────────────────────┼────────────────────────────────┼──────────────────┤ +│ default │ books │ true │ 2810 │ 1490 │ NULL │ NULL │ +└───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/fuse-vacuum-temporary-table.md b/tidb-cloud-lake/sql/fuse-vacuum-temporary-table.md new file mode 100644 index 0000000000000..72b02a884f19f --- /dev/null +++ b/tidb-cloud-lake/sql/fuse-vacuum-temporary-table.md @@ -0,0 +1,43 @@ +--- +title: FUSE_VACUUM_TEMPORARY_TABLE +summary: 临时表通常会在会话结束时自动清理(详见 CREATE TEMP TABLE)。但是,由于查询节点崩溃或会话异常终止等事件,此过程可能失败,从而留下孤立的临时文件。 +--- + +# FUSE_VACUUM_TEMPORARY_TABLE + +## 概述 {#overview} + +临时表通常会在会话结束时自动清理(详见 [CREATE TEMP TABLE](/tidb-cloud-lake/sql/create-temp-table.md))。但是,由于查询节点崩溃或会话异常终止等事件,此过程可能失败,从而留下孤立的临时文件。 + +`FUSE_VACUUM_TEMPORARY_TABLE()` 用于手动删除这些遗留文件,以回收存储空间。 + +**何时使用此函数:** + +- 在已知系统故障或会话异常终止之后。 +- 当你怀疑孤立的临时数据正在占用存储空间时。 +- 在容易出现此类问题的环境中,作为周期性维护任务使用。 + +## 操作安全性 {#operational-safety} + +`FUSE_VACUUM_TEMPORARY_TABLE()` 函数被设计为一种安全且可靠的操作。 + +- **仅针对临时数据:** 它只会识别并删除属于临时表的孤立数据文件和元信息文件。 +- **不会影响普通表:** 该函数不会影响任何常规的持久化表及其数据。其作用域严格限定为清理未被引用的临时表残留内容。 + +## 语法 {#syntax} + +```sql +FUSE_VACUUM_TEMPORARY_TABLE(); +``` + +## 示例 {#examples} + +```sql +SELECT * FROM FUSE_VACUUM_TEMPORARY_TABLE(); + +┌────────┐ +│ result │ +├────────┤ +│ Ok │ +└────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/fuse-virtual-column.md b/tidb-cloud-lake/sql/fuse-virtual-column.md new file mode 100644 index 0000000000000..8e254fca20c37 --- /dev/null +++ b/tidb-cloud-lake/sql/fuse-virtual-column.md @@ -0,0 +1,51 @@ +--- +title: FUSE_VIRTUAL_COLUMN +summary: 返回表的最新或指定快照的虚拟列信息。详情参见 Virtual Column。 +--- + +# FUSE_VIRTUAL_COLUMN + +返回表的最新或指定快照的虚拟列信息。详情参见 [虚拟列](/tidb-cloud-lake/guides/virtual-column.md)。 + +## 语法 {#syntax} + +```sql +FUSE_VIRTUAL_COLUMN('', ''[, '']) +``` + +## 示例 {#examples} + +```sql +CREATE TABLE test(id int, val variant); + +INSERT INTO + test +VALUES + ( + 1, + '{"id":1,"name":"datalake"}' + ), + ( + 2, + '{"id":2,"name":"databricks"}' + ); + +SELECT * FROM FUSE_VIRTUAL_COLUMN('default', 'test'); + +╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ +│ snapshot_id │ timestamp │ virtual_block_ │ virtual_block_ │ row_count │ column_name │ column_type │ column_id │ block_offset │ bytes_compress │ +│ String │ Timestamp │ location │ size │ UInt64 │ String │ String │ UInt32 │ UInt64 │ ed │ +│ │ │ String │ UInt64 │ │ │ │ │ │ UInt64 │ +├────────────────┼────────────────┼────────────────┼────────────────┼───────────┼─────────────┼─────────────┼────────────┼──────────────┼────────────────┤ +│ 0196c3aa7cc97f │ 2025-05-12 08: │ 1/385366/_vb/h │ 632 │ 2 │ val['id'] │ UInt64 NULL │ 3000000000 │ 4 │ 48 │ +│ e69995765add1b │ 44:12.361000 │ 0196c8d0d8c976 │ │ │ │ │ │ │ │ +│ a3bd │ │ d19de8bfdd32a7 │ │ │ │ │ │ │ │ +│ │ │ 0a01_v2.parque │ │ │ │ │ │ │ │ +│ │ │ t │ │ │ │ │ │ │ │ +│ 0196c3aa7cc97f │ 2025-05-12 08: │ 1/385366/_vb/h │ 632 │ 2 │ val['name'] │ String NULL │ 3000000001 │ 52 │ 58 │ +│ e69995765add1b │ 44:12.361000 │ 0196c8d0d8c976 │ │ │ │ │ │ │ │ +│ a3bd │ │ d19de8bfdd32a7 │ │ │ │ │ │ │ │ +│ │ │ 0a01_v2.parque │ │ │ │ │ │ │ │ +│ │ │ t │ │ │ │ │ │ │ │ +╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/gen-random-uuid.md b/tidb-cloud-lake/sql/gen-random-uuid.md new file mode 100644 index 0000000000000..586e4ae50a212 --- /dev/null +++ b/tidb-cloud-lake/sql/gen-random-uuid.md @@ -0,0 +1,54 @@ +--- +title: GEN_RANDOM_UUID +summary: 从 1.2.658 版本开始,基于版本 7 生成随机 UUID。此前,此函数基于版本 4 生成 UUID。 +--- + +# GEN_RANDOM_UUID + +从 1.2.658 版本开始,基于版本 7 生成随机 UUID。此前,此函数基于版本 4 生成 UUID。 + +## 语法 {#syntax} + +```sql +GEN_RANDOM_UUID() +``` + +## 别名 {#aliases} + +- [UUID](/tidb-cloud-lake/sql/uuid-sql.md) + +## 为什么使用 UUID v7? {#why-use-uuid-v7} + +- **基于时间的排序**:UUID v7 包含时间戳,因此可以按照创建时间对事件或记录进行时间顺序排序。这在需要跟踪操作先后顺序时尤其有用。 + +- **按时间先后排序**:UUID v7 可确保 UUID 按创建时间有序的,这非常适合需要按时间对事件进行排序的场景,例如事件日志或维护审计追踪。 + +## 版本信息 {#version-information} + +- 1.2.658 及之后的版本:UUID 版本从 v4 升级为 v7。 +- 1.2.658 之前的版本:UUID 生成功能基于 v4。 + +## 示例 {#examples} + +在记录事件的应用中,保持操作的正确顺序至关重要。UUID v7 可确保每个事件都按时间有序,便于按时间顺序跟踪操作。 + +```sql +-- Log a user logging in +SELECT GEN_RANDOM_UUID(), 'User logged in' AS event, CURRENT_TIMESTAMP AS event_time; + +-- Log a user making a purchase +SELECT GEN_RANDOM_UUID(), 'User made a purchase' AS event, CURRENT_TIMESTAMP AS event_time; +``` + +这些查询的结果可能如下所示: + +```sql +┌──────────────────────────────────────────────────────────────────────────────────────────┐ +│ gen_random_uuid() │ event │ event_time │ +├──────────────────────────────────────┼──────────────────────┼────────────────────────────┤ +│ 019329e6-26a2-7b01-b9f5-1c3c02600578 │ User logged in │ 2024-11-14 08:59:29.313906 │ +│ 019329e6-329e-73c3-b0a8-a413ce298607 │ User made a purchase │ 2024-11-14 08:59:32.381497 │ +└──────────────────────────────────────────────────────────────────────────────────────────┘ +``` + +请注意,`gen_random_uuid()` 的值是按照事件发生的顺序生成的,因此可以轻松保持时间顺序。 \ No newline at end of file diff --git a/tidb-cloud-lake/sql/generate-series.md b/tidb-cloud-lake/sql/generate-series.md new file mode 100644 index 0000000000000..3dc6585d65d19 --- /dev/null +++ b/tidb-cloud-lake/sql/generate-series.md @@ -0,0 +1,123 @@ +--- +title: GENERATE_SERIES +summary: 生成一个从指定起点开始、到另一个指定终点结束,并可选择指定递增值的数据集。GENERATE_SERIES 函数支持以下数据类型。 +--- + +# GENERATE_SERIES + +生成一个从指定起点开始、到另一个指定终点结束,并可选择指定递增值的数据集。GENERATE_SERIES 函数支持以下数据类型: + +- 整数型 +- 日期 +- 时间戳 + +## 语法 {#syntax} + +```sql +GENERATE_SERIES(, [, ]) +``` + +## 参数 {#arguments} + +| 参数 | 描述 | +|--------------- |------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| start | 起始值,表示序列中的第一个数字、日期或时间戳。 | +| stop | 结束值,表示序列中的最后一个数字、日期或时间戳。 | +| step_interval | 步长间隔,用于确定序列中相邻值之间的差值。对于整数序列,默认值为 1。对于日期序列,默认步长间隔为 1 天。对于时间戳序列,默认步长间隔为 1 微秒。 | + +> **注意:** +> +> 在处理 GENERATE_SERIES 和 RANGE 这类函数时,一个关键区别在于它们的边界特性。GENERATE_SERIES 同时包含左边界和右边界,而 RANGE 仅包含左边界。例如,使用 RANGE(1, 11) 等价于 GENERATE_SERIES(1, 10)。 + +## 返回类型 {#return-type} + +返回一个列表,其中包含从 *start* 到 *stop* 的连续数字值、日期或时间戳序列。 + +## 示例 {#examples} + +### 示例 1:生成数字、日期和时间戳数据 {#example-1-generating-numeric-date-and-timestamp-data} + +```sql +SELECT * FROM GENERATE_SERIES(1, 10, 2); + +generate_series| +---------------+ + 1| + 3| + 5| + 7| + 9| + +SELECT * FROM GENERATE_SERIES('2023-03-20'::date, '2023-03-27'::date); + +generate_series| +---------------+ + 2023-03-20| + 2023-03-21| + 2023-03-22| + 2023-03-23| + 2023-03-24| + 2023-03-25| + 2023-03-26| + 2023-03-27| + +SELECT * FROM GENERATE_SERIES('2023-03-26 00:00'::timestamp, '2023-03-27 12:00'::timestamp, 86400000000); + +generate_series | +-------------------+ +2023-03-26 00:00:00| +2023-03-27 00:00:00| +``` + +### 示例 2:填补查询结果中的空缺 {#example-2-filling-query-result-gaps} + +本示例使用 GENERATE_SERIES 函数和 left join 运算符,处理由于特定范围内信息缺失而导致的查询结果空缺。 + +```sql +CREATE TABLE t_metrics ( + date Date, + value INT +); + +INSERT INTO t_metrics VALUES + ('2020-01-01', 200), + ('2020-01-01', 300), + ('2020-01-04', 300), + ('2020-01-04', 300), + ('2020-01-05', 400), + ('2020-01-10', 700); + +SELECT date, SUM(value), COUNT() FROM t_metrics GROUP BY date ORDER BY date; + +date |sum(value)|count()| +----------+----------+-------+ +2020-01-01| 500| 2| +2020-01-04| 600| 2| +2020-01-05| 400| 1| +2020-01-10| 700| 1| +``` + +要填补 2020 年 1 月 1 日到 1 月 10 日之间的空缺,请使用以下查询: + +```sql +SELECT t.date, COALESCE(SUM(t_metrics.value), 0), COUNT(t_metrics.value) +FROM generate_series( + '2020-01-01'::Date, + '2020-01-10'::Date +) AS t(date) +LEFT JOIN t_metrics ON t_metrics.date = t.date +GROUP BY t.date ORDER BY t.date; + +date |coalesce(sum(t_metrics.value), 0)|count(t_metrics.value)| +----------+---------------------------------+----------------------+ +2020-01-01| 500| 2| +2020-01-02| 0| 0| +2020-01-03| 0| 0| +2020-01-04| 600| 2| +2020-01-05| 400| 1| +2020-01-06| 0| 0| +2020-01-07| 0| 0| +2020-01-08| 0| 0| +2020-01-09| 0| 0| +2020-01-10| 700| 1| +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/geo-distance.md b/tidb-cloud-lake/sql/geo-distance.md new file mode 100644 index 0000000000000..cd2459549f4ee --- /dev/null +++ b/tidb-cloud-lake/sql/geo-distance.md @@ -0,0 +1,39 @@ +--- +title: GEO_DISTANCE +summary: 返回地球上两点之间以米为单位的近似距离。 +--- + +# GEO_DISTANCE + +返回地球上两点之间以米为单位的近似距离。点的位置使用经度和纬度(单位为度)指定,距离基于 WGS84 的近似方法计算。 + +## 语法 {#syntax} + +```sql +GEO_DISTANCE(, , , ) +``` + +## 参数 {#arguments} + +| 参数 | 描述 | +|-----------|-------------| +| `` | 第一个点的经度,单位为度。 | +| `` | 第一个点的纬度,单位为度。 | +| `` | 第二个点的经度,单位为度。 | +| `` | 第二个点的纬度,单位为度。 | + +## 返回类型 {#return-type} + +Float32。 + +## 示例 {#examples} + +```sql +SELECT GEO_DISTANCE(55.755831, 37.617673, -55.755831, -37.617673) AS distance; + +╭────────────╮ +│ distance │ +├────────────┤ +│ 14128353.0 │ +╰────────────╯ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/geo-to-h3.md b/tidb-cloud-lake/sql/geo-to-h3.md new file mode 100644 index 0000000000000..5a349a6844227 --- /dev/null +++ b/tidb-cloud-lake/sql/geo-to-h3.md @@ -0,0 +1,26 @@ +--- +title: GEO_TO_H3 +summary: 返回给定位置所在六边形单元的 H3 索引。返回 0 表示发生了错误。 +--- + +# GEO_TO_H3 + +返回给定位置所在六边形单元的 [H3](https://eng.uber.com/h3/) 索引。返回 0 表示发生了错误。 + +## 语法 {#syntax} + +```sql +GEO_TO_H3(lon, lat, res) +``` + +## 示例 {#examples} + +```sql +SELECT GEO_TO_H3(37.79506683, 55.71290588, 15); + +┌─────────────────────────────────────────┐ +│ geo_to_h3(37.79506683, 55.71290588, 15) │ +├─────────────────────────────────────────┤ +│ 644325524701193974 │ +└─────────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/geohash-decode.md b/tidb-cloud-lake/sql/geohash-decode.md new file mode 100644 index 0000000000000..275b936b13890 --- /dev/null +++ b/tidb-cloud-lake/sql/geohash-decode.md @@ -0,0 +1,26 @@ +--- +title: GEOHASH_DECODE +summary: 将 Geohash 编码的字符串转换为纬度/经度坐标。 +--- + +# GEOHASH_DECODE + +将 [Geohash](https://en.wikipedia.org/wiki/Geohash) 编码的字符串转换为纬度/经度坐标。 + +## 语法 {#syntax} + +```sql +GEOHASH_DECODE('') +``` + +## 示例 {#examples} + +```sql +SELECT GEOHASH_DECODE('ezs42'); + +┌─────────────────────────────────┐ +│ geohash_decode('ezs42') │ +├─────────────────────────────────┤ +│ (-5.60302734375,42.60498046875) │ +└─────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/geohash-encode.md b/tidb-cloud-lake/sql/geohash-encode.md new file mode 100644 index 0000000000000..30afb09618a67 --- /dev/null +++ b/tidb-cloud-lake/sql/geohash-encode.md @@ -0,0 +1,26 @@ +--- +title: GEOHASH_ENCODE +summary: 将一对纬度和经度坐标转换为 Geohash 编码的字符串。 +--- + +# GEOHASH_ENCODE + +将一对纬度和经度坐标转换为 [Geohash](https://en.wikipedia.org/wiki/Geohash) 编码的字符串。 + +## 语法 {#syntax} + +```sql +GEOHASH_ENCODE(lon, lat) +``` + +## 示例 {#examples} + +```sql +SELECT GEOHASH_ENCODE(-5.60302734375, 42.593994140625); + +┌────────────────────────────────────────────────────┐ +│ geohash_encode((- 5.60302734375), 42.593994140625) │ +├────────────────────────────────────────────────────┤ +│ ezs42d000000 │ +└────────────────────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/geometry.md b/tidb-cloud-lake/sql/geometry.md new file mode 100644 index 0000000000000..0150a27bdefad --- /dev/null +++ b/tidb-cloud-lake/sql/geometry.md @@ -0,0 +1,93 @@ +--- +title: TO_GEOMETRY +summary: 解析输入并返回 GEOMETRY 类型的值。 +--- + +# TO_GEOMETRY + +解析输入并返回 GEOMETRY 类型的值。 + +如果在解析过程中发生错误,`TRY_TO_GEOMETRY` 会返回 `NULL` 值。 + +## 语法 {#syntax} + +```sql +TO_GEOMETRY(, []) +TO_GEOMETRY(, []) +TO_GEOMETRY(, []) +TRY_TO_GEOMETRY(, []) +TRY_TO_GEOMETRY(, []) +TRY_TO_GEOMETRY(, []) +``` + +## 参数 {#arguments} + +| 参数 | 描述 | +|-------------|-----------------------------------------------------------------------------------------------------------| +| `` | 该参数必须是字符串表达式,格式可以是十六进制格式的 WKT、EWKT、WKB 或 EWKB,或 GeoJSON 格式。 | +| `` | 该参数必须是 WKB 或 EWKB 格式的二进制表达式。 | +| `` | 该参数必须是 GeoJSON 格式的 JSON OBJECT。 | +| `` | 要使用的 SRID 的整数值。 | + +## 返回类型 {#return-type} + +Geometry。 + +## 示例 {#examples} + +```sql +SELECT + TO_GEOMETRY( + 'POINT(1820.12 890.56)' + ) AS pipeline_geometry; + +┌───────────────────────┐ +│ pipeline_geometry │ +├───────────────────────┤ +│ POINT(1820.12 890.56) │ +└───────────────────────┘ + +SELECT + TO_GEOMETRY( + '0101000020797f000066666666a9cb17411f85ebc19e325641', 4326 + ) AS pipeline_geometry; + +┌───────────────────────────────────────┐ +│ pipeline_geometry │ +├───────────────────────────────────────┤ +│ SRID=4326;POINT(389866.35 5819003.03) │ +└───────────────────────────────────────┘ + +SELECT + TO_GEOMETRY( + FROM_HEX('0101000020797f000066666666a9cb17411f85ebc19e325641'), 4326 + ) AS pipeline_geometry; + +┌───────────────────────────────────────┐ +│ pipeline_geometry │ +├───────────────────────────────────────┤ +│ SRID=4326;POINT(389866.35 5819003.03) │ +└───────────────────────────────────────┘ + +SELECT + TO_GEOMETRY( + '{"coordinates":[[389866,5819003],[390000,5830000]],"type":"LineString"}' + ) AS pipeline_geometry; + +┌───────────────────────────────────────────┐ +│ pipeline_geometry │ +├───────────────────────────────────────────┤ +│ LINESTRING(389866 5819003,390000 5830000) │ +└───────────────────────────────────────────┘ + +SELECT + TO_GEOMETRY( + PARSE_JSON('{"coordinates":[[389866,5819003],[390000,5830000]],"type":"LineString"}') + ) AS pipeline_geometry; + +┌───────────────────────────────────────────┐ +│ pipeline_geometry │ +├───────────────────────────────────────────┤ +│ LINESTRING(389866 5819003,390000 5830000) │ +└───────────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/geospatial-functions.md b/tidb-cloud-lake/sql/geospatial-functions.md new file mode 100644 index 0000000000000..1ebc2c9905c76 --- /dev/null +++ b/tidb-cloud-lake/sql/geospatial-functions.md @@ -0,0 +1,176 @@ +--- +title: Geospatial Functions +summary: "{{{ .lake }}} 提供两组互补的地理空间能力:用于构建和分析形状的 PostGIS 风格几何函数,以及用于全局六边形索引的 H3 工具。下表按任务对这些函数进行了分组,便于你快速找到合适的工具,布局方式类似于 Snowflake 文档。" +--- + +# Geospatial Functions + +{{{ .lake }}} 提供两组互补的地理空间能力:用于构建和分析形状的 PostGIS 风格几何函数,以及用于全局六边形索引的 H3 工具。下表按任务对这些函数进行了分组,便于你快速找到合适的工具,布局方式类似于 Snowflake 文档。 + +## 构造函数 {#constructors} + +| 函数 | 描述 | 说明 | 示例 | +|----------|-------------|------|---------| +| [ST_MAKEGEOMPOINT](/tidb-cloud-lake/sql/st-makegeompoint.md) / [ST_GEOM_POINT](/tidb-cloud-lake/sql/st-geom-point.md) | 构造 Point 几何对象 | 仅 GEOGRAPHY | `ST_MAKEGEOMPOINT(-122.35, 37.55)` → `POINT(-122.35 37.55)` | +| [ST_MAKEPOINT](/tidb-cloud-lake/sql/st-makepoint.md) / [ST_POINT](/tidb-cloud-lake/sql/st-point.md) | 构造 Point geography 对象 | 仅 GEOGRAPHY | `ST_MAKEPOINT(-122.35, 37.55)` → `POINT(-122.35 37.55)` | +| [ST_MAKELINE](/tidb-cloud-lake/sql/st-makeline.md) / [ST_MAKE_LINE](/tidb-cloud-lake/sql/st-make-line.md) | 由点创建 LineString | | `ST_MAKELINE(ST_MAKEGEOMPOINT(-122.35, 37.55), ST_MAKEGEOMPOINT(-122.40, 37.60))` → `LINESTRING(-122.35 37.55, -122.40 37.60)` | +| [ST_MAKEPOLYGON](/tidb-cloud-lake/sql/st-makepolygon.md) | 由闭合的 LineString 创建 Polygon | | `ST_MAKEPOLYGON(ST_MAKELINE(...))` → `POLYGON(...)` | +| [ST_POLYGON](/tidb-cloud-lake/sql/st-polygon.md) | 由坐标环创建 Polygon | 仅 GEOGRAPHY | `ST_POLYGON(...)` → `POLYGON(...)` | + +## 转换 {#conversion} + +| 函数 | 描述 | 说明 | 示例 | +|----------|-------------|------|---------| +| [ST_GEOMETRYFROMTEXT](/tidb-cloud-lake/sql/st-geometryfromtext.md) / [ST_GEOMFROMTEXT](/tidb-cloud-lake/sql/st-geomfromtext.md) | 将 WKT 转换为 geometry | 仅 GEOGRAPHY | `ST_GEOMETRYFROMTEXT('POINT(-122.35 37.55)')` → `POINT(-122.35 37.55)` | +| [ST_GEOMETRYFROMWKB](/tidb-cloud-lake/sql/st-geometryfromwkb.md) / [ST_GEOMFROMWKB](/tidb-cloud-lake/sql/st-geomfromwkb.md) | 将 WKB 转换为 geometry | 仅 GEOGRAPHY | `ST_GEOMETRYFROMWKB(...)` → `POINT(...)` | +| [ST_GEOMETRYFROMEWKT](/tidb-cloud-lake/sql/st-geometryfromewkt.md) / [ST_GEOMFROMEWKT](/tidb-cloud-lake/sql/st-geomfromewkt.md) | 将 EWKT 转换为 geometry | 仅 GEOGRAPHY | `ST_GEOMETRYFROMEWKT('SRID=4326;POINT(-122.35 37.55)')` → `POINT(-122.35 37.55)` | +| [ST_GEOMETRYFROMEWKB](/tidb-cloud-lake/sql/st-geometryfromewkb.md) / [ST_GEOMFROMEWKB](/tidb-cloud-lake/sql/st-geomfromewkb.md) | 将 EWKB 转换为 geometry | 仅 GEOGRAPHY | `ST_GEOMETRYFROMEWKB(...)` → `POINT(...)` | +| [ST_GEOGRAPHYFROMWKT](/tidb-cloud-lake/sql/st-geographyfromwkt.md) / [ST_GEOGFROMWKT](/tidb-cloud-lake/sql/st-geogfromwkt.md) | 将 WKT/EWKT 转换为 geography | 仅 GEOGRAPHY | `ST_GEOGRAPHYFROMWKT('POINT(-122.35 37.55)')` → `POINT(-122.35 37.55)` | +| [ST_GEOGRAPHYFROMWKB](/tidb-cloud-lake/sql/st-geographyfromwkb.md) / [ST_GEOGFROMWKB](/tidb-cloud-lake/sql/st-geogfromwkb.md) | 将 WKB/EWKB 转换为 geography | 仅 GEOGRAPHY | `ST_GEOGRAPHYFROMWKB(...)` → `POINT(...)` | +| [ST_GEOMFROMGEOHASH](/tidb-cloud-lake/sql/st-geomfromgeohash.md) | 将 GeoHash 转换为 geometry | 仅 GEOGRAPHY | `ST_GEOMFROMGEOHASH('9q8yyk8')` → `POLYGON(...)` | +| [ST_GEOMPOINTFROMGEOHASH](/tidb-cloud-lake/sql/st-geompointfromgeohash.md) | 将 GeoHash 转换为 Point 几何对象 | 仅 GEOGRAPHY | `ST_GEOMPOINTFROMGEOHASH('9q8yyk8')` → `POINT(...)` | +| [ST_GEOGFROMGEOHASH](/tidb-cloud-lake/sql/st-geogfromgeohash.md) | 将 GeoHash 转换为 geography 多边形 | 仅 GEOGRAPHY | `ST_GEOGFROMGEOHASH('9q8yyk8')` → `POLYGON(...)` | +| [ST_GEOGPOINTFROMGEOHASH](/tidb-cloud-lake/sql/st-geogpointfromgeohash.md) | 将 GeoHash 转换为 geography 点 | 仅 GEOGRAPHY | `ST_GEOGPOINTFROMGEOHASH('9q8yyk8')` → `POINT(...)` | +| [TO_GEOMETRY](/tidb-cloud-lake/sql/geometry.md) | 将多种格式解析为 geometry | 仅 GEOGRAPHY | `TO_GEOMETRY('POINT(-122.35 37.55)')` → `POINT(-122.35 37.55)` | +| [TO_GEOGRAPHY](/tidb-cloud-lake/sql/to-geography.md) / [TRY_TO_GEOGRAPHY](/tidb-cloud-lake/sql/to-geography.md) | 将多种格式解析为 geography | 仅 GEOGRAPHY | `TO_GEOGRAPHY('POINT(-122.35 37.55)')` → `POINT(-122.35 37.55)` | + +## 输出 {#output} + +| 函数 | 描述 | 说明 | 示例 | +|----------|-------------|------|---------| +| [ST_ASTEXT](/tidb-cloud-lake/sql/st-astext.md) | 将 geometry 转换为 WKT | | `ST_ASTEXT(ST_MAKEGEOMPOINT(-122.35, 37.55))` → `'POINT(-122.35 37.55)'` | +| [ST_ASWKT](/tidb-cloud-lake/sql/st-aswkt.md) | 将 geometry 转换为 WKT | | `ST_ASWKT(ST_MAKEGEOMPOINT(-122.35, 37.55))` → `'POINT(-122.35 37.55)'` | +| [ST_ASBINARY](/tidb-cloud-lake/sql/st-asbinary.md) / [ST_ASWKB](/tidb-cloud-lake/sql/st-aswkb.md) | 将 geometry 转换为 WKB | | `ST_ASBINARY(ST_MAKEGEOMPOINT(-122.35, 37.55))` → `WKB representation` | +| [ST_ASEWKT](/tidb-cloud-lake/sql/st-asewkt.md) | 将 geometry 转换为 EWKT | | `ST_ASEWKT(ST_MAKEGEOMPOINT(-122.35, 37.55))` → `'SRID=4326;POINT(-122.35 37.55)'` | +| [ST_ASEWKB](/tidb-cloud-lake/sql/st-asewkb.md) | 将 geometry 转换为 EWKB | | `ST_ASEWKB(ST_MAKEGEOMPOINT(-122.35, 37.55))` → `EWKB representation` | +| [ST_ASGEOJSON](/tidb-cloud-lake/sql/st-asgeojson.md) | 将 geometry 转换为 GeoJSON | | `ST_ASGEOJSON(ST_MAKEGEOMPOINT(-122.35, 37.55))` → '{"type":"Point","coordinates":[-122.35,37.55]}' | +| [ST_GEOHASH](/tidb-cloud-lake/sql/st-geohash.md) | 将 geometry 转换为 GeoHash | | `ST_GEOHASH(ST_MAKEGEOMPOINT(-122.35, 37.55), 7)` → `'9q8yyk8'` | +| [TO_STRING](/tidb-cloud-lake/sql/string.md) | 将 geometry 转换为字符串 | | `TO_STRING(ST_MAKEGEOMPOINT(-122.35, 37.55))` → `'POINT(-122.35 37.55)'` | + +## 访问器和属性 {#accessors-properties} + +| 函数 | 描述 | 说明 | 示例 | +|----------|-------------|------|---------| +| [ST_DIMENSION](/tidb-cloud-lake/sql/st-dimension.md) | 返回拓扑维度 | | `ST_DIMENSION(ST_MAKEGEOMPOINT(-122.35, 37.55))` → `0` | +| [ST_CENTROID](/tidb-cloud-lake/sql/st-centroid.md) | 返回 geometry 的质心 | 仅 GEOMETRY | `ST_CENTROID(TO_GEOMETRY('LINESTRING(0 0, 2 0)'))` → `POINT(1 0)` | +| [ST_ENVELOPE](/tidb-cloud-lake/sql/st-envelope.md) | 返回最小外接矩形 | 仅 GEOMETRY | `ST_ENVELOPE(TO_GEOMETRY('LINESTRING(0 0, 2 3)'))` → `POLYGON((0 0,2 0,2 3,0 3,0 0))` | +| [ST_SRID](/tidb-cloud-lake/sql/st-srid.md) | 返回 geometry 的 SRID | | `ST_SRID(ST_MAKEGEOMPOINT(-122.35, 37.55))` → `4326` | +| [ST_POINTN](/tidb-cloud-lake/sql/st-pointn.md) | 返回 LineString 中指定位置的点 | | `ST_POINTN(ST_MAKELINE(...), 1)` → `POINT(-122.35 37.55)` | +| [ST_STARTPOINT](/tidb-cloud-lake/sql/st-startpoint.md) | 返回 LineString 中的第一个点 | | `ST_STARTPOINT(ST_MAKELINE(...))` → `POINT(-122.35 37.55)` | +| [ST_ENDPOINT](/tidb-cloud-lake/sql/st-endpoint.md) | 返回 LineString 中的最后一个点 | | `ST_ENDPOINT(ST_MAKELINE(...))` → `POINT(-122.40 37.60)` | +| [ST_X](/tidb-cloud-lake/sql/st-x.md) / [ST_Y](/tidb-cloud-lake/sql/st-y.md) | 返回 Point 的 X 或 Y 坐标 | | `ST_X(ST_MAKEGEOMPOINT(-122.35, 37.55))` → `-122.35` | +| [ST_XMIN](/tidb-cloud-lake/sql/st-xmin.md) / [ST_XMAX](/tidb-cloud-lake/sql/st-xmax.md) | 返回最小/最大 X 坐标 | | `ST_XMIN(ST_MAKELINE(...))` → `-122.40` | +| [ST_YMIN](/tidb-cloud-lake/sql/st-ymin.md) / [ST_YMAX](/tidb-cloud-lake/sql/st-ymax.md) | 返回最小/最大 Y 坐标 | | `ST_YMAX(ST_MAKELINE(...))` → `37.60` | + +## 关系与度量 {#relationship-and-measurement} + +| 函数 | 描述 | 说明 | 示例 | +|----------|-------------|------|---------| +| [HAVERSINE](/tidb-cloud-lake/sql/haversine.md) | 计算坐标之间的大圆距离 | | `HAVERSINE(37.55, -122.35, 37.60, -122.40)` → `6.12` | +| [ST_AREA](/tidb-cloud-lake/sql/st-area.md) | 测量 geometry 或 geography 对象的面积 | | `ST_AREA(TO_GEOMETRY('POLYGON((0 0, 1 0, 1 1, 0 1, 0 0))'))` → `1.0` | +| [ST_CONTAINS](/tidb-cloud-lake/sql/st-contains.md) | 测试一个 geometry 是否包含另一个 geometry | 仅 GEOMETRY | `ST_CONTAINS(ST_MAKEPOLYGON(...), ST_MAKEGEOMPOINT(...))` → `TRUE` | +| [ST_CONVEXHULL](/tidb-cloud-lake/sql/st-convexhull.md) | 计算 geometry 的凸包 | 仅 GEOMETRY | `ST_CONVEXHULL(TO_GEOMETRY('POLYGON((0 0,2 0,2 2,0 2,0 0))'))` → `POLYGON((0 0,2 0,2 2,0 2,0 0))` | +| [ST_NPOINTS](/tidb-cloud-lake/sql/st-npoints.md) | 统计 geometry 中的点数 | | `ST_NPOINTS(ST_MAKELINE(...))` → `2` | +| [ST_NUMPOINTS](/tidb-cloud-lake/sql/st-numpoints.md) | 统计 geometry 中的点数 | 仅 GEOMETRY | `ST_NUMPOINTS(ST_MAKELINE(...))` → `2` | +| [ST_INTERSECTS](/tidb-cloud-lake/sql/st-intersects.md) | 测试两个 geometry 是否相交 | 仅 GEOMETRY | `ST_INTERSECTS(TO_GEOMETRY('LINESTRING(0 0, 2 2)'), TO_GEOMETRY('LINESTRING(0 2, 2 0)'))` → `TRUE` | +| [ST_DISJOINT](/tidb-cloud-lake/sql/st-disjoint.md) | 测试两个 geometry 是否不相交 | 仅 GEOMETRY | `ST_DISJOINT(TO_GEOMETRY('POINT(3 3)'), TO_GEOMETRY('POLYGON((0 0,2 0,2 2,0 2,0 0))'))` → `TRUE` | +| [ST_WITHIN](/tidb-cloud-lake/sql/st-within.md) | 测试一个 geometry 是否位于另一个 geometry 内部 | 仅 GEOMETRY | `ST_WITHIN(TO_GEOMETRY('POINT(1 1)'), TO_GEOMETRY('POLYGON((0 0,2 0,2 2,0 2,0 0))'))` → `TRUE` | +| [ST_EQUALS](/tidb-cloud-lake/sql/st-equals.md) | 测试两个 geometry 在空间上是否相等 | 仅 GEOMETRY | `ST_EQUALS(TO_GEOMETRY('POINT(1 1)'), TO_GEOMETRY('POINT(1 1)'))` → `TRUE` | +| [ST_LENGTH](/tidb-cloud-lake/sql/st-length.md) | 测量 LineString 的长度 | | `ST_LENGTH(ST_MAKELINE(...))` → `5.57` | +| [ST_DISTANCE](/tidb-cloud-lake/sql/st-distance.md) | 测量 geometry 之间的距离 | | `ST_DISTANCE(ST_MAKEGEOMPOINT(-122.35, 37.55), ST_MAKEGEOMPOINT(-122.40, 37.60))` → `5.57` | +| [ST_DWITHIN](/tidb-cloud-lake/sql/st-dwithin.md) | 测试两个 geometry 是否在给定距离内 | 仅 GEOMETRY | `ST_DWITHIN(TO_GEOMETRY('POINT(0 0)'), TO_GEOMETRY('POINT(1 1)'), 1.5)` → `TRUE` | +| [ST_UNION](/tidb-cloud-lake/sql/st-union.md) | 返回两个输入合并后的 geometry | 仅 GEOMETRY | `ST_UNION(TO_GEOMETRY('POINT(0 0)'), TO_GEOMETRY('POINT(1 1)'))` → `MULTIPOINT(0 0,1 1)` | +| [ST_INTERSECTION](/tidb-cloud-lake/sql/st-intersection.md) | 返回两个 geometry 的共享部分 | 仅 GEOMETRY | `ST_INTERSECTION(TO_GEOMETRY('LINESTRING(0 0, 1 1)'), TO_GEOMETRY('LINESTRING(0 0, 1 1)'))` → `LINESTRING(0 0,1 1)` | +| [ST_DIFFERENCE](/tidb-cloud-lake/sql/st-difference.md) | 返回第一个 geometry 中未被第二个覆盖的部分 | 仅 GEOMETRY | `ST_DIFFERENCE(TO_GEOMETRY('POINT(0 0)'), TO_GEOMETRY('POINT(1 1)'))` → `POINT(0 0)` | +| [ST_SYMDIFFERENCE](/tidb-cloud-lake/sql/st-symdifference.md) | 返回两个 geometry 中不重叠的部分 | 仅 GEOMETRY | `ST_SYMDIFFERENCE(TO_GEOMETRY('POINT(0 0)'), TO_GEOMETRY('POINT(1 1)'))` → `MULTIPOINT(0 0,1 1)` | + +## 变换 {#transformation} + +| 函数 | 描述 | 说明 | 示例 | +|----------|-------------|------|---------| +| [ST_HILBERT](/tidb-cloud-lake/sql/st-hilbert.md) | 将 geometry 或 geography 编码为 Hilbert 曲线索引 | | `ST_HILBERT(TO_GEOMETRY('POINT(0.5 0.5)'), [0, 0, 1, 1])` → `715827882` | +| [ST_SETSRID](/tidb-cloud-lake/sql/st-setsrid.md) | 为 geometry 指定 SRID | 仅 GEOMETRY | `ST_SETSRID(ST_MAKEGEOMPOINT(-122.35, 37.55), 3857)` → `POINT(-122.35 37.55)` | +| [ST_TRANSFORM](/tidb-cloud-lake/sql/st-transform.md) | 将 geometry 转换到新的 SRID | 仅 GEOMETRY | `ST_TRANSFORM(ST_MAKEGEOMPOINT(-122.35, 37.55), 3857)` → `POINT(-13618288.8 4552395.0)` | + +## 空间关系 {#spatial-relationships} + +| 函数 | 描述 | 示例 | +|----------|-------------|---------| +| [ST_CONTAINS](/tidb-cloud-lake/sql/st-contains.md) | 测试一个 geometry 是否包含另一个 geometry | `ST_CONTAINS(ST_MAKEPOLYGON(...), ST_MAKEGEOMPOINT(...))` → `TRUE` | +| [POINT_IN_POLYGON](/tidb-cloud-lake/sql/point-in-polygon.md) | 检查点是否位于多边形内部 | `POINT_IN_POLYGON([lon, lat], [[p1_lon, p1_lat], ...])` → `TRUE` | + +## 距离与度量 {#distance-measurements} + +| 函数 | 描述 | 示例 | +|----------|-------------|---------| +| [ST_DISTANCE](/tidb-cloud-lake/sql/st-distance.md) | 测量几何图形之间的距离 | `ST_DISTANCE(ST_MAKEGEOMPOINT(-122.35, 37.55), ST_MAKEGEOMPOINT(-122.40, 37.60))` → `5.57` | +| [HAVERSINE](/tidb-cloud-lake/sql/haversine.md) | 计算坐标之间的大圆距离 | `HAVERSINE(37.55, -122.35, 37.60, -122.40)` → `6.12` | + +## H3 索引与转换 {#h3-indexing-conversion} + +| 函数 | 描述 | 示例 | +|----------|-------------|---------| +| [GEO_TO_H3](/tidb-cloud-lake/sql/geo-to-h3.md) | 将经度/纬度转换为 H3 索引 | `GEO_TO_H3(37.7950, 55.7129, 15)` → `644325524701193974` | +| [H3_TO_GEO](/tidb-cloud-lake/sql/h3-to-geo.md) | 将 H3 索引转换为经度/纬度 | `H3_TO_GEO(644325524701193974)` → `[37.7950, 55.7129]` | +| [H3_TO_STRING](/tidb-cloud-lake/sql/h3-to-string.md) | 将 H3 索引转换为其字符串形式 | `H3_TO_STRING(644325524701193974)` → `'8f2830828052d25'` | +| [STRING_TO_H3](/tidb-cloud-lake/sql/string-to-h3.md) | 将 H3 字符串转换为索引 | `STRING_TO_H3('8f2830828052d25')` → `644325524701193974` | +| [GEOHASH_ENCODE](/tidb-cloud-lake/sql/geohash-encode.md) | 将经度/纬度编码为 GeoHash | `GEOHASH_ENCODE(37.7950, 55.7129, 12)` → `'ucfv0nzpt3s7'` | +| [GEOHASH_DECODE](/tidb-cloud-lake/sql/geohash-decode.md) | 将 GeoHash 解码为经度/纬度 | `GEOHASH_DECODE('ucfv0nzpt3s7')` → `[37.7950, 55.7129]` | + +## H3 单元属性 {#h3-cell-properties} + +| 函数 | 描述 | 示例 | +|----------|-------------|---------| +| [H3_GET_RESOLUTION](/tidb-cloud-lake/sql/h3-get-resolution.md) | 返回 H3 索引的分辨率 | `H3_GET_RESOLUTION(644325524701193974)` → `15` | +| [H3_GET_BASE_CELL](/tidb-cloud-lake/sql/h3-get-base-cell.md) | 返回基础单元编号 | `H3_GET_BASE_CELL(644325524701193974)` → `14` | +| [H3_IS_VALID](/tidb-cloud-lake/sql/h3-is-valid.md) | 检查 H3 索引是否有效 | `H3_IS_VALID(644325524701193974)` → `TRUE` | +| [H3_IS_PENTAGON](/tidb-cloud-lake/sql/h3-is-pentagon.md) | 检查 H3 索引是否为五边形 | `H3_IS_PENTAGON(644325524701193974)` → `FALSE` | +| [H3_IS_RES_CLASS_III](/tidb-cloud-lake/sql/h3-is-res-class-iii.md) | 检查 H3 索引是否为 III 类 | `H3_IS_RES_CLASS_III(644325524701193974)` → `FALSE` | +| [H3_GET_FACES](/tidb-cloud-lake/sql/h3-get-faces.md) | 返回相交的二十面体面 | `H3_GET_FACES(644325524701193974)` → `[7]` | +| [H3_TO_PARENT](/tidb-cloud-lake/sql/h3-to-parent.md) | 返回较低分辨率下的父索引 | `H3_TO_PARENT(644325524701193974, 10)` → `622236721289822207` | +| [H3_TO_CHILDREN](/tidb-cloud-lake/sql/h3-to-children.md) | 返回较高分辨率下的子索引 | `H3_TO_CHILDREN(622236721289822207, 11)` → `[...]` | +| [H3_TO_CENTER_CHILD](/tidb-cloud-lake/sql/h3-to-center-child.md) | 返回指定分辨率下的中心子索引 | `H3_TO_CENTER_CHILD(622236721289822207, 11)` → `625561602857582591` | +| [H3_CELL_AREA_M2](/tidb-cloud-lake/sql/h3-cell-area-m2.md) | 返回单元面积(平方米) | `H3_CELL_AREA_M2(644325524701193974)` → `0.8953` | +| [H3_CELL_AREA_RADS2](/tidb-cloud-lake/sql/h3-cell-area-rads2.md) | 返回单元面积(平方弧度) | `H3_CELL_AREA_RADS2(644325524701193974)` → `2.2e-14` | +| [H3_HEX_AREA_KM2](/tidb-cloud-lake/sql/h3-hex-area-km2.md) | 返回平均六边形面积(km²) | `H3_HEX_AREA_KM2(10)` → `0.0152` | +| [H3_HEX_AREA_M2](/tidb-cloud-lake/sql/h3-hex-area-m2.md) | 返回平均六边形面积(m²) | `H3_HEX_AREA_M2(10)` → `15200` | +| [H3_TO_GEO_BOUNDARY](/tidb-cloud-lake/sql/h3-to-geo-boundary.md) | 返回单元边界 | `H3_TO_GEO_BOUNDARY(644325524701193974)` → `[[lon1,lat1], ...]` | +| [H3_NUM_HEXAGONS](/tidb-cloud-lake/sql/h3-num-hexagons.md) | 返回指定分辨率下的六边形数量 | `H3_NUM_HEXAGONS(2)` → `5882` | +| [GEO_DISTANCE](/tidb-cloud-lake/sql/geo-distance.md) | 使用 WGS84 返回近似距离(米) | `GEO_DISTANCE(0, 0, 0, 0)` → `0` | +| [GREAT_CIRCLE_DISTANCE](/tidb-cloud-lake/sql/great-circle-distance.md) | 返回大圆距离(米) | `GREAT_CIRCLE_DISTANCE(0, 0, 0, 0)` → `0` | +| [GREAT_CIRCLE_ANGLE](/tidb-cloud-lake/sql/great-circle-angle.md) | 返回大圆中心角(度) | `GREAT_CIRCLE_ANGLE(0, 0, 45, 0)` → `45` | +| [POINT_IN_POLYGON](/tidb-cloud-lake/sql/point-in-polygon.md) | 检查点是否位于多边形内部 | `POINT_IN_POLYGON([lon, lat], [[p1_lon, p1_lat], ...])` → `TRUE` | +| [POINT_IN_ELLIPSES](/tidb-cloud-lake/sql/point-in-ellipses.md) | 检查点是否位于任一椭圆内部 | `POINT_IN_ELLIPSES(10, 10, 10, 9.1, 1, 0.9999)` → `1` | + +## H3 邻域 {#h3-neighborhoods} + +| 函数 | 描述 | 示例 | +|----------|-------------|---------| +| [H3_DISTANCE](/tidb-cloud-lake/sql/h3-distance.md) | 返回两个索引之间的网格距离 | `H3_DISTANCE(599119489002373119, 599119491149856767)` → `1` | +| [H3_INDEXES_ARE_NEIGHBORS](/tidb-cloud-lake/sql/h3-indexes-are-neighbors.md) | 测试两个索引是否为邻居 | `H3_INDEXES_ARE_NEIGHBORS(599119489002373119, 599119491149856767)` → `TRUE` | +| [H3_K_RING](/tidb-cloud-lake/sql/h3-k-ring.md) | 返回距离不超过 k 的所有索引 | `H3_K_RING(599119489002373119, 1)` → `[599119489002373119, ...]` | +| [H3_HEX_RING](/tidb-cloud-lake/sql/h3-hex-ring.md) | 返回恰好距离 k 步的索引 | `H3_HEX_RING(599119489002373119, 1)` → `[599119491149856767, ...]` | +| [H3_LINE](/tidb-cloud-lake/sql/h3-line.md) | 返回路径上的索引 | `H3_LINE(from_h3, to_h3)` → `[from_h3, ..., to_h3]` | + +## H3 边操作 {#h3-edge-operations} + +| 函数 | 描述 | 示例 | +|----------|-------------|---------| +| [H3_GET_UNIDIRECTIONAL_EDGE](/tidb-cloud-lake/sql/h3-get-unidirectional-edge.md) | 返回两个相邻单元之间的边 | `H3_GET_UNIDIRECTIONAL_EDGE(from_h3, to_h3)` → `edge_index` | +| [H3_UNIDIRECTIONAL_EDGE_IS_VALID](/tidb-cloud-lake/sql/h3-unidirectional-edge-is-valid.md) | 检查边索引是否有效 | `H3_UNIDIRECTIONAL_EDGE_IS_VALID(edge_index)` → `TRUE` | +| [H3_GET_ORIGIN_INDEX_FROM_UNIDIRECTIONAL_EDGE](/tidb-cloud-lake/sql/h3-get-origin-index-unidirectional-edge.md) | 从边返回起始单元 | `H3_GET_ORIGIN_INDEX_FROM_UNIDIRECTIONAL_EDGE(edge_index)` → `from_h3` | +| [H3_GET_DESTINATION_INDEX_FROM_UNIDIRECTIONAL_EDGE](/tidb-cloud-lake/sql/h3-get-destination-index-unidirectional-edge.md) | 从边返回目标单元 | `H3_GET_DESTINATION_INDEX_FROM_UNIDIRECTIONAL_EDGE(edge_index)` → `to_h3` | +| [H3_GET_INDEXES_FROM_UNIDIRECTIONAL_EDGE](/tidb-cloud-lake/sql/h3-get-indexes-unidirectional-edge.md) | 返回一条边对应的两个单元 | `H3_GET_INDEXES_FROM_UNIDIRECTIONAL_EDGE(edge_index)` → `[from_h3, to_h3]` | +| [H3_GET_UNIDIRECTIONAL_EDGES_FROM_HEXAGON](/tidb-cloud-lake/sql/h3-get-unidirectional-edges-hexagon.md) | 列出从某个单元出发的边 | `H3_GET_UNIDIRECTIONAL_EDGES_FROM_HEXAGON(h3_index)` → `[edge1, edge2, ...]` | +| [H3_GET_UNIDIRECTIONAL_EDGE_BOUNDARY](/tidb-cloud-lake/sql/h3-get-unidirectional-edge-boundary.md) | 返回边的边界 | `H3_GET_UNIDIRECTIONAL_EDGE_BOUNDARY(edge_index)` → `[[lon1,lat1], [lon2,lat2]]` | + +## H3 度量与角度 {#h3-measurements-angles} + +| 函数 | 描述 | 示例 | +|----------|-------------|---------| +| [H3_EDGE_LENGTH_KM](/tidb-cloud-lake/sql/h3-edge-length-km.md) | 返回平均边长(千米) | `H3_EDGE_LENGTH_KM(10)` → `0.065` | +| [H3_EDGE_LENGTH_M](/tidb-cloud-lake/sql/h3-edge-length-m.md) | 返回平均边长(米) | `H3_EDGE_LENGTH_M(10)` → `65.91` | +| [H3_EXACT_EDGE_LENGTH_KM](/tidb-cloud-lake/sql/h3-exact-edge-length-km.md) | 返回精确边长(千米) | `H3_EXACT_EDGE_LENGTH_KM(edge_index)` → `0.066` | +| [H3_EXACT_EDGE_LENGTH_M](/tidb-cloud-lake/sql/h3-exact-edge-length-m.md) | 返回精确边长(米) | `H3_EXACT_EDGE_LENGTH_M(edge_index)` → `66.12` | +| [H3_EXACT_EDGE_LENGTH_RADS](/tidb-cloud-lake/sql/h3-exact-edge-length-rads.md) | 返回精确边长(弧度) | `H3_EXACT_EDGE_LENGTH_RADS(edge_index)` → `0.00001` | +| [H3_EDGE_ANGLE](/tidb-cloud-lake/sql/h3-edge-angle.md) | 返回两条边之间的夹角(弧度) | `H3_EDGE_ANGLE(edge1, edge2)` → `1.047` | \ No newline at end of file diff --git a/tidb-cloud-lake/sql/geospatial.md b/tidb-cloud-lake/sql/geospatial.md new file mode 100644 index 0000000000000..7df608913e215 --- /dev/null +++ b/tidb-cloud-lake/sql/geospatial.md @@ -0,0 +1,215 @@ +--- +title: Geospatial +summary: "{{{ .lake }}} 通过两种数据类型存储空间数据。" +--- + +# Geospatial + +{{{ .lake }}} 通过两种数据类型存储空间数据: + +- `GEOMETRY` 是平面类型(默认 SRID 为 0,或使用你指定的任意 SRID),适用于本地/投影类工作负载。 +- `GEOGRAPHY` 是球面类型(WGS 84,SRID 4326),并对全局工作负载中的经纬度进行校验。 + +这两种类型都以 EWKB 格式将坐标持久化为 IEEE 754 `Float64` 值,覆盖所有常见几何对象(从 Point 到 GeometryCollection),可输出 WKT/WKB/GeoJSON,并且可以通过 `ST_TRANSFORM` 等函数进行重投影。 + +## 数据类型 {#data-types} + +### GEOMETRY {#geometry} + +- 使用笛卡尔坐标,适合校园、城市或省级范围的数据,在这些场景中平面计算已足够。 +- 默认 SRID 为 0;你可以在创建列或写入数据时设置其他 SRID。 +- 适用于大多数空间操作符,并且可以通过 `ST_TRANSFORM` 进行重投影,以供下游使用方消费。 + +### GEOGRAPHY {#geography} + +- 在 WGS 84(SRID 4326)上存储经度/纬度对;超出 [-180°, 180°] / [-90°, 90°] 范围的值会被拒绝。 +- 推荐用于需要椭球公式的洲际或全球距离/面积计算。 +- 当需要平面算法时,可以转换为 GEOMETRY。 + +| 特性 | GEOMETRY | GEOGRAPHY | +| :--- | :--- | :--- | +| **坐标系** | 笛卡尔(平面) | 椭球(球面) | +| **SRID** | 0(默认)或自定义 | 仅 4326(WGS 84) | +| **X / Y 含义** | 平面上的 X、Y | 球面上的经度、纬度 | +| **边的解释** | 平面上的直线 | 大圆弧(球面上的最短路径) | +| **主要使用场景** | 本地 / 投影数据(例如城市、建筑) | 全局数据(例如 GPS 轨迹、航运路线) | + +## 精度与坐标控制 {#precision-and-coordinate-control} + +- **全程双精度**:`ST_MAKEPOINT` 和 `ST_GEOMETRYFROMEWKT` 等函数接收 `Float64` 值并以 EWKB 持久化,因此坐标会保留其原始有效数字。 +- **SRID 行为**:GEOMETRY 保留你指定的任意 SRID(默认 0),而 GEOGRAPHY 固定为 SRID 4326,并拒绝其他 SRID。 +- **坐标安全性**:GEOGRAPHY 输入会经过 `check_point`,确保经度/纬度保持在 [-180°, 180°] / [-90°, 90°] 范围内。 +- **投影**:`ST_TRANSFORM` 可切换 GEOMETRY 的 SRID(例如 4326 → 3857),或将 GEOGRAPHY 数据转换为平面坐标系以供下游处理。 + +## 支持的对象类型 {#supported-object-types} + +| 对象类型 | 描述与示例 | 精度说明 | +| --- | --- | --- | +| Point | 单个坐标,例如 `POINT(113.98765432109876 23.456789012345678)` | 每个坐标都以 `Float64` 存储,并保留约 15–16 位精度。 | +| LineString | 连续路径,例如 `LINESTRING(10 20, 30 40, 50 60)` | 每个顶点都使用相同的双精度,因此派生长度依赖原始值。 | +| Polygon | 封闭区域,例如 `POLYGON((10 20, 30 40, 50 60, 10 20))` | 所有环共享 `Float64` 顶点,从而在面积/包含关系测试中保留多边形边界。 | +| MultiPoint | 多个点,例如 `MULTIPOINT((10 20), (30 40))` | 每个成员点都继承与独立点相同的双精度存储方式。 | +| MultiLineString | 多条路径,例如 `MULTILINESTRING((10 20, 30 40), (50 60, 70 80))` | 每个顶点的精度都会保留,从而确保长度或相交计算的准确性。 | +| MultiPolygon | 多个区域,例如 `MULTIPOLYGON(((10 20, 30 40, 50 60, 10 20)), ((15 25, 25 35, 35 45, 15 25)))` | 每个多边形的坐标都保持为 `Float64`,因此组合面积/重叠计算可保留完整精度。 | +| GeometryCollection | 混合对象,例如 `GEOMETRYCOLLECTION(POINT(10 20), LINESTRING(10 20, 30 40))` | 无论几何类型如何,各成员都保留其原生双精度坐标。 | + +## 输出格式 {#output-formats} + +{{{ .lake }}} 以 EWKB 持久化空间值,但提供多种输出格式。你可以设置 `geometry_output_format` 会话参数(默认值:`WKT`),或调用显式转换函数: + +- **WKT / EWKT** – 文本表示;EWKT 会带上 SRID 前缀(例如 `SRID=4326;POINT(-44.3 60.1)`)。 +- **WKB / EWKB** – 紧凑的二进制格式,便于与其他 GIS 运行时互操作。 +- **GeoJSON** – 用于 Web 地图和 API 的 JSON 表示。 + +```sql +SET geometry_output_format = 'GeoJSON'; +SELECT ST_ASWKB(geo), ST_ASEWKT(geo), ST_ASGEOJSON(geo) FROM ...; +``` + +## 函数 {#functions} + +可在此查看已编目的空间函数列表: + +- [Geospatial Functions](/tidb-cloud-lake/sql/geospatial-functions.md) + +## 示例 {#examples} + +下面的每个示例都突出展示一种对象类型、它解决的场景、生成它的 SQL,以及一个示例结果表。`CAST('…' AS GEOMETRY)` 会解析内联 WKT 字面量,因此你无需创建表即可进行实验。 + +### Point — 精确定位单个传感器 {#point-pinpoint-a-single-sensor} + +*场景*:存储 IoT 设备产生的精确经纬度,并同时输出 GeoJSON 和数值坐标。 + +```sql +SELECT + ST_ASGEOJSON(pt) AS sensor_geojson, + ST_X(pt) AS lon, + ST_Y(pt) AS lat +FROM (SELECT CAST('POINT(113.98765432109876 23.456789012345678)' AS GEOMETRY) AS pt); +``` + +``` +┌──────────────────────────────────────────────────────────────────────────────┬──────────────────────┬──────────────────────┐ +│ sensor_geojson │ lon │ lat │ +├──────────────────────────────────────────────────────────────────────────────┼──────────────────────┼──────────────────────┤ +│ {"type":"Point","coordinates":[113.98765432109876,23.456789012345677]} │ 113.98765432109876 │ 23.456789012345677 │ +└──────────────────────────────────────────────────────────────────────────────┴──────────────────────┴──────────────────────┘ +``` + +### LineString — 描述一条路线 {#linestring-describe-a-route} + +*场景*:记录一条简单的驾驶路线,并以坐标单位测量其长度。 + +```sql +SELECT + ST_ASWKT(route) AS road_segment, + ST_LENGTH(route) AS segment_length +FROM (SELECT CAST('LINESTRING(10 20, 30 40, 50 60)' AS GEOMETRY) AS route); +``` + +``` +┌──────────────────────────────────────────────────────────────┬────────────────────┐ +│ road_segment │ segment_length │ +├──────────────────────────────────────────────────────────────┼────────────────────┤ +│ LINESTRING(10 20,30 40,50 60) │ 56.568542495 │ +└──────────────────────────────────────────────────────────────┴────────────────────┘ +``` + +### Polygon — 表示区域或地理围栏 {#polygon-capture-an-area-or-geofence} + +*场景*:为某设施定义一个矩形地理围栏,带 SRID 信息读回,并计算其面积。 + +```sql +SELECT + ST_ASEWKT(area) AS ewkt_polygon, + ST_AREA(area) AS area_units +FROM (SELECT CAST('POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))' AS GEOMETRY) AS area); +``` + +``` +┌──────────────────────────────────────────────────────────────┬──────────────┐ +│ ewkt_polygon │ area_units │ +├──────────────────────────────────────────────────────────────┼──────────────┤ +│ POLYGON((0 0,0 10,10 10,10 0,0 0)) │ 100 │ +└──────────────────────────────────────────────────────────────┴──────────────┘ +``` + +### MultiPoint — 将多个站点归为一组 {#multipoint-tag-multiple-sites-together} + +*场景*:将三个服务点的坐标一起保存,并输出 GeoJSON 载荷和总数量。 + +```sql +SELECT + ST_ASGEOJSON(places) AS places_geojson, + ST_NUMPOINTS(places) AS total_sites +FROM (SELECT CAST('MULTIPOINT((10 20), (30 40), (50 60))' AS GEOMETRY) AS places); +``` + +``` +┌──────────────────────────────────────────────────────────────┬──────────────┐ +│ places_geojson │ total_sites │ +├──────────────────────────────────────────────────────────────┼──────────────┤ +│ {"type":"MultiPoint","coordinates":[[10,20],[30,40],[50,60]]} │ 3 │ +└──────────────────────────────────────────────────────────────┴──────────────┘ +``` + +### MultiLineString — 表示平行线段 {#multilinestring-represent-parallel-lines} + +*场景*:将两条平行道路分段归为一组,以 WKT 读回,并使用 `ST_NUMPOINTS` 统计总顶点数。 + +```sql +SELECT + ST_ASWKT(lines) AS multiline_wkt, + ST_NUMPOINTS(lines) AS vertex_count +FROM (SELECT CAST('MULTILINESTRING((10 20, 30 40), (50 60, 70 80))' AS GEOMETRY) AS lines); +``` + +``` +┌──────────────────────────────────────────────────────────────┬──────────────┐ +│ multiline_wkt │ vertex_count │ +├──────────────────────────────────────────────────────────────┼──────────────┤ +│ MULTILINESTRING((10 20,30 40),(50 60,70 80)) │ 4 │ +└──────────────────────────────────────────────────────────────┴──────────────┘ +``` + +### MultiPolygon — 覆盖不相连的区域 {#multipolygon-cover-disjoint-districts} + +*场景*:表示两个彼此分离的服务区域,并计算其总面积。 + +```sql +SELECT + ST_ASGEOJSON(zones) AS zones_geojson, + ST_AREA(zones) AS total_area +FROM ( + SELECT CAST('MULTIPOLYGON(((0 0, 0 10, 10 10, 10 0, 0 0)), ((20 0, 20 10, 30 10, 30 0, 20 0)))' AS GEOMETRY) AS zones +); +``` + +``` +┌─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┬──────────────┐ +│ zones_geojson │ total_area │ +├─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┼──────────────┤ +│ {"type":"MultiPolygon","coordinates":[[[[0,0],[0,10],[10,10],[10,0],[0,0]]],[[[20,0],[20,10],[30,10],[30,0],[20,0]]]]} │ 200 │ +└─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┴──────────────┘ +``` + +### GeometryCollection — 混合异构形状 {#geometrycollection-mix-heterogenous-shapes} + +*场景*:将地标标记及其连接路径一起保存,并展示混合的 GeoJSON 以及最大维度。 + +```sql +SELECT + ST_ASGEOJSON(feature) AS feature_geojson, + ST_DIMENSION(feature) AS max_dimension +FROM ( + SELECT CAST('GEOMETRYCOLLECTION(POINT(10 20), LINESTRING(10 20, 30 40))' AS GEOMETRY) AS feature +); +``` + +``` +┌────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┬───────────────┐ +│ feature_geojson │ max_dimension │ +├────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┼───────────────┤ +│ {"type":"GeometryCollection","geometries":[{"type":"Point","coordinates":[10,20]},{"type":"LineString","coordinates":[[10,20],[30,40]]}]} │ 1 │ +└────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┴───────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/get-by-keypath.md b/tidb-cloud-lake/sql/get-by-keypath.md new file mode 100644 index 0000000000000..80b54d7eef7e5 --- /dev/null +++ b/tidb-cloud-lake/sql/get-by-keypath.md @@ -0,0 +1,66 @@ +--- +title: GET_BY_KEYPATH +summary: 使用 **key path** 字符串从 `VARIANT` 中提取嵌套值。`GET_BY_KEYPATH` 以 `VARIANT` 返回结果,而 `GET_BY_KEYPATH_STRING` 返回 `STRING`。 +--- + +# GET_BY_KEYPATH + +使用 **key path** 字符串从 `VARIANT` 中提取嵌套值。`GET_BY_KEYPATH` 以 `VARIANT` 返回结果,而 `GET_BY_KEYPATH_STRING` 返回 `STRING`。 + +key path 遵循 Postgres 风格的大括号语法:每个段都用 `{}` 包裹,段与段之间用逗号分隔,例如 `'{user,profile,name}'`。数组索引可以用数字指定,例如 `'{items,0}'`。 + +## 语法 {#syntax} + +```sql +GET_BY_KEYPATH(, ) +GET_BY_KEYPATH_STRING(, ) +``` + +## 返回类型 {#return-type} + +- `GET_BY_KEYPATH`: `VARIANT` +- `GET_BY_KEYPATH_STRING`: `STRING` + +## 示例 {#examples} + +```sql +SELECT GET_BY_KEYPATH(PARSE_JSON('{"user":{"name":"Ada","tags":["a","b"]}}'), '{user,name}') AS profile_name; + +┌──────────────┐ +│ profile_name │ +├──────────────┤ +│ "Ada" │ +└──────────────┘ +``` + +```sql +SELECT GET_BY_KEYPATH(PARSE_JSON('[10, {"a":{"k1":[1,2,3]}}]'), '{1,a,k1}') AS inner_array; + +┌─────────────┐ +│ inner_array │ +├─────────────┤ +│ [1,2,3] │ +└─────────────┘ +``` + +```sql +SELECT GET_BY_KEYPATH_STRING(PARSE_JSON('{"user":{"name":"Ada"}}'), '{user,name}') AS name_text; + +┌──────────┐ +│ name_text│ +├──────────┤ +│ Ada │ +└──────────┘ +``` + +```sql +SELECT GET_BY_KEYPATH_STRING(PARSE_JSON('[10, {"scores":[100,98]}]'), '{1,scores,0}') AS first_score; + +┌──────────────┐ +│ first_score │ +├──────────────┤ +│ 100 │ +└──────────────┘ +``` + +如果 key path 无法解析,这两个函数都返回 `NULL`。 \ No newline at end of file diff --git a/tidb-cloud-lake/sql/get-ignore-case.md b/tidb-cloud-lake/sql/get-ignore-case.md new file mode 100644 index 0000000000000..386115f151ef2 --- /dev/null +++ b/tidb-cloud-lake/sql/get-ignore-case.md @@ -0,0 +1,38 @@ +--- +title: GET_IGNORE_CASE +summary: 从包含 OBJECT 的 VARIANT 中按 field_name 提取值。如果任一参数为 NULL,则返回值为 Variant 或 NULL。 +--- + +# GET_IGNORE_CASE + +从包含 `OBJECT` 的 `VARIANT` 中按 field_name 提取值。如果任一参数为 `NULL`,则返回值为 `Variant` 或 `NULL`。 + +`GET_IGNORE_CASE` 与 `GET` 类似,但对字段名执行不区分大小写的匹配。首先匹配完全相同的字段名;如果未找到,则按字母顺序匹配不区分大小写的字段名。 + +## 语法 {#syntax} + +```sql +GET_IGNORE_CASE( , ) +``` + +## 参数 {#arguments} + +| 参数 | 描述 | +|----------------|------------------------------------------------------------------| +| `` | 包含 ARRAY 或 OBJECT 的 VARIANT 值 | +| `` | 指定 OBJECT 键值对中键的字符串值 | + +## 返回类型 {#return-type} + +VARIANT + +## 示例 {#examples} + +```sql +SELECT get_ignore_case(parse_json('{"aa":1, "aA":2, "Aa":3}'), 'AA'); ++---------------------------------------------------------------+ +| get_ignore_case(parse_json('{"aa":1, "aA":2, "Aa":3}'), 'AA') | ++---------------------------------------------------------------+ +| 3 | ++---------------------------------------------------------------+ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/get-lineage.md b/tidb-cloud-lake/sql/get-lineage.md new file mode 100644 index 0000000000000..179aaed30cd05 --- /dev/null +++ b/tidb-cloud-lake/sql/get-lineage.md @@ -0,0 +1,104 @@ +--- +title: GET_LINEAGE +summary: 返回表、视图、stage 或列的上游或下游血缘。返回结果中的每一行表示血缘路径中的一个源到目标关系。 +--- + +# GET_LINEAGE + +返回表、视图、stage 或列的上游或下游血缘。返回结果中的每一行表示血缘路径中的一个源到目标关系。 + +## 语法 {#syntax} + +```sql +GET_LINEAGE( + '', + '', + '' + [, ] +) +``` + +## 参数 {#arguments} + +| 参数 | 描述 | +|----------|-------------| +| `object_name` | 起始对象。对于表或视图,使用 `[catalog.]database.object`;对于 stage,使用 `stage_name`;对于列,使用 `[catalog.]database.object.column`。如果名称中省略了 catalog 或 database,则使用当前会话中的值。 | +| `object_domain` | 对象类型:`TABLE`、`VIEW`、`STAGE` 或 `COLUMN`。 | +| `direction` | `UPSTREAM` 表示向数据源方向追踪;`DOWNSTREAM` 表示向消费方方向追踪。 | +| `distance` | 可选,表示要遍历的最大跳数,取值范围为 `1` 到 `5`。默认值为 `5`。 | + +参数按位置传递。 + +## 输出列 {#output-columns} + +| 列 | 类型 | 描述 | +|--------|------|-------------| +| `source_object_catalog` | Nullable(String) | 包含源对象的 catalog;对于 stage 为 `NULL`。 | +| `source_object_database` | Nullable(String) | 包含源对象的数据库;对于 stage 为 `NULL`。 | +| `source_object_name` | Nullable(String) | 源对象名称。 | +| `source_object_domain` | Nullable(String) | 源对象的域:`TABLE`、`VIEW` 或 `STAGE`。 | +| `source_column_name` | Nullable(String) | 列血缘中的源列;否则为 `NULL`。 | +| `source_status` | String | `ACTIVE`,或者当源列具有脱敏策略时为 `MASKED`。 | +| `target_object_catalog` | Nullable(String) | 包含目标对象的 catalog;对于 stage 为 `NULL`。 | +| `target_object_database` | Nullable(String) | 包含目标对象的数据库;对于 stage 为 `NULL`。 | +| `target_object_name` | Nullable(String) | 目标对象名称。 | +| `target_object_domain` | Nullable(String) | 目标对象的域:`TABLE`、`VIEW` 或 `STAGE`。 | +| `target_column_name` | Nullable(String) | 列血缘中的目标列;否则为 `NULL`。 | +| `target_status` | String | `ACTIVE`,或者当目标列具有脱敏策略时为 `MASKED`。 | +| `distance` | Int32 | 与请求对象之间的跳数。直接关系的距离为 `1`。 | +| `process` | Nullable(String) | 以 JSON 格式表示的元信息,描述创建该关系的操作,例如其查询 ID、查询文本、用户、时间和血缘类型。 | + +## 示例 {#examples} + +本节提供用于追踪血缘的查询示例。 + +### 查找上游表 {#find-upstream-tables} + +以下查询返回 `agg_customer_sales` 最多两跳的上游关系: + +```sql +SELECT + distance, + source_object_catalog, + source_object_database, + source_object_name, + source_object_domain, + target_object_database, + target_object_name +FROM GET_LINEAGE( + 'lineage_demo.agg_customer_sales', + 'TABLE', + 'UPSTREAM', + 2 +) +ORDER BY distance; +``` + +### 查找下游列 {#find-downstream-columns} + +以下查询追踪 `fact_orders.amount` 被使用的位置: + +```sql +SELECT + distance, + source_object_name, + source_column_name, + target_object_name, + target_column_name +FROM GET_LINEAGE( + 'lineage_demo.fact_orders.amount', + 'COLUMN', + 'DOWNSTREAM', + 5 +) +ORDER BY distance, target_object_name, target_column_name; +``` + +## 使用说明 {#usage-notes} + +- 如果对象存在但没有已记录的血缘,函数不会返回任何行。 +- 结果会根据当前角色可见的对象范围进行过滤。 +- Stage 关系仅支持对象级别;暂存文件中的字段不会作为稳定列返回。 +- 系统对象和 `information_schema` 对象不会被记录为血缘源。 +- 外部 catalog 对象会作为终止端点返回,不会继续遍历。 +- 对于在启用血缘之前已存在的视图,可使用 [`REFRESH LINEAGE`](/tidb-cloud-lake/sql/refresh-lineage.md) 回填血缘。 \ No newline at end of file diff --git a/tidb-cloud-lake/sql/get-path.md b/tidb-cloud-lake/sql/get-path.md new file mode 100644 index 0000000000000..3e5f3ce9375bf --- /dev/null +++ b/tidb-cloud-lake/sql/get-path.md @@ -0,0 +1,59 @@ +--- +title: GET_PATH +summary: 按 `path_name` 从 `VARIANT` 中提取值。如果任一参数为 `NULL`,则返回值为 `Variant` 或 `NULL`。 +--- + +# GET_PATH + +按 `path_name` 从 `VARIANT` 中提取值。如果任一参数为 `NULL`,则返回值为 `Variant` 或 `NULL`。 + +`GET_PATH` 等价于一系列 `GET` 函数的链式调用。`path_name` 由字段名的串联组成,字段名前可以带句点 (`.`)、冒号 (`:`) 或索引运算符(`[index]`)。第一个字段名不需要指定前导标识符。 + +## 语法 {#syntax} + +```sql +GET_PATH( , ) +``` + +## 参数 {#arguments} + +| 参数 | 描述 | +|---------------|------------------------------------------------------------------| +| `` | 包含 ARRAY 或 OBJECT 的 VARIANT 值 | +| `` | 由多个字段名串联组成的 String 值 | + +## 返回类型 {#return-type} + +VARIANT + +## 示例 {#examples} + +```sql +SELECT get_path(parse_json('{"k1":[0,1,2], "k2":{"k3":3,"k4":4}}'), 'k1[0]'); ++-----------------------------------------------------------------------+ +| get_path(parse_json('{"k1":[0,1,2], "k2":{"k3":3,"k4":4}}'), 'k1[0]') | ++-----------------------------------------------------------------------+ +| 0 | ++-----------------------------------------------------------------------+ + +SELECT get_path(parse_json('{"k1":[0,1,2], "k2":{"k3":3,"k4":4}}'), 'k2:k3'); ++-----------------------------------------------------------------------+ +| get_path(parse_json('{"k1":[0,1,2], "k2":{"k3":3,"k4":4}}'), 'k2:k3') | ++-----------------------------------------------------------------------+ +| 3 | ++-----------------------------------------------------------------------+ + +SELECT get_path(parse_json('{"k1":[0,1,2], "k2":{"k3":3,"k4":4}}'), 'k2.k4'); ++-----------------------------------------------------------------------+ +| get_path(parse_json('{"k1":[0,1,2], "k2":{"k3":3,"k4":4}}'), 'k2.k4') | ++-----------------------------------------------------------------------+ +| 4 | ++-----------------------------------------------------------------------+ + +SELECT get_path(parse_json('{"k1":[0,1,2], "k2":{"k3":3,"k4":4}}'), 'k2.k5'); ++-----------------------------------------------------------------------+ +| get_path(parse_json('{"k1":[0,1,2], "k2":{"k3":3,"k4":4}}'), 'k2.k5') | ++-----------------------------------------------------------------------+ +| NULL | ++-----------------------------------------------------------------------+ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/get-sql.md b/tidb-cloud-lake/sql/get-sql.md new file mode 100644 index 0000000000000..82539660c090b --- /dev/null +++ b/tidb-cloud-lake/sql/get-sql.md @@ -0,0 +1,30 @@ +--- +title: GET +summary: 按索引(从 1 开始)从数组中返回一个元素。 +--- + +# GET + +按索引(从 1 开始)从数组中返回一个元素。 + +## 语法 {#syntax} + +```sql +GET( , ) +``` + +## 别名 {#aliases} + +- [ARRAY_GET](/tidb-cloud-lake/sql/array-get.md) + +## 示例 {#examples} + +```sql +SELECT GET([1, 2], 2), ARRAY_GET([1, 2], 2); + +┌───────────────────────────────────────┐ +│ get([1, 2], 2) │ array_get([1, 2], 2) │ +├────────────────┼──────────────────────┤ +│ 2 │ 2 │ +└───────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/get.md b/tidb-cloud-lake/sql/get.md new file mode 100644 index 0000000000000..3fb5c10ad3052 --- /dev/null +++ b/tidb-cloud-lake/sql/get.md @@ -0,0 +1,55 @@ +--- +title: GET +summary: 从包含 ARRAY 的 Variant 中按索引提取值,或从包含 OBJECT 的 Variant 中按 field_name 提取值。如果任一参数为 NULL,则返回的值为 Variant 或 NULL。 +--- + +# GET + +从包含 `ARRAY` 的 `Variant` 中按 `index` 提取值,或从包含 `OBJECT` 的 `Variant` 中按 `field_name` 提取值。如果任一参数为 `NULL`,则返回的值为 `Variant` 或 `NULL`。 + +`GET` 对 `field_name` 采用大小写敏感匹配。若要进行大小写不敏感匹配,请使用 `GET_IGNORE_CASE`。 + +## 语法 {#syntax} + +```sql +GET( , ) + +GET( , ) +``` + +## 参数 {#arguments} + +| 参数 | 描述 | +|----------------|------------------------------------------------------------------| +| `` | 包含 ARRAY 或 OBJECT 的 VARIANT 值 | +| `` | Uint32 值,指定 ARRAY 中值的位置 | +| `` | String 值,指定 OBJECT 中键值对的键 | + +## 返回类型 {#return-type} + +VARIANT + +## 示例 {#examples} + +```sql +SELECT get(parse_json('[2.71, 3.14]'), 0); ++------------------------------------+ +| get(parse_json('[2.71, 3.14]'), 0) | ++------------------------------------+ +| 2.71 | ++------------------------------------+ + +SELECT get(parse_json('{"aa":1, "aA":2, "Aa":3}'), 'aa'); ++---------------------------------------------------+ +| get(parse_json('{"aa":1, "aA":2, "Aa":3}'), 'aa') | ++---------------------------------------------------+ +| 1 | ++---------------------------------------------------+ + +SELECT get(parse_json('{"aa":1, "aA":2, "Aa":3}'), 'AA'); ++---------------------------------------------------+ +| get(parse_json('{"aa":1, "aA":2, "Aa":3}'), 'AA') | ++---------------------------------------------------+ +| NULL | ++---------------------------------------------------+ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/glob.md b/tidb-cloud-lake/sql/glob.md new file mode 100644 index 0000000000000..0c77f5b701137 --- /dev/null +++ b/tidb-cloud-lake/sql/glob.md @@ -0,0 +1,39 @@ +--- +title: GLOB +summary: 使用通配符字符执行大小写敏感的模式匹配。 +--- + +# GLOB + +使用通配符字符执行大小写敏感的模式匹配: + +- `?` 匹配任意单个字符。 +- `*` 匹配零个或多个字符。 + +## 语法 {#syntax} + +```sql +GLOB(, ) +``` + +## 返回类型 {#return-type} + +返回 BOOLEAN:如果输入字符串与模式匹配,则为 `true`;否则为 `false`。 + +## 示例 {#examples} + +```sql +SELECT + GLOB('abc', 'a?c'), + GLOB('abc', 'a*d'), + GLOB('abc', 'abc'), + GLOB('abc', 'abcd'), + GLOB('abcdef', 'a?c*'), + GLOB('hello', 'h*l');; + +┌────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ +│ glob('abc', 'a?c') │ glob('abc', 'a*d') │ glob('abc', 'abc') │ glob('abc', 'abcd') │ glob('abcdef', 'a?c*') │ glob('hello', 'h*l') │ +├────────────────────┼────────────────────┼────────────────────┼─────────────────────┼────────────────────────┼──────────────────────┤ +│ true │ false │ true │ false │ true │ false │ +└────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/grant.md b/tidb-cloud-lake/sql/grant.md new file mode 100644 index 0000000000000..5ea1ba465c3ba --- /dev/null +++ b/tidb-cloud-lake/sql/grant.md @@ -0,0 +1,335 @@ +--- +title: GRANT +summary: 为特定数据库对象授予权限、角色和所有权。这包括。 +--- + +# GRANT + +为特定数据库对象授予权限、角色和所有权。这包括: + +- 向角色授予权限。 +- 将角色分配给用户或其他角色。 +- 将所有权转移给角色。 + +另请参阅: + +- [REVOKE](/tidb-cloud-lake/sql/revoke.md) +- [SHOW GRANTS](/tidb-cloud-lake/sql/show-grants.md) + +> 使用 `GRANT` 修改权限或角色后,运行 [SYSTEM FLUSH PRIVILEGES](/tidb-cloud-lake/guides/privileges.md) 以立即将更新广播到每个查询节点。 + +## 语法 {#syntax} + +### 授予权限 {#granting-privileges} + +要了解什么是权限及其工作方式,请参阅 [权限](/tidb-cloud-lake/guides/privileges.md)。 + +> **注意:** +> +> 会创建所有权对象的 CREATE 类权限不能直接授予给用户。这些权限必须先授予给角色,然后再将该角色分配给用户。这包括: +> +> - CREATE +> - CREATE DATABASE +> - CREATE WAREHOUSE +> - CREATE CONNECTION +> - CREATE SEQUENCE +> - CREATE PROCEDURE +> - CREATE MASKING POLICY +> - CREATE ROW ACCESS POLICY +> +> 由于 `ALL` 包含这些 CREATE 权限,因此 `GRANT ALL ... TO USER` 也会失败。例如,`GRANT ALL ON *.* TO USER u1` 或 `GRANT CREATE DATABASE ON *.* TO USER u1` 都会失败。请改用: +> +> ```sql +> GRANT ALL ON *.* TO ROLE r1; +> GRANT ROLE r1 TO USER u1; +> ``` + +```sql +GRANT { + schemaObjectPrivileges | ALL [ PRIVILEGES ] ON + } +TO ROLE +``` + +其中: + +```sql +schemaObjectPrivileges ::= +-- For TABLE + { SELECT | INSERT } + +-- For SCHEMA + { CREATE | DROP | ALTER } + +-- For USER + { CREATE USER } + +-- For ROLE + { CREATE ROLE} + +-- For STAGE + { READ, WRITE } + +-- For UDF + { USAGE } + +-- For MASKING POLICY (account-level privileges) + { CREATE MASKING POLICY | APPLY MASKING POLICY } + +-- For ROW ACCESS POLICY (account-level privileges) + { CREATE ROW ACCESS POLICY | APPLY ROW ACCESS POLICY } +``` + +```sql +privileges_level ::= + *.* + | db_name.* + | db_name.tbl_name + | STAGE + | UDF + | MASKING POLICY + | ROW ACCESS POLICY +``` + +### 授予 Masking Policy 权限 {#granting-masking-policy-privileges} + +使用以下形式管理对单个 masking policy 的访问: + +```sql +GRANT APPLY ON MASKING POLICY TO ROLE +GRANT ALL [ PRIVILEGES ] ON MASKING POLICY TO ROLE +GRANT OWNERSHIP ON MASKING POLICY TO ROLE '' +``` + +- `CREATE MASKING POLICY` 允许角色创建新的 masking policy。 +- `APPLY MASKING POLICY` 允许被授予者在结合适当的 `ALTER TABLE` 或 policy 命令时,对任意 masking policy 执行附加、分离、描述或删除操作。 +- `GRANT APPLY ON MASKING POLICY ...` 授予被授权者管理特定 masking policy 的权限,而无需授予全局访问权限。 +- OWNERSHIP 提供对 masking policy 的完全控制;{{{ .lake }}} 会自动向创建者角色授予新 policy 的 OWNERSHIP,并在 policy 被删除时回收该权限。 + +### 授予 Row Access Policy 权限 {#granting-row-access-policy-privileges} + +使用以下形式管理对单个 row access policy 的访问: + +```sql +GRANT APPLY ON ROW ACCESS POLICY TO ROLE +GRANT ALL [ PRIVILEGES ] ON ROW ACCESS POLICY TO ROLE +GRANT OWNERSHIP ON ROW ACCESS POLICY TO ROLE '' +``` + +- `CREATE ROW ACCESS POLICY` 允许角色创建新的 row access policy。 +- `APPLY ROW ACCESS POLICY` 授予将任意 row access policy 附加到表或从表分离的权限,同时也包括 DESCRIBE/DROP 命令。 +- `GRANT APPLY ON ROW ACCESS POLICY ...` 将访问限制在特定的 row access policy 上。 +- OWNERSHIP 提供对 row access policy 的完全控制;创建者角色会自动获得 OWNERSHIP,并在 policy 被删除时失去该权限。 + +### 授予角色 {#granting-role} + +要了解什么是角色及其工作方式,请参阅 [角色](/tidb-cloud-lake/guides/roles.md)。 + +```sql +-- Grant a role to a user +GRANT ROLE TO + +-- Grant a role to a role +GRANT ROLE TO ROLE +``` + +> **注意:** +> +> `default_role` 是用户属性——它在你执行 `CREATE USER` 或 `ALTER USER` 时设置,`GRANT`/`REVOKE` 不会修改它。因此,如果你之后回收了某个恰好是他人 `default_role` 的角色,该设置仍然保留,但角色成员关系已经不存在。请使用 `ALTER USER ... WITH DEFAULT_ROLE` 显式更新它。 + +### 授予所有权 {#granting-ownership} + +要了解什么是所有权及其工作方式,请参阅 [所有权](/tidb-cloud-lake/guides/ownership.md)。 + +```sql +-- Grant ownership of a specific table within a database to a role +GRANT OWNERSHIP ON . TO ROLE '' + +-- Grant ownership of a stage to a role +GRANT OWNERSHIP ON STAGE TO ROLE '' + +-- Grant ownership of a user-defined function (UDF) to a role +GRANT OWNERSHIP ON UDF TO ROLE '' +``` + +## 示例 {#examples} + +### 示例 1:向角色授予权限 {#example-1-granting-privileges-to-a-role} + +创建一个角色: + +```sql +CREATE ROLE user1_role; +``` + +将 `default` 数据库中所有现有表的 `ALL` 权限授予角色 `user1_role`: + +```sql +GRANT ALL ON default.* TO ROLE user1_role; +``` + +```sql +SHOW GRANTS FOR ROLE user1_role; ++--------------------------------------------------+ +| Grants | ++--------------------------------------------------+ +| GRANT ALL ON 'default'.* TO ROLE 'user1_role' | ++--------------------------------------------------+ +``` + +将所有数据库的 `ALL` 权限授予角色 `user1_role`: + +```sql +GRANT ALL ON *.* TO ROLE user1_role; +``` + +```sql +SHOW GRANTS FOR ROLE user1_role; ++--------------------------------------------------+ +| Grants | ++--------------------------------------------------+ +| GRANT ALL ON 'default'.* TO ROLE 'user1_role' | +| GRANT ALL ON *.* TO ROLE 'user1_role' | ++--------------------------------------------------+ +``` + +将名为 `s1` 的 stage 的 `ALL` 权限授予角色 `user1_role`: + +```sql +GRANT ALL ON STAGE s1 TO ROLE user1_role; +``` + +```sql +SHOW GRANTS FOR ROLE user1_role; ++--------------------------------------------------+ +| Grants | ++--------------------------------------------------+ +| GRANT ALL ON STAGE s1 TO ROLE 'user1_role' | ++--------------------------------------------------+ +``` + +将名为 `f1` 的 UDF 的 `ALL` 权限授予角色 `user1_role`: + +```sql +GRANT ALL ON UDF f1 TO ROLE user1_role; +``` + +```sql +SHOW GRANTS FOR ROLE user1_role; ++--------------------------------------------------+ +| Grants | ++--------------------------------------------------+ +| GRANT ALL ON UDF f1 TO ROLE 'user1_role' | ++--------------------------------------------------+ +``` + +### 示例 2:向角色授予特定权限 {#example-2-granting-specific-privileges-to-a-role} + +将 `mydb` 数据库中所有现有表的 `SELECT` 权限授予角色 `role1`: + +创建角色: + +```sql +CREATE ROLE role1; +``` + +向角色授予权限: + +```sql +GRANT SELECT ON mydb.* TO ROLE role1; +``` + +显示该角色的授权信息: + +```sql +SHOW GRANTS FOR ROLE role1; ++-------------------------------------+ +| Grants | ++-------------------------------------+ +| GRANT SELECT ON 'mydb'.* TO 'role1' | ++-------------------------------------+ +``` + +### 示例 3:将角色授予用户 {#example-3-granting-a-role-to-a-user} + +创建一个用户: + +```sql +CREATE USER user1 IDENTIFIED BY 'abc123' WITH DEFAULT_ROLE = 'role1'; +``` + +角色 `role1` 的授权信息如下: + +```sql +SHOW GRANTS FOR ROLE role1; ++-------------------------------------+ +| Grants | ++-------------------------------------+ +| GRANT SELECT ON 'mydb'.* TO 'role1' | ++-------------------------------------+ +``` + +将角色 `role1` 授予用户 `user1`: + +```sql + GRANT ROLE role1 TO user1; +``` + +现在,用户 `user1` 的授权信息如下: + +```sql +SHOW GRANTS FOR user1; ++-------------------------------------+ +| Grants | ++-------------------------------------+ +| GRANT ROLE role1 TO 'user1'@'%' | ++-------------------------------------+ +``` + +### 示例 4:向角色授予所有权 {#example-4-granting-ownership-to-a-role} + +```sql +-- Grant ownership of all tables in the 'finance_data' database to the role 'data_owner' +GRANT OWNERSHIP ON finance_data.* TO ROLE 'data_owner'; + +-- Grant ownership of the table 'transactions' in the 'finance_data' schema to the role 'data_owner' +GRANT OWNERSHIP ON finance_data.transactions TO ROLE 'data_owner'; + +-- Grant ownership of the stage 'ingestion_stage' to the role 'data_owner' +GRANT OWNERSHIP ON STAGE ingestion_stage TO ROLE 'data_owner'; + +-- Grant ownership of the user-defined function 'calculate_profit' to the role 'data_owner' +GRANT OWNERSHIP ON UDF calculate_profit TO ROLE 'data_owner'; +``` + +### 示例 5:授予 Masking Policy 权限 {#example-5-granting-masking-policy-privileges} + +```sql +-- Allow the current user to create masking policies +GRANT CREATE MASKING POLICY ON *.* TO ROLE security_admin; + +-- Create a masking policy while assuming the security_admin role +CREATE MASKING POLICY email_mask AS (val STRING) RETURNS STRING -> '***'; + +-- Grant a role the ability to apply the policy when altering tables +GRANT APPLY ON MASKING POLICY email_mask TO ROLE pii_readers; + +-- Review the masking policy privileges +SHOW GRANTS ON MASKING POLICY email_mask; +``` + +### 示例 6:授予 Row Access Policy 权限 {#example-6-granting-row-access-policy-privileges} + +```sql +-- Allow the current role to create row access policies +GRANT CREATE ROW ACCESS POLICY ON *.* TO ROLE row_policy_admin; + +-- Define a row access policy while assuming the row_policy_admin role +CREATE ROW ACCESS POLICY rap_region AS (region STRING) RETURNS BOOLEAN -> region = 'APAC'; + +-- Allow a role to apply the policy when altering tables +GRANT APPLY ON ROW ACCESS POLICY rap_region TO ROLE apac_only; + +-- Review the row access policy privileges +SHOW GRANTS ON ROW ACCESS POLICY rap_region; +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/great-circle-angle.md b/tidb-cloud-lake/sql/great-circle-angle.md new file mode 100644 index 0000000000000..7f41ea092621b --- /dev/null +++ b/tidb-cloud-lake/sql/great-circle-angle.md @@ -0,0 +1,39 @@ +--- +title: GREAT_CIRCLE_ANGLE +summary: 返回球面上两点之间的中心角(以度为单位)。 +--- + +# GREAT_CIRCLE_ANGLE + +返回球面上两点之间的中心角(以度为单位)。这两个点使用经度和纬度(单位为度)指定。 + +## 语法 {#syntax} + +```sql +GREAT_CIRCLE_ANGLE(, , , ) +``` + +## 参数 {#arguments} + +| 参数 | 描述 | +|-----------|-------------| +| `` | 第一个点的经度,单位为度。 | +| `` | 第一个点的纬度,单位为度。 | +| `` | 第二个点的经度,单位为度。 | +| `` | 第二个点的纬度,单位为度。 | + +## 返回类型 {#return-type} + +Float32。 + +## 示例 {#examples} + +```sql +SELECT GREAT_CIRCLE_ANGLE(55.755831, 37.617673, -55.755831, -37.617673) AS angle; + +╭───────────╮ +│ angle │ +├───────────┤ +│ 127.05919 │ +╰───────────╯ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/great-circle-distance.md b/tidb-cloud-lake/sql/great-circle-distance.md new file mode 100644 index 0000000000000..08644f6a755d6 --- /dev/null +++ b/tidb-cloud-lake/sql/great-circle-distance.md @@ -0,0 +1,39 @@ +--- +title: GREAT_CIRCLE_DISTANCE +summary: 返回球面上两点之间的大圆距离,单位为米。 +--- + +# GREAT_CIRCLE_DISTANCE + +返回球面上两点之间的大圆距离,单位为米。点的位置使用以度为单位的经度和纬度指定。 + +## 语法 {#syntax} + +```sql +GREAT_CIRCLE_DISTANCE(, , , ) +``` + +## 参数 {#arguments} + +| 参数 | 描述 | +|-----------|-------------| +| `` | 第一个点的经度,单位为度。 | +| `` | 第一个点的纬度,单位为度。 | +| `` | 第二个点的经度,单位为度。 | +| `` | 第二个点的纬度,单位为度。 | + +## 返回类型 {#return-type} + +Float32。 + +## 示例 {#examples} + +```sql +SELECT GREAT_CIRCLE_DISTANCE(55.755831, 37.617673, -55.755831, -37.617673) AS distance; + +╭────────────╮ +│ distance │ +├────────────┤ +│ 14128353.0 │ +╰────────────╯ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/greatest-ignore-nulls.md b/tidb-cloud-lake/sql/greatest-ignore-nulls.md new file mode 100644 index 0000000000000..44a9452a6a4be --- /dev/null +++ b/tidb-cloud-lake/sql/greatest-ignore-nulls.md @@ -0,0 +1,30 @@ +--- +title: GREATEST_IGNORE_NULLS +summary: 返回一组值中的最大值,并忽略任何 NULL 值。 +--- + +# GREATEST_IGNORE_NULLS + +返回一组值中的最大值,并忽略任何 NULL 值。 + +另请参阅:[GREATEST](/tidb-cloud-lake/sql/greatest.md) + +## 语法 {#syntax} + +```sql +GREATEST_IGNORE_NULLS(, ...) +``` + +## 示例 {#examples} + +```sql +SELECT GREATEST_IGNORE_NULLS(5, 9, 4), GREATEST_IGNORE_NULLS(5, 9, null); +``` + +```sql +┌────────────────────────────────────────────────────────────────────┐ +│ greatest_ignore_nulls(5, 9, 4) │ greatest_ignore_nulls(5, 9, NULL) │ +├────────────────────────────────┼───────────────────────────────────┤ +│ 9 │ 9 │ +└────────────────────────────────────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/greatest.md b/tidb-cloud-lake/sql/greatest.md new file mode 100644 index 0000000000000..460716678815b --- /dev/null +++ b/tidb-cloud-lake/sql/greatest.md @@ -0,0 +1,30 @@ +--- +title: GREATEST +summary: 返回一组值中的最大值。如果集合中的任意值为 NULL,则该函数返回 NULL。 +--- + +# GREATEST + +返回一组值中的最大值。如果集合中的任意值为 `NULL`,则该函数返回 `NULL`。 + +另请参阅:[GREATEST_IGNORE_NULLS](/tidb-cloud-lake/sql/greatest-ignore-nulls.md) + +## 语法 {#syntax} + +```sql +GREATEST(, ...) +``` + +## 示例 {#examples} + +```sql +SELECT GREATEST(5, 9, 4), GREATEST(5, 9, null); +``` + +```sql +┌──────────────────────────────────────────┐ +│ greatest(5, 9, 4) │ greatest(5, 9, NULL) │ +├───────────────────┼──────────────────────┤ +│ 9 │ NULL │ +└──────────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/group-array-moving-avg.md b/tidb-cloud-lake/sql/group-array-moving-avg.md new file mode 100644 index 0000000000000..944573741525c --- /dev/null +++ b/tidb-cloud-lake/sql/group-array-moving-avg.md @@ -0,0 +1,58 @@ +--- +title: GROUP_ARRAY_MOVING_AVG +summary: GROUP_ARRAY_MOVING_AVG 函数用于计算输入值的移动平均值。该函数可以将窗口大小作为参数传入。如果未指定,则函数将窗口大小设为输入值的数量。 +--- + +# GROUP_ARRAY_MOVING_AVG + +GROUP_ARRAY_MOVING_AVG 函数用于计算输入值的移动平均值。该函数可以将窗口大小作为参数传入。如果未指定,则函数将窗口大小设为输入值的数量。 + +## 语法 {#syntax} + +```sql +GROUP_ARRAY_MOVING_AVG() + +GROUP_ARRAY_MOVING_AVG()() +``` + +## 参数 {#arguments} + +| 参数 | 描述 | +|------------------| ------------------------ | +| `` | 任意数值表达式 | +| `` | 任意数值表达式 | + +## 返回类型 {#return-type} + +返回一个 [数组](/tidb-cloud-lake/sql/array.md),其元素类型根据源数据类型为 double 或 decimal。 + +## 示例 {#examples} + +```sql +-- Create a table and insert sample data +CREATE TABLE hits ( + user_id INT, + request_num INT +); + +INSERT INTO hits (user_id, request_num) +VALUES (1, 10), + (2, 15), + (3, 20), + (1, 13), + (2, 21), + (3, 25), + (1, 30), + (2, 41), + (3, 45); + +SELECT user_id, GROUP_ARRAY_MOVING_AVG(2)(request_num) AS avg_request_num +FROM hits +GROUP BY user_id; + +| user_id | avg_request_num | +|---------|------------------| +| 1 | [5.0,11.5,21.5] | +| 3 | [10.0,22.5,35.0] | +| 2 | [7.5,18.0,31.0] | +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/group-array-moving-sum.md b/tidb-cloud-lake/sql/group-array-moving-sum.md new file mode 100644 index 0000000000000..32cdc9667a3a3 --- /dev/null +++ b/tidb-cloud-lake/sql/group-array-moving-sum.md @@ -0,0 +1,58 @@ +--- +title: GROUP_ARRAY_MOVING_SUM +summary: GROUP_ARRAY_MOVING_SUM 函数用于计算输入值的移动和。该函数可以将窗口大小作为参数传入。如果未指定,则函数将窗口大小设为输入值的数量。 +--- + +# GROUP_ARRAY_MOVING_SUM + +GROUP_ARRAY_MOVING_SUM 函数用于计算输入值的移动和。该函数可以将窗口大小作为参数传入。如果未指定,则函数将窗口大小设为输入值的数量。 + +## 语法 {#syntax} + +```sql +GROUP_ARRAY_MOVING_SUM() + +GROUP_ARRAY_MOVING_SUM()() +``` + +## 参数 {#arguments} + +| 参数 | 描述 | +|------------------| ---------------------- | +| `` | 任意数值表达式 | +| `` | 任意数值表达式 | + +## 返回类型 {#return-type} + +返回一个 [数组](/tidb-cloud-lake/sql/array.md),其元素类型与原始数据相同。 + +## 示例 {#examples} + +```sql +-- Create a table and insert sample data +CREATE TABLE hits ( + user_id INT, + request_num INT +); + +INSERT INTO hits (user_id, request_num) +VALUES (1, 10), + (2, 15), + (3, 20), + (1, 13), + (2, 21), + (3, 25), + (1, 30), + (2, 41), + (3, 45); + +SELECT user_id, GROUP_ARRAY_MOVING_SUM(2)(request_num) AS request_num +FROM hits +GROUP BY user_id; + +| user_id | request_num | +|---------|-------------| +| 1 | [10,23,43] | +| 2 | [20,45,70] | +| 3 | [15,36,62] | +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/group-by.md b/tidb-cloud-lake/sql/group-by.md new file mode 100644 index 0000000000000..91e4b809b5e80 --- /dev/null +++ b/tidb-cloud-lake/sql/group-by.md @@ -0,0 +1,8 @@ +--- +title: GROUP BY +summary: "{{{ .lake }}} 支持带有多种扩展的 GROUP BY。" +--- + +# GROUP BY + +{{{ .lake }}} 支持带有多种扩展的 GROUP BY。 \ No newline at end of file diff --git a/tidb-cloud-lake/sql/group-concat.md b/tidb-cloud-lake/sql/group-concat.md new file mode 100644 index 0000000000000..0a1021c86adc4 --- /dev/null +++ b/tidb-cloud-lake/sql/group-concat.md @@ -0,0 +1,8 @@ +--- +title: GROUP_CONCAT +summary: LISTAGG 的别名。 +--- + +# GROUP_CONCAT + +[LISTAGG](/tidb-cloud-lake/sql/listagg.md) 的别名。 \ No newline at end of file diff --git a/tidb-cloud-lake/sql/grouping.md b/tidb-cloud-lake/sql/grouping.md new file mode 100644 index 0000000000000..9c320a5c470ce --- /dev/null +++ b/tidb-cloud-lake/sql/grouping.md @@ -0,0 +1,45 @@ +--- +title: GROUPING +summary: 返回一个位掩码,用于指示哪些 `GROUP BY` 表达式未包含在当前分组集中。位从右到左分配,最右侧参数对应最低有效位;如果对应表达式包含在生成当前结果行的分组集的分组条件中,则该位为 0,否则为 1。 +--- + +# GROUPING + +返回一个位掩码,用于指示哪些 `GROUP BY` 表达式未包含在当前分组集中。位从右到左分配,最右侧参数对应最低有效位;如果对应表达式包含在生成当前结果行的分组集的分组条件中,则该位为 0,否则为 1。 + +## 语法 {#syntax} + +```sql +GROUPING ( expr [, expr, ...] ) +``` + +> **注意:** +> +> `GROUPING` 只能与 `GROUPING SETS`、`ROLLUP` 或 `CUBE` 一起使用,并且其参数必须在 grouping sets 列表中。 + +## 参数 {#arguments} + +分组集项。 + +## 返回类型 {#return-type} + +UInt32。 + +## 示例 {#examples} + +```sql +select a, b, grouping(a), grouping(b), grouping(a,b), grouping(b,a) from t group by grouping sets ((a,b),(a),(b), ()) ; ++------+------+-------------+-------------+----------------+----------------+ +| a | b | grouping(a) | grouping(b) | grouping(a, b) | grouping(b, a) | ++------+------+-------------+-------------+----------------+----------------+ +| NULL | A | 1 | 0 | 2 | 1 | +| a | NULL | 0 | 1 | 1 | 2 | +| b | A | 0 | 0 | 0 | 0 | +| NULL | NULL | 1 | 1 | 3 | 3 | +| a | A | 0 | 0 | 0 | 0 | +| b | B | 0 | 0 | 0 | 0 | +| b | NULL | 0 | 1 | 1 | 2 | +| a | B | 0 | 0 | 0 | 0 | +| NULL | B | 1 | 0 | 2 | 1 | ++------+------+-------------+-------------+----------------+----------------+ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/h3-cell-area-m2.md b/tidb-cloud-lake/sql/h3-cell-area-m2.md new file mode 100644 index 0000000000000..42875a77d3b57 --- /dev/null +++ b/tidb-cloud-lake/sql/h3-cell-area-m2.md @@ -0,0 +1,26 @@ +--- +title: H3_CELL_AREA_M2 +summary: 返回特定单元的精确面积,单位为平方米。 +--- + +# H3_CELL_AREA_M2 + +返回特定单元的精确面积,单位为平方米。 + +## 语法 {#syntax} + +```sql +H3_CELL_AREA_M2(h3) +``` + +## 示例 {#examples} + +```sql +SELECT H3_CELL_AREA_M2(599119489002373119); + +┌─────────────────────────────────────┐ +│ h3_cell_area_m2(599119489002373119) │ +├─────────────────────────────────────┤ +│ 127785582.60809991 │ +└─────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/h3-cell-area-rads2.md b/tidb-cloud-lake/sql/h3-cell-area-rads2.md new file mode 100644 index 0000000000000..91e5bc0f82ae0 --- /dev/null +++ b/tidb-cloud-lake/sql/h3-cell-area-rads2.md @@ -0,0 +1,26 @@ +--- +title: H3_CELL_AREA_RADS2 +summary: 返回特定单元的精确面积,单位为平方弧度。 +--- + +# H3_CELL_AREA_RADS2 + +返回特定单元的精确面积,单位为平方弧度。 + +## 语法 {#syntax} + +```sql +H3_CELL_AREA_RADS2(h3) +``` + +## 示例 {#examples} + +```sql +SELECT H3_CELL_AREA_RADS2(599119489002373119); + +┌────────────────────────────────────────┐ +│ h3_cell_area_rads2(599119489002373119) │ +├────────────────────────────────────────┤ +│ 0.000003148224310427697 │ +└────────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/h3-distance.md b/tidb-cloud-lake/sql/h3-distance.md new file mode 100644 index 0000000000000..057e527134f5c --- /dev/null +++ b/tidb-cloud-lake/sql/h3-distance.md @@ -0,0 +1,26 @@ +--- +title: H3_DISTANCE +summary: 返回给定两个 H3 索引之间的网格距离。 +--- + +# H3_DISTANCE + +返回给定两个 [H3](https://eng.uber.com/h3/) 索引之间的网格距离。 + +## 语法 {#syntax} + +```sql +H3_DISTANCE(h3, a_h3) +``` + +## 示例 {#examples} + +```sql +SELECT H3_DISTANCE(599119489002373119, 599119491149856767); + +┌─────────────────────────────────────────────────────┐ +│ h3_distance(599119489002373119, 599119491149856767) │ +├─────────────────────────────────────────────────────┤ +│ 1 │ +└─────────────────────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/h3-edge-angle.md b/tidb-cloud-lake/sql/h3-edge-angle.md new file mode 100644 index 0000000000000..132d192da762d --- /dev/null +++ b/tidb-cloud-lake/sql/h3-edge-angle.md @@ -0,0 +1,26 @@ +--- +title: H3_EDGE_ANGLE +summary: 返回 H3 六边形边的平均长度(以 grade 为单位)。 +--- + +# H3_EDGE_ANGLE + +返回 H3 六边形边的平均长度(以 grade 为单位)。 + +## 语法 {#syntax} + +```sql +H3_EDGE_ANGLE(res) +``` + +## 示例 {#examples} + +```sql +SELECT H3_EDGE_ANGLE(10); + +┌───────────────────────┐ +│ h3_edge_angle(10) │ +├───────────────────────┤ +│ 0.0006822586214153981 │ +└───────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/h3-edge-length-km.md b/tidb-cloud-lake/sql/h3-edge-length-km.md new file mode 100644 index 0000000000000..06198b1c6b922 --- /dev/null +++ b/tidb-cloud-lake/sql/h3-edge-length-km.md @@ -0,0 +1,26 @@ +--- +title: H3_EDGE_LENGTH_KM +summary: 返回给定分辨率下六边形边长的平均值(单位为千米)。不包括五边形。 +--- + +# H3_EDGE_LENGTH_KM + +返回给定分辨率下六边形边长的平均值(单位为千米)。不包括五边形。 + +## 语法 {#syntax} + +```sql +H3_EDGE_LENGTH_KM(res) +``` + +## 示例 {#examples} + +```sql +SELECT H3_EDGE_LENGTH_KM(1); + +┌──────────────────────┐ +│ h3_edge_length_km(1) │ +├──────────────────────┤ +│ 483.0568390711111 │ +└──────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/h3-edge-length-m.md b/tidb-cloud-lake/sql/h3-edge-length-m.md new file mode 100644 index 0000000000000..63bc2b06f97b7 --- /dev/null +++ b/tidb-cloud-lake/sql/h3-edge-length-m.md @@ -0,0 +1,24 @@ +--- +title: H3_EDGE_LENGTH_M +summary: 返回给定分辨率下六边形边长的平均值(单位为米)。不包括五边形。 +--- + +# H3_EDGE_LENGTH_M + +返回给定分辨率下六边形边长的平均值(单位为米)。不包括五边形。 + +## 语法 {#syntax} + +```sql +H3_EDGE_LENGTH_M(1) +``` + +## 示例 {#examples} + +```sql +┌─────────────────────┐ +│ h3_edge_length_m(1) │ +├─────────────────────┤ +│ 483056.8390711111 │ +└─────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/h3-exact-edge-length-km.md b/tidb-cloud-lake/sql/h3-exact-edge-length-km.md new file mode 100644 index 0000000000000..15b06ccf5e451 --- /dev/null +++ b/tidb-cloud-lake/sql/h3-exact-edge-length-km.md @@ -0,0 +1,26 @@ +--- +title: H3_EXACT_EDGE_LENGTH_KM +summary: 计算此有向边的长度,单位为千米。 +--- + +# H3_EXACT_EDGE_LENGTH_KM + +计算此有向边的长度,单位为千米。 + +## 语法 {#syntax} + +```sql +H3_EXACT_EDGE_LENGTH_KM(h3) +``` + +## 示例 {#examples} + +```sql +SELECT H3_EXACT_EDGE_LENGTH_KM(1319695429381652479); + +┌──────────────────────────────────────────────┐ +│ h3_exact_edge_length_km(1319695429381652479) │ +├──────────────────────────────────────────────┤ +│ 8.267326832647143 │ +└──────────────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/h3-exact-edge-length-m.md b/tidb-cloud-lake/sql/h3-exact-edge-length-m.md new file mode 100644 index 0000000000000..29f3ed9ec40d6 --- /dev/null +++ b/tidb-cloud-lake/sql/h3-exact-edge-length-m.md @@ -0,0 +1,26 @@ +--- +title: H3_EXACT_EDGE_LENGTH_M +summary: 计算此有向边的长度,单位为米。 +--- + +# H3_EXACT_EDGE_LENGTH_M + +计算此有向边的长度,单位为米。 + +## 语法 {#syntax} + +```sql +H3_EXACT_EDGE_LENGTH_M(h3) +``` + +## 示例 {#examples} + +```sql +SELECT H3_EXACT_EDGE_LENGTH_M(1319695429381652479); + +┌─────────────────────────────────────────────┐ +│ h3_exact_edge_length_m(1319695429381652479) │ +├─────────────────────────────────────────────┤ +│ 8267.326832647143 │ +└─────────────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/h3-exact-edge-length-rads.md b/tidb-cloud-lake/sql/h3-exact-edge-length-rads.md new file mode 100644 index 0000000000000..5f566152e4504 --- /dev/null +++ b/tidb-cloud-lake/sql/h3-exact-edge-length-rads.md @@ -0,0 +1,26 @@ +--- +title: H3_EXACT_EDGE_LENGTH_RADS +summary: 计算此有向边的长度,单位为弧度。 +--- + +# H3_EXACT_EDGE_LENGTH_RADS + +计算此有向边的长度,单位为弧度。 + +## 语法 {#syntax} + +```sql +H3_EXACT_EDGE_LENGTH_RADS(h3) +``` + +## 示例 {#examples} + +```sql +SELECT H3_EXACT_EDGE_LENGTH_KM(1319695429381652479); + +┌──────────────────────────────────────────────┐ +│ h3_exact_edge_length_km(1319695429381652479) │ +├──────────────────────────────────────────────┤ +│ 8.267326832647143 │ +└──────────────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/h3-get-base-cell.md b/tidb-cloud-lake/sql/h3-get-base-cell.md new file mode 100644 index 0000000000000..9148ba07e57b0 --- /dev/null +++ b/tidb-cloud-lake/sql/h3-get-base-cell.md @@ -0,0 +1,26 @@ +--- +title: H3_GET_BASE_CELL +summary: 返回给定 [H3](https://eng.uber.com/h3/) 索引的基础单元编号。 +--- + +# H3_GET_BASE_CELL + +返回给定 [H3](https://eng.uber.com/h3/) 索引的基础单元编号。 + +## 语法 {#syntax} + +```sql +H3_GET_BASE_CELL(h3) +``` + +## 示例 {#examples} + +```sql +SELECT H3_GET_BASE_CELL(644325524701193974); + +┌──────────────────────────────────────┐ +│ h3_get_base_cell(644325524701193974) │ +├──────────────────────────────────────┤ +│ 8 │ +└──────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/h3-get-destination-index-unidirectional-edge.md b/tidb-cloud-lake/sql/h3-get-destination-index-unidirectional-edge.md new file mode 100644 index 0000000000000..77c26af7d6e2b --- /dev/null +++ b/tidb-cloud-lake/sql/h3-get-destination-index-unidirectional-edge.md @@ -0,0 +1,26 @@ +--- +title: H3_GET_DESTINATION_INDEX_FROM_UNIDIRECTIONAL_EDGE +summary: 返回单向边 H3Index 的目标六边形索引。 +--- + +# H3_GET_DESTINATION_INDEX_FROM_UNIDIRECTIONAL_EDGE + +返回单向边 H3Index 的目标六边形索引。 + +## 语法 {#syntax} + +```sql +H3_GET_DESTINATION_INDEX_FROM_UNIDIRECTIONAL_EDGE(h3) +``` + +## 示例 {#examples} + +```sql +SELECT H3_GET_DESTINATION_INDEX_FROM_UNIDIRECTIONAL_EDGE(1248204388774707199); + +┌────────────────────────────────────────────────────────────────────────┐ +│ h3_get_destination_index_from_unidirectional_edge(1248204388774707199) │ +├────────────────────────────────────────────────────────────────────────┤ +│ 599686043507097599 │ +└────────────────────────────────────────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/h3-get-faces.md b/tidb-cloud-lake/sql/h3-get-faces.md new file mode 100644 index 0000000000000..05b7467bff8be --- /dev/null +++ b/tidb-cloud-lake/sql/h3-get-faces.md @@ -0,0 +1,26 @@ +--- +title: H3_GET_FACES +summary: 查找与给定 H3 索引相交的所有二十面体面。面以 0-19 的整数表示。 +--- + +# H3_GET_FACES + +查找与给定 [H3](https://eng.uber.com/h3/) 索引相交的所有二十面体面。面以 0-19 的整数表示。 + +## 语法 {#syntax} + +```sql +H3_GET_FACES(h3) +``` + +## 示例 {#examples} + +```sql +SELECT H3_GET_FACES(599119489002373119); + +┌──────────────────────────────────┐ +│ h3_get_faces(599119489002373119) │ +├──────────────────────────────────┤ +│ [0,1,2,3,4] │ +└──────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/h3-get-indexes-unidirectional-edge.md b/tidb-cloud-lake/sql/h3-get-indexes-unidirectional-edge.md new file mode 100644 index 0000000000000..3f1d82a771348 --- /dev/null +++ b/tidb-cloud-lake/sql/h3-get-indexes-unidirectional-edge.md @@ -0,0 +1,26 @@ +--- +title: H3_GET_INDEXES_FROM_UNIDIRECTIONAL_EDGE +summary: 返回给定单向边 H3Index 的起点和终点六边形索引。 +--- + +# H3_GET_INDEXES_FROM_UNIDIRECTIONAL_EDGE + +返回给定单向边 H3Index 的起点和终点六边形索引。 + +## 语法 {#syntax} + +```sql +H3_GET_INDEXES_FROM_UNIDIRECTIONAL_EDGE(h3) +``` + +## 示例 {#examples} + +```sql +SELECT H3_GET_INDEXES_FROM_UNIDIRECTIONAL_EDGE(1248204388774707199); + +┌──────────────────────────────────────────────────────────────┐ +│ h3_get_indexes_from_unidirectional_edge(1248204388774707199) │ +├──────────────────────────────────────────────────────────────┤ +│ (599686042433355775,599686043507097599) │ +└──────────────────────────────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/h3-get-origin-index-unidirectional-edge.md b/tidb-cloud-lake/sql/h3-get-origin-index-unidirectional-edge.md new file mode 100644 index 0000000000000..5f8a08a508186 --- /dev/null +++ b/tidb-cloud-lake/sql/h3-get-origin-index-unidirectional-edge.md @@ -0,0 +1,26 @@ +--- +title: H3_GET_ORIGIN_INDEX_FROM_UNIDIRECTIONAL_EDGE +summary: 返回单向边 H3Index 的起始六边形索引。 +--- + +# H3_GET_ORIGIN_INDEX_FROM_UNIDIRECTIONAL_EDGE + +返回单向边 H3Index 的起始六边形索引。 + +## 语法 {#syntax} + +```sql +H3_GET_ORIGIN_INDEX_FROM_UNIDIRECTIONAL_EDGE(h3) +``` + +## 示例 {#examples} + +```sql +SELECT H3_GET_ORIGIN_INDEX_FROM_UNIDIRECTIONAL_EDGE(1248204388774707199); + +┌───────────────────────────────────────────────────────────────────┐ +│ h3_get_origin_index_from_unidirectional_edge(1248204388774707199) │ +├───────────────────────────────────────────────────────────────────┤ +│ 599686042433355775 │ +└───────────────────────────────────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/h3-get-resolution.md b/tidb-cloud-lake/sql/h3-get-resolution.md new file mode 100644 index 0000000000000..cd7b4078c869f --- /dev/null +++ b/tidb-cloud-lake/sql/h3-get-resolution.md @@ -0,0 +1,26 @@ +--- +title: H3_GET_RESOLUTION +summary: 返回给定 H3 索引的分辨率。 +--- + +# H3_GET_RESOLUTION + +返回给定 [H3](https://eng.uber.com/h3/) 索引的分辨率。 + +## 语法 {#syntax} + +```sql +H3_GET_RESOLUTION(h3) +``` + +## 示例 {#examples} + +```sql +SELECT H3_GET_RESOLUTION(644325524701193974); + +┌───────────────────────────────────────┐ +│ h3_get_resolution(644325524701193974) │ +├───────────────────────────────────────┤ +│ 15 │ +└───────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/h3-get-unidirectional-edge-boundary.md b/tidb-cloud-lake/sql/h3-get-unidirectional-edge-boundary.md new file mode 100644 index 0000000000000..3b1a00dca5e10 --- /dev/null +++ b/tidb-cloud-lake/sql/h3-get-unidirectional-edge-boundary.md @@ -0,0 +1,26 @@ +--- +title: H3_GET_UNIDIRECTIONAL_EDGE_BOUNDARY +summary: 返回定义单向边的坐标。 +--- + +# H3_GET_UNIDIRECTIONAL_EDGE_BOUNDARY + +返回定义单向边的坐标。 + +## 语法 {#syntax} + +```sql +H3_GET_UNIDIRECTIONAL_EDGE_BOUNDARY(h3) +``` + +## 示例 {#examples} + +```sql +SELECT H3_GET_UNIDIRECTIONAL_EDGE_BOUNDARY(1248204388774707199); + +┌─────────────────────────────────────────────────────────────────────────────────┐ +│ h3_get_unidirectional_edge_boundary(1248204388774707199) │ +├─────────────────────────────────────────────────────────────────────────────────┤ +│ [(37.42012867767778,-122.03773496427027),(37.33755608435298,-122.090428929044)] │ +└─────────────────────────────────────────────────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/h3-get-unidirectional-edge.md b/tidb-cloud-lake/sql/h3-get-unidirectional-edge.md new file mode 100644 index 0000000000000..12a2c8c668512 --- /dev/null +++ b/tidb-cloud-lake/sql/h3-get-unidirectional-edge.md @@ -0,0 +1,26 @@ +--- +title: H3_GET_UNIDIRECTIONAL_EDGE +summary: 返回给定两个 H3 索引之间的边。 +--- + +# H3_GET_UNIDIRECTIONAL_EDGE + +返回给定两个 [H3](https://eng.uber.com/h3/) 索引之间的边。 + +## 语法 {#syntax} + +```sql +H3_GET_UNIDIRECTIONAL_EDGE(h3, a_h3) +``` + +## 示例 {#examples} + +```sql +SELECT H3_GET_UNIDIRECTIONAL_EDGE(644325524701193897, 644325524701193754); + +┌────────────────────────────────────────────────────────────────────┐ +│ h3_get_unidirectional_edge(644325524701193897, 644325524701193754) │ +├────────────────────────────────────────────────────────────────────┤ +│ 1581074247194257065 │ +└────────────────────────────────────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/h3-get-unidirectional-edges-hexagon.md b/tidb-cloud-lake/sql/h3-get-unidirectional-edges-hexagon.md new file mode 100644 index 0000000000000..266972e1055ec --- /dev/null +++ b/tidb-cloud-lake/sql/h3-get-unidirectional-edges-hexagon.md @@ -0,0 +1,26 @@ +--- +title: H3_GET_UNIDIRECTIONAL_EDGES_FROM_HEXAGON +summary: 返回给定 H3Index 的所有单向边。 +--- + +# H3_GET_UNIDIRECTIONAL_EDGES_FROM_HEXAGON + +返回给定 H3Index 的所有单向边。 + +## 语法 {#syntax} + +```sql +H3_GET_UNIDIRECTIONAL_EDGES_FROM_HEXAGON(h3) +``` + +## 示例 {#examples} + +```sql +SELECT H3_GET_UNIDIRECTIONAL_EDGES_FROM_HEXAGON(644325524701193754); + +┌───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ +│ h3_get_unidirectional_edges_from_hexagon(644325524701193754) │ +├───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤ +│ [1292843871042545178,1364901465080473114,1436959059118401050,1509016653156328986,1581074247194256922,1653131841232184858] │ +└───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/h3-hex-area-km2.md b/tidb-cloud-lake/sql/h3-hex-area-km2.md new file mode 100644 index 0000000000000..5b01b401dbcc8 --- /dev/null +++ b/tidb-cloud-lake/sql/h3-hex-area-km2.md @@ -0,0 +1,26 @@ +--- +title: H3_HEX_AREA_KM2 +summary: 返回给定分辨率下六边形的平均面积(单位:平方千米)。不包括五边形。 +--- + +# H3_HEX_AREA_KM2 + +返回给定分辨率下六边形的平均面积(单位:平方千米)。不包括五边形。 + +## 语法 {#syntax} + +```sql +H3_HEX_AREA_KM2(res) +``` + +## 示例 {#examples} + +```sql +SELECT H3_HEX_AREA_KM2(1); + +┌────────────────────┐ +│ h3_hex_area_km2(1) │ +├────────────────────┤ +│ 609788.4417941332 │ +└────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/h3-hex-area-m2.md b/tidb-cloud-lake/sql/h3-hex-area-m2.md new file mode 100644 index 0000000000000..e57baae91195f --- /dev/null +++ b/tidb-cloud-lake/sql/h3-hex-area-m2.md @@ -0,0 +1,26 @@ +--- +title: H3_HEX_AREA_M2 +summary: 返回给定分辨率下六边形的平均面积(单位为平方米)。不包括五边形。 +--- + +# H3_HEX_AREA_M2 + +返回给定分辨率下六边形的平均面积(单位为平方米)。不包括五边形。 + +## 语法 {#syntax} + +```sql +H3_HEX_AREA_M2(res) +``` + +## 示例 {#examples} + +```sql +SELECT H3_HEX_AREA_M2(1); + +┌───────────────────┐ +│ h3_hex_area_m2(1) │ +├───────────────────┤ +│ 609788441794.1339 │ +└───────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/h3-hex-ring.md b/tidb-cloud-lake/sql/h3-hex-ring.md new file mode 100644 index 0000000000000..56ac41a178e67 --- /dev/null +++ b/tidb-cloud-lake/sql/h3-hex-ring.md @@ -0,0 +1,26 @@ +--- +title: H3_HEX_RING +summary: 返回给定 [H3](https://eng.uber.com/h3/) 索引在网格距离恰好为 k 处的“空心”六边形环。 +--- + +# H3_HEX_RING + +返回给定 [H3](https://eng.uber.com/h3/) 索引在网格距离恰好为 `k` 处的“空心”六边形环。 + +## 语法 {#syntax} + +```sql +H3_HEX_RING(h3, k) +``` + +## 示例 {#examples} + +```sql +SELECT H3_HEX_RING(599686042433355775, 2); + +┌───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ +│ h3_hex_ring(599686042433355775, 2) │ +├───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤ +│ [599686018811035647,599686034917163007,599686029548453887,599686032769679359,599686198125920255,599686040285872127,599686041359613951,599686039212130303,599686023106002943,599686027400970239,599686013442326527,599686012368584703] │ +└───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/h3-indexes-are-neighbors.md b/tidb-cloud-lake/sql/h3-indexes-are-neighbors.md new file mode 100644 index 0000000000000..2f4d7d9e3eebb --- /dev/null +++ b/tidb-cloud-lake/sql/h3-indexes-are-neighbors.md @@ -0,0 +1,26 @@ +--- +title: H3_INDEXES_ARE_NEIGHBORS +summary: 返回所提供的 H3 索引是否为邻居。 +--- + +# H3_INDEXES_ARE_NEIGHBORS + +返回所提供的 [H3](https://eng.uber.com/h3/) 索引是否为邻居。 + +## 语法 {#syntax} + +```sql +H3_INDEXES_ARE_NEIGHBORS(h3, a_h3) +``` + +## 示例 {#examples} + +```sql +SELECT H3_INDEXES_ARE_NEIGHBORS(644325524701193974, 644325524701193897); + +┌──────────────────────────────────────────────────────────────────┐ +│ h3_indexes_are_neighbors(644325524701193974, 644325524701193897) │ +├──────────────────────────────────────────────────────────────────┤ +│ true │ +└──────────────────────────────────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/h3-is-pentagon.md b/tidb-cloud-lake/sql/h3-is-pentagon.md new file mode 100644 index 0000000000000..b5c6cb0748dee --- /dev/null +++ b/tidb-cloud-lake/sql/h3-is-pentagon.md @@ -0,0 +1,26 @@ +--- +title: H3_IS_PENTAGON +summary: 检查给定的 H3 索引是否表示一个五边形单元。 +--- + +# H3_IS_PENTAGON + +检查给定的 [H3](https://eng.uber.com/h3/) 索引是否表示一个五边形单元。 + +## 语法 {#syntax} + +```sql +H3_IS_PENTAGON(h3) +``` + +## 示例 {#examples} + +```sql +SELECT H3_IS_PENTAGON(599119489002373119); + +┌────────────────────────────────────┐ +│ h3_is_pentagon(599119489002373119) │ +├────────────────────────────────────┤ +│ true │ +└────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/h3-is-res-class-iii.md b/tidb-cloud-lake/sql/h3-is-res-class-iii.md new file mode 100644 index 0000000000000..0922ac9eed2de --- /dev/null +++ b/tidb-cloud-lake/sql/h3-is-res-class-iii.md @@ -0,0 +1,26 @@ +--- +title: H3_IS_RES_CLASS_III +summary: 检查给定的 H3 索引是否具有 Class III 方向的分辨率。 +--- + +# H3_IS_RES_CLASS_III + +检查给定的 [H3](https://eng.uber.com/h3/) 索引是否具有 Class III 方向的分辨率。 + +## 语法 {#syntax} + +```sql +H3_IS_RES_CLASS_III(h3) +``` + +## 示例 {#examples} + +```sql +SELECT H3_IS_RES_CLASS_III(635318325446452991); + +┌─────────────────────────────────────────┐ +│ h3_is_res_class_iii(635318325446452991) │ +├─────────────────────────────────────────┤ +│ true │ +└─────────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/h3-is-valid.md b/tidb-cloud-lake/sql/h3-is-valid.md new file mode 100644 index 0000000000000..a9f743984dd40 --- /dev/null +++ b/tidb-cloud-lake/sql/h3-is-valid.md @@ -0,0 +1,26 @@ +--- +title: H3_IS_VALID +summary: 检查给定的 H3 索引是否有效。 +--- + +# H3_IS_VALID + +检查给定的 [H3](https://eng.uber.com/h3/) 索引是否有效。 + +## 语法 {#syntax} + +```sql +H3_IS_VALID(h3) +``` + +## 示例 {#examples} + +```sql +SELECT H3_IS_VALID(644325524701193974); + +┌─────────────────────────────────┐ +│ h3_is_valid(644325524701193974) │ +├─────────────────────────────────┤ +│ true │ +└─────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/h3-k-ring.md b/tidb-cloud-lake/sql/h3-k-ring.md new file mode 100644 index 0000000000000..34d0bdbd30140 --- /dev/null +++ b/tidb-cloud-lake/sql/h3-k-ring.md @@ -0,0 +1,26 @@ +--- +title: H3_K_RING +summary: 返回一个数组,其中包含围绕输入 H3 索引的 k-ring 六边形的 H3 索引。该数组中的每个元素都是一个 H3 索引。 +--- + +# H3_K_RING + +返回一个数组,其中包含围绕输入 [H3](https://eng.uber.com/h3/) 索引的 k-ring 六边形的 H3 索引。该数组中的每个元素都是一个 H3 索引。 + +## 语法 {#syntax} + +```sql +H3_K_RING(h3, k) +``` + +## 示例 {#examples} + +```sql +SELECT H3_K_RING(644325524701193974, 1); + +┌────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ +│ h3_k_ring(644325524701193974, 1) │ +├────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤ +│ [644325524701193974,644325524701193899,644325524701193869,644325524701193970,644325524701193968,644325524701193972,644325524701193897] │ +└────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/h3-line.md b/tidb-cloud-lake/sql/h3-line.md new file mode 100644 index 0000000000000..634b21f61c343 --- /dev/null +++ b/tidb-cloud-lake/sql/h3-line.md @@ -0,0 +1,26 @@ +--- +title: H3_LINE +summary: 返回给定两个 H3 索引之间的索引连线。 +--- + +# H3_LINE + +返回给定两个 [H3](https://eng.uber.com/h3/) 索引之间的索引连线。 + +## 语法 {#syntax} + +```sql +H3_LINE(h3, a_h3) +``` + +## 示例 {#examples} + +```sql +SELECT H3_LINE(599119489002373119, 599119491149856767); + +┌─────────────────────────────────────────────────┐ +│ h3_line(599119489002373119, 599119491149856767) │ +├─────────────────────────────────────────────────┤ +│ [599119489002373119,599119491149856767] │ +└─────────────────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/h3-num-hexagons.md b/tidb-cloud-lake/sql/h3-num-hexagons.md new file mode 100644 index 0000000000000..787fd8f348e6a --- /dev/null +++ b/tidb-cloud-lake/sql/h3-num-hexagons.md @@ -0,0 +1,26 @@ +--- +title: H3_NUM_HEXAGONS +summary: 返回给定分辨率下唯一 H3 索引的数量。 +--- + +# H3_NUM_HEXAGONS + +返回给定分辨率下唯一 [H3](https://eng.uber.com/h3/) 索引的数量。 + +## 语法 {#syntax} + +```sql +H3_NUM_HEXAGONS(res) +``` + +## 示例 {#examples} + +```sql +SELECT H3_NUM_HEXAGONS(10); + +┌─────────────────────┐ +│ h3_num_hexagons(10) │ +├─────────────────────┤ +│ 33897029882 │ +└─────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/h3-to-center-child.md b/tidb-cloud-lake/sql/h3-to-center-child.md new file mode 100644 index 0000000000000..5d8e18eff0571 --- /dev/null +++ b/tidb-cloud-lake/sql/h3-to-center-child.md @@ -0,0 +1,26 @@ +--- +title: H3_TO_CENTER_CHILD +summary: 返回指定分辨率下的中心子索引。 +--- + +# H3_TO_CENTER_CHILD + +返回指定分辨率下的中心子索引。 + +## 语法 {#syntax} + +```sql +H3_TO_CENTER_CHILD(h3, res) +``` + +## 示例 {#examples} + +```sql +SELECT H3_TO_CENTER_CHILD(599119489002373119, 15); + +┌────────────────────────────────────────────┐ +│ h3_to_center_child(599119489002373119, 15) │ +├────────────────────────────────────────────┤ +│ 644155484202336256 │ +└────────────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/h3-to-children.md b/tidb-cloud-lake/sql/h3-to-children.md new file mode 100644 index 0000000000000..b4765c520479d --- /dev/null +++ b/tidb-cloud-lake/sql/h3-to-children.md @@ -0,0 +1,26 @@ +--- +title: H3_TO_CHILDREN +summary: 返回 `h3` 在分辨率 `child_res` 下包含的索引。 +--- + +# H3_TO_CHILDREN + +返回 `h3` 在分辨率 `child_res` 下包含的索引。 + +## 语法 {#syntax} + +```sql +H3_TO_CHILDREN(h3, child_res) +``` + +## 示例 {#examples} + +```sql +SELECT H3_TO_CHILDREN(635318325446452991, 14); + +┌────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ +│ h3_to_children(635318325446452991, 14) │ +├────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤ +│ [639821925073823431,639821925073823439,639821925073823447,639821925073823455,639821925073823463,639821925073823471,639821925073823479] │ +└────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/h3-to-geo-boundary.md b/tidb-cloud-lake/sql/h3-to-geo-boundary.md new file mode 100644 index 0000000000000..234b7c13e168c --- /dev/null +++ b/tidb-cloud-lake/sql/h3-to-geo-boundary.md @@ -0,0 +1,26 @@ +--- +title: H3_TO_GEO_BOUNDARY +summary: 返回一个数组,其中包含与 H3 索引对应的六边形顶点的经度和纬度坐标。 +--- + +# H3_TO_GEO_BOUNDARY + +返回一个数组,其中包含与 [H3](https://eng.uber.com/h3/) 索引对应的六边形顶点的经度和纬度坐标。 + +## 语法 {#syntax} + +```sql +H3_TO_GEO_BOUNDARY(h3) +``` + +## 示例 {#examples} + +```sql +SELECT H3_TO_GEO_BOUNDARY(644325524701193974); + +┌───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ +│ h3_to_geo_boundary(644325524701193974) │ +├───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤ +│ [(37.79505811173477,55.712900225355526),(37.79506506997187,55.71289713485417),(37.795073126539855,55.71289934095484),(37.795074224871684,55.71290463755745),(37.79506726663349,55.71290772805916),(37.79505921006456,55.712905521957914)] │ +└───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/h3-to-geo.md b/tidb-cloud-lake/sql/h3-to-geo.md new file mode 100644 index 0000000000000..5f0c2ca88dc0e --- /dev/null +++ b/tidb-cloud-lake/sql/h3-to-geo.md @@ -0,0 +1,26 @@ +--- +title: H3_TO_GEO +summary: 返回与给定 H3 索引对应的经度和纬度。 +--- + +# H3_TO_GEO + +返回与给定 [H3](https://eng.uber.com/h3/) 索引对应的经度和纬度。 + +## 语法 {#syntax} + +```sql +H3_TO_GEO(h3) +``` + +## 示例 {#examples} + +```sql +SELECT H3_TO_GEO(644325524701193974); + +┌────────────────────────────────────────┐ +│ h3_to_geo(644325524701193974) │ +├────────────────────────────────────────┤ +│ (37.79506616830255,55.712902431456676) │ +└────────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/h3-to-parent.md b/tidb-cloud-lake/sql/h3-to-parent.md new file mode 100644 index 0000000000000..3cd352a70c91e --- /dev/null +++ b/tidb-cloud-lake/sql/h3-to-parent.md @@ -0,0 +1,26 @@ +--- +title: H3_TO_PARENT +summary: 返回包含分辨率为 `parent_res` 的 `h3` 的父索引。返回 0 表示发生了错误。 +--- + +# H3_TO_PARENT + +返回包含分辨率为 `parent_res` 的 `h3` 的父索引。返回 0 表示发生了错误。 + +## 语法 {#syntax} + +```sql +H3_TO_PARENT(h3, parent_res) +``` + +## 示例 {#examples} + +```sql +SELECT H3_TO_PARENT(635318325446452991, 12); + +┌──────────────────────────────────────┐ +│ h3_to_parent(635318325446452991, 12) │ +├──────────────────────────────────────┤ +│ 630814725819082751 │ +└──────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/h3-to-string.md b/tidb-cloud-lake/sql/h3-to-string.md new file mode 100644 index 0000000000000..4d090522663c3 --- /dev/null +++ b/tidb-cloud-lake/sql/h3-to-string.md @@ -0,0 +1,26 @@ +--- +title: H3_TO_STRING +summary: 将给定 H3 索引的表示形式转换为字符串表示形式。 +--- + +# H3_TO_STRING + +将给定的 [H3](https://eng.uber.com/h3/) 索引表示形式转换为字符串表示形式。 + +## 语法 {#syntax} + +```sql +H3_TO_STRING(h3) +``` + +## 示例 {#examples} + +```sql +SELECT H3_TO_STRING(635318325446452991); + +┌──────────────────────────────────┐ +│ h3_to_string(635318325446452991) │ +├──────────────────────────────────┤ +│ 8d11aa6a38826ff │ +└──────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/h3-unidirectional-edge-is-valid.md b/tidb-cloud-lake/sql/h3-unidirectional-edge-is-valid.md new file mode 100644 index 0000000000000..d98294fce7edd --- /dev/null +++ b/tidb-cloud-lake/sql/h3-unidirectional-edge-is-valid.md @@ -0,0 +1,26 @@ +--- +title: H3_UNIDIRECTIONAL_EDGE_IS_VALID +summary: 判断提供的 H3Index 是否为有效的单向边索引。如果它是单向边,则返回 1;否则返回 0。 +--- + +# H3_UNIDIRECTIONAL_EDGE_IS_VALID + +判断提供的 H3Index 是否为有效的单向边索引。如果它是单向边,则返回 1;否则返回 0。 + +## 语法 {#syntax} + +```sql +H3_UNIDIRECTIONAL_EDGE_IS_VALID(h3) +``` + +## 示例 {#examples} + +```sql +SELECT H3_UNIDIRECTIONAL_EDGE_IS_VALID(1248204388774707199); + +┌──────────────────────────────────────────────────────┐ +│ h3_unidirectional_edge_is_valid(1248204388774707199) │ +├──────────────────────────────────────────────────────┤ +│ true │ +└──────────────────────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/hash-functions.md b/tidb-cloud-lake/sql/hash-functions.md new file mode 100644 index 0000000000000..c1fff03c9f7f4 --- /dev/null +++ b/tidb-cloud-lake/sql/hash-functions.md @@ -0,0 +1,61 @@ +--- +title: 散列函数 +summary: 本页按功能分类,全面概述 {{{ .lake }}} 中的散列函数,便于快速查阅。 +--- + +# 散列函数 + +本页按功能分类,全面概述 {{{ .lake }}} 中的散列函数,便于快速查阅。 + +## 加密散列函数 {#cryptographic-hash-functions} + +| 函数 | 描述 | 示例 | +|----------|-------------|--------| +| [MD5](/tidb-cloud-lake/sql/md.md) | 计算 MD5 128 位校验和 | `MD5('1234567890')` → `'e807f1fcf82d132f9bb018ca6738a19f'` | +| [SHA1](/tidb-cloud-lake/sql/sha.md) / [SHA](/tidb-cloud-lake/sql/sha.md) | 计算 SHA-1 160 位校验和 | `SHA1('1234567890')` → `'01b307acba4f54f55aafc33bb06bbbf6ca803e9a'` | +| [SHA2](/tidb-cloud-lake/sql/sha.md) | 计算 SHA-2 系列散列值(SHA-224、SHA-256、SHA-384、SHA-512) | `SHA2('1234567890', 256)` → `'c775e7b757ede630cd0aa1113bd102661ab38829ca52a6422ab782862f268646'` | +| [BLAKE3](/tidb-cloud-lake/sql/blake.md) | 计算 BLAKE3 散列值 | `BLAKE3('1234567890')` → `'e2cf6ae2a7e65c7b9e089da1ad582100a0d732551a6a07abb07f7a4a119ecc51'` | + +## 非加密散列函数 {#non-cryptographic-hash-functions} + +| 函数 | 描述 | 示例 | +|----------|-------------|--------| +| [XXHASH32](/tidb-cloud-lake/sql/xxhash.md) | 计算 xxHash32 32 位散列值 | `XXHASH32('1234567890')` → `3768853052` | +| [XXHASH64](/tidb-cloud-lake/sql/xxhash.md) | 计算 xxHash64 64 位散列值 | `XXHASH64('1234567890')` → `12237639266330420150` | +| [SIPHASH64](/tidb-cloud-lake/sql/siphash.md) / [SIPHASH](/tidb-cloud-lake/sql/siphash.md) | 计算 SipHash-2-4 64 位散列值 | `SIPHASH64('1234567890')` → `2917646445633666330` | +| [CITY64WITHSEED](/tidb-cloud-lake/sql/city-withseed.md) | 使用数据填充值计算 CityHash64 散列值 | `CITY64WITHSEED('1234567890', 42)` → `5210846883572933352` | + +## 使用示例 {#usage-examples} + +### 数据完整性验证 {#data-integrity-verification} + +```sql +-- Calculate MD5 hash for file content verification +SELECT + filename, + MD5(file_content) AS content_hash +FROM files +ORDER BY filename; +``` + +### 数据匿名化 {#data-anonymization} + +```sql +-- Hash sensitive data before storing or processing +SELECT + user_id, + SHA2(email, 256) AS hashed_email, + SHA2(phone_number, 256) AS hashed_phone +FROM users; +``` + +### 基于散列的分区 {#hash-based-partitioning} + +```sql +-- Use hash functions for data distribution +SELECT + XXHASH64(customer_id) % 10 AS partition_id, + COUNT(*) AS records_count +FROM orders +GROUP BY partition_id; +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/haversine.md b/tidb-cloud-lake/sql/haversine.md new file mode 100644 index 0000000000000..1e077c28748a7 --- /dev/null +++ b/tidb-cloud-lake/sql/haversine.md @@ -0,0 +1,40 @@ +--- +title: HAVERSINE +summary: 使用 [Haversine formula](https://en.wikipedia.org/wiki/Haversine_formula) 计算地球表面两点之间的大圆距离,单位为千米。这两个点通过其以度为单位的纬度和经度指定。 +--- + +# HAVERSINE + +使用 [Haversine formula](https://en.wikipedia.org/wiki/Haversine_formula) 计算地球表面两点之间的大圆距离,单位为千米。这两个点通过其以度为单位的纬度和经度指定。 + +## 语法 {#syntax} + +```sql +HAVERSINE(, , , ) +``` + +## 参数 {#arguments} + +| 参数 | 描述 | +|-----------|------------------------------------| +| `` | 第一个点的纬度。 | +| `` | 第一个点的经度。 | +| `` | 第二个点的纬度。 | +| `` | 第二个点的经度。 | + +## 返回类型 {#return-type} + +Double。 + +## 示例 {#examples} + +```sql +SELECT + HAVERSINE(40.7127, -74.0059, 34.0500, -118.2500) AS distance + +┌────────────────┐ +│ distance │ +├────────────────┤ +│ 3936.390533556 │ +└────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/hex.md b/tidb-cloud-lake/sql/hex.md new file mode 100644 index 0000000000000..dc0ebdb25b6d0 --- /dev/null +++ b/tidb-cloud-lake/sql/hex.md @@ -0,0 +1,8 @@ +--- +title: HEX +summary: TO_HEX 的别名。 +--- + +# HEX + +[TO_HEX](/tidb-cloud-lake/sql/to-hex.md) 的别名。 \ No newline at end of file diff --git a/tidb-cloud-lake/sql/histogram.md b/tidb-cloud-lake/sql/histogram.md new file mode 100644 index 0000000000000..250cc08e9e31d --- /dev/null +++ b/tidb-cloud-lake/sql/histogram.md @@ -0,0 +1,133 @@ +--- +title: HISTOGRAM +summary: 使用“等高”分桶策略生成数据分布直方图。 +--- + +# HISTOGRAM + +使用“等高”分桶策略生成数据分布直方图。 + +## 语法 {#syntax} + +```sql +HISTOGRAM() + +-- The following two forms are equivalent: +HISTOGRAM()() +HISTOGRAM( [, ]) +``` + +| 参数 | 描述 | +|-------------------|-------------------------------------------------------------------------------------| +| `expr` | `expr` 的数据类型应支持排序。 | +| `max_num_buckets` | 可选的正整数,用于指定存储桶的最大数量。默认值为 128。 | + +## 返回类型 {#return-type} + +返回空字符串或具有以下结构的 JSON 对象: + +- **buckets**:包含详细信息的存储桶列表: + - **lower**:存储桶的下界。 + - **upper**:存储桶的上界。 + - **count**:存储桶中的元素数量。 + - **pre_sum**:截至当前存储桶的元素累计数量。 + - **ndv**:存储桶中不同值的数量。 + +## 示例 {#examples} + +以下示例展示了 HISTOGRAM 函数如何分析 `histagg` 表中 `c_int` 值的分布,并返回存储桶边界、不同值数量、元素数量以及累计数量: + +```sql +CREATE TABLE histagg ( + c_id INT, + c_tinyint TINYINT, + c_smallint SMALLINT, + c_int INT +); + +INSERT INTO histagg VALUES + (1, 10, 20, 30), + (1, 11, 21, 33), + (1, 11, 12, 13), + (2, 21, 22, 23), + (2, 31, 32, 33), + (2, 10, 20, 30); + +SELECT HISTOGRAM(c_int) FROM histagg; + +┌───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ +│ histogram(c_int) │ +├───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤ +│ [{"lower":"13","upper":"13","ndv":1,"count":1,"pre_sum":0},{"lower":"23","upper":"23","ndv":1,"count":1,"pre_sum":1},{"lower":"30","upper":"30","ndv":1,"count":2,"pre_sum":2},{"lower":"33","upper":"33","ndv":1,"count":2,"pre_sum":4}] │ +└───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ +``` + +结果以 JSON 数组形式返回: + +```json +[ + { + "lower": "13", + "upper": "13", + "ndv": 1, + "count": 1, + "pre_sum": 0 + }, + { + "lower": "23", + "upper": "23", + "ndv": 1, + "count": 1, + "pre_sum": 1 + }, + { + "lower": "30", + "upper": "30", + "ndv": 1, + "count": 2, + "pre_sum": 2 + }, + { + "lower": "33", + "upper": "33", + "ndv": 1, + "count": 2, + "pre_sum": 4 + } +] +``` + +以下示例展示了 `HISTOGRAM(2)` 如何将 c_int 值分组到两个存储桶中: + +```sql +SELECT HISTOGRAM(2)(c_int) FROM histagg; +-- Or +SELECT HISTOGRAM(c_int, 2) FROM histagg; + +┌───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ +│ histogram(2)(c_int) │ +├───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤ +│ [{"lower":"13","upper":"30","ndv":3,"count":4,"pre_sum":0},{"lower":"33","upper":"33","ndv":1,"count":2,"pre_sum":4}] │ +└───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ +``` + +结果以 JSON 数组形式返回: + +```json +[ + { + "lower": "13", + "upper": "30", + "ndv": 3, + "count": 4, + "pre_sum": 0 + }, + { + "lower": "33", + "upper": "33", + "ndv": 1, + "count": 2, + "pre_sum": 4 + } +] +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/hour.md b/tidb-cloud-lake/sql/hour.md new file mode 100644 index 0000000000000..11a620ca2a2fc --- /dev/null +++ b/tidb-cloud-lake/sql/hour.md @@ -0,0 +1,39 @@ +--- +title: TO_HOUR +summary: 将带时间的日期(timestamp/datetime)转换为一个 UInt8 数值,表示 24 小时制中的小时数(0-23)。该函数假定:如果时钟向前拨动,则拨快 1 小时并发生在凌晨 2 点;如果时钟向后拨动,则拨慢 1 小时并发生在凌晨 3 点。(这并不总是正确——即使在莫斯科,时钟也曾两次在不同时间调整。) +--- + +# TO_HOUR + +将带时间的日期(timestamp/datetime)转换为一个 UInt8 数值,表示 24 小时制中的小时数(0-23)。 + +该函数假定:如果时钟向前拨动,则拨快 1 小时并发生在凌晨 2 点;如果时钟向后拨动,则拨慢 1 小时并发生在凌晨 3 点。(这并不总是正确——即使在莫斯科,时钟也曾两次在不同时间调整。) + +## 语法 {#syntax} + +```sql +TO_HOUR() +``` + +## 参数 {#arguments} + +| 参数 | 描述 | +|-----------|-------------| +| `` | 时间戳 | + +## 返回类型 {#return-type} + +`TINYINT` + +## 示例 {#examples} + +```sql +SELECT + to_hour('2023-11-12 09:38:18.165575'); + +┌───────────────────────────────────────┐ +│ to_hour('2023-11-12 09:38:18.165575') │ +├───────────────────────────────────────┤ +│ 9 │ +└───────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/hours.md b/tidb-cloud-lake/sql/hours.md new file mode 100644 index 0000000000000..aac90aa2f224c --- /dev/null +++ b/tidb-cloud-lake/sql/hours.md @@ -0,0 +1,32 @@ +--- +title: TO_HOURS +summary: 将指定的小时数转换为 Interval 类型。 +--- + +# TO_HOURS + +将指定的小时数转换为 Interval 类型。 + +- 接受正整数、零和负整数作为输入。 + +## 语法 {#syntax} + +```sql +TO_HOURS() +``` + +## 返回类型 {#return-type} + +Interval(格式为 `hh:mm:ss`)。 + +## 示例 {#examples} + +```sql +SELECT TO_HOURS(2), TO_HOURS(0), TO_HOURS((- 2)); + +┌───────────────────────────────────────────┐ +│ to_hours(2) │ to_hours(0) │ to_hours(- 2) │ +├─────────────┼─────────────┼───────────────┤ +│ 2:00:00 │ 00:00:00 │ -2:00:00 │ +└───────────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/humanize-number.md b/tidb-cloud-lake/sql/humanize-number.md new file mode 100644 index 0000000000000..37d85d24fd68d --- /dev/null +++ b/tidb-cloud-lake/sql/humanize-number.md @@ -0,0 +1,35 @@ +--- +title: HUMANIZE_NUMBER +summary: 返回一个易读的数字。 +--- + +# HUMANIZE_NUMBER + +返回一个易读的数字。 + +## 语法 {#syntax} + +```sql +HUMANIZE_NUMBER(x); +``` + +## 参数 {#arguments} + +| 参数 | 描述 | +|-----------|----------------------------| +| x | 数值大小。 | + +## 返回类型 {#return-type} + +字符串。 + +## 示例 {#examples} + +```sql +SELECT HUMANIZE_NUMBER(1000 * 1000) ++-------------------------+ +| HUMANIZE_NUMBER((1000 * 1000)) | ++-------------------------+ +| 1 million | ++-------------------------+ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/humanize-size.md b/tidb-cloud-lake/sql/humanize-size.md new file mode 100644 index 0000000000000..829086aedba6c --- /dev/null +++ b/tidb-cloud-lake/sql/humanize-size.md @@ -0,0 +1,35 @@ +--- +title: HUMANIZE_SIZE +summary: 返回带有后缀(KiB、MiB 等)的可读大小。 +--- + +# HUMANIZE_SIZE + +返回带有后缀(KiB、MiB 等)的可读大小。 + +## 语法 {#syntax} + +```sql +HUMANIZE_SIZE(x); +``` + +## 参数 {#arguments} + +| 参数 | 描述 | +|-----------|----------------------------| +| x | 数值大小。 | + +## 返回类型 {#return-type} + +字符串。 + +## 示例 {#examples} + +```sql +SELECT HUMANIZE_SIZE(1024 * 1024) ++-------------------------+ +| HUMANIZE_SIZE((1024 * 1024)) | ++-------------------------+ +| 1 MiB | ++-------------------------+ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/iceberg-manifest.md b/tidb-cloud-lake/sql/iceberg-manifest.md new file mode 100644 index 0000000000000..9874f8ac72ac1 --- /dev/null +++ b/tidb-cloud-lake/sql/iceberg-manifest.md @@ -0,0 +1,53 @@ +--- +title: ICEBERG_MANIFEST +summary: 返回 Iceberg 表中 manifest 文件的元信息,包括文件路径、分区详情以及关联的快照。 +--- + +# ICEBERG_MANIFEST + +返回 Iceberg 表中 manifest 文件的元信息,包括文件路径、分区详情以及关联的快照。 + +## 语法 {#syntax} + +```sql +ICEBERG_MANIFEST('', ''); +``` + +## 输出 {#output} + +该函数返回一个包含以下列的表: + +- `content` (`INT`): 内容类型(0 表示数据文件,1 表示删除文件)。 +- `path` (`STRING`): 数据文件或删除文件的文件路径。 +- `length` (`BIGINT`): 文件大小,单位为字节。 +- `partition_spec_id` (`INT`): 与该文件关联的分区规范 ID。 +- `added_snapshot_id` (`BIGINT`): 添加该文件的快照 ID。 +- `added_data_files_count` (`INT`): 新增的数据文件数量。 +- `existing_data_files_count` (`INT`): 被引用的现有数据文件数量。 +- `deleted_data_files_count` (`INT`): 已删除的数据文件数量。 +- `added_delete_files_count` (`INT`): 新增的删除文件数量。 +- `partition_summaries` (`MAP`): 与该文件相关的分区值摘要。 + +## 示例 {#examples} + +```sql +SELECT * FROM ICEBERG_MANIFEST('tpcds', 'catalog_returns'); + +╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ +│ content │ path │ length │ partition_spec │ added_snapshot │ added_data_fil │ existing_data_ │ deleted_data_ │ added_delete_ │ existing_dele │ deleted_delet │ partition_sum │ +│ Int32 │ String │ Int64 │ _id │ _id │ es_count │ files_count │ files_count │ files_count │ te_files_coun │ e_files_count │ maries │ +│ │ │ │ Int32 │ Nullable(Int64 │ Nullable(Int32 │ Nullable(Int32 │ Nullable(Int3 │ Nullable(Int3 │ t │ Nullable(Int3 │ Array(Nullabl │ +│ │ │ │ │ ) │ ) │ ) │ 2) │ 2) │ Nullable(Int3 │ 2) │ e(Tuple(Nulla │ +│ │ │ │ │ │ │ │ │ │ 2) │ │ ble(Boolean), │ +│ │ │ │ │ │ │ │ │ │ │ │ Nullable(Bool │ +│ │ │ │ │ │ │ │ │ │ │ │ ean), String, │ +│ │ │ │ │ │ │ │ │ │ │ │ String))) │ +├─────────┼────────────────┼────────┼────────────────┼────────────────┼────────────────┼────────────────┼───────────────┼───────────────┼───────────────┼───────────────┼───────────────┤ +│ 0 │ s3://warehouse │ 9241 │ 0 │ 75657674165904 │ 2 │ 0 │ 0 │ 2 │ 0 │ 0 │ [] │ +│ │ /catalog_retur │ │ │ 11866 │ │ │ │ │ │ │ │ +│ │ ns/metadata/fa │ │ │ │ │ │ │ │ │ │ │ +│ │ 1ea4d5-a382-49 │ │ │ │ │ │ │ │ │ │ │ +│ │ 7a-9f22-1acb9a │ │ │ │ │ │ │ │ │ │ │ +│ │ 74a346-m0.avro │ │ │ │ │ │ │ │ │ │ │ +╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/iceberg-snapshot.md b/tidb-cloud-lake/sql/iceberg-snapshot.md new file mode 100644 index 0000000000000..00f70d6915e2a --- /dev/null +++ b/tidb-cloud-lake/sql/iceberg-snapshot.md @@ -0,0 +1,48 @@ +--- +title: ICEBERG_SNAPSHOT +summary: 返回 Iceberg 表快照的元信息,包括有关数据变更、操作和汇总统计的信息。 +--- + +# ICEBERG_SNAPSHOT + +返回 Iceberg 表快照的元信息,包括有关数据变更、操作和汇总统计的信息。 + +## 语法 {#syntax} + +```sql +ICEBERG_SNAPSHOT('', ''); +``` + +## 输出 {#output} + +该函数返回一个包含以下列的表: + +- `committed_at` (`TIMESTAMP`):提交该快照时的时间戳。 +- `snapshot_id` (`BIGINT`):快照的唯一标识符。 +- `parent_id` (`BIGINT`):父快照 ID(如果适用)。 +- `operation` (`STRING`):执行的操作类型(例如 append、overwrite、delete)。 +- `manifest_list` (`STRING`):与该快照关联的 manifest list 文件路径。 +- `summary` (`MAP`):一种类似 JSON 的结构,包含附加元信息,例如: + - `added-data-files`:新添加的数据文件数量。 + - `added-records`:新添加的记录数。 + - `total-records`:该快照中的记录总数。 + - `total-files-size`:所有数据文件的总大小(以字节为单位)。 + - `total-data-files`:该快照中的数据文件总数。 + - `total-delete-files`:删除文件总数。 + +## 示例 {#examples} + +```sql +SELECT * FROM ICEBERG_SNAPSHOT('tpcds', 'catalog_returns'); + +╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ +│ committed_at │ snapshot_id │ parent_id │ operation │ manifest_list │ summary │ +├────────────────────────────┼─────────────────────┼───────────┼───────────┼──────────────────────────────────────────────────────┼─────────────────────────────────────────────────────┤ +│ 2025-03-12 23:18:26.626000 │ 7565767416590411866 │ 0 │ append │ s3://warehouse/catalog_returns/metadata/snap-7565767 │ {'spark.app.id':'local-1741821433430','added-data-f │ +│ │ │ │ │ 416590411866-1-fa1ea4d5-a382-497a-9f22-1acb9a74a346. │ iles':'2','added-records':'144067','total-equality- │ +│ │ │ │ │ avro │ deletes':'0','changed-partition-count':'1','total-r │ +│ │ │ │ │ │ ecords':'144067','total-files-size':'7679811','tota │ +│ │ │ │ │ │ l-data-files':'2','added-files-size':'7679811','tot │ +│ │ │ │ │ │ al-delete-files':'0','total-position-deletes':'0'} │ +╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/if.md b/tidb-cloud-lake/sql/if.md new file mode 100644 index 0000000000000..1193996f58ef7 --- /dev/null +++ b/tidb-cloud-lake/sql/if.md @@ -0,0 +1,30 @@ +--- +title: IF +summary: 如果 `` 为 TRUE,则返回 ``。否则,如果 `` 为 TRUE,则返回 ``,依此类推。 +--- + +# IF + +如果 `` 为 TRUE,则返回 ``。否则,如果 `` 为 TRUE,则返回 ``,依此类推。 + +## 语法 {#syntax} + +```sql +IF(, , [, ...], ) +``` + +## 别名 {#aliases} + +- [IFF](/tidb-cloud-lake/sql/iff.md) + +## 示例 {#examples} + +```sql +SELECT IF(1 > 2, 3, 4 < 5, 6, 7); + +┌───────────────────────────────┐ +│ if((1 > 2), 3, (4 < 5), 6, 7) │ +├───────────────────────────────┤ +│ 6 │ +└───────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/iff.md b/tidb-cloud-lake/sql/iff.md new file mode 100644 index 0000000000000..86d5dcf4d5587 --- /dev/null +++ b/tidb-cloud-lake/sql/iff.md @@ -0,0 +1,8 @@ +--- +title: IFF +summary: IF 的别名。 +--- + +# IFF + +[IF](/tidb-cloud-lake/sql/if.md) 的别名。 \ No newline at end of file diff --git a/tidb-cloud-lake/sql/ifnull.md b/tidb-cloud-lake/sql/ifnull.md new file mode 100644 index 0000000000000..3deca591343ac --- /dev/null +++ b/tidb-cloud-lake/sql/ifnull.md @@ -0,0 +1,38 @@ +--- +title: IFNULL +summary: 如果 `` 为 NULL,则返回 ``;否则返回 ``。 +--- + +# IFNULL + +如果 `` 为 NULL,则返回 ``;否则返回 ``。 + +## 语法 {#syntax} + +```sql +IFNULL(, ) +``` + +## 别名 {#aliases} + +- [NVL](/tidb-cloud-lake/sql/nvl.md) + +## 示例 {#examples} + +```sql +SELECT IFNULL(NULL, 'b'), IFNULL('a', 'b'); + +┌──────────────────────────────────────┐ +│ ifnull(null, 'b') │ ifnull('a', 'b') │ +├───────────────────┼──────────────────┤ +│ b │ a │ +└──────────────────────────────────────┘ + +SELECT IFNULL(NULL, 2), IFNULL(1, 2); + +┌────────────────────────────────┐ +│ ifnull(null, 2) │ ifnull(1, 2) │ +├─────────────────┼──────────────┤ +│ 2 │ 1 │ +└────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/in.md b/tidb-cloud-lake/sql/in.md new file mode 100644 index 0000000000000..b911586ecabce --- /dev/null +++ b/tidb-cloud-lake/sql/in.md @@ -0,0 +1,26 @@ +--- +title: NOT ] IN +summary: 检查某个值是否(或是否不)在显式列表中。 +--- + +# NOT ] IN + +检查某个值是否(或是否不)在显式列表中。 + +## 语法 {#syntax} + +```sql + [ NOT ] IN (, ...) +``` + +## 示例 {#examples} + +```sql +SELECT 1 NOT IN (2, 3); + +┌────────────────┐ +│ 1 not in(2, 3) │ +├────────────────┤ +│ true │ +└────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/inet-aton.md b/tidb-cloud-lake/sql/inet-aton.md new file mode 100644 index 0000000000000..5f3dfce725e22 --- /dev/null +++ b/tidb-cloud-lake/sql/inet-aton.md @@ -0,0 +1,34 @@ +--- +title: INET_ATON +summary: 将 IPv4 地址转换为 32 位整数。 +--- + +# INET_ATON + +将 IPv4 地址转换为 32 位整数。 + +## 语法 {#syntax} + +```sql +INET_ATON( '' ) +``` + +## 别名 {#aliases} + +- [IPV4_STRING_TO_NUM](/tidb-cloud-lake/sql/ipv4-string-to-num.md) + +## 返回类型 {#return-type} + +整数型。 + +## 示例 {#examples} + +```sql +SELECT IPV4_STRING_TO_NUM('1.2.3.4'), INET_ATON('1.2.3.4'); + +┌──────────────────────────────────────────────────────┐ +│ ipv4_string_to_num('1.2.3.4') │ inet_aton('1.2.3.4') │ +├───────────────────────────────┼──────────────────────┤ +│ 16909060 │ 16909060 │ +└──────────────────────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/inet-ntoa.md b/tidb-cloud-lake/sql/inet-ntoa.md new file mode 100644 index 0000000000000..bc7a59d9b56af --- /dev/null +++ b/tidb-cloud-lake/sql/inet-ntoa.md @@ -0,0 +1,34 @@ +--- +title: INET_NTOA +summary: 将 32 位整数转换为 IPv4 地址。 +--- + +# INET_NTOA + +将 32 位整数转换为 IPv4 地址。 + +## 语法 {#syntax} + +```sql +INET_NOTA( ) +``` + +## 别名 {#aliases} + +- [IPV4_NUM_TO_STRING](/tidb-cloud-lake/sql/ipv4-num-to-string.md) + +## 返回类型 {#return-type} + +字符串。 + +## 示例 {#examples} + +```sql +SELECT IPV4_NUM_TO_STRING(16909060), INET_NTOA(16909060); + +┌────────────────────────────────────────────────────┐ +│ ipv4_num_to_string(16909060) │ inet_ntoa(16909060) │ +├──────────────────────────────┼─────────────────────┤ +│ 1.2.3.4 │ 1.2.3.4 │ +└────────────────────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/infer-schema.md b/tidb-cloud-lake/sql/infer-schema.md new file mode 100644 index 0000000000000..d427d00bbee96 --- /dev/null +++ b/tidb-cloud-lake/sql/infer-schema.md @@ -0,0 +1,261 @@ +--- +title: INFER_SCHEMA +summary: 自动检测文件元信息 schema 并获取列定义。 +--- + +# INFER_SCHEMA + +自动检测文件元信息 schema 并获取列定义。 + +`infer_schema` 当前支持以下文件格式: + +- **Parquet** - 原生支持 schema 推导 +- **CSV** - 支持自定义分隔符和表头检测 +- **NDJSON** - 以换行符分隔的 JSON 文件 + +**压缩支持**:所有格式还支持扩展名为 `.zip`、`.xz`、`.zst` 的压缩文件。 + +> **注意:** +> +> 每个单独文件在进行 schema 推导时的最大大小限制为 **100MB**。 + +> **注意:** +> +> 处理多个文件时,`infer_schema` 会自动合并不同的 schema: +> +> - **兼容类型**会被提升(例如,INT8 + INT16 → INT16) +> - **不兼容类型**会回退为 **VARCHAR**(例如,INT + FLOAT → VARCHAR) +> - 某些文件中**缺失的列**会被标记为 **nullable** +> - 后续文件中的**新列**会被添加到最终 schema 中 +> +> 这可确保所有文件都能使用统一的 schema 进行读取。 + +## 语法 {#syntax} + +```sql +INFER_SCHEMA( + LOCATION => '{ internalStage | externalStage }' + [ PATTERN => ''] + [ FILE_FORMAT => '' ] + [ MAX_RECORDS_PRE_FILE => ] + [ MAX_FILE_COUNT => ] +) +``` + +## 参数 {#parameters} + +| 参数 | 描述 | 默认值 | 示例 | +|-----------|-------------|---------|---------| +| `LOCATION` | stage 位置:`@[/]` | 必填 | `'@my_stage/data/'` | +| `PATTERN` | 用于匹配 stage 中文件的正则表达式模式。它匹配 `@[/]` 之后的文件路径部分。参见 [使用 PATTERN 过滤 stage 中的文件](/tidb-cloud-lake/guides/stage-overview.md#filtering-staged-files-with-pattern)。 | 所有文件 | `'.*[.]csv'`, `'.*[.]parquet'` | +| `FILE_FORMAT` | 用于解析的文件格式名称 | stage 的格式 | `'csv_format'`, `'NDJSON'` | +| `MAX_RECORDS_PRE_FILE` | 每个文件采样的最大记录数 | 所有记录 | `100`, `1000` | +| `MAX_FILE_COUNT` | 要处理的最大文件数 | 所有文件 | `5`, `10` | + +## 示例 {#examples} + +### Parquet 文件 {#parquet-files} + +```sql +-- Create stage and export data +CREATE STAGE test_parquet; +COPY INTO @test_parquet FROM (SELECT number FROM numbers(10)) FILE_FORMAT = (TYPE = 'PARQUET'); + +-- Infer schema from parquet files using pattern +SELECT * FROM INFER_SCHEMA( + location => '@test_parquet', + pattern => '.*[.]parquet' +); +``` + +结果: + +``` ++-------------+-----------------+----------+----------+----------+ +| column_name | type | nullable | filenames| order_id | ++-------------+-----------------+----------+----------+----------+ +| number | BIGINT UNSIGNED | false | data_... | 0 | ++-------------+-----------------+----------+----------+----------+ +``` + +### CSV 文件 {#csv-files} + +```sql +-- Create stage and export CSV data +CREATE STAGE test_csv; +COPY INTO @test_csv FROM (SELECT number FROM numbers(10)) FILE_FORMAT = (TYPE = 'CSV'); + +-- Create a CSV file format +CREATE FILE FORMAT csv_format TYPE = 'CSV'; + +-- Infer schema using pattern and file format +SELECT * FROM INFER_SCHEMA( + location => '@test_csv', + pattern => '.*[.]csv', + file_format => 'csv_format' +); +``` + +结果: + +``` ++-------------+---------+----------+----------+----------+ +| column_name | type | nullable | filenames| order_id | ++-------------+---------+----------+----------+----------+ +| column_1 | BIGINT | true | data_... | 0 | ++-------------+---------+----------+----------+----------+ +``` + +对于带表头的 CSV 文件: + +```sql +-- Create CSV file format with header support +CREATE FILE FORMAT csv_headers_format +TYPE = 'CSV' +field_delimiter = ',' +skip_header = 1; + +-- Export data with headers +CREATE STAGE test_csv_headers; +COPY INTO @test_csv_headers FROM ( + SELECT number as user_id, 'user_' || number::string as user_name + FROM numbers(5) +) FILE_FORMAT = (TYPE = 'CSV', output_header = true); + +-- Infer schema with headers +SELECT * FROM INFER_SCHEMA( + location => '@test_csv_headers', + file_format => 'csv_headers_format' +); +``` + +限制记录数以加快推导速度: + +```sql +-- Sample only first 5 records for schema inference +SELECT * FROM INFER_SCHEMA( + location => '@test_csv', + pattern => '.*[.]csv', + file_format => 'csv_format', + max_records_pre_file => 5 +); +``` + +### NDJSON 文件 {#ndjson-files} + +```sql +-- Create stage and export NDJSON data +CREATE STAGE test_ndjson; +COPY INTO @test_ndjson FROM (SELECT number FROM numbers(10)) FILE_FORMAT = (TYPE = 'NDJSON'); + +-- Infer schema using pattern and NDJSON format +SELECT * FROM INFER_SCHEMA( + location => '@test_ndjson', + pattern => '.*[.]ndjson', + file_format => 'NDJSON' +); +``` + +结果: + +``` ++-------------+---------+----------+----------+----------+ +| column_name | type | nullable | filenames| order_id | ++-------------+---------+----------+----------+----------+ +| number | BIGINT | true | data_... | 0 | ++-------------+---------+----------+----------+----------+ +``` + +限制记录数以加快推导速度: + +```sql +-- Sample only first 5 records for schema inference +SELECT * FROM INFER_SCHEMA( + location => '@test_ndjson', + pattern => '.*[.]ndjson', + file_format => 'NDJSON', + max_records_pre_file => 5 +); +``` + +### 使用多个文件进行 Schema 合并 {#schema-merging-with-multiple-files} + +当文件具有不同的 schema 时,`infer_schema` 会智能地将它们合并: + +```sql +-- Suppose you have multiple CSV files with different schemas: +-- file1.csv: id(INT), name(VARCHAR) +-- file2.csv: id(INT), name(VARCHAR), age(INT) +-- file3.csv: id(FLOAT), name(VARCHAR), age(INT) + +SELECT * FROM INFER_SCHEMA( + location => '@my_stage/', + pattern => '.*[.]csv', + file_format => 'csv_format' +); +``` + +结果会显示合并后的 schema: + +``` ++-------------+---------+----------+-----------+----------+ +| column_name | type | nullable | filenames | order_id | ++-------------+---------+----------+-----------+----------+ +| id | VARCHAR | true | file1,... | 0 | -- INT+FLOAT→VARCHAR +| name | VARCHAR | true | file1,... | 1 | +| age | BIGINT | true | file1,... | 2 | -- Missing in file1→nullable ++-------------+---------+----------+-----------+----------+ +``` + +### 模式匹配和文件数量限制 {#pattern-matching-and-file-limits} + +使用模式匹配从多个文件中推导 schema: + +```sql +-- Infer schema from all CSV files in the directory +SELECT * FROM INFER_SCHEMA( + location => '@my_stage/', + pattern => '.*[.]csv' +); +``` + +限制处理的文件数量以提升性能: + +```sql +-- Process only the first 5 matching files +SELECT * FROM INFER_SCHEMA( + location => '@my_stage/', + pattern => '.*[.]csv', + max_file_count => 5 +); +``` + +### 压缩文件 {#compressed-files} + +`infer_schema` 会自动处理压缩文件: + +```sql +-- Works with compressed CSV files +SELECT * FROM INFER_SCHEMA(location => '@my_stage/data.csv.zip'); + +-- Works with compressed NDJSON files +SELECT * FROM INFER_SCHEMA( + location => '@my_stage/data.ndjson.xz', + file_format => 'NDJSON', + max_records_pre_file => 50 +); +``` + +### 根据推导出的 Schema 创建表 {#create-table-from-inferred-schema} + +`infer_schema` 函数会显示 schema,但不会创建表。要根据推导出的 schema 创建表,请执行以下操作: + +```sql +-- Create table structure from file schema +CREATE TABLE my_table AS +SELECT * FROM @my_stage/ (pattern=>'.*[.]parquet') +LIMIT 0; + +-- Verify the table structure +DESC my_table; +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/information-schema-columns-sql.md b/tidb-cloud-lake/sql/information-schema-columns-sql.md new file mode 100644 index 0000000000000..ba8a5fe56e09a --- /dev/null +++ b/tidb-cloud-lake/sql/information-schema-columns-sql.md @@ -0,0 +1,49 @@ +--- +title: information_schema.columns +summary: 包含表的列信息。 +--- + +# information_schema.columns + +包含表的列信息。 + +```sql +desc information_schema.columns + +╭─────────────────────────────────────────────────────────────────────────╮ +│ Field │ Type │ Null │ Default │ Extra │ +│ String │ String │ String │ String │ String │ +├──────────────────────────┼──────────────────┼────────┼─────────┼────────┤ +│ table_catalog │ VARCHAR │ NO │ '' │ │ +│ table_schema │ VARCHAR │ NO │ '' │ │ +│ table_name │ VARCHAR │ NO │ '' │ │ +│ column_name │ VARCHAR │ NO │ '' │ │ +│ ordinal_position │ TINYINT UNSIGNED │ NO │ 0 │ │ +│ column_default │ NULL │ NO │ NULL │ │ +│ column_comment │ VARCHAR │ NO │ '' │ │ +│ column_key │ NULL │ NO │ NULL │ │ +│ nullable │ TINYINT UNSIGNED │ YES │ NULL │ │ +│ is_nullable │ VARCHAR │ NO │ '' │ │ +│ data_type │ VARCHAR │ NO │ '' │ │ +│ column_type │ VARCHAR │ NO │ '' │ │ +│ character_maximum_length │ NULL │ NO │ NULL │ │ +│ character_octet_length │ NULL │ NO │ NULL │ │ +│ numeric_precision │ NULL │ NO │ NULL │ │ +│ numeric_precision_radix │ NULL │ NO │ NULL │ │ +│ numeric_scale │ NULL │ NO │ NULL │ │ +│ datetime_precision │ NULL │ NO │ NULL │ │ +│ character_set_catalog │ NULL │ NO │ NULL │ │ +│ character_set_schema │ NULL │ NO │ NULL │ │ +│ character_set_name │ NULL │ NO │ NULL │ │ +│ collation_catalog │ NULL │ NO │ NULL │ │ +│ collation_schema │ NULL │ NO │ NULL │ │ +│ collation_name │ NULL │ NO │ NULL │ │ +│ domain_catalog │ NULL │ NO │ NULL │ │ +│ domain_schema │ NULL │ NO │ NULL │ │ +│ domain_name │ NULL │ NO │ NULL │ │ +│ privileges │ NULL │ NO │ NULL │ │ +│ default │ VARCHAR │ NO │ '' │ │ +│ extra │ NULL │ NO │ NULL │ │ +╰─────────────────────────────────────────────────────────────────────────╯ + +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/information-schema-keywords-sql.md b/tidb-cloud-lake/sql/information-schema-keywords-sql.md new file mode 100644 index 0000000000000..edf4af1a24565 --- /dev/null +++ b/tidb-cloud-lake/sql/information-schema-keywords-sql.md @@ -0,0 +1,20 @@ +--- +title: information_schema.keywords +summary: information_schema.keywords 系统表是一个视图,提供 {{{ .lake }}} 中的所有关键字。 +--- + +# information_schema.keywords + +`information_schema.keywords` 系统表是一个视图,提供 {{{ .lake }}} 中的所有关键字。 + +```sql +DESCRIBE information_schema.keywords + +╭─────────────────────────────────────────────────────────╮ +│ Field │ Type │ Null │ Default │ Extra │ +│ String │ String │ String │ String │ String │ +├──────────┼──────────────────┼────────┼─────────┼────────┤ +│ keywords │ VARCHAR │ NO │ '' │ │ +│ reserved │ TINYINT UNSIGNED │ NO │ 0 │ │ +╰─────────────────────────────────────────────────────────╯ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/information-schema-schemata-sql.md b/tidb-cloud-lake/sql/information-schema-schemata-sql.md new file mode 100644 index 0000000000000..81eae6cbb0a7b --- /dev/null +++ b/tidb-cloud-lake/sql/information-schema-schemata-sql.md @@ -0,0 +1,26 @@ +--- +title: information_schema.schemata +summary: 提供系统中所有数据库的元信息。 +--- + +# information_schema.schemata + +提供系统中所有数据库的元信息。 + +```sql +desc information_schema.schemata + +╭─────────────────────────────────────────────────────────────────────╮ +│ Field │ Type │ Null │ Default │ Extra │ +│ String │ String │ String │ String │ String │ +├───────────────────────────────┼─────────┼────────┼─────────┼────────┤ +│ catalog_name │ VARCHAR │ NO │ '' │ │ +│ schema_name │ VARCHAR │ NO │ '' │ │ +│ schema_owner │ VARCHAR │ NO │ '' │ │ +│ default_character_set_catalog │ NULL │ NO │ NULL │ │ +│ default_character_set_schema │ NULL │ NO │ NULL │ │ +│ default_character_set_name │ NULL │ NO │ NULL │ │ +│ default_collation_name │ NULL │ NO │ NULL │ │ +│ sql_path │ NULL │ NO │ NULL │ │ +╰─────────────────────────────────────────────────────────────────────╯ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/information-schema-tables-overview.md b/tidb-cloud-lake/sql/information-schema-tables-overview.md new file mode 100644 index 0000000000000..e9393c66982ce --- /dev/null +++ b/tidb-cloud-lake/sql/information-schema-tables-overview.md @@ -0,0 +1,33 @@ +--- +title: Information_Schema Tables +summary: 本页介绍 TiDB Cloud Lake 中的 Information_Schema 表。 +--- + +# Information_Schema Tables + +## Information Schema {#information-schema} + +| 表 | 描述 | +|----------------------------------------------|------------------------------------------------| +| [tables](/tidb-cloud-lake/sql/information-schema-tables-sql.md) | 用于表的 ANSI SQL 标准元信息视图。 | +| [schemata](/tidb-cloud-lake/sql/information-schema-schemata-sql.md) | 用于数据库的 ANSI SQL 标准元信息视图。 | +| [views](/tidb-cloud-lake/sql/information-schema-views-sql.md) | 用于视图的 ANSI SQL 标准元信息视图。 | +| [keywords](/tidb-cloud-lake/sql/information-schema-keywords-sql.md) | 用于关键字的 ANSI SQL 标准元信息视图。 | +| [columns](/tidb-cloud-lake/sql/information-schema-columns-sql.md) | 用于列的 ANSI SQL 标准元信息视图。 | + +```sql +SHOW VIEWS FROM INFORMATION_SCHEMA; +╭─────────────────────────────╮ +│ Views_in_information_schema │ +│ String │ +├─────────────────────────────┤ +│ columns │ +│ key_column_usage │ +│ keywords │ +│ schemata │ +│ statistics │ +│ tables │ +│ views │ +╰─────────────────────────────╯ + +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/information-schema-tables-sql.md b/tidb-cloud-lake/sql/information-schema-tables-sql.md new file mode 100644 index 0000000000000..85cecbc528f85 --- /dev/null +++ b/tidb-cloud-lake/sql/information-schema-tables-sql.md @@ -0,0 +1,31 @@ +--- +title: information_schema.tables +summary: `information_schema.tables` 系统表是一个视图,用于提供所有数据库中所有表的元信息,包括其 schema、类型、引擎以及创建详情。它还包含诸如数据长度、索引长度和行数等存储指标信息,帮助了解表结构和使用情况。 +--- + +# information_schema.tables + +`information_schema.tables` 系统表是一个视图,用于提供所有数据库中所有表的元信息,包括其 schema、类型、引擎以及创建详情。它还包含诸如数据长度、索引长度和行数等存储指标信息,帮助了解表结构和使用情况。 + +```sql +DESCRIBE information_schema.tables; + +┌────────────────────────────────────────────────────────────────────────────────────┐ +│ Field │ Type │ Null │ Default │ Extra │ +├─────────────────┼─────────────────┼────────┼──────────────────────────────┼────────┤ +│ table_catalog │ VARCHAR │ NO │ '' │ │ +│ table_schema │ VARCHAR │ NO │ '' │ │ +│ table_name │ VARCHAR │ NO │ '' │ │ +│ table_type │ VARCHAR │ NO │ '' │ │ +│ engine │ VARCHAR │ NO │ '' │ │ +│ create_time │ TIMESTAMP │ NO │ '1970-01-01 00:00:00.000000' │ │ +│ drop_time │ TIMESTAMP │ YES │ NULL │ │ +│ data_length │ BIGINT UNSIGNED │ YES │ NULL │ │ +│ index_length │ BIGINT UNSIGNED │ YES │ NULL │ │ +│ table_rows │ BIGINT UNSIGNED │ YES │ NULL │ │ +│ auto_increment │ NULL │ NO │ NULL │ │ +│ table_collation │ NULL │ NO │ NULL │ │ +│ data_free │ NULL │ NO │ NULL │ │ +│ table_comment │ VARCHAR │ NO │ '' │ │ +└────────────────────────────────────────────────────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/information-schema-views-sql.md b/tidb-cloud-lake/sql/information-schema-views-sql.md new file mode 100644 index 0000000000000..b1ce3407add59 --- /dev/null +++ b/tidb-cloud-lake/sql/information-schema-views-sql.md @@ -0,0 +1,32 @@ +--- +title: information_schema.views +summary: 提供所有视图的元信息。 +--- + +# information_schema.views + +提供所有视图的元信息。 + +另请参阅: + +- [SHOW VIEWS](/tidb-cloud-lake/sql/show-views.md) + +```sql +DESCRIBE information_schema.views; + +╭───────────────────────────────────────────────────────────────────────────╮ +│ Field │ Type │ Null │ Default │ Extra │ +│ String │ String │ String │ String │ String │ +├────────────────────────────┼──────────────────┼────────┼─────────┼────────┤ +│ table_catalog │ VARCHAR │ NO │ '' │ │ +│ table_schema │ VARCHAR │ NO │ '' │ │ +│ table_name │ VARCHAR │ NO │ '' │ │ +│ view_definition │ VARCHAR │ NO │ '' │ │ +│ check_option │ VARCHAR │ NO │ '' │ │ +│ is_updatable │ TINYINT UNSIGNED │ NO │ 0 │ │ +│ is_insertable_into │ BOOLEAN │ NO │ false │ │ +│ is_trigger_updatable │ TINYINT UNSIGNED │ NO │ 0 │ │ +│ is_trigger_deletable │ TINYINT UNSIGNED │ NO │ 0 │ │ +│ is_trigger_insertable_into │ TINYINT UNSIGNED │ NO │ 0 │ │ +╰───────────────────────────────────────────────────────────────────────────╯ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/inner-product.md b/tidb-cloud-lake/sql/inner-product.md new file mode 100644 index 0000000000000..109b2383d33a0 --- /dev/null +++ b/tidb-cloud-lake/sql/inner-product.md @@ -0,0 +1,128 @@ +--- +title: INNER_PRODUCT +summary: 计算两个向量的内积(点积),用于衡量向量之间的相似性和投影关系。 +--- + +# INNER_PRODUCT + +计算两个向量的内积(点积),用于衡量向量之间的相似性和投影关系。 + +## 语法 {#syntax} + +```sql +INNER_PRODUCT(vector1, vector2) +``` + +## 参数 {#arguments} + +- `vector1`:第一个向量(VECTOR Data Type) +- `vector2`:第二个向量(VECTOR Data Type) + +## 返回值 {#returns} + +返回一个 FLOAT 值,表示两个向量的内积。 + +## 描述 {#description} + +内积(也称为点积)用于计算两个向量中对应元素乘积之和。该函数会: + +1. 验证两个输入向量的长度是否相同 +2. 将两个向量中对应位置的元素相乘 +3. 将所有乘积求和,得到一个标量值 + +其实现的数学公式为: + +``` +inner_product(v1, v2) = Σ(v1ᵢ * v2ᵢ) +``` + +其中,v1ᵢ 和 v2ᵢ 是输入向量中的元素。 + +内积在以下场景中是基础运算: + +- 衡量向量相似性(值越大表示方向越相似) +- 计算一个向量在另一个向量上的投影 +- 机器学习算法(神经网络、SVM 等) +- 涉及功和能量的物理计算 + +> **注意:** +> +> 此函数在 {{{ .lake }}} 内执行向量计算,不依赖外部 API。 + +## 示例 {#examples} + +### 基本用法 {#basic-usage} + +```sql +SELECT INNER_PRODUCT([1,2,3]::VECTOR(3), [4,5,6]::VECTOR(3)) AS inner_product; +``` + +结果: + +``` +┌───────────────┐ +│ inner_product │ +├───────────────┤ +│ 32.0 │ +└───────────────┘ +``` + +### 结合表数据使用 {#working-with-table-data} + +创建一个包含向量数据的表: + +```sql +CREATE TABLE vector_examples ( + id INT, + vector_a VECTOR(3), + vector_b VECTOR(3) +); + +INSERT INTO vector_examples VALUES + (1, [1.0, 2.0, 3.0], [4.0, 5.0, 6.0]), + (2, [1.0, 0.0, 0.0], [0.0, 1.0, 0.0]), + (3, [2.0, 3.0, 1.0], [1.0, 2.0, 3.0]); +``` + +计算内积: + +```sql +SELECT + id, + vector_a, + vector_b, + INNER_PRODUCT(vector_a, vector_b) AS inner_product +FROM vector_examples; +``` + +结果: + +``` +┌────┬───────────────┬───────────────┬───────────────┐ +│ id │ vector_a │ vector_b │ inner_product │ +├────┼───────────────┼───────────────┼───────────────┤ +│ 1 │ [1.0,2.0,3.0] │ [4.0,5.0,6.0] │ 32.0 │ +│ 2 │ [1.0,0.0,0.0] │ [0.0,1.0,0.0] │ 0.0 │ +│ 3 │ [2.0,3.0,1.0] │ [1.0,2.0,3.0] │ 11.0 │ +└────┴───────────────┴───────────────┴───────────────┘ +``` + +### 向量相似性分析 {#vector-similarity-analysis} + +```sql +-- Calculate inner products to measure vector similarity +SELECT + INNER_PRODUCT([1,0,0]::VECTOR(3), [1,0,0]::VECTOR(3)) AS same_direction, + INNER_PRODUCT([1,0,0]::VECTOR(3), [0,1,0]::VECTOR(3)) AS orthogonal, + INNER_PRODUCT([1,0,0]::VECTOR(3), [-1,0,0]::VECTOR(3)) AS opposite; +``` + +结果: + +``` +┌────────────────┬─────────────┬──────────┐ +│ same_direction │ orthogonal │ opposite │ +├────────────────┼─────────────┼──────────┤ +│ 1.0 │ 0.0 │ -1.0 │ +└────────────────┴─────────────┴──────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/input-output-file-formats.md b/tidb-cloud-lake/sql/input-output-file-formats.md new file mode 100644 index 0000000000000..ae21fee93f63e --- /dev/null +++ b/tidb-cloud-lake/sql/input-output-file-formats.md @@ -0,0 +1,453 @@ +--- +title: 输入与输出文件格式 +summary: "{{{ .lake }}} 支持多种文件格式,既可作为数据加载或卸载的源,也可作为目标。本文介绍支持的文件格式及其可用选项。" +--- + +# 输入与输出文件格式 + +{{{ .lake }}} 支持多种文件格式,既可作为数据加载或卸载的源,也可作为目标。本文介绍支持的文件格式及其可用选项。 + +## 语法 {#syntax} + +要在语句中指定文件格式,请使用以下语法: + +```sql +-- Specify a standard file format +... FILE_FORMAT = ( TYPE = { CSV | TSV | NDJSON | PARQUET | LANCE | ORC | AVRO } [ formatTypeOptions ] ) + +-- Specify a custom file format +... FILE_FORMAT = ( FORMAT_NAME = '' ) +``` + +> **注意:** +> +> - 从 {{{ .lake }}} `v1.2.891-nightly` 开始,支持将 `TEXT` 作为 `TSV` 的别名。 +> - 较旧版本的服务器可能会拒绝 `TYPE = TEXT`,因此本文在语法和示例中继续使用 `TSV` 以保持跨版本兼容性。 +> - 如果你的目标环境仅为 {{{ .lake }}} `v1.2.891-nightly` 或更高版本,建议在新配置中优先使用 `TYPE = TEXT`。 + +{{{ .lake }}} 按以下优先级顺序确定 COPY 或 Select 语句使用的文件格式: + +1. 首先,检查语句中是否显式指定了 FILE_FORMAT。 +2. 如果操作中未指定 FILE_FORMAT,则使用创建 stage 时为该 stage 初始定义的文件格式。 +3. 如果创建 stage 时未定义文件格式,{{{ .lake }}} 默认使用 PARQUET 格式。 + +> **注意:** +> +> - {{{ .lake }}} 当前仅支持将 ORC 和 AVRO 用作源。暂不支持将数据卸载到 ORC 或 AVRO 文件中。 +> - {{{ .lake }}} 当前仅支持将 LANCE 用作卸载目标。`COPY INTO ` 写出的是 Lance 数据集目录,而不是单个独立文件,因此它适用于下游 Lance 工具链,而不是 stage-table 读取或 `COPY INTO
`。 +> - 关于如何在 {{{ .lake }}} 中管理自定义文件格式,请参见 [文件格式](/tidb-cloud-lake/sql/file-format.md)。 + +### formatTypeOptions {#formattypeoptions} + +`formatTypeOptions` 包含一个或多个选项,用于描述文件的其他格式细节。不同文件格式支持的选项不同。请参见下文各节,了解每种受支持文件格式的可用选项。 + +```sql +formatTypeOptions ::= + RECORD_DELIMITER = '' + FIELD_DELIMITER = '' + SKIP_HEADER = + QUOTE = '' + ESCAPE = '' + NAN_DISPLAY = '' + ROW_TAG = '' + COMPRESSION = AUTO | GZIP | BZ2 | BROTLI | ZSTD | DEFLATE | RAW_DEFLATE | XZ | NONE +``` + +## CSV 选项 {#csv-options} + +{{{ .lake }}} 的 CSV 实现符合 [RFC 4180](https://www.rfc-editor.org/rfc/rfc4180),并受以下条件约束: + +- 如果一个字符串包含 [QUOTE](#quote-load-only)、[ESCAPE](#escape)、[RECORD_DELIMITER](#record_delimiter) 或 [FIELD_DELIMITER](#field_delimiter) 中定义的字符,则该字符串必须使用引号包裹。 +- 在带引号的字符串中,除 [QUOTE](#quote-load-only) 外,不会对任何字符进行转义。 +- [FIELD_DELIMITER](#field_delimiter) 与 [QUOTE](#quote-load-only) 之间不应保留空格。 + +### RECORD_DELIMITER {#record-delimiter} + +用于分隔文件中记录的分隔字符。 + +**可用值**: + +- `\r\n` +- 单字节的非字母数字字符,例如 `#` 和 `|`。 +- 带转义字符的字符:`\b`、`\f`、`\r`、`\n`、`\t`、`\0`、`\xHH` + +**默认值**:`\n` + +### FIELD_DELIMITER {#field-delimiter} + +用于分隔一条记录中各字段的分隔字符。 + +**可用值**: + +- 单字节的非字母数字字符,例如 `#` 和 `|`。 +- 带转义字符的字符:`\b`、`\f`、`\r`、`\n`、`\t`、`\0`、`\xHH` + +**默认值**:`,`(逗号) + +### QUOTE (Load Only) {#quote-load-only} + +用于包裹值的字符。 + +在加载数据时,除非字符串中包含 [QUOTE](#quote-load-only)、[ESCAPE](#escape)、[RECORD_DELIMITER](#record_delimiter) 或 [FIELD_DELIMITER](#field_delimiter) 中定义的字符,否则不需要使用引号。 + +**可用值**:`'\''`、`'"'` 或 ``'`'``(反引号) + +**默认值**:`'"'` + +### ESCAPE {#escape} + +用于在带引号的值中对引号字符进行转义的字符,此外 [QUOTE](#quote-load-only) 本身也可用于转义。 + +在某些 CSV 变体中,引号是通过特殊的转义字符(如 `\`)进行转义的,而不是通过重复引号来转义。 + +**可用值**:`'\\'` 或 `''`(空,表示仅使用双引号转义) + +**默认值**:`''` + +### SKIP_HEADER (Load Only) {#skip-header-load-only} + +从文件开头跳过的行数。 + +**默认值**:`0` + +### TRIM_SPACE (Load Only) {#trim-space-load-only} + +在类型转换之前,去除每个字段值前后的 ASCII 空白字符。 + +可去除的字符集合固定为 ASCII 空白字符:空格、tab、LF、CR、VT、FF。 + +对于 CSV,trim 操作发生在 csv-core 提取字段之后,因此带引号字段中的内容也会被去除首尾空白。 + +**默认值**:`false` + +### OUTPUT_HEADER (Unload Only) {#output-header-unload-only} + +包含带列名的表头行。 + +**默认值**:`false` + +### QUOTE_STYLE (Unload Only) {#quote-style-unload-only} + +控制输出时 CSV 值的加引号方式。 + +| 可用值 | 说明 | +|---------------------------|--------------------------------------------------------------| +| `QUOTE_NOT_NULL` (Default)| 对 CSV 输出中的每个非 NULL 字段都加引号。 | +| `QUOTE_MINIMAL` | 仅在 CSV 输出格式要求时才对字段加引号。 | + +**默认值**:`QUOTE_NOT_NULL` + +### NAN_DISPLAY {#nan-display} + +表示 "NaN"(Not-a-Number)的字符串。 + +**可用值**:必须是字面量 `'nan'` 或 `'null'`(不区分大小写) + +**默认值**:`'NaN'` + +### NULL_DISPLAY {#null-display} + +表示 NULL 值的字符串。 + +加载数据时,未加引号且匹配的值始终会转换为 NULL;加引号且匹配的值仅在 `ALLOW_QUOTED_NULLS=true` 时才会转换为 NULL。 + +**默认值**:`'\N'` + +### ALLOW_QUOTED_NULLS (Load Only) {#allow-quoted-nulls-load-only} + +允许将带引号的字符串转换为 NULL 值。 + +只有当该标记为 true 时,与 `NULL_DISPLAY` 匹配的带引号字符串才会变为 NULL。未加引号且匹配的值无论此选项如何都会变为 NULL。 + +**默认值**:`false` + +### ERROR_ON_COLUMN_COUNT_MISMATCH (Load Only) {#error-on-column-count-mismatch-load-only} + +如果数据文件中的列数与目标表中的列数不匹配,则返回错误。 + +**默认值**:`true` + +### EMPTY_FIELD_AS (Load Only) {#empty-field-as-load-only} + +未加引号的空字段(即 `,,`)会被转换为的值。 + +| 可用值 | 转换为 | +|------------------|----------------------------------------------------------------------------------| +| `NULL` | `NULL`。如果列不可为空,则报错。 | +| `STRING` | 对于 String 列:`''`。
对于其他列:`NULL`。如果列不可为空,则报错。 | +| `FIELD_DEFAULT` | 该列的默认值。 | + +**默认值**:`NULL` + +### QUOTED_EMPTY_FIELD_AS (Load Only) {#quoted-empty-field-as-load-only} + +带引号的空字段(即 `,"",`)会被转换为的值。 + +**可用值**:与 [EMPTY_FIELD_AS](#empty_field_as-load-only) 相同 + +**默认值**:`STRING` + +### BINARY_FORMAT {#binary-format} + +`Binary` 列的编码格式。 + +**可用值**:`HEX` 或 `BASE64` + +**默认值**:`HEX` + +### GEOMETRY_FORMAT {#geometry-format} + +`Geometry` 列的编码格式。 + +**可用值**:`EWKT`、`WKB`、`WKB`、`EWKB`、`GEOJSON` + +**默认值**:`EWKT` + +### ENCODING (Load Only) {#encoding-load-only} + +源文件的字符集编码。设置为非 UTF-8 编码时,会先将文件内容转码为 UTF-8,再进行字段解析。 + +接受 [Encoding Standard](https://encoding.spec.whatwg.org/) 识别的任何标签(例如 `UTF-8`、`GBK`、`SHIFT_JIS`、`EUC-KR`、`ISO-8859-1`)。该标签会在创建文件格式 / stage 时进行校验。 + +**默认值**:`UTF-8` + +### ENCODING_ERROR_MODE (Load Only) {#encoding-error-mode-load-only} + +如何处理在声明编码下无效的字节(或者当编码为 `UTF-8` 时的无效 UTF-8 字节)。 + +| 可用值 | 说明 | +|--------------------|----------------------------------------------------------------------| +| `STRICT` (Default) | 在遇到第一个格式错误的字节序列时,报错并退出。 | +| `REPLACE` | 将每个格式错误的字节序列替换为 U+FFFD,然后继续处理。 | + +**默认值**:`STRICT` + +### COMPRESSION {#compression} + +压缩算法。 + +| 可用值 | 说明 | +|------------------|-----------------------------------------------------------------| +| `NONE` | 表示文件未压缩。 | +| `AUTO` | 通过文件扩展名自动检测压缩格式 | +| `GZIP` | | +| `BZ2` | | +| `BROTLI` | 加载/导出 Brotli 压缩文件时必须显式指定。 | +| `ZSTD` | 支持 Zstandard v0.8(及更高版本)。 | +| `DEFLATE` | Deflate 压缩文件(带 zlib 头,RFC1950)。 | +| `RAW_DEFLATE` | Deflate 压缩文件(不带任何头,RFC1951)。 | +| `XZ` | | + +**默认值**:`NONE` + +## TSV 选项 {#tsv-options} + +{{{ .lake }}} TSV(在 `v1.2.891-nightly` 及之后版本中也称为 `TEXT`)在这两个名称下使用相同的格式和选项。为兼容旧版本服务器,本页仍以 `TSV` 作为主要术语。 + +{{{ .lake }}} TSV 需满足以下条件: + +- [RECORD_DELIMITER](#record_delimiter-1)、[FIELD_DELIMITER](#field_delimiter-1) 使用 `\` 转义,以解决[分隔符冲突](https://en.wikipedia.org/wiki/Delimiter#Delimiter_collision) +- 除分隔符外,这些字符也会被转义:`\b`、`\f`、`\r`、`\n`、`\t`、`\0`、`\\`、`\'`。 +- [QUOTE](#quote-load-only) 不是该格式的一部分。 +- NULL 表示为 `\N`。 + +> **注意:** +> +> 1. 在 {{{ .lake }}} 中,TSV 与 CSV 的主要区别**不是**使用制表符而不是逗号作为字段分隔符(这可以通过选项修改),而是使用转义而不是引用来处理 +> [分隔符冲突](https://en.wikipedia.org/wiki/Delimiter#Delimiter_collision) +> 2. 我们建议优先使用 CSV 作为存储格式,因为它有正式标准。 +> 3. TSV 可用于加载以下系统生成的文件: +> 1. [Postgresql TEXT](https://www.postgresql.org/docs/current/sql-copy.html)。 +> 2. [Clickhouse TSV](https://clickhouse.com/docs/integrations/data-formats/csv-tsv#tsv-tab-separated-files) +> 3. [MySQL TabSeparated](https://dev.mysql.com/doc/refman/8.4/en/mysqldump.html) MySQL `mysqldump --tab`。如果使用了 `--fields-enclosed-by` 或 `--fields-optionally-enclosed-by`,请改用 CSV。 +> 4. 使用默认选项的 [Snowflake CSV](https://docs.snowflake.com/en/sql-reference/sql/create-file-format#type-csv)。如果指定了 `ESCAPE_UNENCLOSED_FIELD`,请改用 CSV。 +> 5. Hive Textfile。 + +### RECORD_DELIMITER {#record-delimiter} + +用于分隔文件中记录的分隔字符。 + +**可用值**: + +- `\r\n` +- 任意字符,例如 `#` 和 `|`。 +- 带转义字符的字符:`\b`、`\f`、`\r`、`\n`、`\t`、`\0`、`\xHH` + +**默认值**:`\n` + +### FIELD_DELIMITER {#field-delimiter} + +用于分隔记录中字段的分隔字符。 + +**可用值**: + +- 非字母数字字符,例如 `#` 和 `|`。 +- 带转义字符的字符:`\b`、`\f`、`\r`、`\n`、`\t`、`\0`、`\xHH` + +**默认值**:`\t`(TAB) + +### SKIP_HEADER (Load Only) {#skip-header-load-only} + +与 [CSV 的 SKIP_HEADER 选项](#skip_header-load-only)相同。 + +### TRIM_SPACE (Load Only) {#trim-space-load-only} + +与 [CSV 的 TRIM_SPACE 选项](#trim_space-load-only)相同。 + +### OUTPUT_HEADER (Unload Only) {#output-header-unload-only} + +与 [CSV 的 OUTPUT_HEADER 选项](#output_header-unload-only)相同。 + +### NAN_DISPLAY {#nan-display} + +与 [CSV 的 NAN_DISPLAY 选项](#nan_display)相同。 + +### NULL_DISPLAY {#null-display} + +与 [CSV 的 NULL_DISPLAY 选项](#null_display)相同。 + +### EMPTY_FIELD_AS (Load Only) {#empty-field-as-load-only} + +与 [CSV 的 EMPTY_FIELD_AS 选项](#empty_field_as-load-only)相同。 + +注意:TSV 的默认值为 `FIELD_DEFAULT`(不同于 CSV,后者默认值为 `NULL`)。 + +**默认值**:`FIELD_DEFAULT` + +### ERROR_ON_COLUMN_COUNT_MISMATCH (Load Only) {#error-on-column-count-mismatch-load-only} + +与 [CSV 的 ERROR_ON_COLUMN_COUNT_MISMATCH 选项](#error_on_column_count_mismatch-load-only)相同。 + +### ENCODING (Load Only) {#encoding-load-only} + +与 [CSV 的 ENCODING 选项](#encoding-load-only)相同。 + +### ENCODING_ERROR_MODE (Load Only) {#encoding-error-mode-load-only} + +与 [CSV 的 ENCODING_ERROR_MODE 选项](#encoding_error_mode-load-only)相同。 + +### COMPRESSION {#compression} + +与 [CSV 的 COMPRESSION 选项](#compression)相同。 + +## NDJSON 选项 {#ndjson-options} + +### NULL_FIELD_AS (Load Only) {#null-field-as-load-only} + +`null` 被转换成的值。 + +| 可用值 | 转换为 | +|-------------------------|----------------------------------------------------------| +| `NULL` (Default) | 对可为空字段为 NULL;对非空字段报错。 | +| `FIELD_DEFAULT` | 该字段的默认值。 | + +### MISSING_FIELD_AS (Load Only) {#missing-field-as-load-only} + +缺失字段被转换成的值。 + +| 可用值 | 转换为 | +|------------------|----------------------------------------------------------| +| `ERROR` (Default)| 报错。 | +| `NULL` | 对可为空字段为 NULL;对非空字段报错。 | +| `FIELD_DEFAULT` | 该字段的默认值。 | + +### NULL_IF (Load Only) {#null-if-load-only} + +一个字符串列表。当源文件中的字段值等于这些字符串之一时,会将其加载为 NULL。匹配必须完全一致且大小写敏感。 + +**语法**:`NULL_IF = ('value1', 'value2', ...)` + +**默认值**:空(无额外 NULL 标记) + +### COMPRESSION {#compression} + +与 [CSV 的 COMPRESSION 选项](#compression)相同。 + +## PARQUET 选项 {#parquet-options} + +### MISSING_FIELD_AS (Load Only) {#missing-field-as-load-only} + +缺失字段被转换成的值。 + +| 可用值 | 转换为 | +|------------------|----------------------------------------------------------| +| `ERROR` (Default)| 报错。 | +| `FIELD_DEFAULT` | 该字段的默认值。 | + +### NULL_IF (Load Only) {#null-if-load-only} + +与 [NDJSON 的 NULL_IF 选项](#null_if-load-only)相同。 + +### USE_LOGIC_TYPE (Load Only) {#use-logic-type-load-only} + +启用后,加载时会使用 Parquet logical types(例如 DATE、TIMESTAMP、DECIMAL 注解)来确定目标列类型。禁用后,则只考虑物理存储类型。 + +**默认值**:`true` + +### COMPRESSION (Unload Only) {#compression-unload-only} + +parquet 文件内部块的压缩算法。 + +| 可用值 | 说明 | +|------------------|---------------------------------------------------------------------| +| `ZSTD` (default) | 支持 Zstandard v0.8(及更高版本)。 | +| `SNAPPY` | Snappy 是一种常用且快速的压缩算法,通常与 Parquet 一起使用。 | + +## LANCE 选项 {#lance-options} + +仅在使用 `COPY INTO ` 卸载时支持 `LANCE`。 + +与 CSV、TSV、NDJSON 和 Parquet 相比,Lance 导出**不会**生成一个或多个可由 {{{ .lake }}} 直接读回的独立文件。相反,{{{ .lake }}} 会写入一个数据集目录,其中包含 `.lance` 数据文件以及诸如 `_versions/` 之类的数据集元信息。 + +因此,Lance 更适合下游机器学习、向量以及基于 Arrow 的工作流,这些工作流会使用 Lance 工具(例如 Python `lance`(`pip install pylance`))来消费该数据集。 + +### 格式特定选项 {#format-specific-options} + +Lance 没有格式特定选项。请使用: + +```sql +FILE_FORMAT = (TYPE = LANCE) +``` + +### 行为差异 {#behavioral-differences} + +| 项目 | LANCE 行为 | +|------|----------------| +| 支持的方向 | 仅卸载 | +| 在 {{{ .lake }}} stage 查询中读回 | 不支持 | +| `COPY INTO
` | 不支持 | +| 输出布局 | 包含 `.lance` 文件和元信息的数据集目录 | +| `SINGLE` copy 选项 | 不支持 | +| `PARTITION BY` | 不支持 | + +## ORC 选项 {#orc-options} + +### MISSING_FIELD_AS(仅加载) {#missing-field-as-load-only} + +缺失字段会被转换成的值。 + +| 可用值 | 转换为 | +|------------------|----------------------------------------------------------| +| `ERROR` (Default)| 错误。 | +| `FIELD_DEFAULT` | 字段的默认值。 | + +## AVRO 选项 {#avro-options} + +### MISSING_FIELD_AS(仅加载) {#missing-field-as-load-only} + +缺失字段会被转换成的值。 + +| 可用值 | 转换为 | +|------------------|----------------------------------------------------------| +| `ERROR` (Default)| 错误。 | +| `FIELD_DEFAULT` | 字段的默认值。 | + +### NULL_IF(仅加载) {#null-if-load-only} + +与 [NDJSON 的 NULL_IF 选项](#null_if-load-only) 相同。 + +### USE_LOGIC_TYPE(仅加载) {#use-logic-type-load-only} + +启用后,Avro 逻辑类型(例如 date、timestamp-millis、decimal)将用于在加载期间确定目标列类型。禁用后,则只考虑底层 Avro 类型。 + +**默认值**:`true` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/insert-multi-table.md b/tidb-cloud-lake/sql/insert-multi-table.md new file mode 100644 index 0000000000000..ec01799354191 --- /dev/null +++ b/tidb-cloud-lake/sql/insert-multi-table.md @@ -0,0 +1,283 @@ +--- +title: INSERT(多表) +summary: 在单个事务中向多个表插入行,并且可以选择让插入依赖某些条件(有条件)或不受任何条件限制(无条件)。 +--- + +# INSERT(多表) + +在单个事务中向多个表插入行,并且可以选择让插入依赖某些条件(有条件)或不受任何条件限制(无条件)。 + +> **Tip:** +> +> {{{ .lake }}} 通过原子操作确保数据完整性。插入、修改、替换和删除要么全部成功,要么全部失败。 + +另请参阅:[INSERT](/tidb-cloud-lake/sql/insert.md) + +## 语法 {#syntax} + +```sql +-- Unconditional INSERT ALL: Inserts each row into multiple tables without any conditions or restrictions. +INSERT [ OVERWRITE ] ALL + INTO [ ( [ , ... ] ) ] [ VALUES ( [ , ... ] ) ] + ... +SELECT ... + +-- Conditional INSERT ALL: Inserts each row into multiple tables, but only if certain conditions are met. +INSERT [ OVERWRITE ] ALL + WHEN THEN + INTO [ ( [ , ... ] ) ] [ VALUES ( [ , ... ] ) ] + [ INTO ... ] + + [ WHEN ... ] + + [ ELSE INTO ... ] +SELECT ... + +-- Conditional INSERT FIRST: Inserts each row into multiple tables, but stops after the first successful insertion. +INSERT [ OVERWRITE ] FIRST + WHEN THEN + INTO [ ( [ , ... ] ) ] [ VALUES ( [ , ... ] ) ] + [ INTO ... ] + + [ WHEN ... ] + + [ ELSE INTO ... ] +SELECT ... +``` + +| 参数 | 描述 | +| ---------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| `OVERWRITE` | 指示在插入前是否应截断现有数据。 | +| `( [ , ... ] )` | 指定目标表中将要插入数据的列名。
- 如果省略,则会将数据插入目标表中的所有列。 | +| `VALUES ( [ , ... ] )` | 指定将数据插入目标表时所使用的源列名。
- 如果省略,则子查询返回的所有列都会被插入目标表。
- `` 中列出的列的数据类型必须与 `` 中指定的列匹配或兼容。 | +| `SELECT ...` | 为目标表提供待插入数据的子查询。
- 你可以选择在子查询中为列显式指定别名。这样就可以在 WHEN 子句和 VALUES 子句中通过这些别名引用列。 | +| `WHEN` | 用于确定何时向特定目标表插入数据的条件语句。
- 有条件的多表插入至少需要一个 WHEN 子句。
- 一个 WHEN 子句可以包含多个 INTO 子句,并且这些 INTO 子句可以指向同一个表。
- 如果要无条件执行某个 WHEN 子句,可以使用 `WHEN 1 THEN ...`。 | +| `ELSE` | 指定当 WHEN 子句中定义的条件都不满足时要执行的操作。 | + +## 重要说明 {#important-notes} + +- `VALUES(...)` 表达式中不允许使用聚合函数、外部 UDF 和窗口函数。 + +## 示例 {#examples} + +### 示例 1:无条件 INSERT ALL {#example-1-unconditional-insert-all} + +本示例演示无条件 INSERT ALL 操作,将 `employee_data_source` 表中的每一行同时插入到 `employees` 和 `employee_history` 表中。 + +1. 创建用于管理员工数据的表,包括员工详细信息及其雇佣历史,然后向源表中填充示例员工信息。 + + ```sql + -- Create the employees table + CREATE TABLE employees ( + employee_id INT, + employee_name VARCHAR(100), + hire_date DATE + ); + + -- Create the employee_history table + CREATE TABLE employee_history ( + employee_id INT, + hire_date DATE, + termination_date DATE + ); + + -- Create the employee_data_source table + CREATE TABLE employee_data_source ( + employee_id INT, + employee_name VARCHAR(100), + hire_date DATE + ); + + -- Insert data into the employee_data_source table + INSERT INTO employee_data_source (employee_id, employee_name, hire_date) + VALUES + (1, 'Alice', '2023-01-15'), + (2, 'Bob', '2023-02-20'), + (3, 'Charlie', '2023-03-25'); + ``` + +2. 通过无条件 INSERT ALL 操作,将 `employee_data_source` 表中的数据同时传输到 `employees` 和 `employee_history` 表中。 + +```sql +-- Unconditional INSERT ALL: Insert data into the employees and employee_history tables +INSERT ALL + INTO employees (employee_id, employee_name, hire_date) VALUES (employee_id, employee_name, hire_date) + INTO employee_history (employee_id, hire_date) VALUES (employee_id, hire_date) +SELECT employee_id, employee_name, hire_date FROM employee_data_source; + +-- Query the employees table +SELECT * FROM employees; + +┌─────────────────────────────────────────────────────┐ +│ employee_id │ employee_name │ hire_date │ +├─────────────────┼──────────────────┼────────────────┤ +│ 1 │ Alice │ 2023-01-15 │ +│ 2 │ Bob │ 2023-02-20 │ +│ 3 │ Charlie │ 2023-03-25 │ +└─────────────────────────────────────────────────────┘ + +-- Query the employee_history table +SELECT * FROM employee_history; + +┌─────────────────────────────────────────────────────┐ +│ employee_id │ hire_date │ termination_date │ +├─────────────────┼────────────────┼──────────────────┤ +│ 1 │ 2023-01-15 │ NULL │ +│ 2 │ 2023-02-20 │ NULL │ +│ 3 │ 2023-03-25 │ NULL │ +└─────────────────────────────────────────────────────┘ +``` + +### 示例-2:条件 INSERT ALL 和 FIRST {#example-2-conditional-insert-all-first} + +本示例演示条件 INSERT ALL:根据特定条件将销售数据插入到不同的表中。满足多个条件的记录会被插入到所有对应的表中。 + +1. 创建三个表:products、`high_quantity_sales`、`high_price_sales` 和 `sales_data_source`。然后,向 `sales_data_source` 表中插入三条销售记录。 + + ```sql + -- Create the high_quantity_sales table + CREATE TABLE high_quantity_sales ( + sale_id INT, + product_id INT, + sale_date DATE, + quantity INT, + total_price DECIMAL(10, 2) + ); + + -- Create the high_price_sales table + CREATE TABLE high_price_sales ( + sale_id INT, + product_id INT, + sale_date DATE, + quantity INT, + total_price DECIMAL(10, 2) + ); + + -- Create the sales_data_source table + CREATE TABLE sales_data_source ( + sale_id INT, + product_id INT, + sale_date DATE, + quantity INT, + total_price DECIMAL(10, 2) + ); + + -- Insert data into the sales_data_source table + INSERT INTO sales_data_source (sale_id, product_id, sale_date, quantity, total_price) + VALUES + (1, 101, '2023-01-15', 5, 100.00), + (2, 102, '2023-02-20', 3, 75.00), + (3, 103, '2023-03-25', 10, 200.00); + ``` + +2. 使用条件 INSERT ALL 根据特定条件将行插入到多个表中。数量大于 4 的记录会插入到 `high_quantity_sales` 表中,总价大于 50 的记录会插入到 `high_price_sales` 表中。 + + ```sql + -- Conditional INSERT ALL: Inserts each row into multiple tables, but only if certain conditions are met. + INSERT ALL + WHEN quantity > 4 THEN INTO high_quantity_sales + WHEN total_price > 50 THEN INTO high_price_sales + SELECT * FROM sales_data_source; + + SELECT * FROM high_quantity_sales; + + ┌─────────────────────────────────────────────────────────────────────────────────────────────────┐ + │ sale_id │ product_id │ sale_date │ quantity │ total_price │ + ├─────────────────┼─────────────────┼────────────────┼─────────────────┼──────────────────────────┤ + │ 1 │ 101 │ 2023-01-15 │ 5 │ 100.00 │ + │ 3 │ 103 │ 2023-03-25 │ 10 │ 200.00 │ + └─────────────────────────────────────────────────────────────────────────────────────────────────┘ + + SELECT * FROM high_price_sales; + + ┌─────────────────────────────────────────────────────────────────────────────────────────────────┐ + │ sale_id │ product_id │ sale_date │ quantity │ total_price │ + ├─────────────────┼─────────────────┼────────────────┼─────────────────┼──────────────────────────┤ + │ 1 │ 101 │ 2023-01-15 │ 5 │ 100.00 │ + │ 2 │ 102 │ 2023-02-20 │ 3 │ 75.00 │ + │ 3 │ 103 │ 2023-03-25 │ 10 │ 200.00 │ + └─────────────────────────────────────────────────────────────────────────────────────────────────┘ + ``` + +3. 清空 high_quantity_sales 和 high_price_sales 表中的数据。 + + ```sql + TRUNCATE TABLE high_quantity_sales; + + TRUNCATE TABLE high_price_sales; + ``` + +4. 使用条件 INSERT FIRST 根据特定条件将行插入到多个表中。对于每一行,在第一次成功插入后就会停止。因此,与步骤 2 中条件 INSERT ALL 的结果相比,ID 为 1 和 3 的销售记录只会插入到 `high_quantity_sales` 表中。 + +```sql +-- Conditional INSERT FIRST: Inserts each row into multiple tables, but stops after the first successful insertion. +INSERT FIRST + WHEN quantity > 4 THEN INTO high_quantity_sales + WHEN total_price > 50 THEN INTO high_price_sales +SELECT * FROM sales_data_source; + +SELECT * FROM high_quantity_sales; + +┌─────────────────────────────────────────────────────────────────────────────────────────────────┐ +│ sale_id │ product_id │ sale_date │ quantity │ total_price │ +├─────────────────┼─────────────────┼────────────────┼─────────────────┼──────────────────────────┤ +│ 1 │ 101 │ 2023-01-15 │ 5 │ 100.00 │ +│ 3 │ 103 │ 2023-03-25 │ 10 │ 200.00 │ +└─────────────────────────────────────────────────────────────────────────────────────────────────┘ + +SELECT * FROM high_price_sales; + +┌─────────────────────────────────────────────────────────────────────────────────────────────────┐ +│ sale_id │ product_id │ sale_date │ quantity │ total_price │ +├─────────────────┼─────────────────┼────────────────┼─────────────────┼──────────────────────────┤ +│ 2 │ 102 │ 2023-02-20 │ 3 │ 75.00 │ +└─────────────────────────────────────────────────────────────────────────────────────────────────┘ +``` + +### 示例-3:使用显式别名插入 {#example-3-insert-with-explicit-alias} + +本示例演示如何在 VALUES 子句中使用别名,根据入职日期晚于 '2023-02-01' 的条件,将 `employees` 表中的行有条件地插入到 `employee_history` 表中。 + +1. 创建两个表 `employees` 和 `employee_history`,并向 `employees` 表中插入示例员工数据。 + + ```sql + -- Create tables + CREATE TABLE employees ( + employee_id INT, + first_name VARCHAR(50), + last_name VARCHAR(50), + hire_date DATE + ); + + CREATE TABLE employee_history ( + employee_id INT, + full_name VARCHAR(100), + hire_date DATE + ); + + INSERT INTO employees (employee_id, first_name, last_name, hire_date) + VALUES + (1, 'John', 'Doe', '2023-01-01'), + (2, 'Jane', 'Smith', '2023-02-01'), + (3, 'Michael', 'Johnson', '2023-03-01'); + ``` + +2. 使用带别名的条件插入,将记录从 employees 表转移到 `employee_history` 表中,并筛选入职日期晚于 '2023-02-01' 的记录。 + +```sql +INSERT ALL + WHEN hire_date >= '2023-02-01' THEN INTO employee_history + VALUES (employee_id, full_name, hire_date) -- Insert with the alias 'full_name' +SELECT employee_id, CONCAT(first_name, ' ', last_name) AS full_name, hire_date -- Alias the concatenated full name as 'full_name' +FROM employees; + +SELECT * FROM employee_history; + +┌─────────────────────────────────────────────────────┐ +│ employee_id │ full_name │ hire_date │ +│ Nullable(Int32) │ Nullable(String) │ Nullable(Date) │ +├─────────────────┼──────────────────┼────────────────┤ +│ 2 │ Jane Smith │ 2023-02-01 │ +│ 3 │ Michael Johnson │ 2023-03-01 │ +└─────────────────────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/insert-sql.md b/tidb-cloud-lake/sql/insert-sql.md new file mode 100644 index 0000000000000..412b2f2291600 --- /dev/null +++ b/tidb-cloud-lake/sql/insert-sql.md @@ -0,0 +1,70 @@ +--- +title: INSERT +summary: 返回字符串 str,其中从位置 pos 开始、长度为 len 的子字符串被字符串 newstr 替换。如果 pos 不在字符串长度范围内,则返回原始字符串。如果 len 不在剩余字符串的长度范围内,则从位置 pos 开始替换该位置之后的其余字符串。如果任一参数为 NULL,则返回 NULL。 +--- + +# INSERT + +返回字符串 str,其中从位置 pos 开始、长度为 len 的子字符串被字符串 newstr 替换。如果 pos 不在字符串长度范围内,则返回原始字符串。如果 len 不在剩余字符串的长度范围内,则从位置 pos 开始替换该位置之后的其余字符串。如果任一参数为 NULL,则返回 NULL。 + +## 语法 {#syntax} + +```sql +INSERT(, , , ) +``` + +## 参数 {#arguments} + +| 参数 | 描述 | +|------------|-----------------| +| `` | 字符串。 | +| `` | 位置。 | +| `` | 长度。 | +| `` | 新字符串。 | + +## 返回类型 {#return-type} + +`VARCHAR` + +## 示例 {#examples} + +```sql +SELECT INSERT('Quadratic', 3, 4, 'What'); ++-----------------------------------+ +| INSERT('Quadratic', 3, 4, 'What') | ++-----------------------------------+ +| QuWhattic | ++-----------------------------------+ + +SELECT INSERT('Quadratic', -1, 4, 'What'); ++---------------------------------------+ +| INSERT('Quadratic', (- 1), 4, 'What') | ++---------------------------------------+ +| Quadratic | ++---------------------------------------+ + +SELECT INSERT('Quadratic', 3, 100, 'What'); ++-------------------------------------+ +| INSERT('Quadratic', 3, 100, 'What') | ++-------------------------------------+ +| QuWhat | ++-------------------------------------+ + ++--------------------------------------------+--------+ +| INSERT('123456789', number, number, 'aaa') | number | ++--------------------------------------------+--------+ +| 123456789 | 0 | +| aaa23456789 | 1 | +| 1aaa456789 | 2 | +| 12aaa6789 | 3 | +| 123aaa89 | 4 | +| 1234aaa | 5 | +| 12345aaa | 6 | +| 123456aaa | 7 | +| 1234567aaa | 8 | +| 12345678aaa | 9 | +| 123456789 | 10 | +| 123456789 | 11 | +| 123456789 | 12 | ++--------------------------------------------+--------+ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/insert.md b/tidb-cloud-lake/sql/insert.md new file mode 100644 index 0000000000000..db93e4e55bf04 --- /dev/null +++ b/tidb-cloud-lake/sql/insert.md @@ -0,0 +1,260 @@ +--- +title: INSERT +summary: 向表中插入一行或多行数据。 +--- + +# INSERT + +向表中插入一行或多行数据。 + +> **Tip:** +> +> {{{ .lake }}} 通过原子操作确保数据完整性。插入、修改、替换和删除操作要么全部成功,要么全部失败。 + +另请参阅:[INSERT(多表)](/tidb-cloud-lake/sql/insert-multi-table.md) + +## 语法 {#syntax} + +```sql +INSERT { OVERWRITE [ INTO ] | INTO }
+ -- Optionally specify the columns to insert into + ( [ , ... ] ) + -- Insertion options: + { + -- Directly insert values or default values + VALUES ( | DEFAULT ) [ , ... ] | + -- Insert the result of a query + SELECT ... + } +``` + +| 参数 | 描述 | +|--------------------|----------------------------------------------------------------------------------| +| `OVERWRITE [INTO]` | 指示在插入前是否应截断现有数据。 | +| `VALUES` | 允许直接插入指定值或列的默认值。 | + +## 重要说明 {#important-notes} + +- 在 `VALUES(...)` 表达式中,不允许使用聚合函数、外部 UDF 和窗口函数。 + +## 示例 {#examples} + +### 示例 1:使用 OVERWRITE 插入值 {#example-1-insert-values-with-overwrite} + +在此示例中,使用 INSERT OVERWRITE 语句截断 employee 表并插入新数据,用 employee_id 为 100 的员工数据替换所有现有记录。 + +```sql +CREATE TABLE employee ( + employee_id INT, + employee_name VARCHAR(50) +); + +-- Inserting initial data into the employee table +INSERT INTO employee(employee_id, employee_name) VALUES + (101, 'John Doe'), + (102, 'Jane Smith'); + +-- Inserting new data with OVERWRITE +INSERT OVERWRITE employee VALUES (100, 'John Johnson'); + +-- Displaying the contents of the employee table +SELECT * FROM employee; + +┌────────────────────────────────────┐ +│ employee_id │ employee_name │ +├─────────────────┼──────────────────┤ +│ 100 │ John Johnson │ +└────────────────────────────────────┘ +``` + +### 示例 2:插入查询结果 {#example-2-insert-query-results} + +插入 SELECT 语句的结果时,列映射遵循它们在 SELECT 子句中的位置。因此,SELECT 语句中的列数必须等于或大于 INSERT 目标表中的列数。如果 SELECT 语句中的列与 INSERT 目标表中的列数据类型不同,则会根据需要执行类型转换。 + +```sql +-- Creating a table named 'employee_info' with three columns: 'employee_id', 'employee_name', and 'department' +CREATE TABLE employee_info ( + employee_id INT, + employee_name VARCHAR(50), + department VARCHAR(50) +); + +-- Inserting a record into the 'employee_info' table +INSERT INTO employee_info VALUES ('101', 'John Doe', 'Marketing'); + +-- Creating a table named 'employee_data' with three columns: 'ID', 'Name', and 'Dept' +CREATE TABLE employee_data ( + ID INT, + Name VARCHAR(50), + Dept VARCHAR(50) +); + +-- Inserting data from 'employee_info' into 'employee_data' +INSERT INTO employee_data SELECT * FROM employee_info; + +-- Displaying the contents of the 'employee_data' table +SELECT * FROM employee_data; + +┌───────────────────────────────────────────────────────┐ +│ id │ name │ dept │ +├─────────────────┼──────────────────┼──────────────────┤ +│ 101 │ John Doe │ Marketing │ +└───────────────────────────────────────────────────────┘ +``` + +以下示例展示了如何创建一个名为 "sales_summary" 的汇总表,通过聚合 sales 表中的信息,存储每个产品的销售汇总数据,例如销售总数量和总收入: + +```sql +-- Creating a table for sales data +CREATE TABLE sales ( + product_id INT, + quantity_sold INT, + revenue DECIMAL(10, 2) +); + +-- Inserting some sample sales data +INSERT INTO sales (product_id, quantity_sold, revenue) VALUES + (1, 100, 500.00), + (2, 150, 750.00), + (1, 200, 1000.00), + (3, 50, 250.00); + +-- Creating a summary table to store aggregated sales data +CREATE TABLE sales_summary ( + product_id INT, + total_quantity_sold INT, + total_revenue DECIMAL(10, 2) +); + +-- Inserting aggregated sales data into the summary table +INSERT INTO sales_summary (product_id, total_quantity_sold, total_revenue) +SELECT + product_id, + SUM(quantity_sold) AS total_quantity_sold, + SUM(revenue) AS total_revenue +FROM + sales +GROUP BY + product_id; + +-- Displaying the contents of the sales_summary table +SELECT * FROM sales_summary; + +┌──────────────────────────────────────────────────────────────────┐ +│ product_id │ total_quantity_sold │ total_revenue │ +├─────────────────┼─────────────────────┼──────────────────────────┤ +│ 1 │ 300 │ 1500.00 │ +│ 3 │ 50 │ 250.00 │ +│ 2 │ 150 │ 750.00 │ +└──────────────────────────────────────────────────────────────────┘ +``` + +### 示例 3:插入默认值 {#example-3-insert-default-values} + +本示例展示了如何创建一个名为 "staff_records" 的表,并为 department 和 status 等列设置默认值。随后插入数据,以演示默认值的用法。 + +```sql +-- Creating a table 'staff_records' with columns 'employee_id', 'department', 'salary', and 'status' with default values +CREATE TABLE staff_records ( + employee_id INT NULL, + department VARCHAR(50) DEFAULT 'HR', + salary FLOAT, + status VARCHAR(10) DEFAULT 'Active' +); + +-- Inserting data into 'staff_records' with default values +INSERT INTO staff_records +VALUES + (DEFAULT, DEFAULT, DEFAULT, DEFAULT), + (101, DEFAULT, 50000.00, DEFAULT), + (102, 'Finance', 60000.00, 'Inactive'), + (103, 'Marketing', 70000.00, 'Active'); + +-- Displaying the contents of the 'staff_records' table +SELECT * FROM staff_records; + +┌───────────────────────────────────────────────────────────────────────────┐ +│ employee_id │ department │ salary │ status │ +├─────────────────┼──────────────────┼───────────────────┼──────────────────┤ +│ NULL │ HR │ NULL │ Active │ +│ 101 │ HR │ 50000 │ Active │ +│ 102 │ Finance │ 60000 │ Inactive │ +│ 103 │ Marketing │ 70000 │ Active │ +└───────────────────────────────────────────────────────────────────────────┘ +``` + +### 示例-4:使用 staged files 插入数据 {#example-4-insert-with-staged-files} + +{{{ .lake }}} 支持你使用 `INSERT INTO` 语句将 staged files 中的数据插入到表中。这是通过 {{{ .lake }}} 查询 [查询 Stage 文件](/tidb-cloud-lake/sql/stage.md) 并将查询结果进一步写入表中来实现的。 + +1. 创建一个名为 `sample` 的表: + + ```sql + CREATE TABLE sample + ( + id INT, + city VARCHAR, + score INT, + country VARCHAR DEFAULT 'China' + ); + ``` + +2. 设置一个包含示例数据的内部 stage + + 我们将创建一个名为 `mystage` 的内部 stage,然后用示例数据填充它。 + + ```sql + CREATE STAGE mystage; + + COPY INTO @mystage + FROM + ( + SELECT * + FROM + ( + VALUES + (1, 'Chengdu', 80), + (3, 'Chongqing', 90), + (6, 'Hangzhou', 92), + (9, 'Hong Kong', 88) + ) + ) + FILE_FORMAT = (TYPE = PARQUET); + ``` + +3. 使用 `INSERT INTO` 从 stage 中的 Parquet 文件插入数据 + + > **Tip:** + > + > 你可以使用 [COPY INTO](/tidb-cloud-lake/sql/copy-into-table.md) 命令中提供的 `FILE_FORMAT` 和 `COPY_OPTIONS` 来指定文件格式以及各种与复制相关的设置。当 `purge` 设置为 `true` 时,只有在数据修改成功后,原始文件才会被删除。 + + ```sql + INSERT INTO sample + (id, city, score) + ON + (Id) + SELECT + $1, $2, $3 + FROM + @mystage + (FILE_FORMAT => 'parquet'); + ``` + +4. 验证插入的数据 + +```sql +SELECT * FROM sample; +``` + +结果应如下所示: + +```sql +┌─────────────────────────────────────────────────────────────────────────┐ +│ id │ city │ score │ country │ +├─────────────────┼──────────────────┼─────────────────┼──────────────────┤ +│ 1 │ Chengdu │ 80 │ China │ +│ 3 │ Chongqing │ 90 │ China │ +│ 6 │ Hangzhou │ 92 │ China │ +│ 9 │ Hong Kong │ 88 │ China │ +└─────────────────────────────────────────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/inspect-parquet.md b/tidb-cloud-lake/sql/inspect-parquet.md new file mode 100644 index 0000000000000..21d53e4e5b722 --- /dev/null +++ b/tidb-cloud-lake/sql/inspect-parquet.md @@ -0,0 +1,53 @@ +--- +title: INSPECT_PARQUET +summary: 从 stage 中的 Parquet 文件检索包含完整元信息的表,其中包括以下列。 +--- + +# INSPECT_PARQUET + +从 stage 中的 Parquet 文件检索包含完整元信息的表,其中包括以下列: + +| 列 | 描述 | +|----------------------------------|----------------------------------------------------------------| +| created_by | 负责创建 Parquet 文件的实体或来源 | +| num_columns | Parquet 文件中的列数 | +| num_rows | Parquet 文件中的总行数或记录数 | +| num_row_groups | Parquet 文件中的行组数量 | +| serialized_size | Parquet 文件在磁盘上的大小(压缩后) | +| max_row_groups_size_compressed | 最大行组的大小(压缩后) | +| max_row_groups_size_uncompressed | 最大行组的大小(未压缩) | + +## 语法 {#syntax} + +```sql +INSPECT_PARQUET('@') +``` + +## 示例 {#examples} + +以下示例从 stage 中名为 [books.parquet](https://lakesql-bin.tidbcloud.com/datasets/books.parquet) 的示例 Parquet 文件中检索元信息。该文件包含两条记录: + +```text title='books.parquet' +Transaction Processing,Jim Gray,1992 +Readings in Database Systems,Michael Stonebraker,2004 +``` + +```sql +-- Show the staged file +LIST @my_internal_stage; + +┌──────────────────────────────────────────────────────────────────────────────────────────────┐ +│ name │ size │ md5 │ last_modified │ creator │ +├───────────────┼────────┼──────────────────┼───────────────────────────────┼──────────────────┤ +│ books.parquet │ 998 │ NULL │ 2023-04-19 19:34:51.303 +0000 │ NULL │ +└──────────────────────────────────────────────────────────────────────────────────────────────┘ + +-- Retrieve metadata from the staged file +SELECT * FROM INSPECT_PARQUET('@my_internal_stage/books.parquet'); + +┌────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ +│ created_by │ num_columns │ num_rows │ num_row_groups │ serialized_size │ max_row_groups_size_compressed │ max_row_groups_size_uncompressed │ +├────────────────────────────────────┼─────────────┼──────────┼────────────────┼─────────────────┼────────────────────────────────┼──────────────────────────────────┤ +│ parquet-cpp version 1.5.1-SNAPSHOT │ 3 │ 2 │ 1 │ 998 │ 332 │ 320 │ +└────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/instr.md b/tidb-cloud-lake/sql/instr.md new file mode 100644 index 0000000000000..4999128985532 --- /dev/null +++ b/tidb-cloud-lake/sql/instr.md @@ -0,0 +1,43 @@ +--- +title: INSTR +summary: 返回子字符串 substr 在字符串 str 中首次出现的位置。这与 LOCATE() 的双参数形式相同,只是参数顺序相反。 +--- + +# INSTR + +返回子字符串 substr 在字符串 str 中首次出现的位置。这与 LOCATE() 的双参数形式相同,只是参数顺序相反。 + +## 语法 {#syntax} + +```sql +INSTR(, ) +``` + +## 参数 {#arguments} + +| 参数 | 描述 | +|------------|----------------| +| `` | 字符串。 | +| `` | 子字符串。 | + +## 返回类型 {#return-type} + +`BIGINT` + +## 示例 {#examples} + +```sql +SELECT INSTR('foobarbar', 'bar'); ++---------------------------+ +| INSTR('foobarbar', 'bar') | ++---------------------------+ +| 4 | ++---------------------------+ + +SELECT INSTR('xbar', 'foobar'); ++-------------------------+ +| INSTR('xbar', 'foobar') | ++-------------------------+ +| 0 | ++-------------------------+ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/intdiv.md b/tidb-cloud-lake/sql/intdiv.md new file mode 100644 index 0000000000000..bd3bf011a1f9c --- /dev/null +++ b/tidb-cloud-lake/sql/intdiv.md @@ -0,0 +1,8 @@ +--- +title: INTDIV +summary: DIV 的别名。 +--- + +# INTDIV + +[DIV](/tidb-cloud-lake/sql/div.md) 的别名。 \ No newline at end of file diff --git a/tidb-cloud-lake/sql/intersect-count.md b/tidb-cloud-lake/sql/intersect-count.md new file mode 100644 index 0000000000000..31ccc8f090d63 --- /dev/null +++ b/tidb-cloud-lake/sql/intersect-count.md @@ -0,0 +1,38 @@ +--- +title: INTERSECT_COUNT +summary: 统计两个 bitmap 列之间相交的位数。 +--- + +# INTERSECT_COUNT + +统计两个 bitmap 列之间相交的位数。 + +## 语法 {#syntax} + +```sql +INTERSECT_COUNT( '', '' )( , ) +``` + +## 示例 {#examples} + +```sql +CREATE TABLE agg_bitmap_test(id Int, tag String, v Bitmap); + +INSERT INTO + agg_bitmap_test(id, tag, v) +VALUES + (1, 'a', to_bitmap('0, 1')), + (2, 'b', to_bitmap('0, 1, 2')), + (3, 'c', to_bitmap('1, 3, 4')); + +SELECT id, INTERSECT_COUNT('b', 'c')(v, tag) +FROM agg_bitmap_test GROUP BY id; + +┌─────────────────────────────────────────────────────┐ +│ id │ intersect_count('b', 'c')(v, tag) │ +├─────────────────┼───────────────────────────────────┤ +│ 1 │ 0 │ +│ 3 │ 3 │ +│ 2 │ 3 │ +└─────────────────────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/interval-functions.md b/tidb-cloud-lake/sql/interval-functions.md new file mode 100644 index 0000000000000..008930268d345 --- /dev/null +++ b/tidb-cloud-lake/sql/interval-functions.md @@ -0,0 +1,43 @@ +--- +title: 区间函数 +summary: 本节提供 {{{ .lake }}} 中区间函数的参考信息。区间函数允许你创建各种时间单位的区间值,用于日期和时间计算。 +--- + +# 区间函数 + +本节提供 {{{ .lake }}} 中区间函数的参考信息。区间函数允许你创建各种时间单位的区间值,用于日期和时间计算。 + +## 时间单位转换函数 {#time-unit-conversion-functions} + +### 基于天的区间 {#day-based-intervals} + +| 函数 | 描述 | 示例 | +|----------|-------------|--------| +| [TO_DAYS](/tidb-cloud-lake/sql/days.md) | 将数字转换为天数区间 | `TO_DAYS(2)` → `2 days` | +| [TO_WEEKS](/tidb-cloud-lake/sql/weeks.md) | 将数字转换为周数区间 | `TO_WEEKS(3)` → `21 days` | +| [TO_MONTHS](/tidb-cloud-lake/sql/months.md) | 将数字转换为月数区间 | `TO_MONTHS(2)` → `2 months` | +| [TO_YEARS](/tidb-cloud-lake/sql/years.md) | 将数字转换为年数区间 | `TO_YEARS(1)` → `1 year` | + +### 基于小时的区间 {#hour-based-intervals} + +| 函数 | 描述 | 示例 | +|----------|-------------|--------| +| [TO_HOURS](/tidb-cloud-lake/sql/hours.md) | 将数字转换为小时区间 | `TO_HOURS(5)` → `5:00:00` | +| [TO_MINUTES](/tidb-cloud-lake/sql/minutes.md) | 将数字转换为分钟区间 | `TO_MINUTES(90)` → `1:30:00` | +| [TO_SECONDS](/tidb-cloud-lake/sql/seconds.md) | 将数字转换为秒数区间 | `TO_SECONDS(3600)` → `1:00:00` | +| [EPOCH](/tidb-cloud-lake/sql/epoch.md) | TO_SECONDS 的别名 | `EPOCH(60)` → `00:01:00` | + +### 更小的时间单位 {#smaller-time-units} + +| 函数 | 描述 | 示例 | +|----------|-------------|--------| +| [TO_MILLISECONDS](/tidb-cloud-lake/sql/milliseconds.md) | 将数字转换为毫秒区间 | `TO_MILLISECONDS(2000)` → `00:00:02` | +| [TO_MICROSECONDS](/tidb-cloud-lake/sql/microseconds.md) | 将数字转换为微秒区间 | `TO_MICROSECONDS(2000000)` → `00:00:02` | + +### 更大的时间单位 {#larger-time-units} + +| 函数 | 描述 | 示例 | +|----------|-------------|--------| +| [TO_DECADES](/tidb-cloud-lake/sql/decades.md) | 将数字转换为十年区间 | `TO_DECADES(2)` → `20 years` | +| [TO_CENTRIES](/tidb-cloud-lake/sql/to-centuries.md) | 将数字转换为世纪区间 | `TO_CENTRIES(1)` → `100 years` | +| [TO_MILLENNIA](/tidb-cloud-lake/sql/millennia.md) | 将数字转换为千年区间 | `TO_MILLENNIA(1)` → `1000 years` | \ No newline at end of file diff --git a/tidb-cloud-lake/sql/interval.md b/tidb-cloud-lake/sql/interval.md new file mode 100644 index 0000000000000..14c433f318190 --- /dev/null +++ b/tidb-cloud-lake/sql/interval.md @@ -0,0 +1,99 @@ +--- +title: Interval +summary: INTERVAL 表示一个持续时间,可以写成自然语言文本(`'1 year 2 months'`、`'3 days ago'`),也可以写成以微秒为单位的整数。{{{ .lake }}} 支持从千年到微秒的时间单位,并允许对 interval、日期和时间戳进行算术运算。 +--- + +# Interval + +## 概述 {#overview} + +`INTERVAL` 表示一个持续时间,可以写成自然语言文本(`'1 year 2 months'`、`'3 days ago'`),也可以写成以微秒为单位的整数。{{{ .lake }}} 支持从千年到微秒的时间单位,并允许对 interval、日期和时间戳进行算术运算。 + +> **注意:** +> +> 解析数值型 interval 时,小数部分会被丢弃。`'1.6 seconds'` 会变成一个 1 秒的 interval。 + +## 示例 {#examples} + +### 字面量和数值 {#literals-and-numeric-values} + +```sql +CREATE OR REPLACE TABLE intervals (duration INTERVAL); + +INSERT INTO intervals VALUES + ('1 year 2 months'), -- positive natural language + ('1 year 2 months ago'), -- negative because of "ago" + ('1000000'), -- 1 second in microseconds + ('-1000000'); -- -1 second + +SELECT TO_STRING(duration) AS duration_text FROM intervals; +``` + +结果: + +``` +┌──────────────────────┐ +│ duration_text │ +├──────────────────────┤ +│ 1 year 2 months │ +│ -1 year -2 months │ +│ 0:00:01 │ +│ -0:00:01 │ +└──────────────────────┘ +``` + +```sql +SELECT + TO_STRING(TO_INTERVAL('1 seconds')) AS whole, + TO_STRING(TO_INTERVAL('1.6 seconds')) AS fractional; +``` + +结果: + +``` +┌────────┬────────────┐ +│ whole │ fractional │ +├────────┼────────────┤ +│ 0:00:01 │ 0:00:01 │ +└────────┴────────────┘ +``` + +### Interval 算术运算 {#interval-arithmetic} + +```sql +SELECT + TO_STRING(TO_DAYS(3) + TO_DAYS(1)) AS add_interval, + TO_STRING(TO_DAYS(3) - TO_DAYS(1)) AS subtract_interval; +``` + +结果: + +``` +┌──────────────┬──────────────────┐ +│ add_interval │ subtract_interval │ +├──────────────┼──────────────────┤ +│ 4 days │ 2 days │ +└──────────────┴──────────────────┘ +``` + +### 应用于 DATE 和 TIMESTAMP {#apply-to-date-and-timestamp} + +```sql +SELECT + DATE '2024-12-20' + TO_DAYS(2) AS add_days, + DATE '2024-12-20' - TO_DAYS(2) AS subtract_days, + TIMESTAMP '2024-12-20 10:00:00' + TO_HOURS(36) AS add_hours, + TIMESTAMP '2024-12-20 10:00:00' - TO_HOURS(36) AS subtract_hours; +``` + +结果: + +``` +┌────────────────────┬────────────────────┬────────────────────┬────────────────────┐ +│ add_days │ subtract_days │ add_hours │ subtract_hours │ +├────────────────────┼────────────────────┼────────────────────┼────────────────────┤ +│ 2024-12-22T00:00:00 │ 2024-12-18T00:00:00 │ 2024-12-21T22:00:00 │ 2024-12-18T22:00:00 │ +└────────────────────┴────────────────────┴────────────────────┴────────────────────┘ +``` + +interval 的加减方式与数字类似,因此可以方便地滑动时间窗口,或以精确到微秒的控制来计算偏移。 \ No newline at end of file diff --git a/tidb-cloud-lake/sql/inverted-index.md b/tidb-cloud-lake/sql/inverted-index.md new file mode 100644 index 0000000000000..8b51f679de804 --- /dev/null +++ b/tidb-cloud-lake/sql/inverted-index.md @@ -0,0 +1,24 @@ +--- +title: 倒排索引 +summary: 本页按功能分类,全面概述 {{{ .lake }}} 中的倒排索引操作,便于参考。 +--- + +# 倒排索引 + +本页按功能分类,全面概述 {{{ .lake }}} 中的倒排索引操作,便于参考。 + +## 倒排索引管理 {#inverted-index-management} + +| 命令 | 描述 | +|---------|-------------| +| [CREATE INVERTED INDEX](/tidb-cloud-lake/sql/create-inverted-index.md) | 为全文搜索创建新的倒排索引 | +| [DROP INVERTED INDEX](/tidb-cloud-lake/sql/drop-inverted-index.md) | 删除倒排索引 | +| [REFRESH INVERTED INDEX](/tidb-cloud-lake/sql/refresh-inverted-index.md) | 使用最新数据更新倒排索引 | + +## 相关主题 {#related-topics} + +- [全文索引](/tidb-cloud-lake/guides/full-text-index.md) + +> **注意:** +> +> {{{ .lake }}} 中的倒排索引可为文本数据提供高效的全文搜索能力,从而支持在大型文本列中快速执行关键字搜索。 \ No newline at end of file diff --git a/tidb-cloud-lake/sql/ip-address-functions.md b/tidb-cloud-lake/sql/ip-address-functions.md new file mode 100644 index 0000000000000..44b305c550103 --- /dev/null +++ b/tidb-cloud-lake/sql/ip-address-functions.md @@ -0,0 +1,24 @@ +--- +title: IP Address Functions +summary: 本页提供 {{{ .lake }}} 中与 IP 地址相关的函数参考信息。这些函数可帮助在 IP 地址的字符串表示和数值表示之间进行转换。 +--- + +# IP Address Functions + +本页提供 {{{ .lake }}} 中与 IP 地址相关的函数参考信息。这些函数可帮助在 IP 地址的字符串表示和数值表示之间进行转换。 + +## IP 地址转换函数 {#ip-address-conversion-functions} + +| 函数 | 描述 | 示例 | +|----------|-------------|--------| +| [INET_ATON](/tidb-cloud-lake/sql/inet-aton.md) / [IPV4_STRING_TO_NUM](/tidb-cloud-lake/sql/ipv4-string-to-num.md) | 将 IPv4 地址字符串转换为 32 位整数型 | `INET_ATON('192.168.1.1')` → `3232235777` | +| [INET_NTOA](/tidb-cloud-lake/sql/inet-ntoa.md) / [IPV4_NUM_TO_STRING](/tidb-cloud-lake/sql/ipv4-num-to-string.md) | 将 32 位整数型转换为 IPv4 地址字符串 | `INET_NTOA(3232235777)` → `'192.168.1.1'` | + +## 安全的 IP 地址转换函数 {#safe-ip-address-conversion-functions} + +这些函数会以优雅的方式处理无效输入,即返回 NULL 而不是报错。 + +| 函数 | 描述 | 示例 | +|----------|-------------|--------| +| [TRY_INET_ATON](/tidb-cloud-lake/sql/try-inet-aton.md) / [TRY_IPV4_STRING_TO_NUM](/tidb-cloud-lake/sql/try-ipv4-string-to-num.md) | 安全地将 IPv4 地址字符串转换为 32 位整数型 | `TRY_INET_ATON('invalid')` → `NULL` | +| [TRY_INET_NTOA](/tidb-cloud-lake/sql/try-inet-ntoa.md) / [TRY_IPV4_NUM_TO_STRING](/tidb-cloud-lake/sql/try-ipv4-num-to-string.md) | 安全地将 32 位整数型转换为 IPv4 地址字符串 | `TRY_INET_NTOA(-1)` → `NULL` | \ No newline at end of file diff --git a/tidb-cloud-lake/sql/ipv4-num-to-string.md b/tidb-cloud-lake/sql/ipv4-num-to-string.md new file mode 100644 index 0000000000000..6b8b78c1e7be3 --- /dev/null +++ b/tidb-cloud-lake/sql/ipv4-num-to-string.md @@ -0,0 +1,8 @@ +--- +title: IPV4_NUM_TO_STRING +summary: INET_NTOA 的别名。 +--- + +# IPV4_NUM_TO_STRING + +[INET_NTOA](/tidb-cloud-lake/sql/inet-ntoa.md) 的别名。 \ No newline at end of file diff --git a/tidb-cloud-lake/sql/ipv4-string-to-num.md b/tidb-cloud-lake/sql/ipv4-string-to-num.md new file mode 100644 index 0000000000000..110f96cdfe154 --- /dev/null +++ b/tidb-cloud-lake/sql/ipv4-string-to-num.md @@ -0,0 +1,8 @@ +--- +title: IPV4_STRING_TO_NUM +summary: INET_ATON 的别名。 +--- + +# IPV4_STRING_TO_NUM + +[INET_ATON](/tidb-cloud-lake/sql/inet-aton.md) 的别名。 \ No newline at end of file diff --git a/tidb-cloud-lake/sql/is-array.md b/tidb-cloud-lake/sql/is-array.md new file mode 100644 index 0000000000000..93e2c87361e46 --- /dev/null +++ b/tidb-cloud-lake/sql/is-array.md @@ -0,0 +1,43 @@ +--- +title: IS_ARRAY +summary: 检查输入值是否为 JSON 数组。请注意,JSON 数组与 ARRAY 数据类型并不相同。JSON 数组是 JSON 中常用的一种数据结构,表示由方括号 [] 括起来的有序值集合。它是一种灵活的格式,可用于组织和交换多种数据类型,包括字符串、数字、布尔值、对象和空值。 +--- + +# IS_ARRAY + +检查输入值是否为 JSON 数组。请注意,JSON 数组与 [ARRAY](/tidb-cloud-lake/sql/array.md) 数据类型并不相同。JSON 数组是 JSON 中常用的一种数据结构,表示由方括号 `[ ]` 括起来的有序值集合。它是一种灵活的格式,可用于组织和交换多种数据类型,包括字符串、数字、布尔值、对象和空值。 + +```json title='JSON Array Example:' +[ + "Apple", + 42, + true, + {"name": "John", "age": 30, "isStudent": false}, + [1, 2, 3], + null +] +``` + +## 语法 {#syntax} + +```sql +IS_ARRAY( ) +``` + +## 返回类型 {#return-type} + +如果输入值是 JSON 数组,则返回 `true`;否则返回 `false`。 + +## 示例 {#examples} + +```sql +SELECT + IS_ARRAY(PARSE_JSON('true')), + IS_ARRAY(PARSE_JSON('[1,2,3]')); + +┌────────────────────────────────────────────────────────────────┐ +│ is_array(parse_json('true')) │ is_array(parse_json('[1,2,3]')) │ +├──────────────────────────────┼─────────────────────────────────┤ +│ false │ true │ +└────────────────────────────────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/is-boolean.md b/tidb-cloud-lake/sql/is-boolean.md new file mode 100644 index 0000000000000..4e3a808814b78 --- /dev/null +++ b/tidb-cloud-lake/sql/is-boolean.md @@ -0,0 +1,32 @@ +--- +title: IS_BOOLEAN +summary: 检查输入的 JSON 值是否为布尔值。 +--- + +# IS_BOOLEAN + +检查输入的 JSON 值是否为布尔值。 + +## 语法 {#syntax} + +```sql +IS_BOOLEAN( ) +``` + +## 返回类型 {#return-type} + +如果输入的 JSON 值是布尔值,则返回 `true`;否则返回 `false`。 + +## 示例 {#examples} + +```sql +SELECT + IS_BOOLEAN(PARSE_JSON('true')), + IS_BOOLEAN(PARSE_JSON('[1,2,3]')); + +┌────────────────────────────────────────────────────────────────────┐ +│ is_boolean(parse_json('true')) │ is_boolean(parse_json('[1,2,3]')) │ +├────────────────────────────────┼───────────────────────────────────┤ +│ true │ false │ +└────────────────────────────────────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/is-distinct-from.md b/tidb-cloud-lake/sql/is-distinct-from.md new file mode 100644 index 0000000000000..02275e3da596a --- /dev/null +++ b/tidb-cloud-lake/sql/is-distinct-from.md @@ -0,0 +1,26 @@ +--- +title: IS [ NOT ] DISTINCT FROM +summary: 在考虑可空性的情况下比较两个表达式是否相等(或不相等),这意味着它将 NULL 视为已知值来进行相等性比较。 +--- + +# IS [ NOT ] DISTINCT FROM + +在考虑可空性的情况下比较两个表达式是否相等(或不相等),这意味着它将 NULL 视为已知值来进行相等性比较。 + +## 语法 {#syntax} + +```sql + IS [ NOT ] DISTINCT FROM +``` + +## 示例 {#examples} + +```sql +SELECT NULL IS DISTINCT FROM NULL; + +┌────────────────────────────┐ +│ null is distinct from null │ +├────────────────────────────┤ +│ false │ +└────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/is-error.md b/tidb-cloud-lake/sql/is-error.md new file mode 100644 index 0000000000000..9a76d9b43b4a7 --- /dev/null +++ b/tidb-cloud-lake/sql/is-error.md @@ -0,0 +1,42 @@ +--- +title: IS_ERROR +summary: 返回一个布尔值,指示表达式是否为错误值。 +--- + +# IS_ERROR + +返回一个布尔值,指示表达式是否为错误值。 + +另请参阅:[IS_NOT_ERROR](/tidb-cloud-lake/sql/is-not-error.md) + +## 语法 {#syntax} + +```sql +IS_ERROR( ) +``` + +## 返回类型 {#return-type} + +如果表达式是错误,则返回 `true`;否则返回 `false`。 + +## 示例 {#examples} + +```sql +-- Indicates division by zero, hence an error +SELECT IS_ERROR(1/0), IS_NOT_ERROR(1/0); + +┌───────────────────────────────────────────┐ +│ is_error((1 / 0)) │ is_not_error((1 / 0)) │ +├───────────────────┼───────────────────────┤ +│ true │ false │ +└───────────────────────────────────────────┘ + +-- The conversion to DATE is successful, hence not an error +SELECT IS_ERROR('2024-03-17'::DATE), IS_NOT_ERROR('2024-03-17'::DATE); + +┌─────────────────────────────────────────────────────────────────┐ +│ is_error('2024-03-17'::date) │ is_not_error('2024-03-17'::date) │ +├──────────────────────────────┼──────────────────────────────────┤ +│ false │ true │ +└─────────────────────────────────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/is-float.md b/tidb-cloud-lake/sql/is-float.md new file mode 100644 index 0000000000000..02df286d9a5c2 --- /dev/null +++ b/tidb-cloud-lake/sql/is-float.md @@ -0,0 +1,32 @@ +--- +title: IS_FLOAT +summary: 检查输入的 JSON 值是否为 float。 +--- + +# IS_FLOAT + +检查输入的 JSON 值是否为 float。 + +## 语法 {#syntax} + +```sql +IS_FLOAT( ) +``` + +## 返回类型 {#return-type} + +如果输入的 JSON 值是 float,则返回 `true`;否则返回 `false`。 + +## 示例 {#examples} + +```sql +SELECT + IS_FLOAT(PARSE_JSON('1.23')), + IS_FLOAT(PARSE_JSON('[1,2,3]')); + +┌────────────────────────────────────────────────────────────────┐ +│ is_float(parse_json('1.23')) │ is_float(parse_json('[1,2,3]')) │ +├──────────────────────────────┼─────────────────────────────────┤ +│ true │ false │ +└────────────────────────────────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/is-integer.md b/tidb-cloud-lake/sql/is-integer.md new file mode 100644 index 0000000000000..434f25351028e --- /dev/null +++ b/tidb-cloud-lake/sql/is-integer.md @@ -0,0 +1,32 @@ +--- +title: IS_INTEGER +summary: 检查输入的 JSON 值是否为整数。 +--- + +# IS_INTEGER + +检查输入的 JSON 值是否为整数。 + +## 语法 {#syntax} + +```sql +IS_INTEGER( ) +``` + +## 返回类型 {#return-type} + +如果输入的 JSON 值是整数,则返回 `true`;否则返回 `false`。 + +## 示例 {#examples} + +```sql +SELECT + IS_INTEGER(PARSE_JSON('123')), + IS_INTEGER(PARSE_JSON('[1,2,3]')); + +┌───────────────────────────────────────────────────────────────────┐ +│ is_integer(parse_json('123')) │ is_integer(parse_json('[1,2,3]')) │ +├───────────────────────────────┼───────────────────────────────────┤ +│ true │ false │ +└───────────────────────────────────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/is-not-error.md b/tidb-cloud-lake/sql/is-not-error.md new file mode 100644 index 0000000000000..178715a6b07f8 --- /dev/null +++ b/tidb-cloud-lake/sql/is-not-error.md @@ -0,0 +1,42 @@ +--- +title: IS_NOT_ERROR +summary: 返回一个布尔值,指示表达式是否为错误值。 +--- + +# IS_NOT_ERROR + +返回一个布尔值,指示表达式是否为错误值。 + +另请参阅:[IS_ERROR](/tidb-cloud-lake/sql/is-error.md) + +## 语法 {#syntax} + +```sql +IS_NOT_ERROR( ) +``` + +## 返回类型 {#return-type} + +如果表达式不是错误,则返回 `true`,否则返回 `false`。 + +## 示例 {#examples} + +```sql +-- Indicates division by zero, hence an error +SELECT IS_ERROR(1/0), IS_NOT_ERROR(1/0); + +┌───────────────────────────────────────────┐ +│ is_error((1 / 0)) │ is_not_error((1 / 0)) │ +├───────────────────┼───────────────────────┤ +│ true │ false │ +└───────────────────────────────────────────┘ + +-- The conversion to DATE is successful, hence not an error +SELECT IS_ERROR('2024-03-17'::DATE), IS_NOT_ERROR('2024-03-17'::DATE); + +┌─────────────────────────────────────────────────────────────────┐ +│ is_error('2024-03-17'::date) │ is_not_error('2024-03-17'::date) │ +├──────────────────────────────┼──────────────────────────────────┤ +│ false │ true │ +└─────────────────────────────────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/is-not-null.md b/tidb-cloud-lake/sql/is-not-null.md new file mode 100644 index 0000000000000..83eeffd98a57a --- /dev/null +++ b/tidb-cloud-lake/sql/is-not-null.md @@ -0,0 +1,26 @@ +--- +title: IS_NOT_NULL +summary: 检查一个值是否不是 NULL。 +--- + +# IS_NOT_NULL + +检查一个值是否不是 NULL。 + +## 语法 {#syntax} + +```sql +IS_NOT_NULL() +``` + +## 示例 {#examples} + +```sql +SELECT IS_NOT_NULL(1); + +┌────────────────┐ +│ is_not_null(1) │ +├────────────────┤ +│ true │ +└────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/is-null-value.md b/tidb-cloud-lake/sql/is-null-value.md new file mode 100644 index 0000000000000..dfbee559dab2e --- /dev/null +++ b/tidb-cloud-lake/sql/is-null-value.md @@ -0,0 +1,39 @@ +--- +title: IS_NULL_VALUE +summary: 检查输入值是否为 JSON `null`。请注意,此函数检查的是 JSON `null`,而不是 SQL NULL。要检查某个值是否为 SQL NULL,请使用 IS_NULL。 +--- + +# IS_NULL_VALUE + +检查输入值是否为 JSON `null`。请注意,此函数检查的是 JSON `null`,而不是 SQL NULL。要检查某个值是否为 SQL NULL,请使用 [IS_NULL](/tidb-cloud-lake/sql/is-null.md)。 + +```json title='JSON null Example:' +{ + "name": "John", + "age": null +} +``` + +## 语法 {#syntax} + +```sql +IS_NULL_VALUE( ) +``` + +## 返回类型 {#return-type} + +如果输入值是 JSON `null`,则返回 `true`;否则返回 `false`。 + +## 示例 {#examples} + +```sql +SELECT + IS_NULL_VALUE(PARSE_JSON('{"name":"John", "age":null}') :age), --JSON null + IS_NULL(NULL); --SQL NULL + +┌──────────────────────────────────────────────────────────────────────────────┐ +│ is_null_value(parse_json('{"name":"john", "age":null}'):age) │ is_null(null) │ +├──────────────────────────────────────────────────────────────┼───────────────┤ +│ true │ true │ +└──────────────────────────────────────────────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/is-null.md b/tidb-cloud-lake/sql/is-null.md new file mode 100644 index 0000000000000..e85e926cc5de1 --- /dev/null +++ b/tidb-cloud-lake/sql/is-null.md @@ -0,0 +1,26 @@ +--- +title: IS_NULL +summary: 检查一个值是否为 NULL。 +--- + +# IS_NULL + +检查一个值是否为 NULL。 + +## 语法 {#syntax} + +```sql +IS_NULL() +``` + +## 示例 {#examples} + +```sql +SELECT IS_NULL(1); + +┌────────────┐ +│ is_null(1) │ +├────────────┤ +│ false │ +└────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/is-object.md b/tidb-cloud-lake/sql/is-object.md new file mode 100644 index 0000000000000..5ce19ca4b904f --- /dev/null +++ b/tidb-cloud-lake/sql/is-object.md @@ -0,0 +1,32 @@ +--- +title: IS_OBJECT +summary: 检查输入值是否为 JSON 对象。 +--- + +# IS_OBJECT + +检查输入值是否为 JSON 对象。 + +## 语法 {#syntax} + +```sql +IS_OBJECT( ) +``` + +## 返回类型 {#return-type} + +如果输入的 JSON 值是 JSON 对象,则返回 `true`;否则返回 `false`。 + +## 示例 {#examples} + +```sql +SELECT + IS_OBJECT(PARSE_JSON('{"a":"b"}')), -- JSON Object + IS_OBJECT(PARSE_JSON('["a","b","c"]')); --JSON Array + +┌─────────────────────────────────────────────────────────────────────────────┐ +│ is_object(parse_json('{"a":"b"}')) │ is_object(parse_json('["a","b","c"]')) │ +├────────────────────────────────────┼────────────────────────────────────────┤ +│ true │ false │ +└─────────────────────────────────────────────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/is-string.md b/tidb-cloud-lake/sql/is-string.md new file mode 100644 index 0000000000000..dfa4f33cf9ca8 --- /dev/null +++ b/tidb-cloud-lake/sql/is-string.md @@ -0,0 +1,32 @@ +--- +title: IS_STRING +summary: 检查输入的 JSON 值是否为字符串。 +--- + +# IS_STRING + +检查输入的 JSON 值是否为字符串。 + +## 语法 {#syntax} + +```sql +IS_STRING( ) +``` + +## 返回类型 {#return-type} + +如果输入的 JSON 值是字符串,则返回 `true`;否则返回 `false`。 + +## 示例 {#examples} + +```sql +SELECT + IS_STRING(PARSE_JSON('"abc"')), + IS_STRING(PARSE_JSON('123')); + +┌───────────────────────────────────────────────────────────────┐ +│ is_string(parse_json('"abc"')) │ is_string(parse_json('123')) │ +├────────────────────────────────┼──────────────────────────────┤ +│ true │ false │ +└───────────────────────────────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/jaro-winkler.md b/tidb-cloud-lake/sql/jaro-winkler.md new file mode 100644 index 0000000000000..e5b06ec227572 --- /dev/null +++ b/tidb-cloud-lake/sql/jaro-winkler.md @@ -0,0 +1,75 @@ +--- +title: JARO_WINKLER +summary: 计算两个字符串之间的 Jaro-Winkler 距离。它通常用于衡量字符串之间的相似度,取值范围为 0.0(完全不相似)到 1.0(字符串完全相同)。 +--- + +# JARO_WINKLER + +计算两个字符串之间的 [Jaro-Winkler 距离](https://en.wikipedia.org/wiki/Jaro%E2%80%93Winkler_distance)。它通常用于衡量字符串之间的相似度,取值范围为 0.0(完全不相似)到 1.0(字符串完全相同)。 + +## 语法 {#syntax} + +```sql +JARO_WINKLER(, ) +``` + +## 返回类型 {#return-type} + +`JARO_WINKLER` 函数返回一个 `FLOAT64` 值,用于表示两个输入字符串之间的相似度。返回值遵循以下规则: + +- 相似度范围:结果范围为 0.0(完全不相似)到 1.0(完全相同)。 + + ```sql title='Examples:' + SELECT JARO_WINKLER('datalake', 'Datalake') AS similarity; + + ┌────────────────────┐ + │ similarity │ + ├────────────────────┤ + │ 0.9166666666666666 │ + └────────────────────┘ + + SELECT JARO_WINKLER('datalake', 'database') AS similarity; + + ┌────────────┐ + │ similarity │ + ├────────────┤ + │ 0.9 │ + └────────────┘ + ``` + +- NULL 处理:如果 `string1` 或 `string2` 任一为 NULL,则结果为 NULL。 + + ```sql title='Examples:' + SELECT JARO_WINKLER('datalake', NULL) AS similarity; + + ┌────────────┐ + │ similarity │ + ├────────────┤ + │ NULL │ + └────────────┘ + ``` + +- 空字符串: + - 比较两个空字符串时,返回 1.0。 + + ```sql title='Examples:' + SELECT JARO_WINKLER('', '') AS similarity; + + ┌────────────┐ + │ similarity │ + ├────────────┤ + │ 1 │ + └────────────┘ + ``` + + - 将空字符串与非空字符串进行比较时,返回 0.0。 + + ```sql title='Examples:' + SELECT JARO_WINKLER('datalake', '') AS similarity; + + ┌────────────┐ + │ similarity │ + ├────────────┤ + │ 0 │ + └────────────┘ + ``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/join.md b/tidb-cloud-lake/sql/join.md new file mode 100644 index 0000000000000..4e969ac58d312 --- /dev/null +++ b/tidb-cloud-lake/sql/join.md @@ -0,0 +1,924 @@ +--- +title: JOIN +summary: 连接将两个或多个表中的列组合成一个结果集。{{{ .lake }}} 同时实现了 ANSI SQL 连接和 Lake 特有扩展,使你能够使用相同的语法处理维度数据、缓慢变化的事实数据以及时间序列流。 +--- + +# JOIN + +## 概述 {#overview} + +连接将两个或多个表中的列组合成一个结果集。{{{ .lake }}} 同时实现了 ANSI SQL 连接和 Lake 特有扩展,使你能够使用相同的语法处理维度数据、缓慢变化的事实数据以及时间序列流。 + +## 支持的连接类型 {#supported-join-types} + +* [Inner Join](#inner-join) +* [自然连接](#natural-join) +* [交叉连接](#cross-join) +* [左连接](#left-join) +* [右连接](#right-join) +* [全外连接](#full-outer-join) +* [左 / 右半连接](#left--right-semi-join) +* [左 / 右反连接](#left--right-anti-join) +* [Asof Join](#asof-join) + +## 示例数据 {#sample-data} + +### 准备表 {#prepare-the-tables} + +运行以下 SQL 一次,以创建并填充本页中会反复使用的表: + +```sql +-- VIP profile tables +CREATE OR REPLACE TABLE vip_info (client_id INT, region VARCHAR); +INSERT INTO vip_info VALUES + (101, 'Toronto'), + (102, 'Quebec'), + (103, 'Vancouver'); + +CREATE OR REPLACE TABLE purchase_records (client_id INT, item VARCHAR, qty INT); +INSERT INTO purchase_records VALUES + (100, 'Croissant', 2000), + (102, 'Donut', 3000), + (103, 'Coffee', 6000), + (106, 'Soda', 4000); + +CREATE OR REPLACE TABLE gift (gift VARCHAR); +INSERT INTO gift VALUES + ('Croissant'), ('Donut'), ('Coffee'), ('Soda'); + +-- IoT-style readings for ASOF examples +CREATE OR REPLACE TABLE sensor_readings ( + room VARCHAR, + reading_time TIMESTAMP, + temperature DOUBLE +); +INSERT INTO sensor_readings VALUES + ('LivingRoom', '2024-01-01 09:55:00', 22.8), + ('LivingRoom', '2024-01-01 10:00:00', 23.1), + ('LivingRoom', '2024-01-01 10:05:00', 23.3), + ('LivingRoom', '2024-01-01 10:10:00', 23.8), + ('LivingRoom', '2024-01-01 10:15:00', 24.0); + +CREATE OR REPLACE TABLE hvac_mode ( + room VARCHAR, + mode_time TIMESTAMP, + mode VARCHAR +); +INSERT INTO hvac_mode VALUES + ('LivingRoom', '2024-01-01 09:58:00', 'Cooling'), + ('LivingRoom', '2024-01-01 10:06:00', 'Fan'), + ('LivingRoom', '2024-01-01 10:30:00', 'Heating'); +``` + +### 预览数据 {#preview-the-data} + +除非另有说明,下面的示例都会复用相同的表,以便你可以直接比较每种连接类型的效果。 + +```text +vip_info ++-----------+-----------+ +| client_id | region | ++-----------+-----------+ +| 101 | Toronto | +| 102 | Quebec | +| 103 | Vancouver | ++-----------+-----------+ + +purchase_records ++-----------+-----------+------+ +| client_id | item | qty | ++-----------+-----------+------+ +| 100 | Croissant | 2000 | +| 102 | Donut | 3000 | +| 103 | Coffee | 6000 | +| 106 | Soda | 4000 | ++-----------+-----------+------+ + +gift ++-----------+ +| gift | ++-----------+ +| Croissant | +| Donut | +| Coffee | +| Soda | ++-----------+ +``` + +```text +sensor_readings ++-----------+---------------------+-------------+ +| room | reading_time | temperature | ++-----------+---------------------+-------------+ +| LivingRoom| 2024-01-01 09:55:00 | 22.8 | +| LivingRoom| 2024-01-01 10:00:00 | 23.1 | +| LivingRoom| 2024-01-01 10:05:00 | 23.3 | +| LivingRoom| 2024-01-01 10:10:00 | 23.8 | +| LivingRoom| 2024-01-01 10:15:00 | 24.0 | ++-----------+---------------------+-------------+ + +hvac_mode ++-----------+---------------------+----------+ +| room | mode_time | mode | ++-----------+---------------------+----------+ +| LivingRoom| 2024-01-01 09:58:00 | Cooling | +| LivingRoom| 2024-01-01 10:06:00 | Fan | +| LivingRoom| 2024-01-01 10:30:00 | Heating | ++-----------+---------------------+----------+ +``` + +## Inner Join {#inner-join} + +内连接返回满足所有连接谓词的行。 + +### 可视化 {#visual} + +```text +┌──────────────────────────────┐ +│ vip_info (left) │ +├──────────────────────────────┤ +│ client_id | region │ +│ 101 | Toronto │ +│ 102 | Quebec │ +│ 103 | Vancouver │ +└──────────────────────────────┘ + │ client_id = client_id + ▼ +┌──────────────────────────────┐ +│ purchase_records (right) │ +├──────────────────────────────┤ +│ client_id | item | qty │ +│ 100 | Croissant | 2000 │ +│ 102 | Donut | 3000 │ +│ 103 | Coffee | 6000 │ +│ 106 | Soda | 4000 │ +└──────────────────────────────┘ + │ 仅保留匹配行 + ▼ +┌──────────────────────────────┐ +│ INNER JOIN RESULT │ +├──────────────────────────────┤ +│ 102 | Donut | 3000 │ +│ 103 | Coffee | 6000 │ +└──────────────────────────────┘ +``` + +### 语法 {#syntax} + +```sql +SELECT select_list +FROM table_a + [INNER] JOIN table_b + ON join_condition +``` + +> **Tip:** +> +> `INNER` 是可选的。当连接列具有相同名称时,可以使用 `USING(column_name)` 替代 `ON table_a.column = table_b.column`。 + +### 示例 {#example} + +```sql +SELECT p.client_id, p.item, p.qty +FROM vip_info AS v +INNER JOIN purchase_records AS p + ON v.client_id = p.client_id; +``` + +结果: + +```text ++-----------+--------+------+ +| client_id | item | qty | ++-----------+--------+------+ +| 102 | Donut | 3000 | +| 103 | Coffee | 6000 | ++-----------+--------+------+ +``` + +## 自然连接 {#natural-join} + +自然连接会自动匹配两个表中名称相同的列。结果中每个匹配列只会出现一份。 + +### 图示 {#visual} + +```text +┌──────────────────────────────┐ +│ vip_info │ +├──────────────────────────────┤ +│ client_id | region │ +│ 101 | Toronto │ +│ 102 | Quebec │ +│ 103 | Vancouver │ +└──────────────────────────────┘ + │ 自动匹配共享的列名 + ▼ +┌──────────────────────────────┐ +│ purchase_records │ +├──────────────────────────────┤ +│ client_id | item | qty │ +│ 100 | Croissant | 2000 │ +│ 102 | Donut | 3000 │ +│ 103 | Coffee | 6000 │ +│ 106 | Soda | 4000 │ +└──────────────────────────────┘ + │ 共享列只输出一次 + ▼ +┌──────────────────────────────┐ +│ NATURAL JOIN RESULT │ +├──────────────────────────────┤ +│ 102: Quebec + Donut + 3000 │ +│ 103: Vanc. + Coffee + 6000 │ +└──────────────────────────────┘ +``` + +### 语法 {#syntax} + +```sql +SELECT select_list +FROM table_a +NATURAL JOIN table_b; +``` + +### 示例 {#example} + +```sql +SELECT client_id, item, qty +FROM vip_info +NATURAL JOIN purchase_records; +``` + +结果: + +```text ++-----------+--------+------+ +| client_id | item | qty | ++-----------+--------+------+ +| 102 | Donut | 3000 | +| 103 | Coffee | 6000 | ++-----------+--------+------+ +``` + +## 交叉连接 {#cross-join} + +交叉连接(笛卡尔积)会返回参与连接的表中所有行的每一种组合。 + +### 图示 {#visual} + +```text +┌──────────────────────────────┐ +│ vip_info (3 行) │ +├──────────────────────────────┤ +│ 101 | Toronto │ +│ 102 | Quebec │ +│ 103 | Vancouver │ +└──────────────────────────────┘ + │ 与每个 gift 配对 + ▼ +┌──────────────────────────────┐ +│ gift (4 行) │ +├──────────────────────────────┤ +│ Croissant │ +│ Donut │ +│ Coffee │ +│ Soda │ +└──────────────────────────────┘ + │ 3 × 4 种组合 + ▼ +┌──────────────────────────────┐ +│ CROSS JOIN RESULT (示例) │ +├──────────────────────────────┤ +│ 101 | Toronto | Croissant │ +│ 101 | Toronto | Donut │ +│ 101 | Toronto | Coffee │ +│ ... | ... | ... │ +└──────────────────────────────┘ +``` + +### 语法 {#syntax} + +```sql +SELECT select_list +FROM table_a +CROSS JOIN table_b; +``` + +### 示例 {#example} + +```sql +SELECT v.client_id, v.region, g.gift +FROM vip_info AS v +CROSS JOIN gift AS g; +``` + +结果(前几行): + +```text ++-----------+----------+-----------+ +| client_id | region | gift | ++-----------+----------+-----------+ +| 101 | Toronto | Croissant | +| 101 | Toronto | Donut | +| 101 | Toronto | Coffee | +| 101 | Toronto | Soda | +| ... | ... | ... | ++-----------+----------+-----------+ +``` + +## 左连接 {#left-join} + +左连接会返回左表中的每一行,以及右表中与之匹配的行。如果不存在匹配项,则右侧列为 `NULL`。 + +### 图示 {#visual} + +```text +┌──────────────────────────────┐ +│ vip_info (保留左表全部行) │ +├──────────────────────────────┤ +│ 101 | Toronto │ +│ 102 | Quebec │ +│ 103 | Vancouver │ +└──────────────────────────────┘ + │ 基于 client_id 连接 + ▼ +┌──────────────────────────────┐ +│ purchase_records │ +├──────────────────────────────┤ +│ 100 | Croissant | 2000 │ +│ 102 | Donut | 3000 │ +│ 103 | Coffee | 6000 │ +│ 106 | Soda | 4000 │ +└──────────────────────────────┘ + │ 右表中未匹配的列 -> NULL + ▼ +┌──────────────────────────────┐ +│ LEFT JOIN RESULT │ +├──────────────────────────────┤ +│ 101 | Toronto | NULL | NULL │ +│ 102 | Quebec | Donut | 3000 │ +│ 103 | Vanc. | Coffee | 6000│ +└──────────────────────────────┘ +``` + +### 语法 {#syntax} + +```sql +SELECT select_list +FROM table_a +LEFT [OUTER] JOIN table_b + ON join_condition; +``` + +> **提示:** +> +> `OUTER` 是可选的。 + +### 示例 {#example} + +```sql +SELECT v.client_id, p.item, p.qty +FROM vip_info AS v +LEFT JOIN purchase_records AS p + ON v.client_id = p.client_id; +``` + +结果: + +```text ++-----------+--------+------+ +| client_id | item | qty | ++-----------+--------+------+ +| 101 | NULL | NULL | +| 102 | Donut | 3000 | +| 103 | Coffee | 6000 | ++-----------+--------+------+ +``` + +## 右连接 {#right-join} + +右连接与左连接相对应:右表中的所有行都会出现,而左表中未匹配的行会产生 `NULL`。 + +### 图示 {#visual} + +```text +┌──────────────────────────────┐ +│ purchase_records (right) │ +├──────────────────────────────┤ +│ 100 | Croissant | 2000 │ +│ 102 | Donut | 3000 │ +│ 103 | Coffee | 6000 │ +│ 106 | Soda | 4000 │ +└──────────────────────────────┘ + ▲ 保留右表 + │ 按 client_id 连接 +┌──────────────────────────────┐ +│ vip_info │ +├──────────────────────────────┤ +│ 101 | Toronto │ +│ 102 | Quebec │ +│ 103 | Vancouver │ +└──────────────────────────────┘ + ▼ 缺失的 VIP 数据用 NULL 填充 +┌──────────────────────────────┐ +│ RIGHT JOIN RESULT │ +├──────────────────────────────┤ +│ 100 | Croissant | vip=NULL │ +│ 102 | Donut | region=Quebec │ +│ 103 | Coffee | region=Vanc. │ +│ 106 | Soda | vip=NULL │ +└──────────────────────────────┘ +``` + +### 语法 {#syntax} + +```sql +SELECT select_list +FROM table_a +RIGHT [OUTER] JOIN table_b + ON join_condition; +``` + +### 示例 {#example} + +```sql +SELECT v.client_id, v.region +FROM vip_info AS v +RIGHT JOIN purchase_records AS p + ON v.client_id = p.client_id; +``` + +结果: + +```text ++-----------+-----------+ +| client_id | region | ++-----------+-----------+ +| NULL | NULL | +| 102 | Quebec | +| 103 | Vancouver | +| NULL | NULL | ++-----------+-----------+ +``` + +## 全外连接 {#full-outer-join} + +全外连接返回左连接和右连接的联合体:两张表中的每一行都会返回,在没有匹配时用 `NULL` 填充。 + +### 图示 {#visual} + +```text +┌──────────────────────────────┐ +│ vip_info │ +├──────────────────────────────┤ +│ 101 | Toronto │ +│ 102 | Quebec │ +│ 103 | Vancouver │ +└──────────────────────────────┘ +┌──────────────────────────────┐ +│ purchase_records │ +├──────────────────────────────┤ +│ 100 | Croissant | 2000 │ +│ 102 | Donut | 3000 │ +│ 103 | Coffee | 6000 │ +│ 106 | Soda | 4000 │ +└──────────────────────────────┘ + │ 合并匹配行 + 仅左侧行 + 仅右侧行 + ▼ +┌──────────────────────────────┐ +│ FULL OUTER JOIN RESULT │ +├──────────────────────────────┤ +│ Toronto | NULL │ +│ Quebec | Donut │ +│ Vanc. | Coffee │ +│ NULL | Croissant │ +│ NULL | Soda │ +└──────────────────────────────┘ +``` + +### 语法 {#syntax} + +```sql +SELECT select_list +FROM table_a +FULL [OUTER] JOIN table_b + ON join_condition; +``` + +### 示例 {#example} + +```sql +SELECT v.region, p.item +FROM vip_info AS v +FULL OUTER JOIN purchase_records AS p + ON v.client_id = p.client_id; +``` + +结果: + +```text ++-----------+-----------+ +| region | item | ++-----------+-----------+ +| Toronto | NULL | +| Quebec | Donut | +| Vancouver | Coffee | +| NULL | Croissant | +| NULL | Soda | ++-----------+-----------+ +``` + +## 左 / 右半连接 {#left-right-semi-join} + +半连接会将左表(或右表)过滤为在另一张表中至少有一条匹配记录的行。与内连接不同,半连接只返回被保留一侧的列。 + +### 图示 {#visual} + +```text +LEFT SEMI JOIN +┌──────────────────────────────┐ +│ vip_info │ +├──────────────────────────────┤ +│ 101 | Toronto │ +│ 102 | Quebec │ +│ 103 | Vancouver │ +└──────────────────────────────┘ + │ 保留能找到匹配的行 + ▼ +┌──────────────────────────────┐ +│ purchase_records │ +├──────────────────────────────┤ +│ 100 | Croissant | 2000 │ +│ 102 | Donut | 3000 │ +│ 103 | Coffee | 6000 │ +│ 106 | Soda | 4000 │ +└──────────────────────────────┘ + ▼ +┌──────────────────────────────┐ +│ LEFT SEMI RESULT │ +├──────────────────────────────┤ +│ 102 | Quebec │ +│ 103 | Vanc. │ +└──────────────────────────────┘ + +RIGHT SEMI JOIN +┌──────────────────────────────┐ +│ purchase_records │ +├──────────────────────────────┤ +│ 100 | Croissant | 2000 │ +│ 102 | Donut | 3000 │ +│ 103 | Coffee | 6000 │ +│ 106 | Soda | 4000 │ +└──────────────────────────────┘ + │ 保留与 VIP 匹配的行 + ▼ +┌──────────────────────────────┐ +│ vip_info │ +├──────────────────────────────┤ +│ 101 | Toronto │ +│ 102 | Quebec │ +│ 103 | Vancouver │ +└──────────────────────────────┘ + ▼ +┌──────────────────────────────┐ +│ RIGHT SEMI RESULT │ +├──────────────────────────────┤ +│ 102 | Donut | 3000 │ +│ 103 | Coffee | 6000 │ +└──────────────────────────────┘ +``` + +### 语法 {#syntax} + +```sql +-- Left Semi Join +SELECT select_list +FROM table_a +LEFT SEMI JOIN table_b + ON join_condition; + +-- Right Semi Join +SELECT select_list +FROM table_a +RIGHT SEMI JOIN table_b + ON join_condition; +``` + +### 示例 {#examples} + +左半连接——返回有购买记录的 VIP 客户端: + +```sql +SELECT * +FROM vip_info +LEFT SEMI JOIN purchase_records + ON vip_info.client_id = purchase_records.client_id; +``` + +结果: + +```text ++-----------+-----------+ +| client_id | region | ++-----------+-----------+ +| 102 | Quebec | +| 103 | Vancouver | ++-----------+-----------+ +``` + +右半连接——返回属于 VIP 客户端的购买记录行: + +```sql +SELECT * +FROM vip_info +RIGHT SEMI JOIN purchase_records + ON vip_info.client_id = purchase_records.client_id; +``` + +结果: + +```text ++-----------+--------+------+ +| client_id | item | qty | ++-----------+--------+------+ +| 102 | Donut | 3000 | +| 103 | Coffee | 6000 | ++-----------+--------+------+ +``` + +## Left / Right Anti Join {#left-right-anti-join} + +反连接会返回在另一侧**没有**匹配行的记录,因此非常适合用于存在性检查。 + +### 图示 {#visual} + +```text +LEFT ANTI JOIN +┌──────────────────────────────┐ +│ vip_info │ +├──────────────────────────────┤ +│ 101 | Toronto │ +│ 102 | Quebec │ +│ 103 | Vancouver │ +└──────────────────────────────┘ + │ remove rows with matches + ▼ +┌──────────────────────────────┐ +│ purchase_records │ +├──────────────────────────────┤ +│ 100 | Croissant | 2000 │ +│ 102 | Donut | 3000 │ +│ 103 | Coffee | 6000 │ +│ 106 | Soda | 4000 │ +└──────────────────────────────┘ + ▼ +┌──────────────────────────────┐ +│ LEFT ANTI RESULT │ +├──────────────────────────────┤ +│ 101 | Toronto │ +└──────────────────────────────┘ + +RIGHT ANTI JOIN +┌──────────────────────────────┐ +│ purchase_records │ +├──────────────────────────────┤ +│ 100 | Croissant | 2000 │ +│ 102 | Donut | 3000 │ +│ 103 | Coffee | 6000 │ +│ 106 | Soda | 4000 │ +└──────────────────────────────┘ + │ remove rows with VIP matches + ▼ +┌──────────────────────────────┐ +│ vip_info │ +├──────────────────────────────┤ +│ 101 | Toronto │ +│ 102 | Quebec │ +│ 103 | Vancouver │ +└──────────────────────────────┘ + ▼ +┌──────────────────────────────┐ +│ RIGHT ANTI RESULT │ +├──────────────────────────────┤ +│ 100 | Croissant | 2000 │ +│ 106 | Soda | 4000 │ +└──────────────────────────────┘ +``` + +### 语法 {#syntax} + +```sql +-- Left Anti Join +SELECT select_list +FROM table_a +LEFT ANTI JOIN table_b + ON join_condition; + +-- Right Anti Join +SELECT select_list +FROM table_a +RIGHT ANTI JOIN table_b + ON join_condition; +``` + +### 示例 {#examples} + +左反连接——没有购买记录的 VIP 客户端: + +```sql +SELECT * +FROM vip_info +LEFT ANTI JOIN purchase_records + ON vip_info.client_id = purchase_records.client_id; +``` + +结果: + +```text ++-----------+---------+ +| client_id | region | ++-----------+---------+ +| 101 | Toronto | ++-----------+---------+ +``` + +右反连接——不属于 VIP 客户端的购买记录: + +```sql +SELECT * +FROM vip_info +RIGHT ANTI JOIN purchase_records + ON vip_info.client_id = purchase_records.client_id; +``` + +结果: + +```text ++-----------+-----------+------+ +| client_id | item | qty | ++-----------+-----------+------+ +| 100 | Croissant | 2000 | +| 106 | Soda | 4000 | ++-----------+-----------+------+ +``` + +## Asof Join {#asof-join} + +ASOF(Approximate Sort-Merge)连接会将左侧有序流中的每一行,与右侧时间戳**小于或等于**左侧时间戳的最近一行进行匹配。可选的等值谓词(例如 `symbol` 这样的键)还可以进一步限制匹配范围。ASOF 连接常用于分析场景,例如为每笔交易附加最新的报价。 + +可以将 ASOF 理解为:“给我在这个事件**发生之前或发生当时**的最新上下文行。” + +### 匹配规则 {#matching-rules} + +1. 按等值键(例如 `symbol`)对两个表进行分区。 +2. 在每个分区内,确保两个表都按不等式列(例如 `time`)进行排序。 +3. 访问左表某一行时,附加右表中时间戳 `<=` 左侧时间戳的最新一行;如果不存在,则右侧列为 `NULL`。 + +### 快速示例(室温 vs HVAC 模式) {#quick-example-room-temperature-vs-hvac-mode} + +```text +┌──────────────────────────────┐ +│ sensor_readings(左表) │ +├──────────────────────────────┤ +│ room | time | temperature │ +│ LR | 09:55 | 22.8C │ +│ LR | 10:00 | 23.1C │ +│ LR | 10:05 | 23.3C │ +│ LR | 10:10 | 23.8C │ +│ LR | 10:15 | 24.0C │ +└──────────────────────────────┘ + +┌──────────────────────────────┐ +│ hvac_mode(右表) │ +├──────────────────────────────┤ +│ room | time | mode │ +│ LR | 09:58 | Cooling │ +│ LR | 10:06 | Fan │ +│ LR | 10:30 | Heating │ +└──────────────────────────────┘ + +┌────────────────────────────────────────────────────────────┐ +│ ASOF JOIN ON r.room = m.room 的结果 │ +│ AND r.reading_time >= m.mode_time │ +├────────────────────────────────────────────────────────────┤ +│ 10:00 的读数 -> 匹配 09:58 的模式(最新且 <= 10:00) │ +│ 10:05 的读数 -> 仍匹配 09:58(还没有更新的模式) │ +│ 10:10 的读数 -> 匹配 10:06 的模式 │ +│ 10:15 的读数 -> 匹配 10:06 的模式 │ +│ 09:55 的读数 -> 无行(ASOF 的行为类似 INNER JOIN) │ +└────────────────────────────────────────────────────────────┘ +``` + +在 LEFT ASOF join 中,每条传感器读数都会被保留(例如,09:55 的读数会保留 `NULL`,因为此时还没有任何 HVAC 模式开始)。在 RIGHT ASOF join 中,会保留所有 HVAC 变更(即使此时还没有任何读数可以引用它们)。 + +### 语法 {#syntax} + +```sql +SELECT select_list +FROM table_a +ASOF [LEFT | RIGHT] JOIN table_b + ON table_a.time >= table_b.time + [AND table_a.key = table_b.key]; +``` + +### 示例表 {#example-tables} + +运行以下语句一次,以重现下面展示的 HVAC 场景: + +```sql +CREATE OR REPLACE TABLE sensor_readings ( + reading_time TIMESTAMP, + temperature DOUBLE +); +INSERT INTO sensor_readings VALUES + ('2024-01-01 10:00:00', 23.1), + ('2024-01-01 10:05:00', 23.3), + ('2024-01-01 10:10:00', 23.8), + ('2024-01-01 10:15:00', 24.0); + +CREATE OR REPLACE TABLE hvac_mode ( + mode_time TIMESTAMP, + mode VARCHAR +); +INSERT INTO hvac_mode VALUES + ('2024-01-01 09:58:00', 'Cooling'), + ('2024-01-01 10:06:00', 'Fan'), + ('2024-01-01 10:30:00', 'Heating'); +``` + +### 示例 {#examples} + +将每条温度读数与它之前开始的最新 HVAC 模式进行匹配: + +```sql +SELECT r.reading_time, r.temperature, m.mode +FROM sensor_readings AS r +ASOF JOIN hvac_mode AS m + ON r.room = m.room + AND r.reading_time >= m.mode_time +ORDER BY r.reading_time; +``` + +结果: + +```text +┌─────────────────────┬─────────────┬────────────┐ +│ reading_time │ temperature │ mode │ +├─────────────────────┼─────────────┼────────────┤ +│ 2024-01-01 10:00:00 │ 23.1C │ Cooling │ +│ 2024-01-01 10:05:00 │ 23.3C │ Cooling │ +│ 2024-01-01 10:10:00 │ 23.8C │ Fan │ +│ 2024-01-01 10:15:00 │ 24.0C │ Fan │ +└─────────────────────┴─────────────┴────────────┘ +``` + +ASOF left join——即使尚未有任何 HVAC 模式处于活动状态,也保留所有传感器读数: + +```sql +SELECT r.reading_time, r.temperature, m.mode +FROM sensor_readings AS r +ASOF LEFT JOIN hvac_mode AS m + ON r.room = m.room + AND r.reading_time >= m.mode_time +ORDER BY r.reading_time; +``` + +结果: + +```text +┌─────────────────────┬─────────────┬────────────┐ +│ reading_time │ temperature │ mode │ +├─────────────────────┼─────────────┼────────────┤ +│ 2024-01-01 09:55:00 │ 22.8C │ NULL │ ← 在第一个 HVAC 模式之前 +│ 2024-01-01 10:00:00 │ 23.1C │ Cooling │ +│ 2024-01-01 10:05:00 │ 23.3C │ Cooling │ +│ 2024-01-01 10:10:00 │ 23.8C │ Fan │ +│ 2024-01-01 10:15:00 │ 24.0C │ Fan │ +└─────────────────────┴─────────────┴────────────┘ +``` + +ASOF right join——即使后续没有任何传感器读数引用它们,也保留所有 HVAC 模式变更: + +```sql +SELECT r.reading_time, r.temperature, m.mode_time, m.mode +FROM sensor_readings AS r +ASOF RIGHT JOIN hvac_mode AS m + ON r.room = m.room + AND r.reading_time >= m.mode_time +ORDER BY m.mode_time, r.reading_time; +``` + +结果: + +```text +┌─────────────────────┬─────────────┬─────────────────────┬────────────┐ +│ reading_time │ temperature │ mode_time │ mode │ +├─────────────────────┼─────────────┼─────────────────────┼────────────┤ +│ 2024-01-01 10:00:00 │ 23.1C │ 2024-01-01 09:58:00 │ Cooling │ +│ 2024-01-01 10:05:00 │ 23.3C │ 2024-01-01 09:58:00 │ Cooling │ +│ 2024-01-01 10:10:00 │ 23.8C │ 2024-01-01 10:06:00 │ Fan │ +│ 2024-01-01 10:15:00 │ 24.0C │ 2024-01-01 10:06:00 │ Fan │ +│ NULL │ NULL │ 2024-01-01 10:30:00 │ Heating │ ← 等待读数 +└─────────────────────┴─────────────┴─────────────────────┴────────────┘ +``` + +多个读数可能落在同一个 HVAC 时间区间内,因此 RIGHT ASOF join 对每个 mode 可能会输出多行;最后一行 `NULL` 表示新调度的 `Heating` 模式尚未匹配到任何读数。 \ No newline at end of file diff --git a/tidb-cloud-lake/sql/jq.md b/tidb-cloud-lake/sql/jq.md new file mode 100644 index 0000000000000..8923cbfbee424 --- /dev/null +++ b/tidb-cloud-lake/sql/jq.md @@ -0,0 +1,93 @@ +--- +title: JQ +summary: JQ 函数是一个返回集合的 SQL 函数,允许你对存储在 Variant 列中的 JSON 数据应用 jq 过滤器。使用此函数,你可以通过应用指定的 jq 过滤器来处理 JSON 数据,并将结果作为一组行返回。 +--- + +# JQ + +JQ 函数是一个返回集合的 SQL 函数,允许你对存储在 Variant 列中的 JSON 数据应用 [jq](https://jqlang.github.io/jq/) 过滤器。使用此函数,你可以通过应用指定的 jq 过滤器来处理 JSON 数据,并将结果作为一组行返回。 + +## 语法 {#syntax} + +```sql +JQ (, ) +``` + +| 参数 | 描述 | +|-----------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `jq_expression` | 一个 `jq` 过滤器表达式,用于定义如何使用 `jq` 语法处理和转换 JSON 数据。该表达式可以指定如何在 JSON 对象和数组中选择、修改和操作数据。有关 jq 支持的语法、过滤器和函数的信息,请参阅 [jq Manual](https://jqlang.github.io/jq/manual/#basic-filters)。 | +| `json_data` | 你希望使用 `jq` 过滤器表达式处理或转换的 JSON 格式输入。它可以是 JSON 对象、数组或任何有效的 JSON 数据结构。 | + +## 返回类型 {#return-type} + +JQ 函数返回一组 JSON 值,其中每个值都对应基于 `` 转换或提取结果中的一个元素。 + +## 示例 {#examples} + +首先,我们创建一个名为 `customer_data` 的表,其中包含 `id` 和 `profile` 两列,`profile` 为 JSON 类型,用于存储用户信息: + +```sql +CREATE TABLE customer_data ( + id INT, + profile JSON +); + +INSERT INTO customer_data VALUES + (1, '{"name": "Alice", "age": 30, "city": "New York"}'), + (2, '{"name": "Bob", "age": 25, "city": "Los Angeles"}'), + (3, '{"name": "Charlie", "age": 35, "city": "Chicago"}'); +``` + +以下示例从 JSON 数据中提取特定字段: + +```sql +SELECT + id, + jq('.name', profile) AS customer_name +FROM + customer_data; + +┌─────────────────────────────────────┐ +│ id │ customer_name │ +├─────────────────┼───────────────────┤ +│ 1 │ "Alice" │ +│ 2 │ "Bob" │ +│ 3 │ "Charlie" │ +└─────────────────────────────────────┘ +``` + +以下示例为每个用户选择用户 ID 以及加 1 后的年龄: + +```sql +SELECT + id, + jq('.age + 1', profile) AS updated_age +FROM + customer_data; + +┌─────────────────────────────────────┐ +│ id │ updated_age │ +├─────────────────┼───────────────────┤ +│ 1 │ 31 │ +│ 2 │ 26 │ +│ 3 │ 36 │ +└─────────────────────────────────────┘ +``` + +以下示例将城市名称转换为大写: + +```sql +SELECT + id, + jq('.city | ascii_upcase', profile) AS city_uppercase +FROM + customer_data; + +┌─────────────────────────────────────┐ +│ id │ city_uppercase │ +├─────────────────┼───────────────────┤ +│ 1 │ "NEW YORK" │ +│ 2 │ "LOS ANGELES" │ +│ 3 │ "CHICAGO" │ +└─────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/json-array-agg.md b/tidb-cloud-lake/sql/json-array-agg.md new file mode 100644 index 0000000000000..436944492a047 --- /dev/null +++ b/tidb-cloud-lake/sql/json-array-agg.md @@ -0,0 +1,55 @@ +--- +title: JSON_ARRAY_AGG +summary: 将值转换为 JSON 数组,同时跳过 NULL。 +--- + +# JSON_ARRAY_AGG + +将值转换为 JSON 数组,同时跳过 NULL。 + +另请参阅:[JSON_OBJECT_AGG](/tidb-cloud-lake/sql/json-object-agg.md) + +## 语法 {#syntax} + +```sql +JSON_ARRAY_AGG() +``` + +## 返回类型 {#return-type} + +JSON 数组。 + +## 示例 {#examples} + +以下示例演示了 JSON_ARRAY_AGG 如何将每一列中的值聚合为 JSON 数组: + +```sql +CREATE TABLE d ( + a DECIMAL(10, 2), + b STRING, + c INT, + d VARIANT, + e ARRAY(STRING) +); + +INSERT INTO d VALUES + (20, 'abc', NULL, '{"k":"v"}', ['a','b']), + (10, 'de', 100, 'null', []), + (4.23, NULL, 200, '"uvw"', ['x','y']), + (5.99, 'xyz', 300, '[1,2,3]', ['z']); + +SELECT + json_array_agg(a) AS aggregated_a, + json_array_agg(b) AS aggregated_b, + json_array_agg(c) AS aggregated_c, + json_array_agg(d) AS aggregated_d, + json_array_agg(e) AS aggregated_e +FROM d; + +-[ RECORD 1 ]----------------------------------- +aggregated_a: [20.0,10.0,4.23,5.99] +aggregated_b: ["abc","de","xyz"] +aggregated_c: [100,200,300] +aggregated_d: [{"k":"v"},null,"uvw",[1,2,3]] +aggregated_e: [["a","b"],[],["x","y"],["z"]] +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/json-array-elements.md b/tidb-cloud-lake/sql/json-array-elements.md new file mode 100644 index 0000000000000..ae04dd6a9d8e8 --- /dev/null +++ b/tidb-cloud-lake/sql/json-array-elements.md @@ -0,0 +1,64 @@ +--- +title: JSON_ARRAY_ELEMENTS +summary: 从 JSON 数组中提取元素,并将其作为结果集中的单独行返回。JSON_ARRAY_ELEMENTS 不会递归展开嵌套数组;它会将嵌套数组视为单个元素。 +--- + +# JSON_ARRAY_ELEMENTS + +从 JSON 数组中提取元素,并将其作为结果集中的单独行返回。JSON_ARRAY_ELEMENTS 不会递归展开嵌套数组;它会将嵌套数组视为单个元素。 + +## 语法 {#syntax} + +```sql +JSON_ARRAY_ELEMENTS() +``` + +## 返回类型 {#return-type} + +JSON_ARRAY_ELEMENTS 返回一组 VARIANT 值,其中每个值都表示从输入 JSON 数组中提取出的一个元素。 + +## 示例 {#examples} + +```sql +-- 从包含产品信息的 JSON 数组中提取各个元素 +SELECT + JSON_ARRAY_ELEMENTS( + PARSE_JSON ( + '[ + {"product": "Laptop", "brand": "Apple", "price": 1500}, + {"product": "Smartphone", "brand": "Samsung", "price": 800}, + {"product": "Headphones", "brand": "Sony", "price": 150} +]' + ) + ); + +┌─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ +│ json_array_elements(parse_json('[ \n {"product": "laptop", "brand": "apple", "price": 1500},\n {"product": "smartphone", "brand": "samsung", "price": 800},\n {"product": "headphones", "brand": "sony", "price": 150}\n]')) │ +├─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤ +│ {"brand":"Apple","price":1500,"product":"Laptop"} │ +│ {"brand":"Samsung","price":800,"product":"Smartphone"} │ +│ {"brand":"Sony","price":150,"product":"Headphones"} │ +└─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ + +-- 显示提取元素的数据类型 +SELECT + TYPEOF ( + JSON_ARRAY_ELEMENTS( + PARSE_JSON ( + '[ + {"product": "Laptop", "brand": "Apple", "price": 1500}, + {"product": "Smartphone", "brand": "Samsung", "price": 800}, + {"product": "Headphones", "brand": "Sony", "price": 150} +]' + ) + ) + ); + +┌─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ +│ typeof(json_array_elements(parse_json('[ \n {"product": "laptop", "brand": "apple", "price": 1500},\n {"product": "smartphone", "brand": "samsung", "price": 800},\n {"product": "headphones", "brand": "sony", "price": 150}\n]'))) │ +├─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤ +│ VARIANT NULL │ +│ VARIANT NULL │ +│ VARIANT NULL │ +└─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/json-array-transform.md b/tidb-cloud-lake/sql/json-array-transform.md new file mode 100644 index 0000000000000..5319a02944841 --- /dev/null +++ b/tidb-cloud-lake/sql/json-array-transform.md @@ -0,0 +1,32 @@ +--- +title: JSON_ARRAY_TRANSFORM +summary: 使用指定的转换 Lambda 表达式对 JSON 数组中的每个元素进行转换。有关 Lambda 表达式的更多信息,请参见 Lambda Expressions。 +--- + +# JSON_ARRAY_TRANSFORM + +使用指定的转换 Lambda 表达式对 JSON 数组中的每个元素进行转换。有关 Lambda 表达式的更多信息,请参见 [Lambda 表达式](/tidb-cloud-lake/sql/stored-procedure-scripting.md#lambda-expressions)。 + +## 语法 {#syntax} + +```sql +ARRAY_TRANSFORM(, ) +``` + +## 返回类型 {#return-type} + +JSON 数组。 + +## 示例 {#examples} + +在此示例中,数组中的每个数值元素都乘以 10,将原始数组转换为 `[10, 20, 30, 40]`: + +```sql +SELECT ARRAY_TRANSFORM( + [1, 2, 3, 4], + data -> (data::Int * 10) +); + +-[ RECORD 1 ]----------------------------------- +array_transform([1, 2, 3, 4], data -> data::Int32 * 10): [10,20,30,40] +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/json-contains-left.md b/tidb-cloud-lake/sql/json-contains-left.md new file mode 100644 index 0000000000000..5bb198ea90f4b --- /dev/null +++ b/tidb-cloud-lake/sql/json-contains-left.md @@ -0,0 +1,70 @@ +--- +title: JSON_CONTAINS_IN_LEFT +summary: 测试两个 VARIANT 值之间的包含关系。 +--- + +# JSON_CONTAINS_IN_LEFT + +测试两个 `VARIANT` 值之间的包含关系: + +- `JSON_CONTAINS_IN_LEFT(left, right)` 在 *left* 包含 *right* 时返回 `TRUE`(即 *left* 是超集)。 +- `JSON_CONTAINS_IN_RIGHT(left, right)` 在 *right* 包含 *left* 时返回 `TRUE`。 + +包含关系同时适用于 JSON 对象和数组。 + +## 语法 {#syntax} + +```sql +JSON_CONTAINS_IN_LEFT(, ) +JSON_CONTAINS_IN_RIGHT(, ) +``` + +## 返回类型 {#return-type} + +`BOOLEAN` + +## 示例 {#examples} + +```sql +SELECT JSON_CONTAINS_IN_LEFT(PARSE_JSON('{"a":1,"b":{"c":2}}'), + PARSE_JSON('{"b":{"c":2}}')) AS left_contains; + +┌──────────────┐ +│ left_contains│ +├──────────────┤ +│ true │ +└──────────────┘ +``` + +```sql +SELECT JSON_CONTAINS_IN_LEFT(PARSE_JSON('[1,2,3]'), + PARSE_JSON('[2,3]')) AS left_contains; + +┌──────────────┐ +│ left_contains│ +├──────────────┤ +│ true │ +└──────────────┘ +``` + +```sql +SELECT JSON_CONTAINS_IN_LEFT(PARSE_JSON('[1,2]'), + PARSE_JSON('[2,4]')) AS left_contains; + +┌──────────────┐ +│ left_contains│ +├──────────────┤ +│ false │ +└──────────────┘ +``` + +```sql +SELECT JSON_CONTAINS_IN_RIGHT(PARSE_JSON('{"a":1}'), + PARSE_JSON('{"a":1,"b":2}')) AS right_contains; + +┌───────────────┐ +│ right_contains│ +├───────────────┤ +│ true │ +└───────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/json-each.md b/tidb-cloud-lake/sql/json-each.md new file mode 100644 index 0000000000000..70b773fb72e6b --- /dev/null +++ b/tidb-cloud-lake/sql/json-each.md @@ -0,0 +1,58 @@ +--- +title: JSON_EACH +summary: 从 JSON 对象中提取键值对,将其结构拆分为结果集中的单独行。每一行都表示从输入 JSON 表达式派生出的一个不同键值对。 +--- + +# JSON_EACH + +从 JSON 对象中提取键值对,将其结构拆分为结果集中的单独行。每一行都表示从输入 JSON 表达式派生出的一个不同键值对。 + +## 语法 {#syntax} + +```sql +JSON_EACH() +``` + +## 返回类型 {#return-type} + +JSON_EACH 返回一组元组,每个元组由一个 STRING 键和一个对应的 VARIANT 值组成。 + +## 示例 {#examples} + +```sql +-- 从表示人员信息的 JSON 对象中提取键值对 +SELECT + JSON_EACH( + PARSE_JSON ( + '{"name": "John", "age": 25, "isStudent": false, "grades": [90, 85, 92]}' + ) + ); + +┌──────────────────────────────────────────────────────────────────────────────────────────────────┐ +│ json_each(parse_json('{"name": "john", "age": 25, "isstudent": false, "grades": [90, 85, 92]}')) │ +├──────────────────────────────────────────────────────────────────────────────────────────────────┤ +│ ('age','25') │ +│ ('grades','[90,85,92]') │ +│ ('isStudent','false') │ +│ ('name','"John"') │ +└──────────────────────────────────────────────────────────────────────────────────────────────────┘ + +-- 显示提取值的数据类型 +SELECT + TYPEOF ( + JSON_EACH( + PARSE_JSON ( + '{"name": "John", "age": 25, "isStudent": false, "grades": [90, 85, 92]}' + ) + ) + ); + +┌──────────────────────────────────────────────────────────────────────────────────────────────────────────┐ +│ typeof(json_each(parse_json('{"name": "john", "age": 25, "isstudent": false, "grades": [90, 85, 92]}'))) │ +├──────────────────────────────────────────────────────────────────────────────────────────────────────────┤ +│ TUPLE(STRING, VARIANT) NULL │ +│ TUPLE(STRING, VARIANT) NULL │ +│ TUPLE(STRING, VARIANT) NULL │ +│ TUPLE(STRING, VARIANT) NULL │ +└──────────────────────────────────────────────────────────────────────────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/json-exists-key.md b/tidb-cloud-lake/sql/json-exists-key.md new file mode 100644 index 0000000000000..b66aaa7fd288f --- /dev/null +++ b/tidb-cloud-lake/sql/json-exists-key.md @@ -0,0 +1,66 @@ +--- +title: JSON_EXISTS_KEY +summary: 检查 JSON 对象是否包含一个或多个键。 +--- + +# JSON_EXISTS_KEY + +检查 JSON 对象是否包含一个或多个键。 + +- `JSON_EXISTS_KEY` 测试单个键。 +- `JSON_EXISTS_ANY_KEYS` 接受一个键数组,并在至少存在一个键时返回 `TRUE`。 +- `JSON_EXISTS_ALL_KEYS` 仅在数组中的每个键都存在时返回 `TRUE`。 + +## 语法 {#syntax} + +```sql +JSON_EXISTS_KEY(, ) +JSON_EXISTS_ANY_KEYS(, ) +JSON_EXISTS_ALL_KEYS(, ) +``` + +## 返回类型 {#return-type} + +`BOOLEAN` + +## 示例 {#examples} + +```sql +SELECT JSON_EXISTS_KEY(PARSE_JSON('{"a":1,"b":2}'), 'b') AS has_b; + +┌──────┐ +│ has_b│ +├──────┤ +│ true │ +└──────┘ +``` + +```sql +SELECT JSON_EXISTS_ANY_KEYS(PARSE_JSON('{"a":1,"b":2}'), ['x','b']) AS any_key; + +┌────────┐ +│ any_key│ +├────────┤ +│ true │ +└────────┘ +``` + +```sql +SELECT JSON_EXISTS_ALL_KEYS(PARSE_JSON('{"a":1,"b":2}'), ['a','b','c']) AS all_keys; + +┌────────┐ +│ all_keys│ +├────────┤ +│ false │ +└────────┘ +``` + +```sql +SELECT JSON_EXISTS_ALL_KEYS(PARSE_JSON('{"a":1,"b":2}'), ['a','b']) AS all_keys; + +┌────────┐ +│ all_keys│ +├────────┤ +│ true │ +└────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/json-extract-path-text.md b/tidb-cloud-lake/sql/json-extract-path-text.md new file mode 100644 index 0000000000000..e6070c419b535 --- /dev/null +++ b/tidb-cloud-lake/sql/json-extract-path-text.md @@ -0,0 +1,57 @@ +--- +title: JSON_EXTRACT_PATH_TEXT +summary: 按 `path_name` 从 Json 字符串中提取值。如果任一参数为 `NULL`,则返回值为 `String` 或 `NULL`。此函数等价于 `to_varchar(GET_PATH(PARSE_JSON(JSON), PATH_NAME))`。 +--- + +# JSON_EXTRACT_PATH_TEXT + +按 `path_name` 从 Json 字符串中提取值。如果任一参数为 `NULL`,则返回值为 `String` 或 `NULL`。此函数等价于 `to_varchar(GET_PATH(PARSE_JSON(JSON), PATH_NAME))`。 + +## 语法 {#syntax} + +```sql +JSON_EXTRACT_PATH_TEXT( , ) +``` + +## 参数 {#arguments} + +| 参数 | 描述 | +|---------------|------------------------------------------------------------------| +| `` | Json 字符串值 | +| `` | 由多个字段名拼接而成的字符串值 | + +## 返回类型 {#return-type} + +String + +## 示例 {#examples} + +```sql +SELECT json_extract_path_text('{"k1":[0,1,2], "k2":{"k3":3,"k4":4}}', 'k1[0]'); ++-------------------------------------------------------------------------+ +| json_extract_path_text('{"k1":[0,1,2], "k2":{"k3":3,"k4":4}}', 'k1[0]') | ++-------------------------------------------------------------------------+ +| 0 | ++-------------------------------------------------------------------------+ + +SELECT json_extract_path_text('{"k1":[0,1,2], "k2":{"k3":3,"k4":4}}', 'k2:k3'); ++-------------------------------------------------------------------------+ +| json_extract_path_text('{"k1":[0,1,2], "k2":{"k3":3,"k4":4}}', 'k2:k3') | ++-------------------------------------------------------------------------+ +| 3 | ++-------------------------------------------------------------------------+ + +SELECT json_extract_path_text('{"k1":[0,1,2], "k2":{"k3":3,"k4":4}}', 'k2.k4'); ++-------------------------------------------------------------------------+ +| json_extract_path_text('{"k1":[0,1,2], "k2":{"k3":3,"k4":4}}', 'k2.k4') | ++-------------------------------------------------------------------------+ +| 4 | ++-------------------------------------------------------------------------+ + +SELECT json_extract_path_text('{"k1":[0,1,2], "k2":{"k3":3,"k4":4}}', 'k2.k5'); ++-------------------------------------------------------------------------+ +| json_extract_path_text('{"k1":[0,1,2], "k2":{"k3":3,"k4":4}}', 'k2.k5') | ++-------------------------------------------------------------------------+ +| NULL | ++-------------------------------------------------------------------------+ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/json-functions-overview.md b/tidb-cloud-lake/sql/json-functions-overview.md new file mode 100644 index 0000000000000..ed7b63c3e58e6 --- /dev/null +++ b/tidb-cloud-lake/sql/json-functions-overview.md @@ -0,0 +1,67 @@ +--- +title: JSON 函数 +summary: 本节提供 {{{ .lake }}} 中 JSON 函数的参考信息。JSON 函数支持对 JSON 数据结构进行解析、验证、查询和操作。 +--- + +# JSON 函数 + +本节提供 {{{ .lake }}} 中 JSON 函数的参考信息。JSON 函数支持对 JSON 数据结构进行解析、验证、查询和操作。 + +## JSON 解析与验证 {#json-parsing-validation} + +| 函数 | 描述 | 示例 | +|----------|-------------|---------| +| [PARSE_JSON](/tidb-cloud-lake/sql/parse-json.md) | 将 JSON 字符串解析为 variant 值 | `PARSE_JSON('{"name":"John","age":30}')` → `{"name":"John","age":30}` | +| [CHECK_JSON](/tidb-cloud-lake/sql/check-json.md) | 验证一个字符串是否为有效的 JSON | `CHECK_JSON('{"valid": true}')` → `true` | + +## JSON 类型信息 {#json-type-information} + +| 函数 | 描述 | 示例 | +|----------|-------------|---------| +| [JSON_TYPEOF](/tidb-cloud-lake/sql/json-typeof.md) | 返回 JSON 值的类型 | `JSON_TYPEOF('{"key": "value"}')` → `'OBJECT'` | + +## JSON 转换 {#json-conversion} + +| 函数 | 描述 | 示例 | +|----------|-------------|---------| +| [JSON_TO_STRING](/tidb-cloud-lake/sql/json-to-string.md) | 将 JSON 值转换为字符串 | `JSON_TO_STRING({"name":"John"})` → `'{"name":"John"}'` | + +## JSON 路径操作 {#json-path-operations} + +| 函数 | 描述 | 示例 | +|----------|-------------|---------| +| [JSON_PATH_EXISTS](/tidb-cloud-lake/sql/json-path-exists.md) | 检查 JSON 路径是否存在 | `JSON_PATH_EXISTS('{"a":1}', '$.a')` → `true` | +| [JSON_PATH_MATCH](/tidb-cloud-lake/sql/json-path-match.md) | 将 JSON 值与路径模式进行匹配 | `JSON_PATH_MATCH('{"items":[1,2,3]}', '$.items[*]')` → `[1,2,3]` | +| [JSON_PATH_QUERY](/tidb-cloud-lake/sql/json-path-query.md) | 使用 JSONPath 查询 JSON 数据 | `JSON_PATH_QUERY('{"a":1,"b":2}', '$.a')` → `1` | +| [JSON_PATH_QUERY_ARRAY](/tidb-cloud-lake/sql/json-path-query-array.md) | 查询 JSON 数据并以数组形式返回结果 | `JSON_PATH_QUERY_ARRAY('[1,2,3]', '$[*]')` → `[1,2,3]` | +| [JSON_PATH_QUERY_FIRST](/tidb-cloud-lake/sql/json-path-query-first.md) | 返回 JSON 路径查询的第一个结果 | `JSON_PATH_QUERY_FIRST('[1,2,3]', '$[*]')` → `1` | + +## JSON 数据提取 {#json-data-extraction} + +| 函数 | 描述 | 示例 | +|----------|-------------|---------| +| [GET](/tidb-cloud-lake/sql/get.md) | 按索引或字段名从 JSON 中提取值 | `GET('{"name":"John"}', 'name')` → `"John"` | +| [GET_IGNORE_CASE](/tidb-cloud-lake/sql/get-ignore-case.md) | 以不区分大小写的字段匹配方式提取值 | `GET_IGNORE_CASE('{"Name":"John"}', 'name')` → `"John"` | +| [GET_BY_KEYPATH](/tidb-cloud-lake/sql/get-by-keypath.md) | 使用大括号键路径提取嵌套值 | `GET_BY_KEYPATH('{"user":{"name":"Ada"}}', '{user,name}')` → `"Ada"` | +| [GET_PATH](/tidb-cloud-lake/sql/get-path.md) | 使用路径表示法提取值 | `GET_PATH('{"user":{"name":"John"}}', 'user.name')` → `"John"` | +| [JSON_EXTRACT_PATH_TEXT](/tidb-cloud-lake/sql/json-extract-path-text.md) | 使用路径从 JSON 中提取文本值 | `JSON_EXTRACT_PATH_TEXT('{"name":"John"}', 'name')` → `'John'` | +| [JSON_EACH](/tidb-cloud-lake/sql/json-each.md) | 将 JSON 对象展开为键值对 | `JSON_EACH('{"a":1,"b":2}')` → `[("a",1),("b",2)]` | +| [JSON_ARRAY_ELEMENTS](/tidb-cloud-lake/sql/json-array-elements.md) | 将 JSON 数组展开为单独的元素 | `JSON_ARRAY_ELEMENTS('[1,2,3]')` → `1, 2, 3` | +| [JQ](/tidb-cloud-lake/sql/jq.md) | 使用 jq 风格的查询处理 JSON | `JQ('{"name":"John"}', '.name')` → `"John"` | + +## JSON 格式化与处理 {#json-formatting-processing} + +| 函数 | 描述 | 示例 | +|----------|-------------|---------| +| [JSON_PRETTY](/tidb-cloud-lake/sql/json-pretty.md) | 使用适当的缩进格式化 JSON | `JSON_PRETTY('{"a":1}')` → 格式化后的 JSON 字符串 | +| [STRIP_NULL_VALUE](/tidb-cloud-lake/sql/strip-null-value.md) | 从 JSON 中移除空值 | `STRIP_NULL_VALUE('{"a":1,"b":null}')` → `{"a":1}` | +| [JSON_STRIP_NULLS](/tidb-cloud-lake/sql/json-strip-nulls.md) | 从 JSON 对象中移除空值 | `JSON_STRIP_NULLS(PARSE_JSON('{"a":1,"b":null}'))` → `{"a":1}` | + +## JSON 包含与存在性 {#json-containment-existence} + +| 函数 | 描述 | 示例 | +|----------|-------------|---------| +| [JSON_CONTAINS_IN_LEFT](/tidb-cloud-lake/sql/contains.md) | 测试左侧 JSON 是否包含右侧 JSON | `JSON_CONTAINS_IN_LEFT('{"a":1,"b":2}', '{"b":2}')` → `true` | +| [JSON_EXISTS_KEY](/tidb-cloud-lake/sql/json-exists-key.md) | 检查是否存在指定的键 | `JSON_EXISTS_KEY('{"a":1}', 'a')` → `true` | +| [JSON_EXISTS_ANY_KEYS](/tidb-cloud-lake/sql/json-exists-key.md) | 如果列表中的任意键存在,则返回 `true` | `JSON_EXISTS_ANY_KEYS('{"a":1}', ['x','a'])` → `true` | +| [JSON_EXISTS_ALL_KEYS](/tidb-cloud-lake/sql/json-exists-key.md) | 仅当所有键都存在时返回 `true` | `JSON_EXISTS_ALL_KEYS('{"a":1,"b":2}', ['a','b'])` → `true` | \ No newline at end of file diff --git a/tidb-cloud-lake/sql/json-object-agg.md b/tidb-cloud-lake/sql/json-object-agg.md new file mode 100644 index 0000000000000..1c37f3e6fe15e --- /dev/null +++ b/tidb-cloud-lake/sql/json-object-agg.md @@ -0,0 +1,59 @@ +--- +title: JSON_OBJECT_AGG +summary: 将键值对转换为 JSON 对象。对于输入中的每一行,它都会生成一个键值对,其中键派生自 ``,值派生自 ``。然后,这些键值对会合并为一个 JSON 对象。 +--- + +# JSON_OBJECT_AGG + +将键值对转换为 JSON 对象。对于输入中的每一行,它都会生成一个键值对,其中键派生自 ``,值派生自 ``。然后,这些键值对会合并为一个 JSON 对象。 + +另请参阅:[JSON_ARRAY_AGG](/tidb-cloud-lake/sql/json-array-agg.md) + +## 语法 {#syntax} + +```sql +JSON_OBJECT_AGG(, ) +``` + +| 参数 | 描述 | +|------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------| +| key_expression | 指定 JSON 对象中的键。**仅支持字符串** 表达式。如果 `key_expression` 的计算结果为 NULL,则会跳过该键值对。 | +| value_expression | 指定 JSON 对象中的值。它可以是任何受支持的数据类型。如果 `value_expression` 的计算结果为 NULL,则会跳过该键值对。 | + +## 返回类型 {#return-type} + +JSON 对象。 + +## 示例 {#examples} + +以下示例演示了如何使用 JSON_OBJECT_AGG 将不同类型的数据(例如小数、整数型、JSON 变体和数组)聚合为 JSON 对象,并以列 b 作为每个 JSON 对象的键: + +```sql +CREATE TABLE d ( + a DECIMAL(10, 2), + b STRING, + c INT, + d VARIANT, + e ARRAY(STRING) +); + +INSERT INTO d VALUES + (20, 'abc', NULL, '{"k":"v"}', ['a','b']), + (10, 'de', 100, 'null', []), + (4.23, NULL, 200, '"uvw"', ['x','y']), + (5.99, 'xyz', 300, '[1,2,3]', ['z']); + +SELECT + json_object_agg(b, a) AS json_a, + json_object_agg(b, c) AS json_c, + json_object_agg(b, d) AS json_d, + json_object_agg(b, e) AS json_e +FROM + d; + +-[ RECORD 1 ]----------------------------------- +json_a: {"abc":20.0,"de":10.0,"xyz":5.99} +json_c: {"de":100,"xyz":300} +json_d: {"abc":{"k":"v"},"de":null,"xyz":[1,2,3]} +json_e: {"abc":["a","b"],"de":[],"xyz":["z"]} +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/json-operators.md b/tidb-cloud-lake/sql/json-operators.md new file mode 100644 index 0000000000000..17cab2cef8422 --- /dev/null +++ b/tidb-cloud-lake/sql/json-operators.md @@ -0,0 +1,24 @@ +--- +title: JSON Operators +summary: 本页介绍 TiDB Cloud Lake 中的 JSON 运算符。 +--- + +# JSON 运算符 + +| 运算符 | 描述 | 示例 | 结果 | +| ----------- | -------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------- | +| `->` | 使用索引或键检索 JSON 数组或对象,并返回一个 JSON 对象。 | - **Using a key**:
`SELECT '{"Datalake": "Cloud Native Warehouse"}'::JSON -> 'Datalake'`
- **Using an index**:
`SELECT '["Datalake", "Cloud Native Warehouse"]'::JSON -> 1` | `"Cloud Native Warehouse"` | +| `->>` | 使用索引或键检索 JSON 数组或对象,并返回一个字符串。 | - **Using a key**:
`SELECT '{"Datalake": "Cloud Native Warehouse"}'::JSON ->> 'Datalake'`
- **Using an index**:
`SELECT '["Datalake", "Cloud Native Warehouse"]'::JSON ->> 1` | `Cloud Native Warehouse` | +| `#>` | 通过指定键路径检索 JSON 数组或对象,并返回一个 JSON 对象。 | `SELECT '{"example": {"Datalake": "Cloud Native Warehouse"}}'::JSON #> '{example, Datalake}'` | `"Cloud Native Warehouse"` | +| `#>>` | 通过指定键路径检索 JSON 数组或对象,并返回一个字符串。 | `SELECT '{"example": {"Datalake": "Cloud Native Warehouse"}}'::JSON #>> '{example, Datalake}'` | `Cloud Native Warehouse` | +| `?` | 检查给定字符串是否作为键存在于 JSON 对象中,或是否存在于数组中;若为真则返回 1,否则返回 0。 | `SELECT '{"a":1,"b":2,"c":3}'::JSON ? 'b'` | `true` | +| `?\|` | 检查给定数组中的任意字符串是否存在为键或数组元素;若为真则返回 1,否则返回 0。 | `SELECT '{"a":1,"b":2,"c":3}'::JSON ?\|` ['b','e'] | `true` | +| `?&` | 检查给定数组中的每个字符串是否都存在为键或数组元素;若为真则返回 1,否则返回 0。 | `SELECT '{"a":1,"b":2,"c":3}'::JSON ?& ['b','e']` | `false` | +| `@>` | 检查左侧 JSON 表达式是否包含右侧 JSON 表达式中的所有键值对;若为真则返回 1,否则返回 0。 | `SELECT '{"name":"Alice","age":30}'::JSON @> '{"name":"Alice"}'::JSON` | `true` | +| `<@` | 检查左侧 JSON 表达式是否为右侧 JSON 表达式的子集;若为真则返回 1,否则返回 0。 | `SELECT '{"name":"Alice"}'::JSON <@ '{"name":"Bob"}'::JSON` | `false` | +| `@@` | 检查指定的 JSON 路径表达式是否与 JSON 数据中的某些条件匹配;若为真则返回 1,否则返回 0。 | `SELECT '{"a":1,"b":[1,2,3]}'::JSON @@ '$.a == 1'` | `true` | +| `@?` | 检查针对指定 JSON 值的 JSON 路径表达式是否返回任意项;若为真则返回 1,否则返回 0。 | `SELECT '{"a":1,"b":[1,2,3]}'::JSON @? '$.b[3]'` | `false` | +| `- ''` | 从 JSON 对象中删除一个键值对。 | `SELECT '{"a":1,"b":2}'::JSON - 'a'` | `{"b":2}` | +| `- ` | 从数组中删除指定索引处的元素(负整数表示从末尾开始计数)。 | `SELECT '[1,2,3]'::JSON - 2` | `[1,2]` | +| `#-` | 通过键和/或索引删除一个键值对或数组元素。 | `SELECT '{"a":1,"b":[1,2,3]}'::JSON #- '{b,2}'` | `{"a":1,"b":[1,2]}` | +| \|\| | 将多个 JSON 对象合并为一个对象。 | `SELECT '{"a": 1}'::JSON` \|\| `{"B": 1}'::JSON;` | `{"B":1,"a":1}`| \ No newline at end of file diff --git a/tidb-cloud-lake/sql/json-path-exists.md b/tidb-cloud-lake/sql/json-path-exists.md new file mode 100644 index 0000000000000..07253e6ab3117 --- /dev/null +++ b/tidb-cloud-lake/sql/json-path-exists.md @@ -0,0 +1,50 @@ +--- +title: JSON_PATH_EXISTS +summary: 检查 JSON 数据中指定路径是否存在。 +--- + +# JSON_PATH_EXISTS + +检查 JSON 数据中指定路径是否存在。 + +## 语法 {#syntax} + +```sql +JSON_PATH_EXISTS(, ) +``` + +- json_data:指定要在其中搜索的 JSON 数据。它可以是 JSON 对象或数组。 + +- json_path_expression:指定要在 JSON 数据中检查的路径,该路径从 JSON 数据根开始,以 `$` 表示。你还可以在表达式中包含条件,使用 `@` 引用当前正在求值的节点或元素,以过滤结果。 + +## 返回类型 {#return-type} + +该函数返回: + +- 如果指定的 JSON 路径(以及条件,如果有)在 JSON 数据中存在,则返回 `true`。 +- 如果指定的 JSON 路径(以及条件,如果有)在 JSON 数据中不存在,则返回 `false`。 +- 如果 json_data 或 json_path_expression 之一为 NULL 或无效,则返回 NULL。 + +## 示例 {#examples} + +```sql +SELECT JSON_PATH_EXISTS(parse_json('{"a": 1, "b": 2}'), '$.a ? (@ == 1)'); + +---- +true + +SELECT JSON_PATH_EXISTS(parse_json('{"a": 1, "b": 2}'), '$.a ? (@ > 1)'); + +---- +false + +SELECT JSON_PATH_EXISTS(NULL, '$.a'); + +---- +NULL + +SELECT JSON_PATH_EXISTS(parse_json('{"a": 1, "b": 2}'), NULL); + +---- +NULL +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/json-path-match.md b/tidb-cloud-lake/sql/json-path-match.md new file mode 100644 index 0000000000000..9f4cf079d6d23 --- /dev/null +++ b/tidb-cloud-lake/sql/json-path-match.md @@ -0,0 +1,74 @@ +--- +title: JSON_PATH_MATCH +summary: 检查指定的 JSON 路径表达式是否与 JSON 数据中的特定条件匹配。请注意,`@@` 运算符是此函数的同义形式。更多信息,参见 JSON Operators。 +--- + +# JSON_PATH_MATCH + +检查指定的 JSON 路径表达式是否与 JSON 数据中的特定条件匹配。请注意,`@@` 运算符是此函数的同义形式。更多信息,参见 [JSON 运算符](/tidb-cloud-lake/sql/json-operators.md)。 + +## 语法 {#syntax} + +```sql +JSON_PATH_MATCH(, ) +``` + +- `json_data`:指定要检查的 JSON 数据。它可以是 JSON 对象或数组。 +- `json_path_expression`:指定要在 JSON 数据中检查的条件。该表达式描述了要匹配的具体路径或条件,例如验证 JSON 结构中特定字段的值是否满足某些条件。`$` 符号表示 JSON 数据的根。它用于开始路径表达式,并表示 JSON 结构中的顶层对象。 + +## 返回类型 {#return-type} + +该函数返回: + +- 如果指定的 JSON 路径表达式与 JSON 数据中的条件匹配,则返回 `true`。 +- 如果指定的 JSON 路径表达式与 JSON 数据中的条件不匹配,则返回 `false`。 +- 如果 `json_data` 或 `json_path_expression` 任一为 NULL 或无效,则返回 NULL。 + +## 示例 {#examples} + +```sql +-- Check if the value at JSON path $.a is equal to 1 +SELECT JSON_PATH_MATCH(parse_json('{"a":1,"b":[1,2,3]}'), '$.a == 1'); + +┌────────────────────────────────────────────────────────────────┐ +│ json_path_match(parse_json('{"a":1,"b":[1,2,3]}'), '$.a == 1') │ +├────────────────────────────────────────────────────────────────┤ +│ true │ +└────────────────────────────────────────────────────────────────┘ + +-- Check if the first element in the array at JSON path $.b is greater than 1 +SELECT JSON_PATH_MATCH(parse_json('{"a":1,"b":[1,2,3]}'), '$.b[0] > 1'); + +┌──────────────────────────────────────────────────────────────────┐ +│ json_path_match(parse_json('{"a":1,"b":[1,2,3]}'), '$.b[0] > 1') │ +├──────────────────────────────────────────────────────────────────┤ +│ false │ +└──────────────────────────────────────────────────────────────────┘ + +-- Check if any element in the array at JSON path $.b +-- from the second one to the last are greater than or equal to 2 +SELECT JSON_PATH_MATCH(parse_json('{"a":1,"b":[1,2,3]}'), '$.b[1 to last] >= 2'); + +┌───────────────────────────────────────────────────────────────────────────┐ +│ json_path_match(parse_json('{"a":1,"b":[1,2,3]}'), '$.b[1 to last] >= 2') │ +├───────────────────────────────────────────────────────────────────────────┤ +│ true │ +└───────────────────────────────────────────────────────────────────────────┘ + +-- NULL is returned if either the json_data or json_path_expression is NULL or invalid. +SELECT JSON_PATH_MATCH(parse_json('{"a":1,"b":[1,2,3]}'), NULL); + +┌──────────────────────────────────────────────────────────┐ +│ json_path_match(parse_json('{"a":1,"b":[1,2,3]}'), null) │ +├──────────────────────────────────────────────────────────┤ +│ NULL │ +└──────────────────────────────────────────────────────────┘ + +SELECT JSON_PATH_MATCH(NULL, '$.a == 1'); + +┌───────────────────────────────────┐ +│ json_path_match(null, '$.a == 1') │ +├───────────────────────────────────┤ +│ NULL │ +└───────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/json-path-query-array.md b/tidb-cloud-lake/sql/json-path-query-array.md new file mode 100644 index 0000000000000..2eed1713d9c2a --- /dev/null +++ b/tidb-cloud-lake/sql/json-path-query-array.md @@ -0,0 +1,54 @@ +--- +title: JSON_PATH_QUERY_ARRAY +summary: 获取指定 JSON 值中由 JSON 路径返回的所有 JSON 项,并将结果包装为数组。 +--- + +# JSON_PATH_QUERY_ARRAY + +获取指定 JSON 值中由 JSON 路径返回的所有 JSON 项,并将结果包装为数组。 + +## 语法 {#syntax} + +```sql +JSON_PATH_QUERY_ARRAY(, '') +``` + +## 返回类型 {#return-type} + +VARIANT + +## 示例 {#example} + +**创建表并插入示例数据** + +```sql +CREATE TABLE products ( + name VARCHAR, + details VARIANT +); + +INSERT INTO products (name, details) +VALUES ('Laptop', '{"brand": "Dell", "colors": ["Black", "Silver"], "price": 1200, "features": {"ram": "16GB", "storage": "512GB"}}'), + ('Smartphone', '{"brand": "Apple", "colors": ["White", "Black"], "price": 999, "features": {"ram": "4GB", "storage": "128GB"}}'), + ('Headphones', '{"brand": "Sony", "colors": ["Black", "Blue", "Red"], "price": 150, "features": {"battery": "20h", "bluetooth": "5.0"}}'); +``` + +**查询演示:将产品详情中的所有 features 提取为数组** + +```sql +SELECT + name, + JSON_PATH_QUERY_ARRAY(details, '$.features.*') AS all_features +FROM + products; +``` + +**结果** + +``` + name | all_features +-----------+----------------------- + Laptop | ["16GB", "512GB"] + Smartphone | ["4GB", "128GB"] + Headphones | ["20h", "5.0"] +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/json-path-query-first.md b/tidb-cloud-lake/sql/json-path-query-first.md new file mode 100644 index 0000000000000..a383074d12ba9 --- /dev/null +++ b/tidb-cloud-lake/sql/json-path-query-first.md @@ -0,0 +1,60 @@ +--- +title: JSON_PATH_QUERY_FIRST +summary: 获取指定 JSON 值中由 JSON path 返回的第一个 JSON 项。 +--- + +# JSON_PATH_QUERY_FIRST + +获取指定 JSON 值中由 JSON path 返回的第一个 JSON 项。 + +## 语法 {#syntax} + +```sql +JSON_PATH_QUERY_FIRST(, '') +``` + +## 返回类型 {#return-type} + +VARIANT + +## 示例 {#example} + +**创建表并插入示例数据** + +```sql +CREATE TABLE products ( + name VARCHAR, + details VARIANT +); + +INSERT INTO products (name, details) +VALUES ('Laptop', '{"brand": "Dell", "colors": ["Black", "Silver"], "price": 1200, "features": {"ram": "16GB", "storage": "512GB"}}'), + ('Smartphone', '{"brand": "Apple", "colors": ["White", "Black"], "price": 999, "features": {"ram": "4GB", "storage": "128GB"}}'), + ('Headphones', '{"brand": "Sony", "colors": ["Black", "Blue", "Red"], "price": 150, "features": {"battery": "20h", "bluetooth": "5.0"}}'); +``` + +**查询演示:从产品详情中提取第一个特性** + +```sql +SELECT + name, + JSON_PATH_QUERY(details, '$.features.*') AS all_features, + JSON_PATH_QUERY_FIRST(details, '$.features.*') AS first_feature +FROM + products; +``` + +**结果** + +```sql ++------------+--------------+---------------+ +| name | all_features | first_feature | ++------------+--------------+---------------+ +| Laptop | "16GB" | "16GB" | +| Laptop | "512GB" | "16GB" | +| Smartphone | "4GB" | "4GB" | +| Smartphone | "128GB" | "4GB" | +| Headphones | "20h" | "20h" | +| Headphones | "5.0" | "20h" | ++------------+--------------+---------------+ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/json-path-query.md b/tidb-cloud-lake/sql/json-path-query.md new file mode 100644 index 0000000000000..7aa9ca8f444e3 --- /dev/null +++ b/tidb-cloud-lake/sql/json-path-query.md @@ -0,0 +1,59 @@ +--- +title: JSON_PATH_QUERY +summary: 获取指定 JSON 值中由 JSON 路径返回的所有 JSON 项。 +--- + +# JSON_PATH_QUERY + +获取指定 JSON 值中由 JSON 路径返回的所有 JSON 项。 + +## 语法 {#syntax} + +```sql +JSON_PATH_QUERY(, '') +``` + +## 返回类型 {#return-type} + +VARIANT + +## 示例 {#example} + +**创建表并插入示例数据** + +```sql +CREATE TABLE products ( + name VARCHAR, + details VARIANT +); + +INSERT INTO products (name, details) +VALUES ('Laptop', '{"brand": "Dell", "colors": ["Black", "Silver"], "price": 1200, "features": {"ram": "16GB", "storage": "512GB"}}'), + ('Smartphone', '{"brand": "Apple", "colors": ["White", "Black"], "price": 999, "features": {"ram": "4GB", "storage": "128GB"}}'), + ('Headphones', '{"brand": "Sony", "colors": ["Black", "Blue", "Red"], "price": 150, "features": {"battery": "20h", "bluetooth": "5.0"}}'); +``` + +**查询演示:从产品详情中提取所有特性** + +```sql +SELECT + name, + JSON_PATH_QUERY(details, '$.features.*') AS all_features +FROM + products; +``` + +**结果** + +```sql ++------------+--------------+ +| name | all_features | ++------------+--------------+ +| Laptop | "16GB" | +| Laptop | "512GB" | +| Smartphone | "4GB" | +| Smartphone | "128GB" | +| Headphones | "20h" | +| Headphones | "5.0" | ++------------+--------------+ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/json-pretty.md b/tidb-cloud-lake/sql/json-pretty.md new file mode 100644 index 0000000000000..bce68b3b6b6ea --- /dev/null +++ b/tidb-cloud-lake/sql/json-pretty.md @@ -0,0 +1,51 @@ +--- +title: JSON_PRETTY +summary: 格式化 JSON 数据,使其更易于阅读和展示。它会自动为 JSON 数据添加缩进、换行和其他格式,以获得更好的可视化效果。 +--- + +# JSON_PRETTY + +格式化 JSON 数据,使其更易于阅读和展示。它会自动为 JSON 数据添加缩进、换行和其他格式,以获得更好的可视化效果。 + +## 语法 {#syntax} + +```sql +JSON_PRETTY() +``` + +## 返回类型 {#return-type} + +字符串。 + +## 示例 {#examples} + +```sql +SELECT JSON_PRETTY(PARSE_JSON('{"name":"Alice","age":30}')); + +--- +┌──────────────────────────────────────────────────────┐ +│ json_pretty(parse_json('{"name":"alice","age":30}')) │ +│ String │ +├──────────────────────────────────────────────────────┤ +│ { │ +│ "age": 30, │ +│ "name": "Alice" │ +│ } │ +└──────────────────────────────────────────────────────┘ + +SELECT JSON_PRETTY(PARSE_JSON('{"person": {"name": "Bob", "age": 25}, "location": "City"}')); + +--- +┌───────────────────────────────────────────────────────────────────────────────────────┐ +│ json_pretty(parse_json('{"person": {"name": "bob", "age": 25}, "location": "city"}')) │ +│ String │ +├───────────────────────────────────────────────────────────────────────────────────────┤ +│ { │ +│ "location": "City", │ +│ "person": { │ +│ "age": 25, │ +│ "name": "Bob" │ +│ } │ +│ } │ +└───────────────────────────────────────────────────────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/json-strip-nulls.md b/tidb-cloud-lake/sql/json-strip-nulls.md new file mode 100644 index 0000000000000..ab4f0fd401d35 --- /dev/null +++ b/tidb-cloud-lake/sql/json-strip-nulls.md @@ -0,0 +1,34 @@ +--- +title: JSON_STRIP_NULLS +summary: 从 JSON 对象中移除所有值为 null 的属性。 +--- + +# JSON_STRIP_NULLS + +从 JSON 对象中移除所有值为 null 的属性。 + +## 语法 {#syntax} + +```sql +JSON_STRIP_NULLS() +``` + +## 参数 {#arguments} + +一个 VARIANT 类型的表达式。 + +## 返回类型 {#return-type} + +VARIANT。 + +## 示例 {#examples} + +```sql +SELECT JSON_STRIP_NULLS(PARSE_JSON('{"name": "Alice", "age": 30, "city": null}')) AS value; + +╭───────────────────────────╮ +│ value │ +├───────────────────────────┤ +│ {"age":30,"name":"Alice"} │ +╰───────────────────────────╯ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/json-to-string.md b/tidb-cloud-lake/sql/json-to-string.md new file mode 100644 index 0000000000000..a2869d79fe57c --- /dev/null +++ b/tidb-cloud-lake/sql/json-to-string.md @@ -0,0 +1,8 @@ +--- +title: JSON_TO_STRING +summary: TO_STRING 的别名。 +--- + +# JSON_TO_STRING + +[TO_STRING](/tidb-cloud-lake/sql/to-string.md) 的别名。 \ No newline at end of file diff --git a/tidb-cloud-lake/sql/json-typeof.md b/tidb-cloud-lake/sql/json-typeof.md new file mode 100644 index 0000000000000..03f9fd9e379d6 --- /dev/null +++ b/tidb-cloud-lake/sql/json-typeof.md @@ -0,0 +1,73 @@ +--- +title: JSON_TYPEOF +summary: 返回 JSON 结构最外层的类型。 +--- + +# JSON_TYPEOF + +返回 JSON 结构最外层的类型。 + +## 语法 {#syntax} + +```sql +JSON_TYPEOF() +``` + +## 返回类型 {#return-type} + +json_typeof 函数(或类似函数)的返回类型是一个字符串,用于指示已解析 JSON 值的数据类型。可能的返回值包括:`'null'`、`'boolean'`、`'string'`、`'number'`、`'array'` 和 `'object'`。 + +## 示例 {#examples} + +```sql +-- 解析一个值为 NULL 的 JSON 值 +SELECT JSON_TYPEOF(PARSE_JSON(NULL)); + +-- +json_typeof(parse_json(null))| +-----------------------------+ + | + +-- 解析一个值为字符串 'null' 的 JSON 值 +SELECT JSON_TYPEOF(PARSE_JSON('null')); + +-- +json_typeof(parse_json('null'))| +-------------------------------+ +null | + +SELECT JSON_TYPEOF(PARSE_JSON('true')); + +-- +json_typeof(parse_json('true'))| +-------------------------------+ +boolean | + +SELECT JSON_TYPEOF(PARSE_JSON('"Datalake"')); + +-- +json_typeof(parse_json('"datalake"'))| +-------------------------------------+ +string | + +SELECT JSON_TYPEOF(PARSE_JSON('-1.23')); + +-- +json_typeof(parse_json('-1.23'))| +--------------------------------+ +number | + +SELECT JSON_TYPEOF(PARSE_JSON('[1,2,3]')); + +-- +json_typeof(parse_json('[1,2,3]'))| +----------------------------------+ +array | + +SELECT JSON_TYPEOF(PARSE_JSON('{"name": "Alice", "age": 30}')); + +-- +json_typeof(parse_json('{"name": "alice", "age": 30}'))| +-------------------------------------------------------+ +object | +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/kill.md b/tidb-cloud-lake/sql/kill.md new file mode 100644 index 0000000000000..2184805df21a0 --- /dev/null +++ b/tidb-cloud-lake/sql/kill.md @@ -0,0 +1,30 @@ +--- +title: KILL +summary: 强制终止当前正在运行的查询。 +--- + +# KILL + +强制终止当前正在运行的查询。 + +另请参阅:[SHOW PROCESSLIST](/tidb-cloud-lake/sql/show-processlist.md) + +## 语法 {#syntax} + +```sql +KILL QUERY|CONNECTION +``` + +## 示例 {#examples} + +```sql +SHOW PROCESSLIST; ++--------------------------------------+-------+-----------------+------+-------+----------+--------------------------------------------------------------------------------------+--------------+------------------------+-------------------------+-------------------------+--------------------------+ +| id | type | host | user | state | database | extra_info | memory_usage | dal_metrics_read_bytes | dal_metrics_write_bytes | scan_progress_read_rows | scan_progress_read_bytes | ++--------------------------------------+-------+-----------------+------+-------+----------+--------------------------------------------------------------------------------------+--------------+------------------------+-------------------------+-------------------------+--------------------------+ +| e04dd121-88f4-4290-85be-2b45c6e3b011 | MySQL | 127.0.0.1:65291 | root | Query | default | SELECT sum(number) from numbers_mt(10000000000) group by number%3, number%4,number%5 | 0 | 0 | 0 | 2391200000 | 19129600000 | +| 179c99d5-1894-4d4c-a89e-4b293d404c88 | MySQL | 127.0.0.1:64597 | root | Query | default | show processlist | 0 | 0 | 0 | 0 | 0 | ++--------------------------------------+-------+-----------------+------+-------+----------+--------------------------------------------------------------------------------------+--------------+------------------------+-------------------------+-------------------------+--------------------------+ + +KILL QUERY 'e04dd121-88f4-4290-85be-2b45c6e3b011'; +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/kurtosis.md b/tidb-cloud-lake/sql/kurtosis.md new file mode 100644 index 0000000000000..dc6e383c0c005 --- /dev/null +++ b/tidb-cloud-lake/sql/kurtosis.md @@ -0,0 +1,61 @@ +--- +title: KURTOSIS +summary: 聚合函数。 +--- + +# KURTOSIS + +聚合函数。 + +`KURTOSIS()` 函数返回所有输入值的超额峰度。 + +## 语法 {#syntax} + +```sql +KURTOSIS() +``` + +## 参数 {#arguments} + +| 参数 | 描述 | +|-----------| ----------- | +| `` | 任意数值表达式 | + +## 返回类型 {#return-type} + +可为空的 Float64。 + +## 示例 {#example} + +**创建表并插入示例数据** + +```sql +CREATE TABLE stock_prices ( + id INT, + stock_symbol VARCHAR, + price FLOAT +); + +INSERT INTO stock_prices (id, stock_symbol, price) +VALUES (1, 'AAPL', 150), + (2, 'AAPL', 152), + (3, 'AAPL', 148), + (4, 'AAPL', 160), + (5, 'AAPL', 155); +``` + +**查询演示:计算 Apple 股票价格的超额峰度** + +```sql +SELECT KURTOSIS(price) AS excess_kurtosis +FROM stock_prices +WHERE stock_symbol = 'AAPL'; +``` + +**结果** + +```sql +| excess_kurtosis | +|-------------------------| +| 0.06818181325581445 | +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/l1-distance.md b/tidb-cloud-lake/sql/l1-distance.md new file mode 100644 index 0000000000000..0017de268baf3 --- /dev/null +++ b/tidb-cloud-lake/sql/l1-distance.md @@ -0,0 +1,88 @@ +--- +title: L1_DISTANCE +summary: 计算两个向量之间的曼哈顿(L1)距离,即对应元素绝对差之和。 +--- + +# L1_DISTANCE + +计算两个向量之间的曼哈顿(L1)距离,即对应元素绝对差之和。 + +## 语法 {#syntax} + +```sql +L1_DISTANCE(vector1, vector2) +``` + +## 参数 {#arguments} + +- `vector1`:第一个向量(VECTOR 数据类型) +- `vector2`:第二个向量(VECTOR 数据类型) + +## 返回值 {#returns} + +返回一个 FLOAT 值,表示两个向量之间的曼哈顿(L1)距离。该值始终为非负数: + +- 0:两个向量相同 +- 更大的值:两个向量距离更远 + +## 描述 {#description} + +L1 距离也称为曼哈顿距离或出租车距离,用于计算两个向量对应元素绝对差的总和。它适用于特征比较和稀疏数据分析。 + +公式:`L1_DISTANCE(a, b) = |a1 - b1| + |a2 - b2| + ... + |an - bn|` + +## 示例 {#examples} + +### 基本用法 {#basic-usage} + +```sql +-- Calculate L1 distance between two vectors +SELECT L1_DISTANCE([1.0, 2.0, 3.0]::vector(3), [4.0, 5.0, 6.0]::vector(3)) AS distance; +``` + +结果: + +``` +╭──────────╮ +│ distance │ +├──────────┤ +│ 9 │ +╰──────────╯ +``` + +创建一个包含向量数据的表: + +```sql +CREATE OR REPLACE TABLE vectors ( + id INT, + vec VECTOR(3) +); + +INSERT INTO vectors VALUES + (1, [1.0000, 2.0000, 3.0000]), + (2, [1.0000, 2.2000, 3.0000]), + (3, [4.0000, 5.0000, 6.0000]); +``` + +使用 L1 距离查找最接近 [1, 2, 3] 的向量: + +```sql +SELECT + id, + vec, + L1_DISTANCE(vec, [1.0000, 2.0000, 3.0000]::VECTOR(3)) AS distance +FROM + vectors +ORDER BY + distance ASC; +``` + +``` +╭─────────────────────────────╮ +│ id │ vec │ distance │ +├────┼───────────┼────────────┤ +│ 1 │ [1,2,3] │ 0 │ +│ 2 │ [1,2.2,3] │ 0.20000005 │ +│ 3 │ [4,5,6] │ 9 │ +╰─────────────────────────────╯ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/l2-distance.md b/tidb-cloud-lake/sql/l2-distance.md new file mode 100644 index 0000000000000..8f0b9e6ef7980 --- /dev/null +++ b/tidb-cloud-lake/sql/l2-distance.md @@ -0,0 +1,104 @@ +--- +title: L2_DISTANCE +summary: 计算两个向量之间的欧几里得(L2)距离,用于衡量它们在向量空间中的直线距离。 +--- + +# L2_DISTANCE + +计算两个向量之间的欧几里得(L2)距离,用于衡量它们在向量空间中的直线距离。 + +## 语法 {#syntax} + +```sql +L2_DISTANCE(vector1, vector2) +``` + +## 参数 {#arguments} + +- `vector1`:第一个向量(VECTOR 数据类型) +- `vector2`:第二个向量(VECTOR 数据类型) + +## 返回值 {#returns} + +返回一个 FLOAT 值,表示两个向量之间的欧几里得(L2)距离。该值始终为非负数: + +- 0:向量相同 +- 更大的值:向量之间距离更远 + +## 描述 {#description} + +L2 距离也称为欧几里得距离,用于衡量欧几里得空间中两点之间的直线距离。它是向量相似度搜索和机器学习应用中最常用的指标之一。 + +该函数会: + +1. 验证两个输入向量的长度是否相同 +2. 计算对应元素差值平方的总和 +3. 返回该总和的平方根 + +实现的数学公式为: + +``` +L2_distance(v1, v2) = √(Σ(v1ᵢ - v2ᵢ)²) +``` + +其中,v1ᵢ 和 v2ᵢ 是输入向量中的元素。 + +> **注意:** +> +> - 此函数在 {{{ .lake }}} 内执行向量计算,不依赖外部 API。 + +## 示例 {#examples} + +### 基本用法 {#basic-usage} + +```sql +-- Calculate L2 distance between two vectors +SELECT L2_DISTANCE([1.0, 2.0, 3.0]::vector(3), [4.0, 5.0, 6.0]::vector(3)) AS distance; +``` + +结果: + +``` +╭──────────╮ +│ distance │ +├──────────┤ +│ 5.196152 │ +╰──────────╯ +``` + +创建一个包含向量数据的表: + +```sql +CREATE OR REPLACE TABLE vectors ( + id INT, + vec VECTOR(3) +); + +INSERT INTO vectors VALUES + (1, [1.0000, 2.0000, 3.0000]), + (2, [1.0000, 2.2000, 3.0000]), + (3, [4.0000, 5.0000, 6.0000]); +``` + +使用 L2 距离查找最接近 [1, 2, 3] 的向量: + +```sql +SELECT + id, + vec, + L2_DISTANCE(vec, [1.0000, 2.0000, 3.0000]::VECTOR(3)) AS distance +FROM + vectors +ORDER BY + distance ASC; +``` + +``` +╭─────────────────────────────╮ +│ id │ vec │ distance │ +├────┼───────────┼────────────┤ +│ 1 │ [1,2,3] │ 0 │ +│ 2 │ [1,2.2,3] │ 0.20000005 │ +│ 3 │ [4,5,6] │ 5.196152 │ +╰─────────────────────────────╯ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/lag.md b/tidb-cloud-lake/sql/lag.md new file mode 100644 index 0000000000000..12827b6a0a45d --- /dev/null +++ b/tidb-cloud-lake/sql/lag.md @@ -0,0 +1,98 @@ +--- +title: LAG +summary: 返回结果集前一行的值。 +--- + +# LAG + +返回结果集中前一行的值。 + +另请参阅:[LEAD](/tidb-cloud-lake/sql/lead.md) + +## 语法 {#syntax} + +```sql +LAG( + expression + [, offset ] + [, default ] +) +OVER ( + [ PARTITION BY partition_expression ] + ORDER BY sort_expression +) +``` + +**参数:** + +- `expression`:要计算的列或表达式 +- `offset`:当前行之前的行数(默认值:1) +- `default`:当不存在前一行时返回的值(默认值:NULL) + +**说明:** + +- 负的偏移值与 LEAD 函数的行为类似 +- 如果偏移超出分区边界,则返回 NULL + +## 示例 {#examples} + +```sql +-- Create sample data +CREATE TABLE scores ( + student VARCHAR(20), + test_date DATE, + score INT +); + +INSERT INTO scores VALUES + ('Alice', '2024-01-01', 85), + ('Alice', '2024-02-01', 90), + ('Alice', '2024-03-01', 88), + ('Bob', '2024-01-01', 78), + ('Bob', '2024-02-01', 82), + ('Bob', '2024-03-01', 85); +``` + +**获取每个学生上一次测试的分数:** + +```sql +SELECT student, test_date, score, + LAG(score) OVER (PARTITION BY student ORDER BY test_date) AS previous_score +FROM scores +ORDER BY student, test_date; +``` + +结果: + +``` +student | test_date | score | previous_score +--------+------------+-------+--------------- +Alice | 2024-01-01 | 85 | NULL +Alice | 2024-02-01 | 90 | 85 +Alice | 2024-03-01 | 88 | 90 +Bob | 2024-01-01 | 78 | NULL +Bob | 2024-02-01 | 82 | 78 +Bob | 2024-03-01 | 85 | 82 +``` + +**获取前 2 次测试的分数:** + +```sql +SELECT student, test_date, score, + LAG(score, 2, 0) OVER (PARTITION BY student ORDER BY test_date) AS score_2_tests_ago +FROM scores +ORDER BY student, test_date; +``` + +结果: + +``` +student | test_date | score | score_2_tests_ago +--------+------------+-------+------------------ +Alice | 2024-01-01 | 85 | 0 +Alice | 2024-02-01 | 90 | 0 +Alice | 2024-03-01 | 88 | 85 +Bob | 2024-01-01 | 78 | 0 +Bob | 2024-02-01 | 82 | 0 +Bob | 2024-03-01 | 85 | 78 +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/last-day.md b/tidb-cloud-lake/sql/last-day.md new file mode 100644 index 0000000000000..34bac98d912a5 --- /dev/null +++ b/tidb-cloud-lake/sql/last-day.md @@ -0,0 +1,37 @@ +--- +title: LAST_DAY +summary: 根据提供的日期或时间戳,返回指定时间区间(周、月、季度或年)的最后一天。 +--- + +# LAST_DAY + +根据提供的日期或时间戳,返回指定时间区间(周、月、季度或年)的最后一天。 + +## 语法 {#syntax} + +```sql +LAST_DAY(, ) +``` + +| 参数 | 描述 | +|---------------------|---------------------------------------------------------------------------------------------------------------| +| `` | 用于计算指定时间区间最后一天的 DATE 或 TIMESTAMP 值。 | +| `` | 要查找最后一天的 date_part。可接受的值为 `week`、`month`、`quarter` 和 `year`。 | + +## 返回类型 {#return-type} + +Date。 + +## 示例 {#examples} + +假设你想根据事务中的某个任意日期(例如 2024-11-13)来确定账单日期,而账单日期始终是当月的最后一天: + +```sql +SELECT LAST_DAY(to_date('2024-11-13'), month) AS billing_date; + +┌──────────────┐ +│ billing_date │ +├──────────────┤ +│ 2024-11-30 │ +└──────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/last-query-id.md b/tidb-cloud-lake/sql/last-query-id.md new file mode 100644 index 0000000000000..2c5152a56a363 --- /dev/null +++ b/tidb-cloud-lake/sql/last-query-id.md @@ -0,0 +1,145 @@ +--- +title: LAST_QUERY_ID +summary: 根据当前会话中的顺序返回查询的 ID。 +--- + +# LAST_QUERY_ID + +根据当前会话中的顺序返回查询的 ID。 + +> **Note:** +> +> 该函数当前仅通过 MySQL 协议支持,这意味着你必须使用兼容 MySQL 协议的客户端连接到 {{{ .lake }}} 才能使用该函数。 + +## 语法 {#syntax} + +```sql +LAST_QUERY_ID() +``` + +`index` 指定当前会话中的查询顺序,接受正数和负数,默认值为 `-1`。 + +- 正索引(从 `1` 开始)获取从会话开始起的第 n 个查询。 +- 负索引从当前查询开始向后回溯获取第 n 个查询。 + - 当 `index` 为 `-1` 时,返回当前查询的查询 ID。 + - 要获取上一个查询,请将 `index` 设置为 `-2`。 +- 如果索引超出查询历史范围,则返回 NULL。 + +## 示例 {#examples} + +此示例在一个新会话中运行三个简单查询,然后同时使用正索引和负索引来获取 `SELECT 3` 的查询 ID: + +| | 正索引 | 负索引 | +|----------------------------------------------|----------|----------| +| `SELECT 1` | 1 | -4 | +| `SELECT 2` | 2 | -3 | +| `SELECT 3` | 3 | -2 | +| `SELECT LAST_QUERY_ID(-2), LAST_QUERY_ID(3)` | 4 | -1 | + +```bash +MacBook-Air:~ eric$ mysql -u root -h 127.0.0.1 -P 3307 +Welcome to the MySQL monitor. Commands end with ; or \g. +Your MySQL connection id is 9 +Server version: 8.0.90-v1.2.720-nightly-2280cc9480(rust-1.85.0-nightly-2025-04-08T04:40:36.379825500Z) 0 + +Copyright (c) 2000, 2025, Oracle and/or its affiliates. + +Oracle is a registered trademark of Oracle Corporation and/or its +affiliates. Other names may be trademarks of their respective +owners. + +Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. + +mysql> select 1; ++------+ +| 1 | ++------+ +| 1 | ++------+ +1 row in set (0.02 sec) +Read 1 rows, 1.00 B in 0.004 sec., 264.46 rows/sec., 264.46 B/sec. + +mysql> select 2; ++------+ +| 2 | ++------+ +| 2 | ++------+ +1 row in set (0.01 sec) +Read 1 rows, 1.00 B in 0.003 sec., 366.94 rows/sec., 366.94 B/sec. + +mysql> select 3; ++------+ +| 3 | ++------+ +| 3 | ++------+ +1 row in set (0.01 sec) +Read 1 rows, 1.00 B in 0.003 sec., 373.16 rows/sec., 373.16 B/sec. + +mysql> SELECT LAST_QUERY_ID(-2), LAST_QUERY_ID(3); ++--------------------------------------+--------------------------------------+ +| last_query_id(- 2) | last_query_id(3) | ++--------------------------------------+--------------------------------------+ +| 74dd6dca-f9b0-44cd-99f4-ac7d11d47fee | 74dd6dca-f9b0-44cd-99f4-ac7d11d47fee | ++--------------------------------------+--------------------------------------+ +1 row in set (0.02 sec) +Read 1 rows, 1.00 B in 0.006 sec., 167.95 rows/sec., 167.95 B/sec. +``` + +此示例演示了当 `` 为 `-1` 时,该函数返回当前查询的查询 ID: + +```bash +MacBook-Air:~ eric$ mysql -u root -h 127.0.0.1 -P 3307 +Welcome to the MySQL monitor. Commands end with ; or \g. +Your MySQL connection id is 10 +Server version: 8.0.90-v1.2.720-nightly-2280cc9480(rust-1.85.0-nightly-2025-04-08T04:40:36.379825500Z) 0 + +Copyright (c) 2000, 2025, Oracle and/or its affiliates. + +Oracle is a registered trademark of Oracle Corporation and/or its +affiliates. Other names may be trademarks of their respective +owners. + +Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. + +mysql> SELECT LAST_QUERY_ID(-1), LAST_QUERY_ID(); ++--------------------------------------+--------------------------------------+ +| last_query_id(- 1) | last_query_id() | ++--------------------------------------+--------------------------------------+ +| 5a1afbc2-dc16-4b69-a0e6-615e0b970cb1 | 5a1afbc2-dc16-4b69-a0e6-615e0b970cb1 | ++--------------------------------------+--------------------------------------+ +1 row in set (0.01 sec) +Read 1 rows, 1.00 B in 0.003 sec., 393.68 rows/sec., 393.68 B/sec. + +mysql> SELECT LAST_QUERY_ID(-2); ++--------------------------------------+ +| last_query_id(- 2) | ++--------------------------------------+ +| 5a1afbc2-dc16-4b69-a0e6-615e0b970cb1 | ++--------------------------------------+ +1 row in set (0.01 sec) +Read 1 rows, 1.00 B in 0.003 sec., 381.61 rows/sec., 381.61 B/sec. + +mysql> SELECT LAST_QUERY_ID(1); ++--------------------------------------+ +| last_query_id(1) | ++--------------------------------------+ +| 5a1afbc2-dc16-4b69-a0e6-615e0b970cb1 | ++--------------------------------------+ +1 row in set (0.01 sec) +Read 1 rows, 1.00 B in 0.003 sec., 353.63 rows/sec., 353.63 B/sec. +``` + +当 `index` 超出查询历史范围时,返回 NULL。 + +```bash +mysql> SELECT LAST_QUERY_ID(-100), LAST_QUERY_ID(100); ++----------------------+--------------------+ +| last_query_id(- 100) | last_query_id(100) | ++----------------------+--------------------+ +| | | ++----------------------+--------------------+ +1 row in set (0.02 sec) +Read 1 rows, 1.00 B in 0.008 sec., 128.69 rows/sec., 128.69 B/sec. +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/last-value.md b/tidb-cloud-lake/sql/last-value.md new file mode 100644 index 0000000000000..d3aaf09fcb31f --- /dev/null +++ b/tidb-cloud-lake/sql/last-value.md @@ -0,0 +1,153 @@ +--- +title: LAST_VALUE +summary: 返回窗口框架中的最后一个值。 +--- + +# LAST_VALUE + +返回窗口框架中的最后一个值。 + +另请参阅: + +- [FIRST_VALUE](/tidb-cloud-lake/sql/first-value.md) +- [NTH_VALUE](/tidb-cloud-lake/sql/nth-value.md) + +## 语法 {#syntax} + +```sql +LAST_VALUE(expression) [ { RESPECT | IGNORE } NULLS ] +OVER ( + [ PARTITION BY partition_expression ] + ORDER BY sort_expression [ ASC | DESC ] + [ window_frame ] +) +``` + +**参数:** + +- `expression`:必需。要返回其最后一个值的列或表达式。 +- `PARTITION BY`:可选。将行划分为多个分区。 +- `ORDER BY`:必需。确定窗口内的排序顺序。 +- `window_frame`:可选。定义窗口框架。默认值为 `RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW`。 + +**说明:** + +- 返回已排序窗口框架中的最后一个值。 +- 支持 `IGNORE NULLS` 以跳过空值,支持 `RESPECT NULLS` 以保留默认行为。 +- 当你需要分区中真正的最后一行时,请使用在当前行之后结束的框架(例如 `ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING`)。 +- 适用于查找每个组中的最新值,或前瞻窗口中的最近值。 + +## 示例 {#examples} + +```sql +-- Sample order data +CREATE OR REPLACE TABLE orders_window_demo ( + customer VARCHAR, + order_id INT, + order_time TIMESTAMP, + amount INT, + sales_rep VARCHAR +); + +INSERT INTO orders_window_demo VALUES + ('Alice', 1001, to_timestamp('2024-05-01 09:00:00'), 120, 'Erin'), + ('Alice', 1002, to_timestamp('2024-05-01 11:00:00'), 135, NULL), + ('Alice', 1003, to_timestamp('2024-05-02 14:30:00'), 125, 'Glen'), + ('Bob', 1004, to_timestamp('2024-05-01 08:30:00'), 90, NULL), + ('Bob', 1005, to_timestamp('2024-05-01 20:15:00'), 105, 'Kai'), + ('Bob', 1006, to_timestamp('2024-05-03 10:00:00'), 95, NULL), + ('Carol', 1007, to_timestamp('2024-05-04 09:45:00'), 80, 'Lily'); +``` + +**示例 1:每个客户分区中的最新订单** + +```sql +SELECT customer, + order_id, + order_time, + LAST_VALUE(order_id) OVER ( + PARTITION BY customer + ORDER BY order_time + ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING + ) AS last_order_for_customer +FROM orders_window_demo +ORDER BY customer, order_time; +``` + +结果: + +``` +customer | order_id | order_time | last_order_for_customer +---------+----------+----------------------+------------------------- +Alice | 1001 | 2024-05-01 09:00:00 | 1003 +Alice | 1002 | 2024-05-01 11:00:00 | 1003 +Alice | 1003 | 2024-05-02 14:30:00 | 1003 +Bob | 1004 | 2024-05-01 08:30:00 | 1006 +Bob | 1005 | 2024-05-01 20:15:00 | 1006 +Bob | 1006 | 2024-05-03 10:00:00 | 1006 +Carol | 1007 | 2024-05-04 09:45:00 | 1007 +``` + +**示例 2:在每个客户内向前查看 12 小时** + +```sql +SELECT customer, + order_id, + order_time, + amount, + LAST_VALUE(amount) OVER ( + PARTITION BY customer + ORDER BY order_time + RANGE BETWEEN CURRENT ROW AND INTERVAL 12 HOUR FOLLOWING + ) AS last_amount_next_12h +FROM orders_window_demo +ORDER BY customer, order_time; +``` + +结果: + +``` +customer | order_id | order_time | amount | last_amount_next_12h +---------+----------+----------------------+--------+---------------------- +Alice | 1001 | 2024-05-01 09:00:00 | 120 | 135 +Alice | 1002 | 2024-05-01 11:00:00 | 135 | 135 +Alice | 1003 | 2024-05-02 14:30:00 | 125 | 125 +Bob | 1004 | 2024-05-01 08:30:00 | 90 | 105 +Bob | 1005 | 2024-05-01 20:15:00 | 105 | 105 +Bob | 1006 | 2024-05-03 10:00:00 | 95 | 95 +Carol | 1007 | 2024-05-04 09:45:00 | 80 | 80 +``` + +**示例 3:向前扫描最后一个销售代表时跳过空值** + +```sql +SELECT customer, + order_id, + sales_rep, + LAST_VALUE(sales_rep) RESPECT NULLS OVER ( + PARTITION BY customer + ORDER BY order_time + ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING + ) AS last_rep_respect, + LAST_VALUE(sales_rep) IGNORE NULLS OVER ( + PARTITION BY customer + ORDER BY order_time + ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING + ) AS last_rep_ignore +FROM orders_window_demo +ORDER BY customer, order_id; +``` + +结果: + +``` +customer | order_id | sales_rep | last_rep_respect | last_rep_ignore +---------+----------+-----------+------------------+----------------- +Alice | 1001 | Erin | Glen | Glen +Alice | 1002 | NULL | Glen | Glen +Alice | 1003 | Glen | Glen | Glen +Bob | 1004 | NULL | NULL | Kai +Bob | 1005 | Kai | NULL | Kai +Bob | 1006 | NULL | NULL | Kai +Carol | 1007 | Lily | Lily | Lily +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/last.md b/tidb-cloud-lake/sql/last.md new file mode 100644 index 0000000000000..5036cac186f7d --- /dev/null +++ b/tidb-cloud-lake/sql/last.md @@ -0,0 +1,12 @@ +--- +title: LAST +summary: LAST_VALUE 的别名。 +--- + +# LAST + +> **注意:** +> +> 在 v1.1.50 中引入。 + +[LAST_VALUE](/tidb-cloud-lake/sql/last-value.md) 的别名。 \ No newline at end of file diff --git a/tidb-cloud-lake/sql/lcase.md b/tidb-cloud-lake/sql/lcase.md new file mode 100644 index 0000000000000..6eb62d7e02aab --- /dev/null +++ b/tidb-cloud-lake/sql/lcase.md @@ -0,0 +1,8 @@ +--- +title: LCASE +summary: LOWER 的别名。 +--- + +# LCASE + +[LOWER](/tidb-cloud-lake/sql/lower.md) 的别名。 \ No newline at end of file diff --git a/tidb-cloud-lake/sql/lead.md b/tidb-cloud-lake/sql/lead.md new file mode 100644 index 0000000000000..ab3a4e0d6b18d --- /dev/null +++ b/tidb-cloud-lake/sql/lead.md @@ -0,0 +1,98 @@ +--- +title: LEAD +summary: 返回结果集中后续行的值。 +--- + +# LEAD + +返回结果集中后续行的值。 + +另请参阅:[LAG](/tidb-cloud-lake/sql/lag.md) + +## 语法 {#syntax} + +```sql +LEAD( + expression + [, offset ] + [, default ] +) +OVER ( + [ PARTITION BY partition_expression ] + ORDER BY sort_expression +) +``` + +**参数:** + +- `expression`:要计算的列或表达式 +- `offset`:当前行之后的行数(默认值:1) +- `default`:当不存在下一行时返回的值(默认值:NULL) + +**说明:** + +- 负的偏移值与 LAG 函数的行为相同 +- 如果偏移超出分区边界,则返回 NULL + +## 示例 {#examples} + +```sql +-- Create sample data +CREATE TABLE scores ( + student VARCHAR(20), + test_date DATE, + score INT +); + +INSERT INTO scores VALUES + ('Alice', '2024-01-01', 85), + ('Alice', '2024-02-01', 90), + ('Alice', '2024-03-01', 88), + ('Bob', '2024-01-01', 78), + ('Bob', '2024-02-01', 82), + ('Bob', '2024-03-01', 85); +``` + +**获取每个学生下一次测试的分数:** + +```sql +SELECT student, test_date, score, + LEAD(score) OVER (PARTITION BY student ORDER BY test_date) AS next_score +FROM scores +ORDER BY student, test_date; +``` + +结果: + +``` +student | test_date | score | next_score +--------+------------+-------+----------- +Alice | 2024-01-01 | 85 | 90 +Alice | 2024-02-01 | 90 | 88 +Alice | 2024-03-01 | 88 | NULL +Bob | 2024-01-01 | 78 | 82 +Bob | 2024-02-01 | 82 | 85 +Bob | 2024-03-01 | 85 | NULL +``` + +**获取后第 2 次测试的分数:** + +```sql +SELECT student, test_date, score, + LEAD(score, 2, 0) OVER (PARTITION BY student ORDER BY test_date) AS score_2_tests_later +FROM scores +ORDER BY student, test_date; +``` + +结果: + +``` +student | test_date | score | score_2_tests_later +--------+------------+-------+-------------------- +Alice | 2024-01-01 | 85 | 88 +Alice | 2024-02-01 | 90 | 0 +Alice | 2024-03-01 | 88 | 0 +Bob | 2024-01-01 | 78 | 85 +Bob | 2024-02-01 | 82 | 0 +Bob | 2024-03-01 | 85 | 0 +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/least-ignore-nulls.md b/tidb-cloud-lake/sql/least-ignore-nulls.md new file mode 100644 index 0000000000000..364df9e1209e1 --- /dev/null +++ b/tidb-cloud-lake/sql/least-ignore-nulls.md @@ -0,0 +1,30 @@ +--- +title: LEAST_IGNORE_NULLS +summary: 返回一组值中的最大值,并忽略任何 NULL 值。 +--- + +# LEAST_IGNORE_NULLS + +返回一组值中的最大值,并忽略任何 NULL 值。 + +另请参阅:[LEAST](/tidb-cloud-lake/sql/least.md) + +## 语法 {#syntax} + +```sql +LEAST_IGNORE_NULLS(, ...) +``` + +## 示例 {#examples} + +```sql +SELECT LEAST_IGNORE_NULLS(5, 9, 4), LEAST_IGNORE_NULLS(5, 9, null); +``` + +```sql +┌──────────────────────────────────────────────────────────────┐ +│ least_ignore_nulls(5, 9, 4) │ least_ignore_nulls(5, 9, NULL) │ +├─────────────────────────────┼────────────────────────────────┤ +│ 4 │ 5 │ +└──────────────────────────────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/least.md b/tidb-cloud-lake/sql/least.md new file mode 100644 index 0000000000000..472309a942068 --- /dev/null +++ b/tidb-cloud-lake/sql/least.md @@ -0,0 +1,30 @@ +--- +title: LEAST +summary: 返回一组值中的最小值。如果该组中的任意值为 NULL,则该函数返回 NULL。 +--- + +# LEAST + +返回一组值中的最小值。如果该组中的任意值为 `NULL`,则该函数返回 `NULL`。 + +另请参阅:[LEAST_IGNORE_NULLS](/tidb-cloud-lake/sql/least-ignore-nulls.md) + +## 语法 {#syntax} + +```sql +LEAST(, ...) +``` + +## 示例 {#examples} + +```sql +SELECT LEAST(5, 9, 4), LEAST(5, 9, null); +``` + +``` +┌────────────────────────────────────┐ +│ least(5, 9, 4) │ least(5, 9, NULL) │ +├────────────────┼───────────────────┤ +│ 4 │ NULL │ +└────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/left.md b/tidb-cloud-lake/sql/left.md new file mode 100644 index 0000000000000..edea7f8a03b70 --- /dev/null +++ b/tidb-cloud-lake/sql/left.md @@ -0,0 +1,37 @@ +--- +title: LEFT +summary: 返回字符串 `str` 最左侧的 `len` 个字符;如果任一参数为 NULL,则返回 NULL。如果 `len` 大于 `str` 的长度,则返回整个 `str`。 +--- + +# LEFT + +返回字符串 `str` 最左侧的 `len` 个字符;如果任一参数为 NULL,则返回 NULL。如果 `len` 大于 `str` 的长度,则返回整个 `str`。 + +## 语法 {#syntax} + +```sql +LEFT(, ); +``` + +## 参数 {#arguments} + +| 参数 | 描述 | +|-----------|----------------------------------------------------------| +| `` | 要从中提取字符的主字符串 | +| `` | 字符数量 | + +## 返回类型 {#return-type} + +`VARCHAR` + +## 示例 {#examples} + +```sql +SELECT LEFT('foobarbar', 5), LEFT('foobarbar', 10); + +┌──────────────────────────────────────────────┐ +│ left('foobarbar', 5) │ left('foobarbar', 10) │ +├──────────────────────┼───────────────────────┤ +│ fooba │ foobarbar │ +└──────────────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/length-utf8.md b/tidb-cloud-lake/sql/length-utf8.md new file mode 100644 index 0000000000000..4a15e47119047 --- /dev/null +++ b/tidb-cloud-lake/sql/length-utf8.md @@ -0,0 +1,8 @@ +--- +title: LENGTH_UTF8 +summary: LENGTH 的别名。 +--- + +# LENGTH_UTF8 + +[LENGTH](/tidb-cloud-lake/sql/length.md) 的别名。 \ No newline at end of file diff --git a/tidb-cloud-lake/sql/length.md b/tidb-cloud-lake/sql/length.md new file mode 100644 index 0000000000000..48033078ddfda --- /dev/null +++ b/tidb-cloud-lake/sql/length.md @@ -0,0 +1,36 @@ +--- +title: LENGTH +summary: 返回给定输入字符串或二进制值的长度。对于字符串,长度表示字符数,其中每个 UTF-8 字符都视为单个字符。对于二进制数据,长度对应于字节数。 +--- + +# LENGTH + +返回给定输入字符串或二进制值的长度。对于字符串,长度表示字符数,其中每个 UTF-8 字符都视为单个字符。对于二进制数据,长度对应于字节数。 + +## 语法 {#syntax} + +```sql +LENGTH() +``` + +## 别名 {#aliases} + +- [CHAR_LENGTH](/tidb-cloud-lake/sql/char-length.md) +- [CHARACTER_LENGTH](/tidb-cloud-lake/sql/character-length.md) +- [LENGTH_UTF8](/tidb-cloud-lake/sql/length-utf8.md) + +## 返回类型 {#return-type} + +BIGINT + +## 示例 {#examples} + +```sql +SELECT LENGTH('Hello'), LENGTH_UTF8('Hello'), CHAR_LENGTH('Hello'), CHARACTER_LENGTH('Hello'); + +┌───────────────────────────────────────────────────────────────────────────────────────────┐ +│ length('hello') │ length_utf8('hello') │ char_length('hello') │ character_length('hello') │ +├─────────────────┼──────────────────────┼──────────────────────┼───────────────────────────┤ +│ 5 │ 5 │ 5 │ 5 │ +└───────────────────────────────────────────────────────────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/like.md b/tidb-cloud-lake/sql/like.md new file mode 100644 index 0000000000000..32d97e3cecdd7 --- /dev/null +++ b/tidb-cloud-lake/sql/like.md @@ -0,0 +1,28 @@ +--- +title: LIKE +summary: 使用 SQL 模式进行模式匹配。返回 1 (TRUE) 或 0 (FALSE)。如果 expr 或 pat 任一为 NULL,结果为 NULL。 +--- + +# LIKE + +使用 SQL 模式进行模式匹配。返回 1 (TRUE) 或 0 (FALSE)。如果 expr 或 pat 任一为 NULL,结果为 NULL。 + +## 语法 {#syntax} + +```sql + LIKE +``` + +## 示例 {#examples} + +```sql +SELECT name, category FROM system.functions WHERE name like 'tou%' ORDER BY name; ++----------+------------+ +| name | category | ++----------+------------+ +| touint16 | conversion | +| touint32 | conversion | +| touint64 | conversion | +| touint8 | conversion | ++----------+------------+ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/list-stage-files.md b/tidb-cloud-lake/sql/list-stage-files.md new file mode 100644 index 0000000000000..6439c5b6d8137 --- /dev/null +++ b/tidb-cloud-lake/sql/list-stage-files.md @@ -0,0 +1,69 @@ +--- +title: LIST STAGE FILES +summary: 列出 stage 中的文件。 +--- + +# LIST STAGE FILES + +列出 stage 中的文件。 + +另请参阅: + +- [LIST_STAGE](/tidb-cloud-lake/sql/list-stage.md):此函数用于列出 stage 中的文件,并允许你根据文件扩展名筛选 stage 中的文件,同时获取每个文件的详细信息。 +- [PRESIGN](/tidb-cloud-lake/sql/presign.md):{{{ .lake }}} 建议使用 Presigned URL 方法将文件上传到 stage。 +- [REMOVE STAGE FILES](/tidb-cloud-lake/sql/remove-stage-files.md):从 stage 中删除文件。 + +## 语法 {#syntax} + +```sql +LIST { userStage | internalStage | externalStage } [ PATTERN = '' ] +``` + +`PATTERN` 使用正则表达式筛选已暂存的文件。它匹配 `@[/]` 之后的文件路径部分。参见 [使用 PATTERN 筛选已暂存文件](/tidb-cloud-lake/guides/stage-overview.md#filtering-staged-files-with-pattern)。 + +## 示例 {#examples} + +下面的 stage 包含一个名为 **books.parquet** 的文件和一个名为 **2023** 的文件夹。 + +默认情况下,LIST 命令会列出 stage 中的所有文件: + +```sql +LIST @my_internal_stage; ++-----------------+------+------------------------------------+-------------------------------+---------+ +| name | size | md5 | last_modified | creator | ++-----------------+------+------------------------------------+-------------------------------+---------+ +| 2023/meta.log | 475 | "4208ff530b252236e14b3cd797abdfbd" | 2023-04-19 20:23:24.000 +0000 | NULL | +| 2023/query.log | 1348 | "1c6654b207472c277fc8c6207c035e18" | 2023-04-19 20:23:24.000 +0000 | NULL | +| 2023/readme.txt | 1193 | "8c0fbbebfedf26f93324541f97f5ac14" | 2023-04-19 20:23:24.000 +0000 | NULL | +| books.parquet | 998 | "88432bf90aadb79073682988b39d461c" | 2023-04-19 20:08:42.000 +0000 | NULL | ++-----------------+------+------------------------------------+-------------------------------+---------+ +``` + +要列出 **2023** 文件夹中的文件,请运行以下命令: + +> **注意:** +> +> 必须在命令中的路径末尾添加斜杠 `/`,否则命令可能无法按预期工作,并可能导致错误。 + +```sql +LIST @my_internal_stage/2023/; ++-----------------+------+------------------------------------+-------------------------------+---------+ +| name | size | md5 | last_modified | creator | ++-----------------+------+------------------------------------+-------------------------------+---------+ +| 2023/meta.log | 475 | "4208ff530b252236e14b3cd797abdfbd" | 2023-04-19 20:23:24.000 +0000 | NULL | +| 2023/query.log | 1348 | "1c6654b207472c277fc8c6207c035e18" | 2023-04-19 20:23:24.000 +0000 | NULL | +| 2023/readme.txt | 1193 | "8c0fbbebfedf26f93324541f97f5ac14" | 2023-04-19 20:23:24.000 +0000 | NULL | ++-----------------+------+------------------------------------+-------------------------------+---------+ +``` + +要列出 stage 中所有扩展名为 `.log` 的文件,请运行以下命令: + +```sql +LIST @my_internal_stage PATTERN = '.*[.]log'; ++----------------+------+------------------------------------+-------------------------------+---------+ +| name | size | md5 | last_modified | creator | ++----------------+------+------------------------------------+-------------------------------+---------+ +| 2023/meta.log | 475 | "4208ff530b252236e14b3cd797abdfbd" | 2023-04-19 20:23:24.000 +0000 | NULL | +| 2023/query.log | 1348 | "1c6654b207472c277fc8c6207c035e18" | 2023-04-19 20:23:24.000 +0000 | NULL | ++----------------+------+------------------------------------+-------------------------------+---------+ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/list-stage.md b/tidb-cloud-lake/sql/list-stage.md new file mode 100644 index 0000000000000..5c8a894534335 --- /dev/null +++ b/tidb-cloud-lake/sql/list-stage.md @@ -0,0 +1,56 @@ +--- +title: LIST_STAGE +summary: 列出 stage 中的文件。你可以根据文件扩展名筛选 stage 中的文件,并获取每个文件的详细信息。该函数类似于 DDL 命令 [LIST STAGE FILES](/tidb-cloud-lake/sql/list-stage.md),但它允许你通过 SELECT 语句灵活地获取特定文件信息,例如文件名、大小、MD5 哈希、最后修改时间戳和创建者,而不是返回所有文件信息。 +--- + +# LIST_STAGE + +列出 stage 中的文件。你可以根据文件扩展名筛选 stage 中的文件,并获取每个文件的详细信息。该函数类似于 DDL 命令 [LIST STAGE FILES](/tidb-cloud-lake/sql/list-stage.md),但它允许你通过 SELECT 语句灵活地获取特定文件信息,例如文件名、大小、MD5 哈希、最后修改时间戳和创建者,而不是返回所有文件信息。 + +## 语法 {#syntax} + +```sql +LIST_STAGE( + LOCATION => '{ internalStage | externalStage | userStage }' + [ PATTERN => ''] +) +``` + +其中: + +### internalStage {#internalstage} + +```sql +internalStage ::= @[/] +``` + +### externalStage {#externalstage} + +```sql +externalStage ::= @[/] +``` + +### userStage {#userstage} + +```sql +userStage ::= @~[/] +``` + +### PATTERN {#pattern} + +使用正则表达式筛选 staged 文件。它匹配 `@[/]` 之后的文件路径部分。参见[使用 PATTERN 筛选 staged 文件](/tidb-cloud-lake/guides/stage-overview.md#filtering-staged-files-with-pattern)。 + +## 示例 {#examples} + +```sql +SELECT * FROM list_stage(location => '@my_stage/', pattern => '.*[.]log'); ++----------------+------+------------------------------------+-------------------------------+---------+ +| name | size | md5 | last_modified | creator | ++----------------+------+------------------------------------+-------------------------------+---------+ +| 2023/meta.log | 475 | "4208ff530b252236e14b3cd797abdfbd" | 2023-04-19 20:23:24.000 +0000 | NULL | +| 2023/query.log | 1348 | "1c6654b207472c277fc8c6207c035e18" | 2023-04-19 20:23:24.000 +0000 | NULL | ++----------------+------+------------------------------------+-------------------------------+---------+ + +-- Equivalent to the following statement: +LIST @my_stage PATTERN = '.*[.]log'; +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/listagg.md b/tidb-cloud-lake/sql/listagg.md new file mode 100644 index 0000000000000..8fd462494354c --- /dev/null +++ b/tidb-cloud-lake/sql/listagg.md @@ -0,0 +1,101 @@ +--- +title: LISTAGG +summary: 将多行中的值连接为一个字符串,并使用指定的分隔符分隔。此操作可以通过两种不同的函数类型执行:- 聚合函数:连接会在整个结果集的所有行上进行。- 窗口函数:连接会在结果集的每个分区内进行,分区由 `PARTITION BY` 子句定义。 +--- + +# LISTAGG + +将多行中的值连接为一个字符串,并使用指定的分隔符分隔。此操作可以通过两种不同的函数类型执行: + +- 聚合函数:连接会在整个结果集的所有行上进行。 +- 窗口函数:连接会在结果集的每个分区内进行,分区由 `PARTITION BY` 子句定义。 + +## 语法 {#syntax} + +```sql +-- Aggregate Function +LISTAGG([DISTINCT] [, ]) + [WITHIN GROUP (ORDER BY )] + +-- Window Function +LISTAGG([DISTINCT] [, ]) + [WITHIN GROUP (ORDER BY )] + OVER ([PARTITION BY ]) +``` + +| 参数 | 描述 | +|---------------------------------|---------------------------------------------------------------------------------------------------| +| `DISTINCT` | 可选。连接前移除重复值。 | +| `` | 要连接的表达式(通常是列或表达式)。 | +| `` | 可选。用于分隔每个连接值的字符串。如果省略,默认为空字符串。 | +| `ORDER BY ` | 定义值连接时的顺序。 | +| `PARTITION BY ` | 将行划分为多个分区,以便在每个组内分别执行聚合。 | + +## 别名 {#aliases} + +- [STRING_AGG](/tidb-cloud-lake/sql/string-agg.md) +- [GROUP_CONCAT](/tidb-cloud-lake/sql/group-concat.md) + +## 返回类型 {#return-type} + +字符串。 + +## 示例 {#examples} + +在此示例中,我们有一张客户订单表。每个订单都属于某个客户,我们希望创建一个列表,列出每个客户购买过的所有产品。 + +```sql +CREATE TABLE orders ( + customer_id INT, + product_name VARCHAR +); + +INSERT INTO orders (customer_id, product_name) VALUES +(1, 'Laptop'), +(1, 'Mouse'), +(1, 'Laptop'), +(2, 'Phone'), +(2, 'Headphones'); +``` + +以下示例将 `LISTAGG` 用作聚合函数,并结合 GROUP BY 将每个客户购买的所有产品连接为一个字符串: + +```sql +SELECT + customer_id, + LISTAGG(product_name, ', ') WITHIN GROUP (ORDER BY product_name) AS product_list +FROM orders +GROUP BY customer_id; +``` + +```sql +┌─────────────────────────────────────────┐ +│ customer_id │ product_list │ +├─────────────────┼───────────────────────┤ +│ 2 │ Headphones, Phone │ +│ 1 │ Laptop, Laptop, Mouse │ +└─────────────────────────────────────────┘ +``` + +以下示例将 `LISTAGG` 用作窗口函数,因此每一行都会保留其原始明细,同时还会显示该客户分组的完整产品列表: + +```sql +SELECT + customer_id, + product_name, + LISTAGG(product_name, ', ') WITHIN GROUP (ORDER BY product_name) + OVER (PARTITION BY customer_id) AS product_list +FROM orders; +``` + +```sql +┌────────────────────────────────────────────────────────────┐ +│ customer_id │ product_name │ product_list │ +├─────────────────┼──────────────────┼───────────────────────┤ +│ 2 │ Phone │ Headphones, Phone │ +│ 2 │ Headphones │ Headphones, Phone │ +│ 1 │ Laptop │ Laptop, Laptop, Mouse │ +│ 1 │ Mouse │ Laptop, Laptop, Mouse │ +│ 1 │ Laptop │ Laptop, Laptop, Mouse │ +└────────────────────────────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/ln.md b/tidb-cloud-lake/sql/ln.md new file mode 100644 index 0000000000000..a6486c2c35232 --- /dev/null +++ b/tidb-cloud-lake/sql/ln.md @@ -0,0 +1,26 @@ +--- +title: LN +summary: 返回 `x` 的自然对数;也就是以 e 为底的 `x` 的对数。如果 x 小于或等于 0.0E0,该函数返回 NULL。 +--- + +# LN + +返回 `x` 的自然对数;也就是以 e 为底的 `x` 的对数。如果 x 小于或等于 0.0E0,该函数返回 NULL。 + +## 语法 {#syntax} + +```sql +LN( ) +``` + +## 示例 {#examples} + +```sql +SELECT LN(2); + +┌────────────────────┐ +│ ln(2) │ +├────────────────────┤ +│ 0.6931471805599453 │ +└────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/locate.md b/tidb-cloud-lake/sql/locate.md new file mode 100644 index 0000000000000..a669e2f2c7615 --- /dev/null +++ b/tidb-cloud-lake/sql/locate.md @@ -0,0 +1,52 @@ +--- +title: LOCATE +summary: 第一种语法返回子字符串 substr 在字符串 str 中首次出现的位置。第二种语法返回子字符串 substr 在字符串 str 中从位置 pos 开始首次出现的位置。如果 substr 不在 str 中,则返回 0。如果任一参数为 NULL,则返回 NULL。 +--- + +# LOCATE + +第一种语法返回子字符串 substr 在字符串 str 中首次出现的位置。第二种语法返回子字符串 substr 在字符串 str 中从位置 pos 开始首次出现的位置。如果 substr 不在 str 中,则返回 0。如果任一参数为 NULL,则返回 NULL。 + +## 语法 {#syntax} + +```sql +LOCATE(, ) +LOCATE(, , ) +``` + +## 参数 {#arguments} + +| 参数 | 描述 | +|------------|----------------| +| `` | 子字符串。 | +| `` | 字符串。 | +| `` | 位置。 | + +## 返回类型 {#return-type} + +`BIGINT` + +## 示例 {#examples} + +```sql +SELECT LOCATE('bar', 'foobarbar') ++----------------------------+ +| LOCATE('bar', 'foobarbar') | ++----------------------------+ +| 4 | ++----------------------------+ + +SELECT LOCATE('xbar', 'foobar') ++--------------------------+ +| LOCATE('xbar', 'foobar') | ++--------------------------+ +| 0 | ++--------------------------+ + +SELECT LOCATE('bar', 'foobarbar', 5) ++-------------------------------+ +| LOCATE('bar', 'foobarbar', 5) | ++-------------------------------+ +| 7 | ++-------------------------------+ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/log-b-x.md b/tidb-cloud-lake/sql/log-b-x.md new file mode 100644 index 0000000000000..9d9bea9ec095f --- /dev/null +++ b/tidb-cloud-lake/sql/log-b-x.md @@ -0,0 +1,26 @@ +--- +title: LOG(b, x) +summary: 返回 `x` 以 `b` 为底的对数。如果 `x` 小于或等于 0.0E0,则该函数返回 NULL。 +--- + +# LOG(b, x) + +返回 `x` 以 `b` 为底的对数。如果 `x` 小于或等于 0.0E0,则该函数返回 NULL。 + +## 语法 {#syntax} + +```sql +LOG( ) +``` + +## 示例 {#examples} + +```sql +SELECT LOG(2, 65536); + +┌───────────────┐ +│ log(2, 65536) │ +├───────────────┤ +│ 16 │ +└───────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/log-sql.md b/tidb-cloud-lake/sql/log-sql.md new file mode 100644 index 0000000000000..49824e732f3ab --- /dev/null +++ b/tidb-cloud-lake/sql/log-sql.md @@ -0,0 +1,26 @@ +--- +title: LOG2 +summary: 返回 `x` 的以 2 为底的对数。如果 `x` 小于或等于 0.0E0,则该函数返回 NULL。 +--- + +# LOG2 + +返回 `x` 的以 2 为底的对数。如果 `x` 小于或等于 0.0E0,则该函数返回 NULL。 + +## 语法 {#syntax} + +```sql +LOG2( ) +``` + +## 示例 {#examples} + +```sql +SELECT LOG2(65536); + +┌─────────────┐ +│ log2(65536) │ +├─────────────┤ +│ 16 │ +└─────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/log-x.md b/tidb-cloud-lake/sql/log-x.md new file mode 100644 index 0000000000000..05eece0115b32 --- /dev/null +++ b/tidb-cloud-lake/sql/log-x.md @@ -0,0 +1,26 @@ +--- +title: LOG(x) +summary: 返回 `x` 的自然对数。如果 x 小于或等于 0.0E0,则该函数返回 NULL。 +--- + +# LOG(x) + +返回 `x` 的自然对数。如果 x 小于或等于 0.0E0,则该函数返回 NULL。 + +## 语法 {#syntax} + +```sql +LOG( ) +``` + +## 示例 {#examples} + +```sql +SELECT LOG(2); + +┌────────────────────┐ +│ log(2) │ +├────────────────────┤ +│ 0.6931471805599453 │ +└────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/log.md b/tidb-cloud-lake/sql/log.md new file mode 100644 index 0000000000000..1ec32afd0ba2f --- /dev/null +++ b/tidb-cloud-lake/sql/log.md @@ -0,0 +1,26 @@ +--- +title: LOG10 +summary: 返回 `x` 的以 10 为底的对数。如果 `x` 小于或等于 0.0E0,则该函数返回 NULL。 +--- + +# LOG10 + +返回 `x` 的以 10 为底的对数。如果 `x` 小于或等于 0.0E0,则该函数返回 NULL。 + +## 语法 {#syntax} + +```sql +LOG10( ) +``` + +## 示例 {#examples} + +```sql +SELECT LOG10(100); + +┌────────────┐ +│ log10(100) │ +├────────────┤ +│ 2 │ +└────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/logical-operators.md b/tidb-cloud-lake/sql/logical-operators.md new file mode 100644 index 0000000000000..f4661adf91d83 --- /dev/null +++ b/tidb-cloud-lake/sql/logical-operators.md @@ -0,0 +1,12 @@ +--- +title: 逻辑运算符 +summary: 本页介绍 TiDB Cloud Lake 中的逻辑运算符。 +--- + +# 逻辑运算符 + +| 运算符 | 描述 | 示例 | 结果 | +|----------|----------------------------------------|---------------|--------| +| **AND** | 同时匹配两个表达式(`a` 和 `b`) | **1 AND 1** | TRUE | +| **NOT** | 不匹配该表达式 | **NOT 1** | FALSE | +| **OR** | 匹配任一表达式 | **1 OR 0** | TRUE | \ No newline at end of file diff --git a/tidb-cloud-lake/sql/lower.md b/tidb-cloud-lake/sql/lower.md new file mode 100644 index 0000000000000..ead68c841df81 --- /dev/null +++ b/tidb-cloud-lake/sql/lower.md @@ -0,0 +1,34 @@ +--- +title: LOWER +summary: 返回一个将所有字符都转换为小写的字符串。 +--- + +# LOWER + +返回一个将所有字符都转换为小写的字符串。 + +## 语法 {#syntax} + +```sql +LOWER() +``` + +## 别名 {#aliases} + +- [LCASE](/tidb-cloud-lake/sql/lcase.md) + +## 返回类型 {#return-type} + +VARCHAR + +## 示例 {#examples} + +```sql +SELECT LOWER('Hello, DataLake!'), LCASE('Hello, DataLake!'); + +┌───────────────────────────────────────────────────────┐ +│ lower('hello, datalake!') │ lcase('hello, datalake!') │ +├───────────────────────────┼───────────────────────────┤ +│ hello, datalake! │ hello, datalake! │ +└───────────────────────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/lpad.md b/tidb-cloud-lake/sql/lpad.md new file mode 100644 index 0000000000000..da10e78b812f2 --- /dev/null +++ b/tidb-cloud-lake/sql/lpad.md @@ -0,0 +1,44 @@ +--- +title: LPAD +summary: 返回字符串 str,在其左侧使用字符串 padstr 填充,直到长度达到 len 个字符。如果 str 的长度大于 len,则返回值会被截短为 len 个字符。 +--- + +# LPAD + +返回字符串 str,在其左侧使用字符串 padstr 填充,直到长度达到 len 个字符。如果 str 的长度大于 len,则返回值会被截短为 len 个字符。 + +## 语法 {#syntax} + +```sql +LPAD(, , ) +``` + +## 参数 {#arguments} + +| 参数 | 描述 | +|------------|-----------------| +| `` | 字符串。 | +| `` | 长度。 | +| `` | 填充字符串。 | + +## 返回类型 {#return-type} + +`VARCHAR` + +## 示例 {#examples} + +```sql +SELECT LPAD('hi',4,'??'); ++---------------------+ +| LPAD('hi', 4, '??') | ++---------------------+ +| ??hi | ++---------------------+ + +SELECT LPAD('hi',1,'??'); ++---------------------+ +| LPAD('hi', 1, '??') | ++---------------------+ +| h | ++---------------------+ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/ltrim.md b/tidb-cloud-lake/sql/ltrim.md new file mode 100644 index 0000000000000..16e1b42dd5d1d --- /dev/null +++ b/tidb-cloud-lake/sql/ltrim.md @@ -0,0 +1,31 @@ +--- +title: LTRIM +summary: 从字符串左侧移除指定 trim 字符串中出现的所有字符。 +--- + +# LTRIM + +从字符串左侧移除指定 trim 字符串中出现的所有字符。 + +另请参阅: + +- [TRIM_LEADING](/tidb-cloud-lake/sql/trim-leading.md) +- [RTRIM](/tidb-cloud-lake/sql/rtrim.md) + +## 语法 {#syntax} + +```sql +LTRIM(, ) +``` + +## 示例 {#examples} + +```sql +SELECT LTRIM('xxdatalake', 'xx'), LTRIM('xxdatalake', 'xy'); + +┌───────────────────────────────────────────────────────┐ +│ ltrim('xxdatalake', 'xx') │ ltrim('xxdatalake', 'xy') │ +├───────────────────────────┼───────────────────────────┤ +│ datalake │ datalake │ +└───────────────────────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/map-cat.md b/tidb-cloud-lake/sql/map-cat.md new file mode 100644 index 0000000000000..cedfb251c4d7c --- /dev/null +++ b/tidb-cloud-lake/sql/map-cat.md @@ -0,0 +1,41 @@ +--- +title: MAP_CAT +summary: 返回两个 MAP 的拼接结果。 +--- + +# MAP_CAT + +返回两个 MAP 的拼接结果。 + +## 语法 {#syntax} + +```sql +MAP_CAT( , ) +``` + +## 参数 {#arguments} + +| 参数 | 描述 | +|-----------|---------------------------------| +| `` | 源 MAP。 | +| `` | 要追加到 map1 的 MAP。 | + +> **注意:** +> +> - 如果 map1 和 map2 都包含相同的键,则输出的 map 包含 map2 中的值。 +> - 如果任一参数为 NULL,则该函数返回 NULL,且不会报告任何错误。 + +## 返回类型 {#return-type} + +Map。 + +## 示例 {#examples} + +```sql +SELECT MAP_CAT({'a':1,'b':2,'c':3}, {'c':5,'d':6}); +┌─────────────────────────────────────────────┐ +│ map_cat({'a':1,'b':2,'c':3}, {'c':5,'d':6}) │ +├─────────────────────────────────────────────┤ +│ {'a':1,'b':2,'c':5,'d':6} │ +└─────────────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/map-contains-key.md b/tidb-cloud-lake/sql/map-contains-key.md new file mode 100644 index 0000000000000..18cb6480c7772 --- /dev/null +++ b/tidb-cloud-lake/sql/map-contains-key.md @@ -0,0 +1,43 @@ +--- +title: MAP_CONTAINS_KEY +summary: 判断指定的 MAP 是否包含指定的键。 +--- + +# MAP_CONTAINS_KEY + +判断指定的 MAP 是否包含指定的键。 + +## 语法 {#syntax} + +```sql +MAP_CONTAINS_KEY( , ) +``` + +## 参数 {#arguments} + +| 参数 | 描述 | +|-----------|-------------------------| +| `` | 要搜索的 map。 | +| `` | 要查找的键。 | + +## 返回类型 {#return-type} + +Boolean。 + +## 示例 {#examples} + +```sql +SELECT MAP_CONTAINS_KEY({'a':1,'b':2,'c':3}, 'c'); +┌────────────────────────────────────────────┐ +│ map_contains_key({'a':1,'b':2,'c':3}, 'c') │ +├────────────────────────────────────────────┤ +│ true │ +└────────────────────────────────────────────┘ + +SELECT MAP_CONTAINS_KEY({'a':1,'b':2,'c':3}, 'x'); +┌────────────────────────────────────────────┐ +│ map_contains_key({'a':1,'b':2,'c':3}, 'x') │ +├────────────────────────────────────────────┤ +│ false │ +└────────────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/map-delete.md b/tidb-cloud-lake/sql/map-delete.md new file mode 100644 index 0000000000000..eccfed5362058 --- /dev/null +++ b/tidb-cloud-lake/sql/map-delete.md @@ -0,0 +1,50 @@ +--- +title: MAP_DELETE +summary: 返回一个删除了一个或多个键的现有 MAP。 +--- + +# MAP_DELETE + +返回一个删除了一个或多个键的现有 MAP。 + +## 语法 {#syntax} + +```sql +MAP_DELETE( , [, , ... ] ) +MAP_DELETE( , ) +``` + +## 参数 {#arguments} + +| 参数 | 描述 | +|-----------|--------------------------------------------------------| +| `` | 包含待删除 KEY 的 MAP。 | +| `` | 将从返回的 MAP 中省略的 KEY。 | +| `` | 将从返回的 MAP 中省略的 KEY 数组。 | + +> **注意:** +> +> - 键表达式的类型必须与 map 中键的类型相同。 +> - 如果在 map 中找不到某个键值,则会忽略该键值。 + +## 返回类型 {#return-type} + +Map。 + +## 示例 {#examples} + +```sql +SELECT MAP_DELETE({'a':1,'b':2,'c':3}, 'a', 'c'); +┌───────────────────────────────────────────┐ +│ map_delete({'a':1,'b':2,'c':3}, 'a', 'c') │ +├───────────────────────────────────────────┤ +│ {'b':2} │ +└───────────────────────────────────────────┘ + +SELECT MAP_DELETE({'a':1,'b':2,'c':3}, ['a', 'b']); +┌─────────────────────────────────────────────┐ +│ map_delete({'a':1,'b':2,'c':3}, ['a', 'b']) │ +├─────────────────────────────────────────────┤ +│ {'c':3} │ +└─────────────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/map-filter.md b/tidb-cloud-lake/sql/map-filter.md new file mode 100644 index 0000000000000..5e5410a6eac43 --- /dev/null +++ b/tidb-cloud-lake/sql/map-filter.md @@ -0,0 +1,32 @@ +--- +title: MAP_FILTER +summary: 根据使用 [lambda 表达式](/tidb-cloud-lake/sql/stored-procedure-scripting.md#lambda-expressions) 定义的指定条件,过滤 JSON 对象中的键值对。 +--- + +# MAP_FILTER + +根据使用 [lambda 表达式](/tidb-cloud-lake/sql/stored-procedure-scripting.md#lambda-expressions) 定义的指定条件,过滤 JSON 对象中的键值对。 + +## 语法 {#syntax} + +```sql +MAP_FILTER(, (, ) -> ) +``` + +## 返回类型 {#return-type} + +返回一个仅包含满足指定条件的键值对的 JSON 对象。 + +## 示例 {#examples} + +以下示例从 JSON 对象中仅提取 `"status": "active"` 这一键值对,并过滤掉其他字段: + +```sql +SELECT MAP_FILTER('{"status":"active", "user":"admin", "time":"2024-11-01"}'::VARIANT, (k, v) -> k = 'status') AS filtered_metadata; + +┌─────────────────────┐ +│ filtered_metadata │ +├─────────────────────┤ +│ {"status":"active"} │ +└─────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/map-functions.md b/tidb-cloud-lake/sql/map-functions.md new file mode 100644 index 0000000000000..85888a0be5382 --- /dev/null +++ b/tidb-cloud-lake/sql/map-functions.md @@ -0,0 +1,44 @@ +--- +title: Map 函数 +summary: 本节提供 {{{ .lake }}} 中 map 函数的参考信息。Map 函数可用于创建、操作以及从 map 数据结构(键值对)中提取信息。 +--- + +# Map 函数 + +本节提供 {{{ .lake }}} 中 map 函数的参考信息。Map 函数可用于创建、操作以及从 map 数据结构(键值对)中提取信息。 + +## Map 创建与组合 {#map-creation-and-combination} + +| 函数 | 描述 | 示例 | +|----------|-------------|--------| +| [MAP_CAT](/tidb-cloud-lake/sql/map-cat.md) | 将多个 map 合并为一个 map | `MAP_CAT({'a':1}, {'b':2})` → `{'a':1,'b':2}` | + +## Map 访问与信息 {#map-access-and-information} + +| 函数 | 描述 | 示例 | +|----------|-------------|--------| +| [MAP_KEYS](/tidb-cloud-lake/sql/map-keys.md) | 以数组形式返回 map 中的所有键 | `MAP_KEYS({'a':1,'b':2})` → `['a','b']` | +| [MAP_VALUES](/tidb-cloud-lake/sql/map-values.md) | 以数组形式返回 map 中的所有值 | `MAP_VALUES({'a':1,'b':2})` → `[1,2]` | +| [MAP_SIZE](/tidb-cloud-lake/sql/map-size.md) | 返回 map 中键值对的数量 | `MAP_SIZE({'a':1,'b':2,'c':3})` → `3` | +| [MAP_CONTAINS_KEY](/tidb-cloud-lake/sql/map-contains-key.md) | 检查 map 是否包含指定的键 | `MAP_CONTAINS_KEY({'a':1,'b':2}, 'a')` → `TRUE` | + +## Map 修改 {#map-modification} + +| 函数 | 描述 | 示例 | +|----------|-------------|--------| +| [MAP_INSERT](/tidb-cloud-lake/sql/map-insert.md) | 向 map 中插入一个键值对 | `MAP_INSERT({'a':1,'b':2}, 'c', 3)` → `{'a':1,'b':2,'c':3}` | +| [MAP_DELETE](/tidb-cloud-lake/sql/map-delete.md) | 从 map 中移除一个键值对 | `MAP_DELETE({'a':1,'b':2,'c':3}, 'b')` → `{'a':1,'c':3}` | + +## Map 转换 {#map-transformation} + +| 函数 | 描述 | 示例 | +|----------|-------------|--------| +| [MAP_TRANSFORM_KEYS](/tidb-cloud-lake/sql/map-transform-keys.md) | 对 map 中的每个键应用一个函数 | `MAP_TRANSFORM_KEYS({'a':1,'b':2}, x -> UPPER(x))` → `{'A':1,'B':2}` | +| [MAP_TRANSFORM_VALUES](/tidb-cloud-lake/sql/map-transform-values.md) | 对 map 中的每个值应用一个函数 | `MAP_TRANSFORM_VALUES({'a':1,'b':2}, x -> x * 10)` → `{'a':10,'b':20}` | + +## Map 过滤与选择 {#map-filtering-and-selection} + +| 函数 | 描述 | 示例 | +|----------|-------------|--------| +| [MAP_FILTER](/tidb-cloud-lake/sql/map-filter.md) | 根据谓词过滤键值对 | `MAP_FILTER({'a':1,'b':2,'c':3}, (k,v) -> v > 1)` → `{'b':2,'c':3}` | +| [MAP_PICK](/tidb-cloud-lake/sql/map-pick.md) | 仅使用指定的键创建一个新的 map | `MAP_PICK({'a':1,'b':2,'c':3}, ['a','c'])` → `{'a':1,'c':3}` | \ No newline at end of file diff --git a/tidb-cloud-lake/sql/map-insert.md b/tidb-cloud-lake/sql/map-insert.md new file mode 100644 index 0000000000000..23d22601ad00f --- /dev/null +++ b/tidb-cloud-lake/sql/map-insert.md @@ -0,0 +1,45 @@ +--- +title: MAP_INSERT +summary: 返回一个新的 MAP,该 MAP 由输入 MAP 插入一个新的键值对后组成(如果键已存在,则用新值修改该键)。 +--- + +# MAP_INSERT + +返回一个新的 MAP,该 MAP 由输入 MAP 插入一个新的键值对后组成(如果键已存在,则用新值修改该键)。 + +## 语法 {#syntax} + +```sql +MAP_INSERT( , , [, ] ) +``` + +## 参数 {#arguments} + +| 参数 | 描述 | +|----------------|----------------------------------------------------------------------------------------------| +| `` | 输入的 MAP。 | +| `` | 要插入到 MAP 中的新键。 | +| `` | 要插入到 MAP 中的新值。 | +| `` | 一个布尔(命令行)标记/参数,表示是否可以覆盖已存在的键。默认值为 FALSE。 | + +## 返回类型 {#return-type} + +Map。 + +## 示例 {#examples} + +```sql +SELECT MAP_INSERT({'a':1,'b':2,'c':3}, 'd', 4); +┌─────────────────────────────────────────┐ +│ map_insert({'a':1,'b':2,'c':3}, 'd', 4) │ +├─────────────────────────────────────────┤ +│ {'a':1,'b':2,'c':3,'d':4} │ +└─────────────────────────────────────────┘ + +SELECT MAP_INSERT({'a':1,'b':2,'c':3}, 'a', 5, true); +┌───────────────────────────────────────────────┐ +│ map_insert({'a':1,'b':2,'c':3}, 'a', 5, TRUE) │ +├───────────────────────────────────────────────┤ +│ {'a':5,'b':2,'c':3} │ +└───────────────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/map-keys.md b/tidb-cloud-lake/sql/map-keys.md new file mode 100644 index 0000000000000..35b992655b020 --- /dev/null +++ b/tidb-cloud-lake/sql/map-keys.md @@ -0,0 +1,36 @@ +--- +title: MAP_KEYS +summary: 返回 map 中的键。 +--- + +# MAP_KEYS + +返回 map 中的键。 + +## 语法 {#syntax} + +```sql +MAP_KEYS( ) +``` + +## 参数 {#arguments} + +| 参数 | 描述 | +|-----------|----------------| +| `` | 输入的 map。 | + +## 返回类型 {#return-type} + +Array。 + +## 示例 {#examples} + +```sql +SELECT MAP_KEYS({'a':1,'b':2,'c':3}); + +┌───────────────────────────────┐ +│ map_keys({'a':1,'b':2,'c':3}) │ +├───────────────────────────────┤ +│ ['a','b','c'] │ +└───────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/map-pick.md b/tidb-cloud-lake/sql/map-pick.md new file mode 100644 index 0000000000000..5b3c3abaeef75 --- /dev/null +++ b/tidb-cloud-lake/sql/map-pick.md @@ -0,0 +1,50 @@ +--- +title: MAP_PICK +summary: 返回一个新的 MAP,其中包含现有 MAP 中指定的键值对。 +--- + +# MAP_PICK + +返回一个新的 MAP,其中包含现有 MAP 中指定的键值对。 + +## 语法 {#syntax} + +```sql +MAP_PICK( , [, , ... ] ) +MAP_PICK( , ) +``` + +## 参数 {#arguments} + +| 参数 | 描述 | +|-----------|-------------------------------------------------------- | +| `` | 输入的 MAP。 | +| `` | 返回的 MAP 中要包含的 KEY。 | +| `` | 返回的 MAP 中要包含的 KEY 数组。 | + +> **注意:** +> +> - 键表达式的类型必须与 map 中键的类型相同。 +> - 在 map 中找不到的键值将被忽略。 + +## 返回类型 {#return-type} + +Map。 + +## 示例 {#examples} + +```sql +SELECT MAP_PICK({'a':1,'b':2,'c':3}, 'a', 'c'); +┌─────────────────────────────────────────┐ +│ map_pick({'a':1,'b':2,'c':3}, 'a', 'c') │ +├─────────────────────────────────────────┤ +│ {'a':1,'c':3} │ +└─────────────────────────────────────────┘ + +SELECT MAP_PICK({'a':1,'b':2,'c':3}, ['a', 'b']); +┌───────────────────────────────────────────┐ +│ map_pick({'a':1,'b':2,'c':3}, ['a', 'b']) │ +├───────────────────────────────────────────┤ +│ {'a':1,'b':2} │ +└───────────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/map-size.md b/tidb-cloud-lake/sql/map-size.md new file mode 100644 index 0000000000000..94176f41b78d3 --- /dev/null +++ b/tidb-cloud-lake/sql/map-size.md @@ -0,0 +1,36 @@ +--- +title: MAP_SIZE +summary: 返回 MAP 的大小。 +--- + +# MAP_SIZE + +返回 MAP 的大小。 + +## 语法 {#syntax} + +```sql +MAP_SIZE( ) +``` + +## 参数 {#arguments} + +| 参数 | 描述 | +|-----------|----------------| +| `` | 输入的 map。 | + +## 返回类型 {#return-type} + +UInt64。 + +## 示例 {#examples} + +```sql +SELECT MAP_SIZE({'a':1,'b':2,'c':3}); + +┌───────────────────────────────┐ +│ map_size({'a':1,'b':2,'c':3}) │ +├───────────────────────────────┤ +│ 3 │ +└───────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/map-transform-keys.md b/tidb-cloud-lake/sql/map-transform-keys.md new file mode 100644 index 0000000000000..b19bceb61c47c --- /dev/null +++ b/tidb-cloud-lake/sql/map-transform-keys.md @@ -0,0 +1,32 @@ +--- +title: MAP_TRANSFORM_KEYS +summary: 使用 [lambda 表达式](/tidb-cloud-lake/sql/stored-procedure-scripting.md#lambda-expressions) 对 JSON 对象中的每个键应用转换。 +--- + +# MAP_TRANSFORM_KEYS + +使用 [lambda 表达式](/tidb-cloud-lake/sql/stored-procedure-scripting.md#lambda-expressions) 对 JSON 对象中的每个键应用转换。 + +## 语法 {#syntax} + +```sql +MAP_TRANSFORM_KEYS(, (, ) -> ) +``` + +## 返回类型 {#return-type} + +返回一个 JSON 对象,其值与输入 JSON 对象相同,但键会根据指定的 lambda 转换进行修改。 + +## 示例 {#examples} + +以下示例为每个键追加 `"_v1"`,从而创建一个键已修改的新 JSON 对象: + +```sql +SELECT MAP_TRANSFORM_KEYS('{"name":"John", "role":"admin"}'::VARIANT, (k, v) -> CONCAT(k, '_v1')) AS versioned_metadata; + +┌──────────────────────────────────────┐ +│ versioned_metadata │ +├──────────────────────────────────────┤ +│ {"name_v1":"John","role_v1":"admin"} │ +└──────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/map-transform-values.md b/tidb-cloud-lake/sql/map-transform-values.md new file mode 100644 index 0000000000000..1b07b5b128fd1 --- /dev/null +++ b/tidb-cloud-lake/sql/map-transform-values.md @@ -0,0 +1,32 @@ +--- +title: MAP_TRANSFORM_VALUES +summary: 使用 [Lambda 表达式](/tidb-cloud-lake/sql/stored-procedure-scripting.md#lambda-expressions) 对 JSON 对象中的每个值应用转换。 +--- + +# MAP_TRANSFORM_VALUES + +使用 [Lambda 表达式](/tidb-cloud-lake/sql/stored-procedure-scripting.md#lambda-expressions) 对 JSON 对象中的每个值应用转换。 + +## 语法 {#syntax} + +```sql +MAP_TRANSFORM_VALUES(, (, ) -> ) +``` + +## 返回类型 {#return-type} + +返回一个 JSON 对象,其键与输入的 JSON 对象相同,但值会根据指定的 lambda 转换进行修改。 + +## 示例 {#examples} + +以下示例将每个数值乘以 10,把原始对象转换为 `{"a":10,"b":20}`: + +```sql +SELECT MAP_TRANSFORM_VALUES('{"a":1,"b":2}'::VARIANT, (k, v) -> v * 10) AS transformed_values; + +┌────────────────────┐ +│ transformed_values │ +├────────────────────┤ +│ {"a":10,"b":20} │ +└────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/map-values.md b/tidb-cloud-lake/sql/map-values.md new file mode 100644 index 0000000000000..4650ab5bd579f --- /dev/null +++ b/tidb-cloud-lake/sql/map-values.md @@ -0,0 +1,36 @@ +--- +title: MAP_VALUES +summary: 返回 map 中的值。 +--- + +# MAP_VALUES + +返回 map 中的值。 + +## 语法 {#syntax} + +```sql +MAP_VALUES( ) +``` + +## 参数 {#arguments} + +| 参数 | 描述 | +|-----------|----------------| +| `` | 输入的 map。 | + +## 返回类型 {#return-type} + +Array。 + +## 示例 {#examples} + +```sql +SELECT MAP_VALUES({'a':1,'b':2,'c':3}); + +┌─────────────────────────────────┐ +│ map_values({'a':1,'b':2,'c':3}) │ +├─────────────────────────────────┤ +│ [1,2,3] │ +└─────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/map.md b/tidb-cloud-lake/sql/map.md new file mode 100644 index 0000000000000..d91699fe7c629 --- /dev/null +++ b/tidb-cloud-lake/sql/map.md @@ -0,0 +1,126 @@ +--- +title: Map +summary: `MAP(K, V)` 以 `ARRAY(TUPLE(key, value))` 的形式在内部存储键值对。需要预先定义键类型 `K`(Boolean、numeric、decimal、string、date 或 timestamp)。键必须为非空且唯一;值可以是任意类型,包括嵌套结构。可以使用 map 字面量(`{key: value}`)或 `MAP(keys, values)` 函数来构建 map 表达式。 +--- + +# Map + +## 概述 {#overview} + +`MAP(K, V)` 以 `ARRAY(TUPLE(key, value))` 的形式在内部存储键值对。需要预先定义键类型 `K`(Boolean、numeric、decimal、string、date 或 timestamp)。键必须为非空且唯一;值可以是任意类型,包括嵌套结构。可以使用 map 字面量(`{key: value}`)或 `MAP(keys, values)` 函数来构建 map 表达式。 + +```sql +SELECT + {'k1': 1, 'k2': 2} AS literal_map, + MAP(['x', 'y'], [10, 20]) AS from_arrays; +``` + +结果: + +``` +┌───────────────────────┬──────────────────┐ +│ literal_map │ from_arrays │ +├───────────────────────┼──────────────────┤ +│ {'k1':1,'k2':2} │ {'x':10,'y':20} │ +└───────────────────────┴──────────────────┘ +``` + +## 示例 {#examples} + +### 创建和查询 {#create-and-query} + +```sql +CREATE TABLE web_traffic_data ( + id INT64, + traffic_info MAP(STRING, STRING) +); + +INSERT INTO web_traffic_data VALUES + (1, {'ip': '192.168.1.1', 'url': 'example.com/home'}), + (2, {'ip': '192.168.1.2', 'url': 'example.com/about'}), + (3, {'ip': '192.168.1.1', 'url': 'example.com/contact'}); + +SELECT + id, + traffic_info['ip'] AS ip_address, + traffic_info['url'] AS url +FROM web_traffic_data; +``` + +结果: + +``` +┌────┬─────────────┬───────────────────────┐ +│ id │ ip_address │ url │ +├────┼─────────────┼───────────────────────┤ +│ 1 │ 192.168.1.1 │ example.com/home │ +│ 2 │ 192.168.1.2 │ example.com/about │ +│ 3 │ 192.168.1.1 │ example.com/contact │ +└────┴─────────────┴───────────────────────┘ +``` + +```sql +SELECT + traffic_info['ip'] AS ip_address, + COUNT(*) AS visits +FROM web_traffic_data +GROUP BY traffic_info['ip'] +ORDER BY visits DESC; +``` + +结果: + +``` +┌─────────────┬────────┐ +│ ip_address │ visits │ +├─────────────┼────────┤ +│ 192.168.1.1 │ 2 │ +│ 192.168.1.2 │ 1 │ +└─────────────┴────────┘ +``` + +### 布隆过滤器索引 {#bloom-filter-index} + +Map 列会针对受支持的值类型(numeric、string、timestamp、date)自动维护布隆过滤器。在 `map['key']` 上进行过滤时,如果该值不存在,可以快速跳过数据块。 + +```sql +CREATE TABLE nginx_log ( + id INT, + log MAP(STRING, STRING) +); + +INSERT INTO nginx_log VALUES + (1, {'ip': '205.91.162.148', 'url': 'test-1'}), + (2, {'ip': '205.91.162.141', 'url': 'test-2'}); +``` + +```sql +SELECT * +FROM nginx_log +WHERE log['ip'] = '205.91.162.148'; +``` + +结果: + +``` +┌────┬─────────────────────────────────────────┐ +│ id │ log │ +├────┼─────────────────────────────────────────┤ +│ 1 │ {'ip':'205.91.162.148','url':'test-1'} │ +└────┴─────────────────────────────────────────┘ +``` + +```sql +SELECT * +FROM nginx_log +WHERE log['ip'] = '205.91.162.200'; +``` + +结果: + +``` +┌────┬────┐ +│ id │ log │ +├────┼────┤ +└────┴────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/markov-generate.md b/tidb-cloud-lake/sql/markov-generate.md new file mode 100644 index 0000000000000..30b5ed924e2e4 --- /dev/null +++ b/tidb-cloud-lake/sql/markov-generate.md @@ -0,0 +1,70 @@ +--- +title: MARKOV_GENERATE +summary: 使用由 MARKOV_TRAIN 训练得到的模型对数据集进行匿名化。 +--- + +# MARKOV_GENERATE + +使用由 [MARKOV_TRAIN](/tidb-cloud-lake/sql/markov-train.md) 训练得到的模型对数据集进行匿名化。 + +## 语法 {#syntax} + +```sql +MARKOV_GENERATE( , , , ) +``` + +## 参数 {#arguments} + +| 参数 | 描述 | +| ----------- | ----------- | +| `model` | markov_train 返回的模型 | +| `params`| Json 字符串:`{"order": 5, "sliding_window_size": 8}`
order:用于生成字符串的 markov model 的阶数,
源字符串中滑动窗口的大小——其哈希值会作为 markov model 中 RNG 的 seed | +| `seed` | seed | +| `determinator`| 源字符串 | + +## 返回类型 {#return-type} + +字符串。 + +## 示例 {#examples} + +从较小的数据填充集合中生成多个类似 PII 的列(name + email): + +```sql +-- 1) Train separate models on names and emails (PII text) +CREATE TABLE markov_name_model AS +SELECT markov_train(name) AS model +FROM ( + VALUES ('Alice Johnson'),('Bob Smith'),('Carol Davis'),('David Miller'),('Emma Wilson'), + ('Frank Brown'),('Grace Lee'),('Henry Clark'),('Irene Torres'),('Jack White') +) AS t(name); + +CREATE TABLE markov_email_model AS +SELECT markov_train(email) AS model +FROM ( + VALUES ('alice.johnson@gmail.com'),('bob.smith@yahoo.com'),('carol.davis@outlook.com'), + ('david.miller@example.com'),('emma.wilson@example.com'),('frank.brown@gmail.com'), + ('grace.lee@example.com'),('henry.clark@example.com'),('irene.torres@example.com'), + ('jack.white@example.com') +) AS t(email); + +-- 2) Generate synthetic name + email pairs; seed keeps it reproducible +SELECT + markov_generate(n.model, '{"order":3,"sliding_window_size":12}', 3030, CONCAT('orig_', number)) AS fake_name, + markov_generate(e.model, '{"order":3,"sliding_window_size":12}', 3030, CONCAT('orig_', number, '@example.com')) AS fake_email +FROM numbers(6) +JOIN markov_name_model n +JOIN markov_email_model e +LIMIT 6; +-- Sample output ++----------------+-------------------------+ +| fake_name | fake_email | ++----------------+-------------------------+ +| Frank Brown | henry.clark@example | +| Grace Johnso | quinn.foster@example | +| Rachel | paul.adams@example | +| Carol David | olivia.baker@example | +| Jack White | frank.brown@gmail.com | +| Noah Harris | race.johnson@example | ++----------------+-------------------------+ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/markov-train.md b/tidb-cloud-lake/sql/markov-train.md new file mode 100644 index 0000000000000..9ec92a8916355 --- /dev/null +++ b/tidb-cloud-lake/sql/markov-train.md @@ -0,0 +1,52 @@ +--- +title: MARKOV_TRAIN +summary: 使用 Markov 模型从数据集中提取模式。 +--- + +# MARKOV_TRAIN + +使用 Markov 模型从数据集中提取模式 + +## 语法 {#syntax} + +```sql +MARKOV_TRAIN() + +MARKOV_TRAIN()() + +MARKOV_TRAIN(, , , , ) () +``` + +## 参数 {#arguments} + +| 参数 | 描述 | +|------------------| ------------------ | +| `string` | 输入 | +| `order` | 用于生成字符串的 Markov 模型阶数 | +| `frequency-cutoff` | Markov 模型的频率截断:移除所有计数小于指定值的存储桶 | +| `num-buckets-cutoff` | 上下文可用的不同后续项数量的截断值:移除所有存储桶数量小于指定值的直方图 | +| `frequency-add` | 为每个计数增加一个常数,以降低概率分布偏斜 | +| `frequency-desaturate` | 0..1 - 将每个频率向平均值移动,以降低概率分布偏斜 | + +## 返回类型 {#return-type} + +根据具体实现,它仅用作 [MARKOV_GENERATE](/tidb-cloud-lake/sql/markov-generate.md) 的参数。 + +## 示例 {#examples} + +```sql +create table model as +select markov_train(concat('bar', number::string)) as bar from numbers(100); + +select markov_generate(bar,'{"order":5,"sliding_window_size":8}', 151, (number+100000)::string) as generate +from numbers(5), model; ++-----------+ +| generate | ++-----------+ +│ bar95 │ +│ bar64 │ +│ bar85 │ +│ bar56 │ +│ bar95 │ ++-----------+ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/masking-policy-sql.md b/tidb-cloud-lake/sql/masking-policy-sql.md new file mode 100644 index 0000000000000..0f61a199e7515 --- /dev/null +++ b/tidb-cloud-lake/sql/masking-policy-sql.md @@ -0,0 +1,24 @@ +--- +title: 脱敏策略 +summary: 本页按功能分类,全面概述了 {{{ .lake }}} 中脱敏策略的相关操作,便于参考。 +--- + +# 脱敏策略 + +本页按功能分类,全面概述了 {{{ .lake }}} 中脱敏策略的相关操作,便于参考。 + +## 脱敏策略管理 {#masking-policy-management} + +| 命令 | 描述 | +|---------|-------------| +| [CREATE MASKING POLICY](/tidb-cloud-lake/sql/create-masking-policy.md) | 创建新的脱敏策略,用于数据混淆 | +| [DESCRIBE MASKING POLICY](/tidb-cloud-lake/sql/desc-masking-policy.md) | 显示特定脱敏策略的详细信息 | +| [DROP MASKING POLICY](/tidb-cloud-lake/sql/drop-masking-policy.md) | 删除脱敏策略 | + +## 相关主题 {#related-topics} + +- [脱敏策略](/tidb-cloud-lake/guides/masking-policy.md) + +> **注意:** +> +> {{{ .lake }}} 中的脱敏策略允许你在缺少适当权限的用户查询数据时,通过动态转换或混淆数据来保护敏感信息。 \ No newline at end of file diff --git a/tidb-cloud-lake/sql/match.md b/tidb-cloud-lake/sql/match.md new file mode 100644 index 0000000000000..573ae7676dadf --- /dev/null +++ b/tidb-cloud-lake/sql/match.md @@ -0,0 +1,75 @@ +--- +title: MATCH +summary: 在已建立索引的列中搜索与关键字匹配的内容,并且只能在 WHERE 子句中使用。 +--- + +# MATCH + +`MATCH` 用于在列出的列中搜索包含给定关键字的行。该函数只能出现在 `WHERE` 子句中。 + +> **Note:** +> +> {{{ .lake }}} 的 MATCH 函数受 Elasticsearch 的 [MATCH](https://www.elastic.co/guide/en/elasticsearch/reference/current/sql-functions-search.html#sql-functions-search-match) 启发。 + +## 语法 {#syntax} + +```sql +MATCH('', ''[, '']) +``` + +- ``:要搜索的列列表,以逗号分隔。可追加 `^` 以提高某一列相对于其他列的权重。 +- ``:要搜索的词项。可追加 `*` 进行后缀匹配,例如 `rust*`。 +- ``:可选参数,以分号分隔的 `key=value` 列表,用于微调搜索行为。 + +## 选项 {#options} + +| 选项 | 取值 | 描述 | 示例 | +|--------|--------|-------------|---------| +| `fuzziness` | `1` 或 `2` | 在指定的 Levenshtein 距离内匹配关键字。 | `MATCH('summary, tags', 'pedestrain', 'fuzziness=1')` 可匹配包含正确拼写 `pedestrian` 的行。 | +| `operator` | `OR`(默认)或 `AND` | 当未指定布尔运算符时,控制如何组合多个关键字。 | `MATCH('summary, tags', 'traffic light red', 'operator=AND')` 要求同时包含这些词。 | +| `lenient` | `true` 或 `false` | 当为 `true` 时,抑制解析错误并返回空结果集。 | `MATCH('summary, tags', '()', 'lenient=true')` 会返回空结果,而不是报错。 | + +## 示例 {#examples} + +在许多 AI 流水线中,你可能会在 `VARIANT` 列中保存结构化元信息,同时将便于人类阅读的摘要物化出来以供搜索。以下示例存储了从 JSON 负载中提取的行车记录仪帧摘要和标签。 + +### 示例:构建可搜索的摘要 {#example-build-searchable-summaries} + +```sql +CREATE OR REPLACE TABLE frame_notes ( + id INT, + camera STRING, + summary STRING, + tags STRING, + INVERTED INDEX idx_notes (summary, tags) +); + +INSERT INTO frame_notes VALUES + (1, 'dashcam_front', + 'Green light at Market & 5th with pedestrian entering the crosswalk', + 'downtown commute green-light pedestrian'), + (2, 'dashcam_front', + 'Vehicle stopped at Mission & 6th red traffic light with cyclist ahead', + 'stop urban red-light cyclist'), + (3, 'dashcam_front', + 'School zone caution sign in SOMA with pedestrian waiting near crosswalk', + 'school-zone caution pedestrian'); +``` + +### 示例:布尔 AND {#example-boolean-and} + +```sql +SELECT id, summary +FROM frame_notes +WHERE MATCH('summary, tags', 'traffic light red', 'operator=AND'); +-- Returns id 2 +``` + +### 示例:模糊匹配 {#example-fuzzy-matching} + +```sql +SELECT id, summary +FROM frame_notes +WHERE MATCH('summary^2, tags', 'pedestrain', 'fuzziness=1'); +-- Returns ids 1 and 3 +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/materialized-view.md b/tidb-cloud-lake/sql/materialized-view.md new file mode 100644 index 0000000000000..90e0bd458a4d2 --- /dev/null +++ b/tidb-cloud-lake/sql/materialized-view.md @@ -0,0 +1,110 @@ +--- +title: 物化视图 +summary: 物化视图会将查询结果以物理方式存储。在创建物化视图时,TiDB Cloud Lake 会对源表启用变更跟踪。 +--- + +# 物化视图 + +物化视图会将查询结果以物理方式存储。它定义在 `default` catalog 中的一张持久化 FUSE 表之上。在创建物化视图时,{{{ .lake }}} 会对源表启用变更跟踪。 + +与逻辑视图不同,物化视图可以通过显式刷新来持久化其源表中的变更。即使物理存储落后于源表,读也能保持一致。在第一次刷新之前,{{{ .lake }}} 会根据源表计算该定义。当源表存在尚未刷新的变更时,{{{ .lake }}} 会使用 **read fix**:在读取时,将已持久化的物化视图数据与所需的源表增量数据进行联合体,并对该增量应用视图定义。因此,查询会返回当前结果,而不是过期的物化数据。 + +## 限制 {#limitations} + +- 定义必须是基于且仅基于一张基表的简单 `SELECT ... FROM ... [WHERE ...] [GROUP BY ...]` 查询。不支持 Join、子查询、集合操作以及非确定性函数。 +- 聚合仅支持 `sum`、`min`、`max`、`avg`、`count` 和 `approx_count_distinct`。不支持 `DISTINCT`、`FILTER`、窗口函数以及带排序的聚合形式。 +- 源必须是 `default` catalog 中的持久化 FUSE 基表。物化视图不能将其他视图或不同表引擎的表作为源。 +- 物化视图是只读的。请使用 `REFRESH MATERIALIZED VIEW` 来维护其内容;不支持 `INSERT`、`UPDATE`、`DELETE`、`TRUNCATE` 和普通的 `ALTER TABLE` 操作。 + +## 创建物化视图 {#create-a-materialized-view} + +```sql +CREATE [ OR REPLACE ] MATERIALIZED VIEW [ IF NOT EXISTS ] + [ . ][ . ] + [ ( , ... ) ] + [ CLUSTER BY ( , ... ) ] + [ COMMENT = '' ] + [ = ... ] +AS +``` + +`CLUSTER BY` 需要显式列列表,并且可以引用非聚合输出列或 `GROUP BY` 键。可选的 Fuse 表选项用于控制物理存储布局;支持的选项请参见 [CREATE TABLE](/tidb-cloud-lake/sql/create-table.md)。 + +创建操作会记录定义,但不会同步地填充物理存储。请运行 `REFRESH MATERIALIZED VIEW` 以物化初始数据。 + +```sql +CREATE TABLE orders ( + order_id INT, + customer_id INT, + amount DECIMAL(10, 2), + paid BOOLEAN +); + +CREATE MATERIALIZED VIEW paid_orders_by_customer + (customer_id, total_amount, order_count) + CLUSTER BY (customer_id) + COMMENT = 'Paid-order totals by customer' +AS +SELECT customer_id, sum(amount), count(*) +FROM orders +WHERE paid +GROUP BY customer_id; + +REFRESH MATERIALIZED VIEW paid_orders_by_customer; +``` + +`CREATE OR REPLACE` 会替换现有的物化视图。若名称已存在,`IF NOT EXISTS` 不会执行任何操作。 + +## 刷新物化视图 {#refresh-a-materialized-view} + +```sql +REFRESH MATERIALIZED VIEW [ . ][ . ] +``` + +第一次刷新会将源数据物化。后续刷新会对仅追加的变更进行增量地处理。如果源表存在 `UPDATE`、`DELETE` 或 `TRUNCATE` 变更,{{{ .lake }}} 会根据当前源状态重建物化视图,以确保结果正确。 + +## 修改物理布局 {#change-physical-layout} + +对于支持的维护操作,请使用专用的 `ALTER MATERIALIZED VIEW` 语法: + +```sql +ALTER MATERIALIZED VIEW CLUSTER BY ( , ... ); +ALTER MATERIALIZED VIEW DROP CLUSTER KEY; +ALTER MATERIALIZED VIEW RECLUSTER [ FINAL ] [ LIMIT ]; +ALTER MATERIALIZED VIEW SET OPTIONS (
'[, seed => ]) +``` + +## 示例 {#examples} + +```sql +CREATE OR REPLACE TABLE demo_customers AS +SELECT * +FROM ( + VALUES + (1,'Alice Johnson','alice.johnson@gmail.com','555-123-0001','123 Maple St, Springfield, IL'), + (2,'Bob Smith','bob.smith@yahoo.com','555-123-0002','456 Oak Ave, Dayton, OH'), + (3,'Carol Davis','carol.davis@outlook.com','555-123-0003','789 Pine Rd, Austin, TX'), + (4,'David Miller','david.miller@example.com','555-123-0004','321 Birch Blvd, Denver, CO'), + (5,'Emma Wilson','emma.wilson@example.com','555-123-0005','654 Cedar Ln, Seattle, WA'), + (6,'Frank Brown','frank.brown@gmail.com','555-123-0006','987 Walnut Dr, Portland, OR'), + (7,'Grace Lee','grace.lee@example.com','555-123-0007','159 Ash Ct, Boston, MA'), + (8,'Henry Clark','henry.clark@example.com','555-123-0008','753 Elm St, Phoenix, AZ') +) AS t(id, full_name, email, phone, address); + +-- 一次调用即可完成整表脱敏;seed 可确保结果可复现 +SELECT * FROM obfuscate(demo_customers, seed=>2025) +ORDER BY id; + +-- 示例输出 +┌────id┬───────────────┬────────────────────────────────┬──────────────┬────────────────────────────────────┐ +│ 1 │ Alice Johnson │ emma.wilson@example.com │ 555-123-0002 │ 123 Maple St, Phoenix, AZ │ +│ 2 │ Alice Johnson │ grace.lee@example.com │ 555-123-0007 │ 753 Elm St, Phoenix, AZ │ +│ 3 │ David Miller │ frank.brown@gmail.com │ 555-123-0001 │ 321 Birch Blvd, Denver, │ +│ 4 │ Alice Johnson │ emma.wilson@example.com │ 555-123-0001 │ 654 Cedar Ln, Seattle, WA │ +│ 5 │ Grace Lee │ carol.david.miller@example │ 555-123-0003 │ 123 Maple St, Phoenix, AZ │ +│ 6 │ Carol David │ emma.wilson@example.com │ 555-123-0003 │ 654 Cedar Ln, Seattle, │ +│ 7 │ Emma Wilson │ bob.smith@yahoo.com │ 555-123-0004 │ 456 Oak Ave, Dayton, MA │ +│ 9 │ Carol David │ frank.brown@gmail.com │ 555-123-0006 │ 456 Oak Ave, Dayton, MA │ +└──────┴───────────────┴────────────────────────────────┴──────────────┴────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/object-construct-keep-null.md b/tidb-cloud-lake/sql/object-construct-keep-null.md new file mode 100644 index 0000000000000..4915a87df706e --- /dev/null +++ b/tidb-cloud-lake/sql/object-construct-keep-null.md @@ -0,0 +1,69 @@ +--- +title: OBJECT_CONSTRUCT_KEEP_NULL +summary: 创建包含键和值的 JSON 对象。 +--- + +# OBJECT_CONSTRUCT_KEEP_NULL + +创建包含键和值的 JSON 对象。 + +- 参数是零个或多个键值对(其中键为字符串,值可以是任意类型)。 +- 如果键为 NULL,则结果对象中会省略该键值对。但是,如果值为 NULL,则会保留该键值对。 +- 键之间必须互不相同,并且结果 JSON 中键的顺序可能与您指定的顺序不同。 +- `TRY_OBJECT_CONSTRUCT_KEEP_NULL` 在构建对象时如果发生错误,会返回 NULL 值。 + +## 别名 {#aliases} + +- `JSON_OBJECT_KEEP_NULL` +- `TRY_JSON_OBJECT_KEEP_NULL` + +另请参阅:[OBJECT_CONSTRUCT](/tidb-cloud-lake/sql/object-construct.md) + +## 语法 {#syntax} + +```sql +OBJECT_CONSTRUCT_KEEP_NULL(key1, value1[, key2, value2[, ...]]) + +TRY_OBJECT_CONSTRUCT_KEEP_NULL(key1, value1[, key2, value2[, ...]]) +``` + +## 返回类型 {#return-type} + +JSON 对象。 + +## 示例 {#examples} + +```sql +SELECT OBJECT_CONSTRUCT_KEEP_NULL(); +┌──────────────────────────────┐ +│ object_construct_keep_null() │ +├──────────────────────────────┤ +│ {} │ +└──────────────────────────────┘ + +SELECT OBJECT_CONSTRUCT_KEEP_NULL('a', 3.14, 'b', 'xx', 'c', NULL); +┌───────────────────────────────────────────────────────────┐ +│ object_construct_keep_null('a', 3.14, 'b', 'xx', 'c', null) │ +├───────────────────────────────────────────────────────────┤ +│ {"a":3.14,"b":"xx","c":null} │ +└───────────────────────────────────────────────────────────┘ + +SELECT OBJECT_CONSTRUCT_KEEP_NULL('fruits', ['apple', 'banana', 'orange'], 'vegetables', ['carrot', 'celery']); +┌───────────────────────────────────────────────────────────────────────────────────────────────────────┐ +│ object_construct_keep_null('fruits', ['apple', 'banana', 'orange'], 'vegetables', ['carrot', 'celery']) │ +├───────────────────────────────────────────────────────────────────────────────────────────────────────┤ +│ {"fruits":["apple","banana","orange"],"vegetables":["carrot","celery"]} │ +└───────────────────────────────────────────────────────────────────────────────────────────────────────┘ + +SELECT OBJECT_CONSTRUCT_KEEP_NULL('key'); + | +1 | SELECT OBJECT_CONSTRUCT_KEEP_NULL('key') + | ^^^^^^^^^^^^^^^^^^ The number of keys and values must be equal while evaluating function `object_construct_keep_null('key')` + +SELECT TRY_OBJECT_CONSTRUCT_KEEP_NULL('key'); +┌─────────────────────────────────────┐ +│ try_object_construct_keep_null('key') │ +├─────────────────────────────────────┤ +│ NULL │ +└─────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/object-construct.md b/tidb-cloud-lake/sql/object-construct.md new file mode 100644 index 0000000000000..99b53831eade4 --- /dev/null +++ b/tidb-cloud-lake/sql/object-construct.md @@ -0,0 +1,69 @@ +--- +title: OBJECT_CONSTRUCT +summary: 创建包含键和值的 JSON 对象。 +--- + +# OBJECT_CONSTRUCT + +创建包含键和值的 JSON 对象。 + +- 参数是零个或多个键值对(其中键为字符串,值可以是任意类型)。 +- 如果键或值为 NULL,则该键值对会从结果对象中省略。 +- 键之间必须互不相同,并且结果 JSON 中键的顺序可能与您指定的顺序不同。 +- `TRY_OBJECT_CONSTRUCT` 在构建对象时如果发生错误,会返回 NULL 值。 + +## 别名 {#aliases} + +- `JSON_OBJECT` +- `TRY_JSON_OBJECT` + +另请参阅:[OBJECT_CONSTRUCT_KEEP_NULL](/tidb-cloud-lake/sql/object-construct-keep-null.md) + +## 语法 {#syntax} + +```sql +OBJECT_CONSTRUCT(key1, value1[, key2, value2[, ...]]) + +TRY_OBJECT_CONSTRUCT(key1, value1[, key2, value2[, ...]]) +``` + +## 返回类型 {#return-type} + +JSON 对象。 + +## 示例 {#examples} + +```sql +SELECT OBJECT_CONSTRUCT(); +┌────────────────┐ +│ object_construct() │ +├────────────────┤ +│ {} │ +└────────────────┘ + +SELECT OBJECT_CONSTRUCT('a', 3.14, 'b', 'xx', 'c', NULL); +┌──────────────────────────────────────────────┐ +│ object_construct('a', 3.14, 'b', 'xx', 'c', null) │ +├──────────────────────────────────────────────┤ +│ {"a":3.14,"b":"xx"} │ +└──────────────────────────────────────────────┘ + +SELECT OBJECT_CONSTRUCT('fruits', ['apple', 'banana', 'orange'], 'vegetables', ['carrot', 'celery']); +┌──────────────────────────────────────────────────────────────────────────────────────────┐ +│ object_construct('fruits', ['apple', 'banana', 'orange'], 'vegetables', ['carrot', 'celery']) │ +├──────────────────────────────────────────────────────────────────────────────────────────┤ +│ {"fruits":["apple","banana","orange"],"vegetables":["carrot","celery"]} │ +└──────────────────────────────────────────────────────────────────────────────────────────┘ + +SELECT OBJECT_CONSTRUCT('key'); + | +1 | SELECT OBJECT_CONSTRUCT('key') + | ^^^^^^^^^^^^^^^^^^ The number of keys and values must be equal while evaluating function `object_construct('key')` + +SELECT TRY_OBJECT_CONSTRUCT('key'); +┌───────────────────────────┐ +│ try_object_construct('key') │ +├───────────────────────────┤ +│ NULL │ +└───────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/object-delete.md b/tidb-cloud-lake/sql/object-delete.md new file mode 100644 index 0000000000000..5bf17444de083 --- /dev/null +++ b/tidb-cloud-lake/sql/object-delete.md @@ -0,0 +1,52 @@ +--- +title: OBJECT_DELETE +summary: 从 JSON 对象中删除指定的键,并返回修改后的对象。如果指定的键在对象中不存在,则会被忽略。 +--- + +# OBJECT_DELETE + +从 JSON 对象中删除指定的键,并返回修改后的对象。如果指定的键在对象中不存在,则会被忽略。 + +## 别名 {#aliases} + +- `JSON_OBJECT_DELETE` + +## 语法 {#syntax} + +```sql +OBJECT_DELETE(, [, , ...]) +``` + +## 参数 {#parameters} + +| 参数 | 描述 | +|-----------|-------------| +| json_object | 要从中删除键的 JSON 对象(VARIANT 类型)。 | +| key1, key2, ... | 一个或多个字符串字面量,表示要从对象中删除的键。 | + +## 返回类型 {#return-type} + +返回一个 VARIANT,其中包含已删除指定键后的 JSON 对象。 + +## 示例 {#examples} + +删除单个键: + +```sql +SELECT OBJECT_DELETE('{"a":1,"b":2,"c":3}'::VARIANT, 'a'); +-- Result: {"b":2,"c":3} +``` + +删除多个键: + +```sql +SELECT OBJECT_DELETE('{"a":1,"b":2,"d":4}'::VARIANT, 'a', 'c'); +-- Result: {"b":2,"d":4} +``` + +删除不存在的键(该键会被忽略): + +```sql +SELECT OBJECT_DELETE('{"a":1,"b":2}'::VARIANT, 'x'); +-- Result: {"a":1,"b":2} +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/object-functions.md b/tidb-cloud-lake/sql/object-functions.md new file mode 100644 index 0000000000000..5a4dc4b0418a0 --- /dev/null +++ b/tidb-cloud-lake/sql/object-functions.md @@ -0,0 +1,34 @@ +--- +title: 对象函数 +summary: 本节提供 {{{ .lake }}} 中对象函数的参考信息。对象函数支持从 JSON 对象数据结构中创建、操作和提取信息。 +--- + +# 对象函数 + +本节提供 {{{ .lake }}} 中对象函数的参考信息。对象函数支持从 JSON 对象数据结构中创建、操作和提取信息。 + +## 对象构造 {#object-construction} + +| 函数 | 描述 | 示例 | +|----------|-------------|---------| +| [OBJECT_CONSTRUCT](/tidb-cloud-lake/sql/object-construct.md) | 从键值对创建 JSON 对象 | `OBJECT_CONSTRUCT('name', 'John', 'age', 30)` → `{"name":"John","age":30}` | +| [OBJECT_CONSTRUCT_KEEP_NULL](/tidb-cloud-lake/sql/object-construct-keep-null.md) | 创建 JSON 对象并保留空值 | `OBJECT_CONSTRUCT_KEEP_NULL('a', 1, 'b', null)` → `{"a":1,"b":null}` | + +## 对象信息 {#object-information} + +| 函数 | 描述 | 示例 | +|----------|-------------|---------| +| [OBJECT_KEYS](/tidb-cloud-lake/sql/object-keys.md) | 以数组形式返回 JSON 对象中的所有键 | `OBJECT_KEYS({"name":"John","age":30})` → `["name","age"]` | + +## 对象修改 {#object-modification} + +| 函数 | 描述 | 示例 | +|----------|-------------|---------| +| [OBJECT_INSERT](/tidb-cloud-lake/sql/object-insert.md) | 在 JSON 对象中插入或修改键值对 | `OBJECT_INSERT({"name":"John"}, "age", 30)` → `{"name":"John","age":30}` | +| [OBJECT_DELETE](/tidb-cloud-lake/sql/object-delete.md) | 从 JSON 对象中移除键值对 | `OBJECT_DELETE({"name":"John","age":30}, "age")` → `{"name":"John"}` | + +## 对象选择 {#object-selection} + +| 函数 | 描述 | 示例 | +|----------|-------------|---------| +| [OBJECT_PICK](/tidb-cloud-lake/sql/object-pick.md) | 创建仅包含指定键的新对象 | `OBJECT_PICK({"a":1,"b":2,"c":3}, ["a","c"])` → `{"a":1,"c":3}` | \ No newline at end of file diff --git a/tidb-cloud-lake/sql/object-insert.md b/tidb-cloud-lake/sql/object-insert.md new file mode 100644 index 0000000000000..773bc67dcdb4b --- /dev/null +++ b/tidb-cloud-lake/sql/object-insert.md @@ -0,0 +1,63 @@ +--- +title: OBJECT_INSERT +summary: 在 JSON 对象中插入或修改一个键值对。 +--- + +# OBJECT_INSERT + +在 JSON 对象中插入或修改一个键值对。 + +## 别名 {#aliases} + +- `JSON_OBJECT_INSERT` + +## 语法 {#syntax} + +```sql +OBJECT_INSERT(, , [, ]) +``` + +| 参数 | 描述 | | +|---------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---| +| `` | 输入的 JSON 对象。 | | +| `` | 要插入或修改的键。 | | +| `` | 要赋给该键的值。 | | +| `` | 一个布尔(命令行)标记/参数,用于控制当指定键已存在于 JSON 对象中时是否替换其值。如果为 `true`,则当键已存在时,函数会替换该值。如果为 `false`(或省略),则如果该键已存在会报错。 | | + +## 返回类型 {#return-type} + +返回修改后的 JSON 对象。 + +## 示例 {#examples} + +以下示例演示如何在现有 JSON 对象中插入一个新键 `'c'`,其值为 3: + +```sql +SELECT OBJECT_INSERT('{"a":1,"b":2,"d":4}'::variant, 'c', 3); + +┌────────────────────────────────────────────────────────────┐ +│ object_insert('{"a":1,"b":2,"d":4}'::VARIANT, 'c', 3) │ +├────────────────────────────────────────────────────────────┤ +│ {"a":1,"b":2,"c":3,"d":4} │ +└────────────────────────────────────────────────────────────┘ +``` + +以下示例展示如何在将 update flag 设置为 `true` 的情况下,把现有键 `'a'` 的值从 1 修改为 10,从而允许替换该键的值: + +```sql +SELECT OBJECT_INSERT('{"a":1,"b":2,"d":4}'::variant, 'a', 10, true); + +┌───────────────────────────────────────────────────────────────────┐ +│ object_insert('{"a":1,"b":2,"d":4}'::VARIANT, 'a', 10, TRUE) │ +├───────────────────────────────────────────────────────────────────┤ +│ {"a":10,"b":2,"d":4} │ +└───────────────────────────────────────────────────────────────────┘ +``` + +以下示例演示了当尝试为已存在的键 `'a'` 插入值、但未将 update flag 指定为 `true` 时发生的错误: + +```sql +SELECT OBJECT_INSERT('{"a":1,"b":2,"d":4}'::variant, 'a', 10); + +error: APIError: ResponseError with 1006: ObjectDuplicateKey while evaluating function `object_insert('{"a":1,"b":2,"d":4}', 'a', 10)` in expr `object_insert('{"a":1,"b":2,"d":4}', 'a', 10)` +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/object-keys.md b/tidb-cloud-lake/sql/object-keys.md new file mode 100644 index 0000000000000..80bdcd4012723 --- /dev/null +++ b/tidb-cloud-lake/sql/object-keys.md @@ -0,0 +1,44 @@ +--- +title: OBJECT_KEYS +summary: 以字符串数组的形式返回最外层 JSON 对象的键。 +--- + +# OBJECT_KEYS + +以字符串数组的形式返回最外层 JSON 对象的键。 + +## 别名 {#aliases} + +- `JSON_OBJECT_KEYS` + +## 语法 {#syntax} + +```sql +OBJECT_KEYS() +``` + +## 返回类型 {#return-type} + +STRING 的 ARRAY。 + +## 示例 {#examples} + +```sql +SELECT OBJECT_KEYS('{"a":1, "b":2, "c": {"d":3}}'::VARIANT); + +-[ RECORD 1 ]----------------------------------- +object_keys('{"a":1, "b":2, "c": {"d":3}}'::VARIANT): ["a","b","c"] + +-- Example with a table +CREATE TABLE t (var VARIANT); +INSERT INTO t VALUES ('{"a":1, "b":2}'), ('{"x":10, "y":20}'); + +SELECT id, object_keys(var), json_object_keys(var) FROM t; + +┌───────────┬──────────────────┬───────────────────────┐ +│ id │ object_keys(var) │ json_object_keys(var) │ +├───────────┼──────────────────┼───────────────────────┤ +│ 1 │ ["a","b"] │ ["a","b"] │ +│ 2 │ ["x","y"] │ ["x","y"] │ +└───────────┴──────────────────┴───────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/object-pick.md b/tidb-cloud-lake/sql/object-pick.md new file mode 100644 index 0000000000000..8eedd214b9d04 --- /dev/null +++ b/tidb-cloud-lake/sql/object-pick.md @@ -0,0 +1,52 @@ +--- +title: OBJECT_PICK +summary: 创建一个新的 JSON 对象,该对象仅包含输入 JSON 对象中指定的键。如果指定的键在输入对象中不存在,则会在结果中省略。 +--- + +# OBJECT_PICK + +创建一个新的 JSON 对象,该对象仅包含输入 JSON 对象中指定的键。如果指定的键在输入对象中不存在,则会在结果中省略。 + +## 别名 {#aliases} + +- `JSON_OBJECT_PICK` + +## 语法 {#syntax} + +```sql +OBJECT_PICK(, [, , ...]) +``` + +## 参数 {#parameters} + +| 参数 | 描述 | +|-----------|-------------| +| json_object | 要从中选取键的 JSON 对象(VARIANT 类型)。 | +| key1, key2, ... | 一个或多个字符串字面量,表示要包含在结果对象中的键。 | + +## 返回类型 {#return-type} + +返回一个 VARIANT,其中包含一个仅带有指定键及其对应值的新 JSON 对象。 + +## 示例 {#examples} + +选取单个键: + +```sql +SELECT OBJECT_PICK('{"a":1,"b":2,"c":3}'::VARIANT, 'a'); +-- Result: {"a":1} +``` + +选取多个键: + +```sql +SELECT OBJECT_PICK('{"a":1,"b":2,"d":4}'::VARIANT, 'a', 'b'); +-- Result: {"a":1,"b":2} +``` + +选取包含不存在的键的情况(不存在的键会被忽略): + +```sql +SELECT OBJECT_PICK('{"a":1,"b":2,"d":4}'::VARIANT, 'a', 'c'); +-- Result: {"a":1} +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/oct.md b/tidb-cloud-lake/sql/oct.md new file mode 100644 index 0000000000000..3a6986293ae98 --- /dev/null +++ b/tidb-cloud-lake/sql/oct.md @@ -0,0 +1,25 @@ +--- +title: OCT +summary: 返回 N 的八进制值的字符串表示。 +--- + +# OCT + +返回 N 的八进制值的字符串表示。 + +## 语法 {#syntax} + +```sql +OCT() +``` + +## 示例 {#examples} + +```sql +SELECT OCT(12); ++---------+ +| OCT(12) | ++---------+ +| 014 | ++---------+ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/octet-length.md b/tidb-cloud-lake/sql/octet-length.md new file mode 100644 index 0000000000000..e5ee0866b878d --- /dev/null +++ b/tidb-cloud-lake/sql/octet-length.md @@ -0,0 +1,25 @@ +--- +title: OCTET_LENGTH +summary: OCTET_LENGTH() 是 LENGTH() 的同义词。 +--- + +# OCTET_LENGTH + +OCTET_LENGTH() 是 LENGTH() 的同义词。 + +## 语法 {#syntax} + +```sql +OCTET_LENGTH() +``` + +## 示例 {#examples} + +```sql +SELECT OCTET_LENGTH('datalake'); ++--------------------------+ +| OCTET_LENGTH('datalake') | ++--------------------------+ +| 8 | ++--------------------------+ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/optimize-table.md b/tidb-cloud-lake/sql/optimize-table.md new file mode 100644 index 0000000000000..72377a5760ee2 --- /dev/null +++ b/tidb-cloud-lake/sql/optimize-table.md @@ -0,0 +1,171 @@ +--- +title: OPTIMIZE TABLE +summary: 在 {{{ .lake }}} 中优化表涉及压缩或清除历史数据,以节省存储空间并提升查询性能。 +--- + +# OPTIMIZE TABLE + +在 {{{ .lake }}} 中优化表涉及压缩或清除历史数据,以节省存储空间并提升查询性能。 + +
+ 为什么要优化? +
{{{ .lake }}} 使用 Parquet 格式将数据存储在表中,而 Parquet 格式按 block 组织。此外,{{{ .lake }}} 支持 time travel 功能,其中每次对表进行修改的操作都会生成一个 Parquet 文件,用于捕获并反映对表所做的更改。

+ +
随着表随时间累积越来越多的 Parquet 文件,可能会导致性能问题并增加存储需求。为了优化表的性能,当历史 Parquet 文件不再需要时,可以将其删除。此类优化有助于提升查询性能,并减少表占用的存储空间。
+
+ +## {{{ .lake }}} 数据存储:Snapshot、Segment 和 Block {#lake-data-storage-snapshot-segment-and-block} + +Snapshot、segment 和 block 是 {{{ .lake }}} 用于数据存储的概念。{{{ .lake }}} 使用它们构建用于存储表数据的层次结构。 + +![Data storage structure](/media/tidb-cloud-lake/storage-structure.PNG) + +{{{ .lake }}} 会在数据修改后自动创建表 snapshot。snapshot 表示表 segment 元信息的一个版本。 + +在使用 {{{ .lake }}} 时,当你通过 [AT](/tidb-cloud-lake/sql/at.md) 子句检索并查询表数据的历史版本时,最可能通过 snapshot ID 来访问某个 snapshot。 + +snapshot 是一个 JSON 文件,它不保存表数据本身,而是指示该 snapshot 链接到哪些 segment。如果你对某个表执行 [FUSE_SNAPSHOT](/tidb-cloud-lake/sql/fuse-snapshot.md),可以查看该表已保存的 snapshots。 + +segment 是一个 JSON 文件,用于组织存储数据的 blocks(最少 1 个,最多 1,000 个)。如果你针对某个带有 snapshot ID 的 snapshot 执行 [FUSE_SEGMENT](/tidb-cloud-lake/sql/fuse-segment.md),可以查看该 snapshot 引用了哪些 segments。 + +{{{ .lake }}} 将实际的表数据保存在 Parquet 文件中,并将每个 Parquet 文件视为一个 block。如果你针对某个带有 snapshot ID 的 snapshot 执行 [FUSE_BLOCK](/tidb-cloud-lake/sql/fuse-block.md),可以查看该 snapshot 引用了哪些 blocks。 + +{{{ .lake }}} 会为每个数据库和表创建唯一 ID,用于存储 snapshot、segment 和 block 文件,并将它们保存在对象存储路径 `////` 下。每个 snapshot、segment 和 block 文件都以 UUID(32 个字符的小写十六进制字符串)命名。 + +| 文件 | 格式 | 文件名 | 存储目录 | +|----------|---------|---------------------------------|-----------------------------------------------------| +| Snapshot | JSON | `<32bitUUID>_.json` | `////_ss/` | +| Segment | JSON | `<32bitUUID>_.json` | `////_sg/` | +| Block | parquet | `<32bitUUID>_.parquet` | `////_b/` | + +## 表优化 {#table-optimizations} + +在 {{{ .lake }}} 中,建议将理想的 block 大小控制为 100MB(未压缩)或 1,000,000 行,并让每个 segment 包含 1,000 个 blocks。为了最大化表优化效果,关键在于清楚了解何时以及如何应用各种优化技术,例如 [Segment Compaction](#segment-compaction) 和 [Block Compaction](#block-compaction)。 + +- 当使用 COPY INTO 或 REPLACE INTO 命令向包含 cluster key 的表写入数据时,{{{ .lake }}} 会自动启动重新聚簇过程,以及 segment 和 block 的 compact 过程。 + +- Segment 和 block compaction 支持在集群环境中分布式执行。你可以通过将 ENABLE_DISTRIBUTED_COMPACT 设置为 1 来启用它们。这有助于提升集群环境中的数据查询性能和扩展性。 + + ```sql + SET enable_distributed_compact = 1; + ``` + +### Segment Compaction {#segment-compaction} + +当表中存在过多小 segment(每个 segment 少于 `100 blocks`)时,执行 segment compaction。 + +```sql +SELECT + block_count, + segment_count, + IF( + block_count / segment_count < 100, + 'The table needs segment compact now', + 'The table does not need segment compact now' + ) AS advice +FROM + fuse_snapshot('your-database', 'your-table') + LIMIT 1; +``` + +**语法** + +```sql +OPTIMIZE TABLE [database.]table_name COMPACT SEGMENT [LIMIT ] +``` + +通过将小 segments 合并为更大的 segments 来压缩表数据。 + +- 选项 LIMIT 用于设置要压缩的最大 segment 数量。在这种情况下,{{{ .lake }}} 会选择并压缩最新的 segments。 + +**示例** + +```sql +-- Check whether need segment compact +SELECT + block_count, + segment_count, + IF( + block_count / segment_count < 100, + 'The table needs segment compact now', + 'The table does not need segment compact now' + ) AS advice +FROM + fuse_snapshot('hits', 'hits'); + ++-------------+---------------+-------------------------------------+ +| block_count | segment_count | advice | ++-------------+---------------+-------------------------------------+ +| 751 | 32 | The table needs segment compact now | ++-------------+---------------+-------------------------------------+ + +-- Compact segment +OPTIMIZE TABLE hits COMPACT SEGMENT; + +-- Check again +SELECT + block_count, + segment_count, + IF( + block_count / segment_count < 100, + 'The table needs segment compact now', + 'The table does not need segment compact now' + ) AS advice +FROM + fuse_snapshot('hits', 'hits') + LIMIT 1; + ++-------------+---------------+---------------------------------------------+ +| block_count | segment_count | advice | ++-------------+---------------+---------------------------------------------+ +| 751 | 1 | The table does not need segment compact now | ++-------------+---------------+---------------------------------------------+ +``` + +### Block Compaction {#block-compaction} + +当表中存在大量小 blocks,或者表中插入、删除或修改的行占比较高时,执行 block compaction。 + +你可以通过检查每个 block 的未压缩大小是否接近理想值 `100MB` 来判断。 + +如果大小小于 `50MB`,建议执行 block compaction,因为这表明存在过多小 blocks: + +```sql +SELECT + block_count, + humanize_size(bytes_uncompressed / block_count) AS per_block_uncompressed_size, + IF( + bytes_uncompressed / block_count / 1024 / 1024 < 50, + 'The table needs block compact now', + 'The table does not need block compact now' + ) AS advice +FROM + fuse_snapshot('your-database', 'your-table') + LIMIT 1; +``` + +> **注意:** +> +> 我们建议先执行 segment compaction,再执行 block compaction。 + +**语法** + +```sql +OPTIMIZE TABLE [database.]table_name COMPACT [LIMIT ] +``` + +通过将小 blocks 和 segments 合并为更大的对象来压缩表数据。 + +- 此命令会基于最新的表数据创建一个新的 snapshot(以及压缩后的 segments 和 blocks),而不会影响现有存储文件,因此在清除历史数据之前,不会释放存储空间。 + +- 根据给定表的大小,执行完成可能需要较长时间。 + +- 选项 LIMIT 用于设置要压缩的最大 segment 数量。在这种情况下,{{{ .lake }}} 会选择并压缩最新的 segments。 + +- {{{ .lake }}} 会在压缩过程完成后,自动对 clustered table 重新进行聚簇。 + +**示例** + +```sql +OPTIMIZE TABLE my_database.my_table COMPACT LIMIT 50; +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/ord.md b/tidb-cloud-lake/sql/ord.md new file mode 100644 index 0000000000000..131749dde5ea1 --- /dev/null +++ b/tidb-cloud-lake/sql/ord.md @@ -0,0 +1,43 @@ +--- +title: ORD +summary: 如果最左侧字符不是多字节字符,ORD() 返回与 ASCII() 函数相同的值。 +--- + +# ORD + +如果最左侧字符不是多字节字符,ORD() 返回与 ASCII() 函数相同的值。 + +如果字符串 str 的最左侧字符是多字节字符,则返回该字符的编码。该编码根据其组成字节的数值,按以下公式计算: + +```sql + (1st byte code) ++ (2nd byte code * 256) ++ (3rd byte code * 256^2) ... +``` + +## 语法 {#syntax} + +```sql +ORD() +``` + +## 参数 {#arguments} + +| 参数 | 描述 | +|-----------|-------------| +| `` | 字符串。 | + +## 返回类型 {#return-type} + +`BIGINT` + +## 示例 {#examples} + +```sql +SELECT ORD('2') ++--------+ +| ORD(2) | ++--------+ +| 50 | ++--------+ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/other-functions.md b/tidb-cloud-lake/sql/other-functions.md new file mode 100644 index 0000000000000..2d1fcb6005f2b --- /dev/null +++ b/tidb-cloud-lake/sql/other-functions.md @@ -0,0 +1,20 @@ +--- +title: 其他函数 +summary: 本节汇总了不属于主要函数分组的各类实用工具。 +--- + +# 其他函数 + +本节汇总了不属于主要函数分组的各类实用工具。 + +| 函数 | 描述 | +|----------|-------------| +| [ASSUME_NOT_NULL](/tidb-cloud-lake/sql/assume-not-null.md) | 提示可为空列中的值永远不是 NULL | +| [EXISTS](/tidb-cloud-lake/sql/exists.md) | 如果子查询产生任意行,则返回 TRUE | +| [GROUPING](/tidb-cloud-lake/sql/grouping.md) | 指示输出列是否在 GROUPING SETS 中被聚合 | +| [HUMANIZE_NUMBER](/tidb-cloud-lake/sql/humanize-number.md) | 使用单位后缀格式化大数字 | +| [HUMANIZE_SIZE](/tidb-cloud-lake/sql/humanize-size.md) | 将字节数格式化为易读单位 | +| [READ_FILE](/tidb-cloud-lake/sql/read-file.md) | 从 stage 读取文件并返回其原始字节 | +| [REMOVE_NULLABLE](/tidb-cloud-lake/sql/remove-nullable.md) | 去除列值的 NULL 属性 | +| [TO_NULLABLE](/tidb-cloud-lake/sql/nullable.md) | 将值转换为可为空类型 | +| [TYPEOF](/tidb-cloud-lake/sql/typeof.md) | 返回值的数据类型名称 | \ No newline at end of file diff --git a/tidb-cloud-lake/sql/parse-json.md b/tidb-cloud-lake/sql/parse-json.md new file mode 100644 index 0000000000000..6aef7b8fde5f8 --- /dev/null +++ b/tidb-cloud-lake/sql/parse-json.md @@ -0,0 +1,45 @@ +--- +title: PARSE_JSON +summary: 解析 JSON 格式的字符串并返回一个 VARIANT 值。对于无效输入,使用 TRY_PARSE_JSON 返回 NULL 而不是报错。 +--- + +# PARSE_JSON + +`parse_json` 和 `try_parse_json` 将输入字符串解析为 JSON 文档,并生成一个 VARIANT 值。 + +如果在解析过程中发生错误,`try_parse_json` 会返回 NULL 值。 + +## 语法 {#syntax} + +```sql +PARSE_JSON() +TRY_PARSE_JSON() +``` + +## 参数 {#arguments} + +| 参数 | 描述 | +|-----------|--------------------------------------------------------------------------------| +| `` | 一个字符串类型的表达式(例如 VARCHAR),其中包含有效的 JSON 信息。 | + +## 返回类型 {#return-type} + +VARIANT + +## 示例 {#examples} + +```sql +SELECT parse_json('[-1, 12, 289, 2188, false]'); ++------------------------------------------+ +| parse_json('[-1, 12, 289, 2188, false]') | ++------------------------------------------+ +| [-1,12,289,2188,false] | ++------------------------------------------+ + +SELECT try_parse_json('{ "x" : "abc", "y" : false, "z": 10} '); ++---------------------------------------------------------+ +| try_parse_json('{ "x" : "abc", "y" : false, "z": 10} ') | ++---------------------------------------------------------+ +| {"x":"abc","y":false,"z":10} | ++---------------------------------------------------------+ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/password-policy-sql.md b/tidb-cloud-lake/sql/password-policy-sql.md new file mode 100644 index 0000000000000..fb82c594be140 --- /dev/null +++ b/tidb-cloud-lake/sql/password-policy-sql.md @@ -0,0 +1,31 @@ +--- +title: 密码策略 +summary: 本页按功能分类,全面介绍 {{{ .lake }}} 中 Password Policy 的相关操作,便于快速查阅。 +--- + +# 密码策略 + +本页按功能分类,全面介绍 {{{ .lake }}} 中 Password Policy 的相关操作,便于快速查阅。 + +## 密码策略管理 {#password-policy-management} + +| 命令 | 描述 | +|---------|-------------| +| [CREATE PASSWORD POLICY](/tidb-cloud-lake/sql/create-password-policy.md) | 创建具有特定要求的新密码策略 | +| [ALTER PASSWORD POLICY](/tidb-cloud-lake/sql/alter-password-policy.md) | 修改现有密码策略 | +| [DROP PASSWORD POLICY](/tidb-cloud-lake/sql/drop-password-policy.md) | 删除密码策略 | + +## 密码策略信息 {#password-policy-information} + +| 命令 | 描述 | +|---------|-------------| +| [DESCRIBE PASSWORD POLICY](/tidb-cloud-lake/sql/desc-password-policy.md) | 显示特定密码策略的详细信息 | +| [SHOW PASSWORD POLICIES](/tidb-cloud-lake/sql/show-password-policies.md) | 列出所有密码策略 | + +## 相关主题 {#related-topics} + +- [密码策略](/tidb-cloud-lake/guides/password-policy.md) + +> **注意:** +> +> {{{ .lake }}} 中的密码策略可用于对用户密码强制执行安全要求,例如最小长度、复杂度和过期规则。 \ No newline at end of file diff --git a/tidb-cloud-lake/sql/percent-rank.md b/tidb-cloud-lake/sql/percent-rank.md new file mode 100644 index 0000000000000..a94624abe5e39 --- /dev/null +++ b/tidb-cloud-lake/sql/percent-rank.md @@ -0,0 +1,73 @@ +--- +title: PERCENT_RANK +summary: 以百分比形式计算每一行的相对排名。返回介于 0 和 1 之间的值,其中 0 表示最低排名,1 表示最高排名。 +--- + +# PERCENT_RANK + +以百分比形式计算每一行的相对排名。返回介于 0 和 1 之间的值,其中 0 表示最低排名,1 表示最高排名。 + +另请参阅:[CUME_DIST](/tidb-cloud-lake/sql/cume-dist.md) + +## 语法 {#syntax} + +```sql +PERCENT_RANK() +OVER ( + [ PARTITION BY partition_expression ] + ORDER BY sort_expression [ ASC | DESC ] +) +``` + +**参数:** + +- `PARTITION BY`:可选。将行划分为不同分区 +- `ORDER BY`:必需。确定排名顺序 +- `ASC | DESC`:可选。排序方向(默认值:ASC) + +**说明:** + +- 返回介于 0 和 1 之间的值(包含 0 和 1) +- 第一行的 PERCENT_RANK 始终为 0 +- 最后一行的 PERCENT_RANK 始终为 1 +- 公式:(rank - 1) / (total_rows - 1) +- 乘以 100 可得到百分位值 + +## 示例 {#examples} + +```sql +-- Create sample data +CREATE TABLE scores ( + student VARCHAR(20), + score INT +); + +INSERT INTO scores VALUES + ('Alice', 95), + ('Bob', 87), + ('Charlie', 87), + ('David', 82), + ('Eve', 78); +``` + +**计算百分比排名(显示百分位位置):** + +```sql +SELECT student, score, + PERCENT_RANK() OVER (ORDER BY score DESC) AS percent_rank, + ROUND(PERCENT_RANK() OVER (ORDER BY score DESC) * 100) AS percentile +FROM scores +ORDER BY score DESC, student; +``` + +结果: + +``` +student | score | percent_rank | percentile +--------+-------+--------------+----------- +Alice | 95 | 0.0 | 0 +Bob | 87 | 0.25 | 25 +Charlie | 87 | 0.25 | 25 +David | 82 | 0.75 | 75 +Eve | 78 | 1.0 | 100 +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/pi.md b/tidb-cloud-lake/sql/pi.md new file mode 100644 index 0000000000000..c25a7f78a8b3f --- /dev/null +++ b/tidb-cloud-lake/sql/pi.md @@ -0,0 +1,26 @@ +--- +title: PI +summary: 返回 π 的值,结果为浮点值。 +--- + +# PI + +返回 π 的值,结果为浮点值。 + +## 语法 {#syntax} + +```sql +PI() +``` + +## 示例 {#examples} + +```sql +SELECT PI(); + +┌───────────────────┐ +│ pi() │ +├───────────────────┤ +│ 3.141592653589793 │ +└───────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/pipe.md b/tidb-cloud-lake/sql/pipe.md new file mode 100644 index 0000000000000..0654faca8d67f --- /dev/null +++ b/tidb-cloud-lake/sql/pipe.md @@ -0,0 +1,16 @@ +--- +title: Pipe +summary: "{{{ .lake }}} 中用于摄取管道的 Pipe 相关 SQL 命令。" +--- + +# Pipe + +{{{ .lake }}} 中用于摄取管道的 Pipe 相关 SQL 命令。 + +## 命令参考 {#command-reference} + +| 命令 | 描述 | +|---------|-------------| +| [CREATE PIPE](/tidb-cloud-lake/sql/create-pipe.md) | 创建一个由 `COPY INTO` 语句支持的 pipe | +| [DESCRIBE PIPE](/tidb-cloud-lake/sql/describe-pipe.md) | 显示 pipe 属性 | +| [DROP PIPE](/tidb-cloud-lake/sql/drop-pipe.md) | 删除一个 pipe | \ No newline at end of file diff --git a/tidb-cloud-lake/sql/pivot.md b/tidb-cloud-lake/sql/pivot.md new file mode 100644 index 0000000000000..d83204eb3e001 --- /dev/null +++ b/tidb-cloud-lake/sql/pivot.md @@ -0,0 +1,86 @@ +--- +title: PIVOT +summary: {{{ .lake }}} 中的 PIVOT 操作允许你通过旋转表并基于指定列聚合结果来转换表。 +--- + +# PIVOT + +{{{ .lake }}} 中的 `PIVOT` 操作允许你通过旋转表并基于指定列聚合结果来转换表。 + +它是一个非常有用的操作,可以用更易读的格式对大量数据进行汇总和分析。本文将介绍其语法,并提供一个如何使用 `PIVOT` 操作的示例。 + +**另请参阅:** [UNPIVOT](/tidb-cloud-lake/sql/unpivot.md) + +## 语法 {#syntax} + +```sql +SELECT ... +FROM ... + PIVOT ( ( ) + FOR IN ( [ , ... ] ) ) + +[ ... ] +``` + +其中: + +* ``:用于合并来自 `pivot_column` 的分组值的聚合函数。 +* ``:将使用指定的 `` 进行聚合的列。 +* ``:其唯一值将在透视结果集中成为新列的列。 +* ``:来自 `` 的一个唯一值,它将在透视结果集中成为一个新列。 + +## 示例 {#examples} + +假设我们有一个名为 monthly_sales 的表,其中包含不同员工在不同月份的销售数据。我们可以使用 `PIVOT` 操作来汇总这些数据,并计算每位员工在每个月的销售总额。 + +### 创建并插入数据 {#creating-and-inserting-data} + +```sql +-- Create the monthly_sales table +CREATE TABLE monthly_sales( + empid INT, + amount INT, + month VARCHAR +); + +-- Insert sales data +INSERT INTO monthly_sales VALUES + (1, 10000, 'JAN'), + (1, 400, 'JAN'), + (2, 4500, 'JAN'), + (2, 35000, 'JAN'), + (1, 5000, 'FEB'), + (1, 3000, 'FEB'), + (2, 200, 'FEB'), + (2, 90500, 'FEB'), + (1, 6000, 'MAR'), + (1, 5000, 'MAR'), + (2, 2500, 'MAR'), + (2, 9500, 'MAR'), + (1, 8000, 'APR'), + (1, 10000, 'APR'), + (2, 800, 'APR'), + (2, 4500, 'APR'); +``` + +### 使用 PIVOT {#using-pivot} + +现在,我们可以使用 `PIVOT` 操作来计算每位员工在每个月的销售总额。我们将使用 `SUM` 聚合函数来计算销售总额,并将 MONTH 列进行透视,为每个月创建一个新列。 + +```sql +SELECT * +FROM monthly_sales +PIVOT(SUM(amount) FOR MONTH IN ('JAN', 'FEB', 'MAR', 'APR')) +ORDER BY EMPID; +``` + +输出: + +```sql ++-------+-------+-------+-------+-------+ +| empid | jan | feb | mar | apr | ++-------+-------+-------+-------+-------+ +| 1 | 10400 | 8000 | 11000 | 18000 | +| 2 | 39500 | 90700 | 12000 | 5300 | ++-------+-------+-------+-------+-------+ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/plus.md b/tidb-cloud-lake/sql/plus.md new file mode 100644 index 0000000000000..6a571c0ba0aa6 --- /dev/null +++ b/tidb-cloud-lake/sql/plus.md @@ -0,0 +1,30 @@ +--- +title: PLUS +summary: 计算两个数值或十进制值的和。 +--- + +# PLUS + +计算两个数值或十进制值的和。 + +## 语法 {#syntax} + +```sql +PLUS(, ) +``` + +## 别名 {#aliases} + +- [ADD](/tidb-cloud-lake/sql/add.md) + +## 示例 {#examples} + +```sql +SELECT ADD(1, 2.3), PLUS(1, 2.3); + +┌───────────────────────────────┐ +│ add(1, 2.3) │ plus(1, 2.3) │ +├───────────────┼───────────────┤ +│ 3.3 │ 3.3 │ +└───────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/point-in-ellipses.md b/tidb-cloud-lake/sql/point-in-ellipses.md new file mode 100644 index 0000000000000..95e18f51c2d56 --- /dev/null +++ b/tidb-cloud-lake/sql/point-in-ellipses.md @@ -0,0 +1,39 @@ +--- +title: POINT_IN_ELLIPSES +summary: 如果该点位于所提供的任意椭圆内,则返回 1;否则返回 0。 +--- + +# POINT_IN_ELLIPSES + +如果该点位于所提供的任意椭圆内,则返回 1;否则返回 0。每个椭圆由一个中心点及其半长轴和半短轴定义。 + +## 语法 {#syntax} + +```sql +POINT_IN_ELLIPSES(x, y, x1, y1, a1, b1 [, x2, y2, a2, b2, ...]) +``` + +## 参数 {#arguments} + +| 参数 | 描述 | +|-----------|-------------| +| `x`, `y` | 要测试的点的坐标。 | +| `x1`, `y1` | 第一个椭圆的中心。 | +| `a1`, `b1` | 第一个椭圆的半长轴和半短轴长度。 | +| `x2`, `y2`, `a2`, `b2`, ... | 可选的其他椭圆,定义方式相同。 | + +## 返回类型 {#return-type} + +UInt8(1 表示 true,0 表示 false)。 + +## 示例 {#examples} + +```sql +SELECT POINT_IN_ELLIPSES(10, 10, 10, 9.1, 1, 0.9999) AS inside; + +╭────────╮ +│ inside │ +├────────┤ +│ 1 │ +╰────────╯ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/point-in-polygon.md b/tidb-cloud-lake/sql/point-in-polygon.md new file mode 100644 index 0000000000000..68e05c98fff1c --- /dev/null +++ b/tidb-cloud-lake/sql/point-in-polygon.md @@ -0,0 +1,26 @@ +--- +title: POINT_IN_POLYGON +summary: 计算给定点是否位于由多个点连接形成的多边形内。多边形是按照坐标对出现的顺序依次连接而成的封闭图形。改变坐标对的顺序可能会形成不同的图形。 +--- + +# POINT_IN_POLYGON + +计算给定点是否位于由多个点连接形成的多边形内。多边形是按照坐标对出现的顺序依次连接而成的封闭图形。改变坐标对的顺序可能会形成不同的图形。 + +## 语法 {#syntax} + +```sql +POINT_IN_POLYGON((x,y), [(a,b), (c,d), (e,f) ... ]) +``` + +## 示例 {#examples} + +```sql +SELECT POINT_IN_POLYGON((3., 3.), [(6, 0), (8, 4), (5, 8), (0, 2)]); + +┌────────────────────────────────────────────────────────────┐ +│ point_in_polygon((3, 3), [(6, 0), (8, 4), (5, 8), (0, 2)]) │ +├────────────────────────────────────────────────────────────┤ +│ 1 │ +└────────────────────────────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/policy-references.md b/tidb-cloud-lake/sql/policy-references.md new file mode 100644 index 0000000000000..420cd36692668 --- /dev/null +++ b/tidb-cloud-lake/sql/policy-references.md @@ -0,0 +1,119 @@ +--- +title: POLICY_REFERENCES +summary: 返回安全策略(Masking Policy 或 Row Access Policy)与表/视图之间的关联。你可以按策略名称查询所有使用该策略的表,或按表名查询应用于该表的所有策略。 +--- + +# POLICY_REFERENCES + +返回安全策略(Masking Policy 或 Row Access Policy)与表/视图之间的关联。你可以按策略名称查询所有使用该策略的表,或按表名查询应用于该表的所有策略。 + +另请参阅: + +- [MASKING POLICY](/tidb-cloud-lake/guides/masking-policy.md) +- [ROW ACCESS POLICY](/tidb-cloud-lake/guides/row-access-policy.md) + +## 语法 {#syntax} + +```sql +-- Find all tables/views using a specific policy +POLICY_REFERENCES(POLICY_NAME => '') + +-- Find all policies applied to a specific table/view +POLICY_REFERENCES( + REF_ENTITY_NAME => '[.]', + REF_ENTITY_DOMAIN => 'TABLE' | 'VIEW' +) +``` + +## 输出列 {#output-columns} + +| 列 | 描述 | +|----------------------|--------------------------------------------------------------------| +| policy_name | 策略名称 | +| policy_kind | 策略类型:`MASKING POLICY` 或 `ROW ACCESS POLICY` | +| ref_database_name | 包含被引用表/视图的数据库 | +| ref_entity_name | 被引用的表或视图名称 | +| ref_entity_domain | `TABLE` 或 `VIEW` | +| ref_column_name | 应用该策略的列(适用于 masking policy) | +| ref_arg_column_names | 策略使用的参数列 | +| policy_status | 策略状态,通常为 `ACTIVE` | + +## 示例 {#examples} + +### 查找使用某个 Row Access Policy 的表 {#find-tables-using-a-row-access-policy} + +```sql +-- Create a row access policy +CREATE ROW ACCESS POLICY rap_employees AS (department STRING) RETURNS BOOLEAN -> + CASE + WHEN current_role() = 'admin' THEN true + WHEN department = 'Engineering' THEN true + ELSE false + END; + +-- Apply the policy to a table +CREATE TABLE employees(id INT, name STRING, department STRING); +ALTER TABLE employees ADD ROW ACCESS POLICY rap_employees ON (department); + +-- Find all tables using this policy +SELECT * FROM policy_references(POLICY_NAME => 'rap_employees'); + +┌─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ +│ policy_name │ policy_kind │ ref_database_name │ ref_entity_name │ ref_entity_domain │ ref_column_name │ ref_arg_column_names │ policy_status │ +├─────────────────┼───────────────────┼───────────────────┼─────────────────┼───────────────────┼─────────────────┼──────────────────────┼───────────────┤ +│ rap_employees │ ROW ACCESS POLICY │ default │ employees │ TABLE │ NULL │ department │ ACTIVE │ +└─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ +``` + +### 查找应用于某个表的所有策略 {#find-all-policies-applied-to-a-table} + +```sql +-- Create a masking policy +CREATE MASKING POLICY mask_salary AS (val INT) RETURNS INT -> + CASE WHEN current_role() = 'admin' THEN val ELSE 0 END; + +-- Apply both policies to the table +ALTER TABLE employees ADD COLUMN salary INT; +ALTER TABLE employees MODIFY COLUMN salary SET MASKING POLICY mask_salary; + +-- Find all policies on this table +SELECT * FROM policy_references( + REF_ENTITY_NAME => 'default.employees', + REF_ENTITY_DOMAIN => 'TABLE' +); + +┌──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ +│ policy_name │ policy_kind │ ref_database_name │ ref_entity_name │ ref_entity_domain │ ref_column_name │ ref_arg_column_names │ policy_status │ +├─────────────────┼───────────────────┼───────────────────┼─────────────────┼───────────────────┼─────────────────┼──────────────────────┼───────────────┤ +│ mask_salary │ MASKING POLICY │ default │ employees │ TABLE │ salary │ NULL │ ACTIVE │ +│ rap_employees │ ROW ACCESS POLICY │ default │ employees │ TABLE │ NULL │ department │ ACTIVE │ +└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ +``` + +### 查找使用带多个参数的 Masking Policy 的表 {#find-tables-using-a-masking-policy-with-multiple-arguments} + +```sql +-- Create a masking policy with conditional arguments +CREATE MASKING POLICY mask_ssn AS (val STRING, user_role STRING) RETURNS STRING -> + CASE + WHEN user_role = current_role() THEN val + ELSE '***-**-****' + END; + +-- Apply to multiple tables +CREATE TABLE employees1(id INT, ssn STRING, role STRING); +CREATE TABLE employees2(id INT, ssn STRING, role STRING); + +ALTER TABLE employees1 MODIFY COLUMN ssn SET MASKING POLICY mask_ssn USING (ssn, role); +ALTER TABLE employees2 MODIFY COLUMN ssn SET MASKING POLICY mask_ssn USING (ssn, role); + +-- Find all tables using this policy +SELECT * FROM policy_references(POLICY_NAME => 'mask_ssn') ORDER BY ref_entity_name; + +┌───────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ +│ policy_name │ policy_kind │ ref_database_name │ ref_entity_name │ ref_entity_domain │ ref_column_name │ ref_arg_column_names │ policy_status │ +├─────────────┼────────────────┼───────────────────┼─────────────────┼───────────────────┼─────────────────┼──────────────────────┼───────────────┤ +│ mask_ssn │ MASKING POLICY │ default │ employees1 │ TABLE │ ssn │ role │ ACTIVE │ +│ mask_ssn │ MASKING POLICY │ default │ employees2 │ TABLE │ ssn │ role │ ACTIVE │ +└───────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/position.md b/tidb-cloud-lake/sql/position.md new file mode 100644 index 0000000000000..0c732e2e6afed --- /dev/null +++ b/tidb-cloud-lake/sql/position.md @@ -0,0 +1,43 @@ +--- +title: POSITION +summary: POSITION(substr IN str) 是 LOCATE(substr,str) 的同义词。返回子字符串 substr 在字符串 str 中首次出现的位置。如果 substr 不在 str 中,则返回 0。如果任一参数为 NULL,则返回 NULL。 +--- + +# POSITION + +POSITION(substr IN str) 是 LOCATE(substr,str) 的同义词。返回子字符串 substr 在字符串 str 中首次出现的位置。如果 substr 不在 str 中,则返回 0。如果任一参数为 NULL,则返回 NULL。 + +## 语法 {#syntax} + +```sql +POSITION( IN ) +``` + +## 参数 {#arguments} + +| 参数 | 描述 | +|------------|----------------| +| `` | 子字符串。 | +| `` | 字符串。 | + +## 返回类型 {#return-type} + +`BIGINT` + +## 示例 {#examples} + +```sql +SELECT POSITION('bar' IN 'foobarbar') ++----------------------------+ +| POSITION('bar' IN 'foobarbar') | ++----------------------------+ +| 4 | ++----------------------------+ + +SELECT POSITION('xbar' IN 'foobar') ++--------------------------+ +| POSITION('xbar' IN 'foobar') | ++--------------------------+ +| 0 | ++--------------------------+ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/pow.md b/tidb-cloud-lake/sql/pow.md new file mode 100644 index 0000000000000..163875c2663d8 --- /dev/null +++ b/tidb-cloud-lake/sql/pow.md @@ -0,0 +1,30 @@ +--- +title: POW +summary: 返回 `x` 的 `y` 次幂值。 +--- + +# POW + +返回 `x` 的 `y` 次幂值。 + +## 语法 {#syntax} + +```sql +POW( ) +``` + +## 别名 {#aliases} + +- [POWER](/tidb-cloud-lake/sql/power.md) + +## 示例 {#examples} + +```sql +SELECT POW(-2, 2), POWER(-2, 2); + +┌─────────────────────────────────┐ +│ pow((- 2), 2) │ power((- 2), 2) │ +├───────────────┼─────────────────┤ +│ 4 │ 4 │ +└─────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/power.md b/tidb-cloud-lake/sql/power.md new file mode 100644 index 0000000000000..0b7d0af11dc73 --- /dev/null +++ b/tidb-cloud-lake/sql/power.md @@ -0,0 +1,8 @@ +--- +title: POWER +summary: [POW](/tidb-cloud-lake/sql/pow.md) 的别名。 +--- + +# POWER + +[POW](/tidb-cloud-lake/sql/pow.md) 的别名。 \ No newline at end of file diff --git a/tidb-cloud-lake/sql/presign.md b/tidb-cloud-lake/sql/presign.md new file mode 100644 index 0000000000000..e73e1303a9289 --- /dev/null +++ b/tidb-cloud-lake/sql/presign.md @@ -0,0 +1,82 @@ +--- +title: PRESIGN +summary: 根据你提供的 stage 名称和文件路径,为 stage 中的文件生成预签名 URL。预签名 URL 使你能够通过 Web 浏览器或 API 请求访问该文件。 +--- + +# PRESIGN + +根据你提供的 stage 名称和文件路径,为 stage 中的文件生成预签名 URL。预签名 URL 使你能够通过 Web 浏览器或 API 请求访问该文件。 + +> **Tip:** +> +> 使用 cURL 与非 S3-like 存储交互时,请记得包含由 PRESIGN 命令生成的 headers,以便安全地上传或下载文件。例如: +> +> ```bash +> curl -H "" -o books.csv +> +> curl -X PUT -T books.csv -H "" +> ``` + +另请参阅: + +- [LIST STAGE FILES](/tidb-cloud-lake/sql/list-stage-files.md):列出 stage 中的文件。 +- [REMOVE STAGE FILES](/tidb-cloud-lake/sql/remove-stage-files.md):删除 stage 中的文件。 + +## 语法 {#syntax} + +```sql +PRESIGN [ { DOWNLOAD | UPLOAD }] @/.../ [ EXPIRE = ] +``` + +其中: + +`[ { DOWNLOAD | UPLOAD }]`:指定预签名 URL 用于下载还是上传。默认值为 `DOWNLOAD`。 + +`[ EXPIRE = ]`:指定预签名 URL 过期前的时长(以秒为单位)。默认值为 3,600 秒。 + +## 示例 {#examples} + +### 生成并使用用于下载的预签名 URL {#generating-and-using-pre-signed-urls-for-download} + +以下示例为 stage `my-stage` 上的文件 `books.csv` 生成用于下载的预签名 URL: + +```sql +PRESIGN @my_stage/books.csv ++--------+---------+---------------------------------------------------------------------------------+ +| method | headers | url | ++--------+---------+---------------------------------------------------------------------------------+ +| GET | {} | https://example.s3.amazonaws.com/books.csv?X-Amz-Algorithm=AWS4-HMAC-SHA256&... | ++--------+---------+---------------------------------------------------------------------------------+ +``` + +以下示例与前一个示例作用相同: + +```sql +PRESIGN DOWNLOAD @my_stage/books.csv +``` + +要使用预签名 URL 下载文件并将其保存为 `books.csv`,执行以下命令: + +```bash +curl -o books.csv +``` + +以下示例生成一个在 7,200 秒(2 小时)后过期的预签名 URL: + +```sql +PRESIGN @my_stage/books.csv EXPIRE = 7200 +``` + +### 生成并使用用于上传的预签名 URL {#generating-and-using-pre-signed-urls-for-upload} + +以下示例生成一个预签名 URL,用于将文件以上传为 `books.csv` 的方式上传到 stage `my_stage`: + +```sql +PRESIGN UPLOAD @my_stage/books.csv +``` + +要使用预签名 URL 上传文件 `books.csv`,执行以下命令: + +```bash +curl -X PUT -T books.csv +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/previous-day.md b/tidb-cloud-lake/sql/previous-day.md new file mode 100644 index 0000000000000..a30dd78768062 --- /dev/null +++ b/tidb-cloud-lake/sql/previous-day.md @@ -0,0 +1,37 @@ +--- +title: PREVIOUS_DAY +summary: 返回给定日期或时间戳之前最近一个指定星期几的日期。 +--- + +# PREVIOUS_DAY + +返回给定日期或时间戳之前最近一个指定星期几的日期。 + +## 语法 {#syntax} + +```sql +PREVIOUS_DAY(, ) +``` + +| 参数 | 描述 | +|---------------------|------------------------------------------------------------------------------------------------------------------------------------------| +| `` | 用于计算指定星期几上一次出现日期的 `DATE` 或 `TIMESTAMP` 值。 | +| `` | 要查找其上一次出现日期的目标星期几。可接受的值包括 `monday`、`tuesday`、`wednesday`、`thursday`、`friday`、`saturday` 和 `sunday`。 | + +## 返回类型 {#return-type} + +日期。 + +## 示例 {#examples} + +如果你需要查找某个给定日期之前最近的星期五,例如 2024-11-13: + +```sql +SELECT PREVIOUS_DAY(to_date('2024-11-13'), friday) AS last_friday; + +┌─────────────┐ +│ last_friday │ +├─────────────┤ +│ 2024-11-08 │ +└─────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/qualify.md b/tidb-cloud-lake/sql/qualify.md new file mode 100644 index 0000000000000..66b654c53a9fd --- /dev/null +++ b/tidb-cloud-lake/sql/qualify.md @@ -0,0 +1,108 @@ +--- +title: QUALIFY +summary: QUALIFY 是一个用于过滤窗口函数结果的子句。因此,要成功使用 QUALIFY 子句,SELECT 列表或 QUALIFY 子句中必须至少包含一个窗口函数(每种情况请参见示例)。换句话说,QUALIFY 会在窗口函数计算完成后再进行求值。以下是包含 QUALIFY 语句子句的查询的典型执行顺序。 +--- + +# QUALIFY + +QUALIFY 是一个用于过滤窗口函数结果的子句。因此,要成功使用 QUALIFY 子句,SELECT 列表或 QUALIFY 子句中必须至少包含一个窗口函数(每种情况请参见[示例](#examples))。换句话说,QUALIFY 会在窗口函数计算完成后再进行求值。以下是包含 QUALIFY 语句子句的查询的典型执行顺序: + +1. FROM +2. WHERE +3. GROUP BY +4. HAVING +5. WINDOW FUNCTION +6. QUALIFY +7. DISTINCT +8. ORDER BY +9. LIMIT + +## 语法 {#syntax} + +```sql +QUALIFY +``` + +## 示例 {#examples} + +本示例演示了如何使用 ROW_NUMBER() 按部门为员工分配连续编号,并按薪资降序排序。借助 QUALIFY 子句,我们可以过滤结果,仅显示每个部门中薪资最高的员工。 + +```sql +-- Prepare the data +CREATE TABLE employees ( + employee_id INT, + first_name VARCHAR, + last_name VARCHAR, + department VARCHAR, + salary INT +); + +INSERT INTO employees (employee_id, first_name, last_name, department, salary) VALUES + (1, 'John', 'Doe', 'IT', 90000), + (2, 'Jane', 'Smith', 'HR', 85000), + (3, 'Mike', 'Johnson', 'IT', 82000), + (4, 'Sara', 'Williams', 'Sales', 77000), + (5, 'Tom', 'Brown', 'HR', 75000); + +-- Select employee details along with the row number partitioned by department and ordered by salary in descending order. +SELECT + employee_id, + first_name, + last_name, + department, + salary, + ROW_NUMBER() OVER (PARTITION BY department ORDER BY salary DESC) AS row_num +FROM + employees; + +┌──────────────────────────────────────────────────────────────────────────────────────────────────────┐ +│ employee_id │ first_name │ last_name │ department │ salary │ row_num │ +├─────────────────┼──────────────────┼──────────────────┼──────────────────┼─────────────────┼─────────┤ +│ 2 │ Jane │ Smith │ HR │ 85000 │ 1 │ +│ 5 │ Tom │ Brown │ HR │ 75000 │ 2 │ +│ 1 │ John │ Doe │ IT │ 90000 │ 1 │ +│ 3 │ Mike │ Johnson │ IT │ 82000 │ 2 │ +│ 4 │ Sara │ Williams │ Sales │ 77000 │ 1 │ +└──────────────────────────────────────────────────────────────────────────────────────────────────────┘ + +-- Select employee details along with the row number partitioned by department and ordered by salary in descending order. +-- Add a filter to only include rows where the row number is 1, selecting the employee with the highest salary in each department. +SELECT + employee_id, + first_name, + last_name, + department, + salary, + ROW_NUMBER() OVER (PARTITION BY department ORDER BY salary DESC) AS row_num +FROM + employees +QUALIFY row_num = 1; + +┌──────────────────────────────────────────────────────────────────────────────────────────────────────┐ +│ employee_id │ first_name │ last_name │ department │ salary │ row_num │ +├─────────────────┼──────────────────┼──────────────────┼──────────────────┼─────────────────┼─────────┤ +│ 2 │ Jane │ Smith │ HR │ 85000 │ 1 │ +│ 1 │ John │ Doe │ IT │ 90000 │ 1 │ +│ 4 │ Sara │ Williams │ Sales │ 77000 │ 1 │ +└──────────────────────────────────────────────────────────────────────────────────────────────────────┘ + +-- {{{ .lake }}} 允许在 QUALIFY 子句中直接使用窗口函数,而无需在 SELECT 列表中显式命名它们。 + +SELECT + employee_id, + first_name, + last_name, + department, + salary +FROM + employees +QUALIFY ROW_NUMBER() OVER (PARTITION BY department ORDER BY salary DESC) = 1; + +┌────────────────────────────────────────────────────────────────────────────────────────────┐ +│ employee_id │ first_name │ last_name │ department │ salary │ +├─────────────────┼──────────────────┼──────────────────┼──────────────────┼─────────────────┤ +│ 2 │ Jane │ Smith │ HR │ 85000 │ +│ 1 │ John │ Doe │ IT │ 90000 │ +│ 4 │ Sara │ Williams │ Sales │ 77000 │ +└────────────────────────────────────────────────────────────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/quantile-cont.md b/tidb-cloud-lake/sql/quantile-cont.md new file mode 100644 index 0000000000000..aa9547d857bfc --- /dev/null +++ b/tidb-cloud-lake/sql/quantile-cont.md @@ -0,0 +1,64 @@ +--- +title: QUANTILE_CONT +summary: `QUANTILE_CONT()` 函数用于计算数值数据序列的插值分位数。 +--- + +# QUANTILE_CONT + +`QUANTILE_CONT()` 函数用于计算数值数据序列的插值分位数。 + +> **注意:** +> +> NULL 值不计入统计。 + +## 语法 {#syntax} + +```sql +QUANTILE_CONT()() +QUANTILE_CONT(level1, level2, ...)() +``` + +## 参数 {#arguments} + +| 参数 | 描述 | +|-------------|-------------------------------------------------------------------------------------------------------------------------------------------------| +| `` | 任意数值表达式 | + +## 返回类型 {#return-type} + +根据级别数量,返回 Float64 或 float64 数组。 + +## 示例 {#example} + +**创建表并插入示例数据** + +```sql +CREATE TABLE sales_data ( + id INT, + sales_person_id INT, + sales_amount FLOAT +); + +INSERT INTO sales_data (id, sales_person_id, sales_amount) +VALUES (1, 1, 5000), + (2, 2, 5500), + (3, 3, 6000), + (4, 4, 6500), + (5, 5, 7000); +``` + +**查询示例:使用插值计算销售额的第 50 百分位数(中位数)** + +```sql +SELECT QUANTILE_CONT(0.5)(sales_amount) AS median_sales_amount +FROM sales_data; +``` + +**结果** + +```sql +| median_sales_amount | +|-----------------------| +| 6000.0 | +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/quantile-disc.md b/tidb-cloud-lake/sql/quantile-disc.md new file mode 100644 index 0000000000000..5d23f680d424f --- /dev/null +++ b/tidb-cloud-lake/sql/quantile-disc.md @@ -0,0 +1,64 @@ +--- +title: QUANTILE_DISC +summary: QUANTILE_DISC() 函数用于计算数值数据序列的精确分位数。 +--- + +# QUANTILE_DISC + +`QUANTILE_DISC()` 函数用于计算数值数据序列的精确分位数。`QUANTILE` 是 `QUANTILE_DISC` 的别名。 + +> **Note:** +> +> NULL 值不计入统计。 + +## 语法 {#syntax} + +```sql +QUANTILE_DISC()() +QUANTILE_DISC(level1, level2, ...)() +``` + +## 参数 {#arguments} + +| 参数 | 描述 | +|------------|-----------------------------------------------------------------------------------------------------------------------------------------------| +| `level(s)` | 分位数的级别。每个级别都是从 0 到 1 的常数浮点数。建议使用 [0.01, 0.99] 范围内的级别值。 | +| `` | 任意数值表达式 | + +## 返回类型 {#return-type} + +根据 level 的数量,返回 InputType 或 InputType 数组。 + +## 示例 {#example} + +**创建表并插入示例数据** + +```sql +CREATE TABLE salary_data ( + id INT, + employee_id INT, + salary FLOAT +); + +INSERT INTO salary_data (id, employee_id, salary) +VALUES (1, 1, 50000), + (2, 2, 55000), + (3, 3, 60000), + (4, 4, 65000), + (5, 5, 70000); +``` + +**查询示例:计算薪资的第 25 和第 75 百分位数** + +```sql +SELECT QUANTILE_DISC(0.25, 0.75)(salary) AS salary_quantiles +FROM salary_data; +``` + +**结果** + +```sql +| salary_quantiles | +|---------------------| +| [55000.0, 65000.0] | +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/quantile-tdigest-weighted.md b/tidb-cloud-lake/sql/quantile-tdigest-weighted.md new file mode 100644 index 0000000000000..d0c387a5e7b41 --- /dev/null +++ b/tidb-cloud-lake/sql/quantile-tdigest-weighted.md @@ -0,0 +1,64 @@ +--- +title: QUANTILE_TDIGEST_WEIGHTED +summary: 使用 [t-digest](https://github.com/tdunning/t-digest/blob/master/docs/t-digest-paper/histo.pdf) 算法计算数值数据序列的近似分位数。该函数会考虑序列中每个成员的权重。内存消耗为 log(n),其中 n 是值的数量。 +--- + +# QUANTILE_TDIGEST_WEIGHTED + +使用 [t-digest](https://github.com/tdunning/t-digest/blob/master/docs/t-digest-paper/histo.pdf) 算法计算数值数据序列的近似分位数。 + +该函数会考虑序列中每个成员的权重。内存消耗为 **log(n)**,其中 **n** 是值的数量。 + +> **注意:** +> +> 计算时不包含 NULL 值。 + +## 语法 {#syntax} + +```sql +QUANTILE_TDIGEST_WEIGHTED([, , ...])(, ) +``` + +## 参数 {#arguments} + +| 参数 | 描述 | +|-----------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------| +| `` | 分位数级别,表示一个范围从 0 到 1 的常数浮点数。建议使用 [0.01, 0.99] 范围内的级别值。 | +| `` | 任意数值表达式 | +| `` | 任意无符号整数表达式。权重表示某个值出现的次数。 | + +## 返回类型 {#return-type} + +根据指定的分位数级别数量,返回一个 Float64 值或一个 Float64 数组。 + +## 示例 {#example} + +```sql +-- Create a table and insert sample data +CREATE TABLE sales_data ( + id INT, + sales_person_id INT, + sales_amount FLOAT +); + +INSERT INTO sales_data (id, sales_person_id, sales_amount) +VALUES (1, 1, 5000), + (2, 2, 5500), + (3, 3, 6000), + (4, 4, 6500), + (5, 5, 7000); + +SELECT QUANTILE_TDIGEST_WEIGHTED(0.5)(sales_amount, 1) AS median_sales_amount +FROM sales_data; + +median_sales_amount| +-------------------+ + 6000.0| + +SELECT QUANTILE_TDIGEST_WEIGHTED(0.5, 0.8)(sales_amount, 1) +FROM sales_data; + +quantile_tdigest_weighted(0.5, 0.8)(sales_amount)| +-------------------------------------------------+ +[6000.0,7000.0] | +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/quantile-tdigest.md b/tidb-cloud-lake/sql/quantile-tdigest.md new file mode 100644 index 0000000000000..b51042595ced2 --- /dev/null +++ b/tidb-cloud-lake/sql/quantile-tdigest.md @@ -0,0 +1,61 @@ +--- +title: QUANTILE_TDIGEST +summary: 使用 t-digest 算法计算数值数据序列的近似分位数。 +--- + +# QUANTILE_TDIGEST + +使用 [t-digest](https://github.com/tdunning/t-digest/blob/master/docs/t-digest-paper/histo.pdf) 算法计算数值数据序列的近似分位数。 + +> **注意:** +> +> 计算中不包含 NULL 值。 + +## 语法 {#syntax} + +```sql +QUANTILE_TDIGEST([, , ...])() +``` + +## 参数 {#arguments} + +| 参数 | 描述 | +|-------------|-------------------------------------------------------------------------------------------------------------------------------------------------| +| `` | 分位数级别表示一个范围从 0 到 1 的浮点常数。建议使用 [0.01, 0.99] 范围内的级别值。 | +| `` | 任意数值表达式 | + +## 返回类型 {#return-type} + +根据指定的分位数级别数量,返回一个 Float64 值或一个 Float64 数组。 + +## 示例 {#example} + +```sql +-- Create a table and insert sample data +CREATE TABLE sales_data ( + id INT, + sales_person_id INT, + sales_amount FLOAT +); + +INSERT INTO sales_data (id, sales_person_id, sales_amount) +VALUES (1, 1, 5000), + (2, 2, 5500), + (3, 3, 6000), + (4, 4, 6500), + (5, 5, 7000); + +SELECT QUANTILE_TDIGEST(0.5)(sales_amount) AS median_sales_amount +FROM sales_data; + +median_sales_amount| +-------------------+ + 6000.0| + +SELECT QUANTILE_TDIGEST(0.5, 0.8)(sales_amount) +FROM sales_data; + +quantile_tdigest(0.5, 0.8)(sales_amount)| +----------------------------------------+ +[6000.0,7000.0] | +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/quarter.md b/tidb-cloud-lake/sql/quarter.md new file mode 100644 index 0000000000000..4209787036d55 --- /dev/null +++ b/tidb-cloud-lake/sql/quarter.md @@ -0,0 +1,8 @@ +--- +title: QUARTER +summary: TO_QUARTER 的别名。 +--- + +# QUARTER + +[TO_QUARTER](/tidb-cloud-lake/sql/to-quarter.md) 的别名。 \ No newline at end of file diff --git a/tidb-cloud-lake/sql/query-history.md b/tidb-cloud-lake/sql/query-history.md new file mode 100644 index 0000000000000..c2e5e97899885 --- /dev/null +++ b/tidb-cloud-lake/sql/query-history.md @@ -0,0 +1,60 @@ +--- +title: QUERY_HISTORY +summary: 获取查询执行日志,用于分析和监控。 +--- + +# QUERY_HISTORY + +获取查询执行日志,用于分析和监控。 + +## 语法 {#syntax} + +```sql +QUERY_HISTORY + [ BY WAREHOUSE ] + [ FROM '' ] + [ TO '' ] + [ LIMIT ] +``` + +| 参数 | 描述 | +| -------------- | ---------------------------------------------------------------------------------------------------------------------------------------- | +| `BY WAREHOUSE` | 可选。将日志过滤到特定的计算集群 (Warehouse)。空名称会报错。 | +| `FROM` | 可选。查询范围的开始时间戳。格式:`YYYY-MM-DD HH:MM:SS`(UTC 或显式时区)。默认值为 `TO` 之前 1 小时。 | +| `TO` | 可选。查询范围的结束时间戳。格式:`YYYY-MM-DD HH:MM:SS`(UTC 或显式时区)。默认值为当前时间。 | +| `LIMIT` | 可选。返回的最大记录数。默认值为 `10`。必须为正整数。 | + +## 输出列 {#output-columns} + +结果包含以下列,例如: + +| 列名 | 描述 | +| ------------ | ------------------------------------- | +| `query_id` | 查询的唯一标识符 | +| `query_text` | 已执行的 SQL 语句 | +| `scan_bytes` | 扫描的数据量 | +| ... | 其他查询指标和元信息 | + +## 示例 {#examples} + +获取特定计算集群的最近查询历史: + +```sql +QUERY_HISTORY + BY WAREHOUSE 'etl-wh' + FROM '2023-08-20 00:00:00' + TO '2023-08-20 06:00:00' + LIMIT 200; +``` + +获取所有计算集群中的最近 10 条查询: + +```sql +QUERY_HISTORY; +``` + +获取带有自定义限制的查询历史: + +```sql +QUERY_HISTORY LIMIT 50; +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/query-operators.md b/tidb-cloud-lake/sql/query-operators.md new file mode 100644 index 0000000000000..1949c5c705d77 --- /dev/null +++ b/tidb-cloud-lake/sql/query-operators.md @@ -0,0 +1,19 @@ +--- +title: 查询运算符 +summary: 本页提供 {{{ .lake }}} 中查询运算符的参考信息。 +--- + +# 查询运算符 + +本页提供 {{{ .lake }}} 中查询运算符的参考信息。 + +## 运算符类型 {#operator-types} + +| 运算符类型 | 描述 | +|--------------|-------------| +| **[算术运算符](/tidb-cloud-lake/sql/arithmetic-operators.md)** | 数学运算(+, -, *, /, %, DIV) | +| **[比较运算符](/tidb-cloud-lake/sql/comparison-operators.md)** | 值比较(=, !=, <, >, <=, >=, BETWEEN, IN) | +| **[逻辑运算符](/tidb-cloud-lake/sql/logical-operators.md)** | 布尔逻辑(AND, OR, NOT, XOR) | +| **[JSON](/tidb-cloud-lake/sql/json-operators.md)** | JSON 数据操作(::, ->, ->>, @>, <@) | +| **[Set](/tidb-cloud-lake/sql/set.md)** | 组合查询结果(UNION, INTERSECT, EXCEPT) | +| **[子查询](/tidb-cloud-lake/sql/subquery-operators.md)** | 嵌套查询(EXISTS, IN, ANY, ALL, SOME) | \ No newline at end of file diff --git a/tidb-cloud-lake/sql/query-syntax.md b/tidb-cloud-lake/sql/query-syntax.md new file mode 100644 index 0000000000000..33e5ba06a2245 --- /dev/null +++ b/tidb-cloud-lake/sql/query-syntax.md @@ -0,0 +1,62 @@ +--- +title: 查询语法 +summary: 本页提供 {{{ .lake }}} 中查询语法的参考信息。每个组件都可以单独使用,也可以组合使用以构建强大的查询。 +--- + +# 查询语法 + +本页提供 {{{ .lake }}} 中查询语法的参考信息。每个组件都可以单独使用,也可以组合使用以构建强大的查询。 + +## 核心查询组件 {#core-query-components} + +| 组件 | 描述 | +|-----------|-------------| +| **[SELECT](/tidb-cloud-lake/sql/select.md)** | 从表中检索数据——所有查询的基础 | +| **[FROM / JOIN](/tidb-cloud-lake/sql/join.md)** | 指定数据源并组合多个表 | +| **[WHERE](/tidb-cloud-lake/sql/select.md#where-clause)** | 根据条件过滤行 | +| **[GROUP BY](/tidb-cloud-lake/sql/group-by.md)** | 对行进行分组并执行聚合(SUM、COUNT、AVG 等) | +| **[HAVING](/tidb-cloud-lake/sql/group-by.md)** | 过滤分组后的结果 | +| **[ORDER BY](/tidb-cloud-lake/sql/select.md#order-by-clause)** | 对查询结果进行排序 | +| **[LIMIT / TOP](/tidb-cloud-lake/sql/top.md)** | 限制返回的行数 | + +## 高级功能 {#advanced-features} + +| 组件 | 描述 | +|-----------|-------------| +| **[WITH (CTE)](/tidb-cloud-lake/sql/clause.md)** | 为复杂逻辑定义可复用的查询块 | +| **[PIVOT](/tidb-cloud-lake/sql/pivot.md)** | 将行转换为列(宽格式) | +| **[UNPIVOT](/tidb-cloud-lake/sql/unpivot.md)** | 将列转换为行(长格式) | +| **[QUALIFY](/tidb-cloud-lake/sql/qualify.md)** | 在窗口函数计算后过滤行 | +| **[VALUES](/tidb-cloud-lake/sql/values.md)** | 创建内联临时数据集 | + +## 时间旅行与流处理 {#time-travel-streaming} + +| 组件 | 描述 | +|-----------|-------------| +| **[AT](/tidb-cloud-lake/sql/at.md)** | 查询特定时间点的数据 | +| **[CHANGES](/tidb-cloud-lake/sql/changes.md)** | 跟踪插入、修改和删除 | +| **[WITH CONSUME](/tidb-cloud-lake/sql/with-consume.md)** | 通过偏移管理处理流式数据 | +| **[WITH STREAM HINTS](/tidb-cloud-lake/sql/stream-hints.md)** | 优化流处理行为 | + +## 查询执行 {#query-execution} + +| 组件 | 描述 | +|-----------|-------------| +| **[SETTINGS 子句](/tidb-cloud-lake/sql/settings-clause.md)** | 配置查询优化和执行参数 | + +## 查询结构 {#query-structure} + +一个典型的 {{{ .lake }}} 查询遵循以下结构: + +```sql +[WITH cte_expressions] +SELECT [TOP n] columns +FROM table +[JOIN other_tables] +[WHERE conditions] +[GROUP BY columns] +[HAVING group_conditions] +[QUALIFY window_conditions] +[ORDER BY columns] +[LIMIT n] +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/query.md b/tidb-cloud-lake/sql/query.md new file mode 100644 index 0000000000000..94bda0a52489c --- /dev/null +++ b/tidb-cloud-lake/sql/query.md @@ -0,0 +1,182 @@ +--- +title: QUERY +summary: 使用 Lucene 风格的查询对具有倒排索引的列进行行过滤,并支持对嵌套 `VARIANT` 字段使用点表示法。 +--- + +# QUERY + +`QUERY` 通过将 Lucene 风格的查询表达式与具有倒排索引的列进行匹配来过滤行。使用点表示法可以访问 `VARIANT` 列中的嵌套字段。该函数仅在 `WHERE` 子句中有效。 + +> **Note:** +> +> {{{ .lake }}} 的 QUERY 函数受 Elasticsearch 的 [QUERY](https://www.elastic.co/guide/en/elasticsearch/reference/current/sql-functions-search.html#sql-functions-search-query) 启发。 + +## 语法 {#syntax} + +```sql +QUERY(''[, '']) +``` + +`` 是可选的、以分号分隔的 `key=value` 对列表,用于调整搜索的工作方式。 + +## 构建查询表达式 {#building-query-expressions} + +| 表达式 | 用途 | 示例 | +|------------|---------|---------| +| `column:keyword` | 匹配 `column` 包含该关键字的行。追加 `*` 可进行后缀匹配。 | `QUERY('meta.detections.label:pedestrian')` | +| `column:"exact phrase"` | 匹配包含该精确短语的行。 | `QUERY('meta.scene.summary:"vehicle stopped at red traffic light"')` | +| `column:+required -excluded` | 在同一列中要求包含或排除某些词项。 | `QUERY('meta.tags:+commute -cyclist')` | +| `column:term1 AND term2` / `column:term1 OR term2` | 使用布尔运算符组合多个词项。`AND` 的优先级高于 `OR`。 | `QUERY('meta.signals.traffic_light:red AND meta.vehicle.lane:center')` | +| `column:IN [value1 value2 ...]` | 匹配列表中的任意值。 | `QUERY('meta.tags:IN [stop urban]')` | +| `column:[min TO max]` | 执行包含边界的范围搜索。使用 `*` 可使一侧保持开放。 | `QUERY('meta.vehicle.speed_kmh:[0 TO 10]')` | +| `column:{min TO max}` | 执行不包含边界值的范围搜索。 | `QUERY('meta.vehicle.speed_kmh:{0 TO 10}')` | +| `column:term^boost` | 提高特定列中匹配结果的权重。 | `QUERY('meta.signals.traffic_light:red^1.0 meta.tags:urban^2.0')` | + +### 嵌套 `VARIANT` 字段 {#nested-variant-fields} + +使用点表示法来访问 `VARIANT` 列中的内部字段。{{{ .lake }}} 会在对象和数组中对该路径进行求值。 + +| 模式 | 描述 | 示例 | +|---------|-------------|---------| +| `variant_col.field:value` | 匹配内部字段。 | `QUERY('meta.signals.traffic_light:red')` | +| `variant_col.field:IN [ ... ]` | 匹配数组中的任意值。 | `QUERY('meta.detections.label:IN [pedestrian cyclist]')` | +| `variant_col.field:[min TO max]` | 对数值型内部字段应用范围搜索。 | `QUERY('meta.vehicle.speed_kmh:[0 TO 10]')` | + +## 选项 {#options} + +| 选项 | 值 | 描述 | 示例 | +|--------|--------|-------------|---------| +| `fuzziness` | `1` 或 `2` | 匹配与指定 Levenshtein 距离以内的词项。 | `SELECT id FROM frames WHERE QUERY('meta.detections.label:pedestrain', 'fuzziness=1');` | +| `operator` | `OR`(默认)或 `AND` | 控制在未显式提供布尔运算符时,如何组合多个词项。 | `SELECT id FROM frames WHERE QUERY('meta.scene.weather:rain fog', 'operator=AND');` | +| `lenient` | `true` 或 `false` | 当为 `true` 时,抑制解析错误并返回空结果集。 | `SELECT id FROM frames WHERE QUERY('meta.detections.label:()', 'lenient=true');` | + +## 示例 {#examples} + +### 建立一个智能驾驶数据集 {#set-up-a-smart-driving-dataset} + +```sql +CREATE OR REPLACE TABLE frames ( + id INT, + meta VARIANT, + INVERTED INDEX idx_meta (meta) +); + +INSERT INTO frames VALUES + (1, '{ + "frame":{"source":"dashcam_front","timestamp":"2025-10-21T08:32:05Z","location":{"city":"San Francisco","intersection":"Market & 5th","gps":[37.7825,-122.4072]}}, + "vehicle":{"speed_kmh":48,"acceleration":0.8,"lane":"center"}, + "signals":{"traffic_light":"green","distance_m":55,"speed_limit_kmh":50}, + "detections":[ + {"label":"car","confidence":0.96,"distance_m":15,"relative_speed_kmh":2}, + {"label":"pedestrian","confidence":0.88,"distance_m":12,"intent":"crossing"} + ], + "scene":{"weather":"clear","time_of_day":"day","visibility":"good"}, + "tags":["downtown","commute","green-light"], + "model":"perception-net-v5" + }'), + (2, '{ + "frame":{"source":"dashcam_front","timestamp":"2025-10-21T08:32:06Z","location":{"city":"San Francisco","intersection":"Mission & 6th","gps":[37.7829,-122.4079]}}, + "vehicle":{"speed_kmh":9,"acceleration":-1.1,"lane":"center"}, + "signals":{"traffic_light":"red","distance_m":18,"speed_limit_kmh":40}, + "detections":[ + {"label":"traffic_light","state":"red","confidence":0.99,"distance_m":18}, + {"label":"bike","confidence":0.82,"distance_m":9,"relative_speed_kmh":3} + ], + "scene":{"weather":"clear","time_of_day":"day","visibility":"good"}, + "tags":["stop","cyclist","urban"], + "model":"perception-net-v5" + }'), + (3, '{ + "frame":{"source":"dashcam_front","timestamp":"2025-10-21T08:32:07Z","location":{"city":"San Francisco","intersection":"SOMA School Zone","gps":[37.7808,-122.4016]}}, + "vehicle":{"speed_kmh":28,"acceleration":0.2,"lane":"right"}, + "signals":{"traffic_light":"yellow","distance_m":32,"speed_limit_kmh":25}, + "detections":[ + {"label":"traffic_sign","text":"SCHOOL","confidence":0.91,"distance_m":25}, + {"label":"pedestrian","confidence":0.76,"distance_m":8,"intent":"waiting"} + ], + "scene":{"weather":"overcast","time_of_day":"day","visibility":"moderate"}, + "tags":["school-zone","caution"], + "model":"perception-net-v5" + }'); +``` + +### 示例:布尔 AND {#example-boolean-and} + +```sql +SELECT id, meta['frame']['timestamp'] AS ts +FROM frames +WHERE QUERY('meta.signals.traffic_light:red AND meta.vehicle.speed_kmh:[0 TO 10]'); +-- Returns id 2 +``` + +### 示例:布尔 OR {#example-boolean-or} + +```sql +SELECT id, meta['frame']['timestamp'] AS ts +FROM frames +WHERE QUERY('meta.signals.traffic_light:red OR meta.detections.label:bike'); +-- Returns id 2 +``` + +### 示例:IN 列表匹配 {#example-in-list-matching} + +```sql +SELECT id, meta['frame']['timestamp'] AS ts +FROM frames +WHERE QUERY('meta.tags:IN [stop urban]'); +-- Returns id 2 +``` + +### 示例:包含边界的范围 {#example-inclusive-range} + +```sql +SELECT id, meta['frame']['timestamp'] AS ts +FROM frames +WHERE QUERY('meta.vehicle.speed_kmh:[0 TO 10]'); +-- Returns id 2 +``` + +### 示例:不包含边界的范围 {#example-exclusive-range} + +```sql +SELECT id, meta['frame']['timestamp'] AS ts +FROM frames +WHERE QUERY('meta.vehicle.speed_kmh:{0 TO 10}'); +-- Returns id 2 +``` + +### 示例:跨字段 Boost {#example-boost-across-fields} + +```sql +SELECT id, meta['frame']['timestamp'] AS ts, SCORE() +FROM frames +WHERE QUERY('meta.signals.traffic_light:red^1.0 AND meta.tags:urban^2.0'); +-- Returns id 2 with higher relevance +``` + +### 示例:检测高置信度行人 {#example-detect-high-confidence-pedestrians} + +```sql +SELECT id, meta['frame']['timestamp'] AS ts +FROM frames +WHERE QUERY('meta.detections.label:IN [pedestrian cyclist] AND meta.detections.confidence:[0.8 TO *]'); +-- Returns ids 1 and 3 +``` + +### 示例:按短语过滤 {#example-filter-by-phrase} + +```sql +SELECT id, meta['frame']['timestamp'] AS ts +FROM frames +WHERE QUERY('meta.scene.summary:"vehicle stopped at red traffic light"'); +-- Returns id 2 +``` + +### 示例:学区过滤 {#example-school-zone-filter} + +```sql +SELECT id, meta['frame']['timestamp'] AS ts +FROM frames +WHERE QUERY('meta.detections.text:SCHOOL AND meta.scene.time_of_day:day'); +-- Returns id 3 +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/quote.md b/tidb-cloud-lake/sql/quote.md new file mode 100644 index 0000000000000..c90ab82591981 --- /dev/null +++ b/tidb-cloud-lake/sql/quote.md @@ -0,0 +1,32 @@ +--- +title: QUOTE +summary: 为字符串添加引号,生成可在 SQL 语句中用作正确转义的数据值的结果。 +--- + +# QUOTE + +为字符串添加引号,生成可在 SQL 语句中用作正确转义的数据值的结果。 + +## 语法 {#syntax} + +```sql +QUOTE() +``` + +## 示例 {#examples} + +```sql +SELECT QUOTE('Don\'t!'); ++-----------------+ +| QUOTE('Don't!') | ++-----------------+ +| Don\'t! | ++-----------------+ + +SELECT QUOTE(NULL); ++-------------+ +| QUOTE(NULL) | ++-------------+ +| NULL | ++-------------+ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/radians.md b/tidb-cloud-lake/sql/radians.md new file mode 100644 index 0000000000000..eafbc7f4fbf27 --- /dev/null +++ b/tidb-cloud-lake/sql/radians.md @@ -0,0 +1,26 @@ +--- +title: RADIANS +summary: 返回参数 `x` 从角度转换为弧度后的值。 +--- + +# RADIANS + +返回参数 `x` 从角度转换为弧度后的值。 + +## 语法 {#syntax} + +```sql +RADIANS( ) +``` + +## 示例 {#examples} + +```sql +SELECT RADIANS(90); + +┌────────────────────┐ +│ radians(90) │ +├────────────────────┤ +│ 1.5707963267948966 │ +└────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/rand-n.md b/tidb-cloud-lake/sql/rand-n.md new file mode 100644 index 0000000000000..179d34d68feb4 --- /dev/null +++ b/tidb-cloud-lake/sql/rand-n.md @@ -0,0 +1,26 @@ +--- +title: RAND(n) +summary: 返回范围 `0 <= v < 1.0` 内的随机 float 值 v。若要获取范围 `i <= R < j` 内的随机整数型 R,请使用表达式 `FLOOR(i + RAND() * (j − i))`。参数 `n` 用作数据填充值。对于相同的参数值,RAND(n) 每次都会返回相同的值,因此会生成可重复的列值序列。 +--- + +# RAND(n) + +返回范围 `0 <= v < 1.0` 内的随机 float 值 v。若要获取范围 `i <= R < j` 内的随机整数型 R,请使用表达式 `FLOOR(i + RAND() * (j − i))`。参数 `n` 用作数据填充值。对于相同的参数值,RAND(n) 每次都会返回相同的值,因此会生成可重复的列值序列。 + +## 语法 {#syntax} + +```sql +RAND( ) +``` + +## 示例 {#examples} + +```sql +SELECT RAND(1); + +┌────────────────────┐ +│ rand(1) │ +├────────────────────┤ +│ 0.7133693869548766 │ +└────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/rand.md b/tidb-cloud-lake/sql/rand.md new file mode 100644 index 0000000000000..75f53d93fd34f --- /dev/null +++ b/tidb-cloud-lake/sql/rand.md @@ -0,0 +1,26 @@ +--- +title: RAND() +summary: 返回范围 `0 <= v < 1.0` 内的随机 float 值 v。要获取范围 `i <= R < j` 内的随机整数型 R,请使用表达式 `FLOOR(i + RAND() * (j − i))`。 +--- + +# RAND() + +返回范围 `0 <= v < 1.0` 内的随机 float 值 v。要获取范围 `i <= R < j` 内的随机整数型 R,请使用表达式 `FLOOR(i + RAND() * (j − i))`。 + +## 语法 {#syntax} + +```sql +RAND() +``` + +## 示例 {#examples} + +```sql +SELECT RAND(); + +┌────────────────────┐ +│ rand() │ +├────────────────────┤ +│ 0.5191511074382174 │ +└────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/range-between.md b/tidb-cloud-lake/sql/range-between.md new file mode 100644 index 0000000000000..5d8d04da0dfe9 --- /dev/null +++ b/tidb-cloud-lake/sql/range-between.md @@ -0,0 +1,286 @@ +--- +title: RANGE BETWEEN +summary: 使用基于值的边界为窗口函数定义窗口框架。 +--- + +# RANGE BETWEEN + +使用基于值的边界为窗口函数定义窗口框架。 + +## 概述 {#overview} + +`RANGE BETWEEN` 子句用于指定窗口框架中应包含哪些行,其依据是逻辑值范围,而不是物理行数。它特别适用于基于时间的窗口、基于值的分组以及处理重复值的场景。 + +## 语法 {#syntax} + +```sql +FUNCTION() OVER ( + [ PARTITION BY partition_expression ] + [ ORDER BY sort_expression ] + RANGE BETWEEN frame_start AND frame_end +) +``` + +### 框架边界 {#frame-boundaries} + +| 边界 | 描述 | 示例 | +|----------|-------------|---------| +| `UNBOUNDED PRECEDING` | 分区起始位置 | `RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW` | +| `value PRECEDING` | 当前行之前的值范围 | `RANGE BETWEEN INTERVAL '7' DAY PRECEDING AND CURRENT ROW` | +| `CURRENT ROW` | 当前行的值 | `RANGE BETWEEN CURRENT ROW AND CURRENT ROW` | +| `value FOLLOWING` | 当前行之后的值范围 | `RANGE BETWEEN CURRENT ROW AND INTERVAL '7' DAY FOLLOWING` | +| `UNBOUNDED FOLLOWING` | 分区结束位置 | `RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING` | + +## RANGE 与 ROWS 的区别 {#range-vs-rows} + +| 方面 | RANGE | ROWS | +|--------|-------|------| +| **定义** | 逻辑值范围 | 物理行数 | +| **边界** | 基于值的位置 | 行位置 | +| **并列值** | 相同值共享同一个框架 | 每一行彼此独立 | +| **性能** | 有重复值时可能更慢 | 通常更快 | +| **使用场景** | 基于时间的窗口、百分位数计算 | 移动平均、累计总和 | + +## RANGE 的值类型 {#value-types-for-range} + +### 1. 数值 {#1-numeric-values} + +```sql +-- Include rows within ±10 units +RANGE BETWEEN 10 PRECEDING AND 10 FOLLOWING + +-- Include rows with values up to 50 less than current +RANGE BETWEEN 50 PRECEDING AND CURRENT ROW +``` + +### 2. Interval 值(用于 DATE/TIMESTAMP) {#2-interval-values-for-date-timestamp} + +```sql +-- 7-day window +RANGE BETWEEN INTERVAL '7' DAY PRECEDING AND CURRENT ROW + +-- 1-hour window +RANGE BETWEEN INTERVAL '1' HOUR PRECEDING AND CURRENT ROW + +-- 30-minute centered window +RANGE BETWEEN INTERVAL '15' MINUTE PRECEDING AND INTERVAL '15' MINUTE FOLLOWING +``` + +### 3. 未指定值(默认) {#3-no-value-specified-default} + +当 `PRECEDING` 或 `FOLLOWING` 未指定值时,默认值为 `CURRENT ROW`: + +```sql +RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW -- Default behavior +``` + +## 示例 {#examples} + +### 示例数据 {#sample-data} + +```sql +CREATE TABLE temperature_readings ( + reading_time TIMESTAMP, + sensor_id VARCHAR(10), + temperature DECIMAL(5,2) +); + +INSERT INTO temperature_readings VALUES + ('2024-01-01 00:00:00', 'S1', 20.5), + ('2024-01-01 01:00:00', 'S1', 21.0), + ('2024-01-01 02:00:00', 'S1', 20.8), + ('2024-01-01 03:00:00', 'S1', 22.1), + ('2024-01-01 04:00:00', 'S1', 21.5), + ('2024-01-01 00:00:00', 'S2', 19.8), + ('2024-01-01 01:00:00', 'S2', 20.2), + ('2024-01-01 02:00:00', 'S2', 19.9), + ('2024-01-01 03:00:00', 'S2', 21.0), + ('2024-01-01 04:00:00', 'S2', 20.5); +``` + +### 1. 24 小时滚动平均值 {#1-24-hour-rolling-average} + +```sql +SELECT reading_time, sensor_id, temperature, + AVG(temperature) OVER ( + PARTITION BY sensor_id + ORDER BY reading_time + RANGE BETWEEN INTERVAL '24' HOUR PRECEDING AND CURRENT ROW + ) AS avg_24h +FROM temperature_readings +ORDER BY sensor_id, reading_time; +``` + +### 2. 基于值的窗口(在 ±0.5 度范围内) {#2-value-based-window-within-05-degrees} + +```sql +SELECT reading_time, sensor_id, temperature, + COUNT(*) OVER ( + PARTITION BY sensor_id + ORDER BY temperature + RANGE BETWEEN 0.5 PRECEDING AND 0.5 FOLLOWING + ) AS similar_readings_count +FROM temperature_readings +ORDER BY sensor_id, temperature; +``` + +### 3. 处理重复值 {#3-handling-duplicate-values} + +```sql +CREATE TABLE sales_duplicates ( + sale_date DATE, + amount DECIMAL(10,2) +); + +INSERT INTO sales_duplicates VALUES + ('2024-01-01', 100.00), + ('2024-01-01', 100.00), -- Duplicate date + ('2024-01-02', 150.00), + ('2024-01-03', 200.00), + ('2024-01-03', 200.00); -- Duplicate date + +-- RANGE treats duplicate dates as the same "row" for window calculations +SELECT sale_date, amount, + SUM(amount) OVER ( + ORDER BY sale_date + RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW + ) AS running_total_range, + SUM(amount) OVER ( + ORDER BY sale_date + ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW + ) AS running_total_rows +FROM sales_duplicates +ORDER BY sale_date; +``` + +**结果对比:** + +``` +sale_date | amount | running_total_range | running_total_rows +------------+--------+---------------------+-------------------- +2024-01-01 | 100.00 | 200.00 | 100.00 +2024-01-01 | 100.00 | 200.00 | 200.00 -- ROWS: different +2024-01-02 | 150.00 | 350.00 | 350.00 +2024-01-03 | 200.00 | 750.00 | 550.00 +2024-01-03 | 200.00 | 750.00 | 750.00 -- ROWS: different +``` + +### 4. 基于时间的居中窗口 {#4-time-based-centered-window} + +```sql +SELECT reading_time, sensor_id, temperature, + AVG(temperature) OVER ( + PARTITION BY sensor_id + ORDER BY reading_time + RANGE BETWEEN INTERVAL '30' MINUTE PRECEDING + AND INTERVAL '30' MINUTE FOLLOWING + ) AS avg_hour_centered +FROM temperature_readings +ORDER BY sensor_id, reading_time; +``` + +## 常见模式 {#common-patterns} + +### 基于时间的窗口 {#time-based-windows} + +**语法示例:** + +```sql +-- 7-day rolling window +RANGE BETWEEN INTERVAL '7' DAY PRECEDING AND CURRENT ROW + +-- 1-hour centered window +RANGE BETWEEN INTERVAL '30' MINUTE PRECEDING AND INTERVAL '30' MINUTE FOLLOWING + +-- Month-to-date (when ORDER BY is date) +RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW +``` + +**完整示例:** + +```sql +-- 7-day rolling average +SELECT sale_date, amount, + AVG(amount) OVER ( + ORDER BY sale_date + RANGE BETWEEN INTERVAL '7' DAY PRECEDING AND CURRENT ROW + ) AS avg_7day +FROM sales_duplicates +ORDER BY sale_date; +``` + +### 基于值的窗口 {#value-based-windows} + +**语法示例:** + +```sql +-- Within ±10 units +RANGE BETWEEN 10 PRECEDING AND 10 FOLLOWING + +-- Values up to 100 less than current +RANGE BETWEEN 100 PRECEDING AND CURRENT ROW + +-- Note: Complex expressions like (current * 0.05) may not be supported +-- Use fixed values or simple expressions +``` + +**完整示例:** + +```sql +-- Include rows within ±0.5 units +SELECT temperature, reading_time, + COUNT(*) OVER ( + ORDER BY temperature + RANGE BETWEEN 0.5 PRECEDING AND 0.5 FOLLOWING + ) AS similar_readings +FROM temperature_readings +ORDER BY temperature; +``` + +### 处理重复值 {#handling-duplicates} + +**语法示例:** + +```sql +-- Include all duplicate values in same window +RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW + +-- Value-based grouping (groups identical values) +RANGE BETWEEN 0 PRECEDING AND 0 FOLLOWING +``` + +**完整示例:** + +```sql +-- RANGE treats duplicate dates as same window +SELECT sale_date, amount, + SUM(amount) OVER ( + ORDER BY sale_date + RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW + ) AS running_total_range +FROM sales_duplicates +ORDER BY sale_date; +``` + +## 最佳实践 {#best-practices} + +1. **对基于值的窗口使用 RANGE** - 当你关注的是逻辑值范围而不是行数时 +2. **与 DATE/TIMESTAMP 一起使用** - 非常适合基于时间的计算 +3. **有意识地处理重复值** - RANGE 会将 `ORDER BY` 的重复值分组 +4. **考虑性能** - 当存在大量重复值时,RANGE 可能比 ROWS 更慢 +5. **清晰指定间隔** - 对日期/时间窗口使用显式的 INTERVAL 语法 + +## 限制 {#limitations} + +1. **ORDER BY 必须是数值或时间类型** - RANGE 需要可排序的值 +2. **仅支持一个 ORDER BY 列** - RANGE 适用于单列排序 +3. **值表达式受限** - 支持简单的数值/间隔值,不支持复杂表达式 +4. **性能注意事项** - 当存在大量重复值时,可能比 ROWS 更慢 +5. **框架边界必须兼容** - PRECEDING/FOLLOWING 必须使用相同的单位类型 + +## 另请参阅 {#see-also} + +- [窗口函数概览](/tidb-cloud-lake/sql/window-functions-overview.md) +- [ROWS BETWEEN](/tidb-cloud-lake/sql/rows-between.md) - 基于行的窗口框架 +- [聚合函数](/tidb-cloud-lake/sql/aggregate-functions.md) - 可使用窗口框架的函数 +- [日期与时间函数](/tidb-cloud-lake/sql/date-time-functions.md) - 与 RANGE 间隔配合使用很有帮助 \ No newline at end of file diff --git a/tidb-cloud-lake/sql/range.md b/tidb-cloud-lake/sql/range.md new file mode 100644 index 0000000000000..9889bc7b5f664 --- /dev/null +++ b/tidb-cloud-lake/sql/range.md @@ -0,0 +1,26 @@ +--- +title: RANGE +summary: 返回由 [start, end) 收集的数组。 +--- + +# RANGE + +返回由 [start, end) 收集的数组。 + +## 语法 {#syntax} + +```sql +RANGE( , ) +``` + +## 示例 {#examples} + +```sql +SELECT RANGE(1, 5); + +┌───────────────┐ +│ range(1, 5) │ +├───────────────┤ +│ [1,2,3,4] │ +└───────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/rank.md b/tidb-cloud-lake/sql/rank.md new file mode 100644 index 0000000000000..e2e4e055a8d6f --- /dev/null +++ b/tidb-cloud-lake/sql/rank.md @@ -0,0 +1,103 @@ +--- +title: RANK +summary: 为分区内的每一行分配一个排名。值相等的行会获得相同的排名,后续排名会出现间隔。 +--- + +# RANK + +为分区内的每一行分配一个排名。值相等的行会获得相同的排名,后续排名会出现间隔。 + +## 语法 {#syntax} + +```sql +RANK() +OVER ( + [ PARTITION BY partition_expression ] + ORDER BY sort_expression [ ASC | DESC ] +) +``` + +**参数:** + +- `PARTITION BY`:可选。将行划分为多个分区 +- `ORDER BY`:必需。确定排名顺序 +- `ASC | DESC`:可选。排序方向(默认值:ASC) + +**说明:** + +- 排名从 1 开始 +- 相等的值会获得相同的排名 +- 并列之后的排名序列会出现间隔 +- 示例:1, 2, 2, 4, 5(而不是 1, 2, 2, 3, 4) + +## 示例 {#examples} + +```sql +-- Create sample data +CREATE TABLE scores ( + student VARCHAR(20), + subject VARCHAR(20), + score INT +); + +INSERT INTO scores VALUES + ('Alice', 'Math', 95), + ('Alice', 'English', 87), + ('Alice', 'Science', 92), + ('Bob', 'Math', 85), + ('Bob', 'English', 85), + ('Bob', 'Science', 80), + ('Charlie', 'Math', 88), + ('Charlie', 'English', 85), + ('Charlie', 'Science', 85); +``` + +**对所有分数进行排名(展示并列时带间隔的处理方式):** + +```sql +SELECT student, subject, score, + RANK() OVER (ORDER BY score DESC) AS score_rank +FROM scores +ORDER BY score DESC, student, subject; +``` + +结果: + +``` +student | subject | score | score_rank +--------+---------+-------+----------- +Alice | Math | 95 | 1 +Alice | Science | 92 | 2 +Charlie | Math | 88 | 3 +Alice | English | 87 | 4 +Bob | English | 85 | 5 +Bob | Math | 85 | 5 +Charlie | English | 85 | 5 +Charlie | Science | 85 | 5 +Bob | Science | 80 | 9 +``` + +**在每个学生内部对分数进行排名(展示分区内的并列情况):** + +```sql +SELECT student, subject, score, + RANK() OVER (PARTITION BY student ORDER BY score DESC) AS subject_rank +FROM scores +ORDER BY student, score DESC, subject; +``` + +结果: + +``` +student | subject | score | subject_rank +--------+---------+-------+------------- +Alice | Math | 95 | 1 +Alice | Science | 92 | 2 +Alice | English | 87 | 3 +Bob | English | 85 | 1 +Bob | Math | 85 | 1 +Bob | Science | 80 | 3 +Charlie | Math | 88 | 1 +Charlie | English | 85 | 2 +Charlie | Science | 85 | 2 +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/read-file.md b/tidb-cloud-lake/sql/read-file.md new file mode 100644 index 0000000000000..c8d30c9a86300 --- /dev/null +++ b/tidb-cloud-lake/sql/read-file.md @@ -0,0 +1,90 @@ +--- +title: READ_FILE +summary: 从 stage 读取文件并返回其原始字节。 +--- + +# READ_FILE + +从 stage 读取文件,并将其内容作为原始字节返回。 + +当你希望将已暂存的资源(如文档、镜像或模型输入)打包到下游数据集中时,`READ_FILE` 非常有用,例如将训练数据卸载到 Lance 时。 + +## 语法 {#syntax} + +```sql +READ_FILE('@/') +READ_FILE('@', '') +``` + +## 参数 {#arguments} + +| 参数 | 描述 | +|-----------|-------------| +| `@/` | 完整的 stage 文件路径。该表达式必须解析为以 `@` 开头的 stage 文件路径。 | +| `@` | 双参数形式中的 stage 名称。使用常量 stage 引用,例如 `@assets`。 | +| `` | 相对于 stage 的文件路径。可以是字符串字面量、列,或解析为字符串的表达式。 | + +## 返回类型 {#return-type} + +`BINARY` + +如果任一参数为 `NULL`,结果为 `NULL`。 + +## 使用说明 {#usage-notes} + +- `READ_FILE` 从 stage 读取文件。它不会读取 {{{ .lake }}} server 上的本地文件。 +- 目标必须是文件,而不是目录。 +- 调用方必须具有读取该 stage 的权限。 + +## 示例 {#examples} + +使用完整的 stage 路径读取文件: + +```sql +SELECT TO_HEX(READ_FILE('@data/csv/prefix/ab.csv')); +``` + +结果: + +```text +31 +``` + +使用 stage 名称加相对路径读取文件: + +```sql +SELECT TO_HEX(READ_FILE('@data', 'csv/prefix/ab.csv')); +``` + +结果: + +```text +31 +``` + +通过将常量 stage 与每行的相对路径组合来读取多个文件: + +```sql +CREATE OR REPLACE TABLE read_file_rel_paths(path STRING); + +INSERT INTO read_file_rel_paths VALUES + ('csv/prefix/ab.csv'), + ('csv/prefix/ab/cd.csv'), + (NULL); + +SELECT path, TO_HEX(READ_FILE('@data', path)) +FROM read_file_rel_paths +ORDER BY path; +``` + +结果: + +```text ++----------------------+--------------------------------+ +| path | to_hex(read_file('@data',path)) | ++----------------------+--------------------------------+ +| csv/prefix/ab.csv | 31 | +| csv/prefix/ab/cd.csv | 32 | +| NULL | NULL | ++----------------------+--------------------------------+ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/recluster-table.md b/tidb-cloud-lake/sql/recluster-table.md new file mode 100644 index 0000000000000..437b15a096897 --- /dev/null +++ b/tidb-cloud-lake/sql/recluster-table.md @@ -0,0 +1,64 @@ +--- +title: RECLUSTER TABLE +summary: 对表重新聚簇。关于为什么以及何时需要对表重新聚簇,请参见 Re-clustering Table。 +--- + +# RECLUSTER TABLE + +> **注意:** +> +> 于 v1.2.25 引入。 + +对表重新聚簇。关于为什么以及何时需要对表重新聚簇,请参见 [对表重新聚簇](/tidb-cloud-lake/sql/cluster-key.md#cluster-key-management)。 + +## 语法 {#syntax} + +```sql +ALTER TABLE [ IF EXISTS ] RECLUSTER [ FINAL ] [ WHERE condition ] [ LIMIT ] +``` + +该命令对可处理的 segment 数量有一个限制,默认值为 `max_thread * 4`。你可以使用 **LIMIT** 选项修改此限制。或者,你还可以通过以下两种方式进一步对表中的数据进行聚簇: + +- 对该表多次运行此命令。 +- 使用 **FINAL** 选项持续优化该表,直到其完成全部聚簇。 + +> **注意:** +> +> 对表重新聚簇会消耗时间(如果包含 **FINAL** 选项,耗时会更长)和 credits(当你使用 {{{ .lake }}} 时)。在优化过程中,请勿对该表执行 DML 操作。 + +该命令不会从头开始对表进行聚簇。相反,它会使用聚簇算法,从最新的 **LIMIT** 个 segment 中选择并重组最混乱的现有存储块。 + +### 示例 {#examples} + +```sql +-- create table +create table t(a int, b int) cluster by(a+1); + +-- insert some data to t +insert into t values(1,1),(3,3); +insert into t values(2,2),(5,5); +insert into t values(4,4); + +select * from clustering_information('default','t')\G +*************************** 1. row *************************** + cluster_key: ((a + 1)) + total_block_count: 3 + constant_block_count: 1 +unclustered_block_count: 0 + average_overlaps: 1.3333 + average_depth: 2.0 + block_depth_histogram: {"00002":3} + +-- alter table recluster +ALTER TABLE t RECLUSTER FINAL WHERE a != 4; + +select * from clustering_information('default','t')\G +*************************** 1. row *************************** + cluster_key: ((a + 1)) + total_block_count: 2 + constant_block_count: 1 +unclustered_block_count: 0 + average_overlaps: 1.0 + average_depth: 2.0 + block_depth_histogram: {"00002":2} +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/refresh-aggregating-index.md b/tidb-cloud-lake/sql/refresh-aggregating-index.md new file mode 100644 index 0000000000000..0e07fcb5d01ab --- /dev/null +++ b/tidb-cloud-lake/sql/refresh-aggregating-index.md @@ -0,0 +1,34 @@ +--- +title: REFRESH AGGREGATING INDEX +summary: "{{{ .lake }}} 会在新数据摄取时自动以 `SYNC` 模式维护聚合索引。当你在一个已包含数据的表上新增索引时,运行 REFRESH AGGREGATING INDEX 以回填更早的行。" +--- + +# REFRESH AGGREGATING INDEX + +{{{ .lake }}} 会在新数据摄取时自动以 `SYNC` 模式维护聚合索引。当你在一个已包含数据的表上新增索引时,运行 `REFRESH AGGREGATING INDEX` 以回填更早的行。 + +## 语法 {#syntax} + +```sql +REFRESH AGGREGATING INDEX +``` + +## 示例 {#examples} + +本示例会在一个已包含数据的表上创建聚合索引,然后运行一次 `REFRESH` 来回填这些行: + +```sql +-- Prepare a table and load data before the index exists +CREATE TABLE agg(a int, b int, c int); +INSERT INTO agg VALUES (1,1,4), (1,2,1), (1,2,4); + +-- Declare the aggregating index (existing rows are not indexed yet) +CREATE AGGREGATING INDEX my_agg_index AS SELECT MIN(a), MAX(c) FROM agg; + +-- Backfill previously inserted rows +REFRESH AGGREGATING INDEX my_agg_index; + +-- Insert new data after the index exists (no manual refresh needed) +INSERT INTO agg VALUES (2,2,5); +-- SYNC mode keeps the index current automatically +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/refresh-inverted-index.md b/tidb-cloud-lake/sql/refresh-inverted-index.md new file mode 100644 index 0000000000000..38b2d1db9e630 --- /dev/null +++ b/tidb-cloud-lake/sql/refresh-inverted-index.md @@ -0,0 +1,36 @@ +--- +title: REFRESH INVERTED INDEX +summary: "{{{ .lake }}} 会在写入新数据时自动刷新 `SYNC` 模式的倒排索引。`REFRESH INVERTED INDEX` 主要用于回填在声明索引之前已存在的行。" +--- + +# REFRESH INVERTED INDEX + +{{{ .lake }}} 会在写入新数据时自动刷新 `SYNC` 模式的倒排索引。`REFRESH INVERTED INDEX` 主要用于回填在声明索引之前已存在的行。 + +## 语法 {#syntax} + +```sql +REFRESH INVERTED INDEX ON [.]
[LIMIT ] +``` + +| 参数 | 描述 | +|-----------|----------------------------------------------------------------------------------------------------------------------------------| +| `` | 指定索引刷新期间要处理的最大行数。如果未指定,则会处理表中的所有行。 | + +## 示例 {#examples} + +```sql +-- Existing table with data loaded before the index was declared +CREATE TABLE IF NOT EXISTS customer_feedback(id INT, body STRING); +INSERT INTO customer_feedback VALUES + (1, 'Great coffee beans'), + (2, 'Needs fresh roasting'); + +-- Create the inverted index afterward +CREATE INVERTED INDEX customer_feedback_idx ON customer_feedback(body); + +-- Backfill historical rows so the index covers earlier inserts +REFRESH INVERTED INDEX customer_feedback_idx ON customer_feedback; + +-- Future inserts refresh automatically in SYNC mode +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/refresh-lineage.md b/tidb-cloud-lake/sql/refresh-lineage.md new file mode 100644 index 0000000000000..cc9a598e893ee --- /dev/null +++ b/tidb-cloud-lake/sql/refresh-lineage.md @@ -0,0 +1,69 @@ +--- +title: REFRESH LINEAGE +summary: 为 {{{ .lake }}} 中现有视图回填或协调 lineage。 +--- + +# REFRESH LINEAGE + +为 `default` catalog 中的现有视图回填或协调 lineage。在已包含视图的部署上启用 data lineage 后,请使用此命令。启用 lineage 后新创建的视图会被自动跟踪。 + +此命令需要全局 `SUPER` 权限,并且必须已启用 lineage。参见[数据 lineage](/tidb-cloud-lake/guides/data-lineage.md#enable-data-lineage)。 + +## 语法 {#syntax} + +```sql +REFRESH LINEAGE FOR ALL VIEWS [ DRY RUN ] +``` + +`DRY RUN` 会计算并报告变更,但不会将其写入。建议先运行它,以查看执行 refresh 时将进行的操作。 + +## 输出列 {#output-columns} + +| 列 | 描述 | +|--------|-------------| +| `object_domain` | 对象域;当前为 `VIEW`。 | +| `catalog` | 包含该视图的 catalog;当前为 `default`。 | +| `database` | 包含该视图的数据库。 | +| `object_name` | 视图名称。 | +| `status` | `DRY_RUN`、`REFRESHED` 或 `ERROR`。 | +| `edge_count` | 在当前视图定义中找到的 lineage 边数量。 | +| `upsert_count` | 需要新增或修改的缺失或已变更边数量。 | +| `delete_count` | 需要删除的过期边数量。 | +| `error` | 当 `status` 为 `ERROR` 时的错误详情;否则为 `NULL`。 | + +对于成功且无变更的视图,结果中不会显示。 + +## 示例 {#examples} + +预览现有视图所需的变更: + +```sql +REFRESH LINEAGE FOR ALL VIEWS DRY RUN; +``` + +应用这些变更: + +```sql +REFRESH LINEAGE FOR ALL VIEWS; +``` + +命令完成后,可使用 [`GET_LINEAGE`](/tidb-cloud-lake/sql/get-lineage.md) 查询某个视图的上游 lineage: + +```sql +SELECT + distance, + source_object_database, + source_object_name, + target_object_database, + target_object_name +FROM GET_LINEAGE( + 'lineage_demo.sales_view', + 'VIEW', + 'UPSTREAM', + 1 +); +``` + +> **注意:** +> +> 如需修改逻辑视图定义,请使用 [`CREATE OR REPLACE VIEW`](/tidb-cloud-lake/sql/create-view.md)。不支持 `ALTER VIEW ... AS ...`,因为在不重建视图的情况下修改定义,可能会导致持久化的 lineage 不一致。 \ No newline at end of file diff --git a/tidb-cloud-lake/sql/refresh-ngram-index.md b/tidb-cloud-lake/sql/refresh-ngram-index.md new file mode 100644 index 0000000000000..0b6b80f8bc82c --- /dev/null +++ b/tidb-cloud-lake/sql/refresh-ngram-index.md @@ -0,0 +1,33 @@ +--- +title: 刷新 NGRAM 索引 +summary: "{{{ .lake }}} 在数据摄取时会自动刷新 NGRAM 索引。当你需要回填在索引定义之前已存在的数据时,请使用 REFRESH NGRAM INDEX。" +--- + +# 刷新 NGRAM 索引 + +{{{ .lake }}} 在数据摄取时会自动刷新 NGRAM 索引。当你需要回填在索引定义之前已存在的数据时,请使用 `REFRESH NGRAM INDEX`。 + +## 语法 {#syntax} + +```sql +REFRESH NGRAM INDEX [IF EXISTS] +ON [.]; +``` + +## 示例 {#examples} + +```sql +-- Table already populated before the NGRAM index exists +CREATE TABLE IF NOT EXISTS amazon_reviews_ngram(review_id INT, review STRING); +INSERT INTO amazon_reviews_ngram VALUES + (1, 'coffee beans from Colombia'), + (2, 'best roasting kit'); + +-- Declare the NGRAM index afterward +CREATE NGRAM INDEX idx1 ON amazon_reviews_ngram(review) WITH (ngram_size = 3); + +-- Refresh so the pre-existing rows are indexed +REFRESH NGRAM INDEX idx1 ON amazon_reviews_ngram; + +-- Subsequent inserts refresh automatically in SYNC mode +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/refresh-spatial-index.md b/tidb-cloud-lake/sql/refresh-spatial-index.md new file mode 100644 index 0000000000000..712388b9e3d97 --- /dev/null +++ b/tidb-cloud-lake/sql/refresh-spatial-index.md @@ -0,0 +1,40 @@ +--- +title: REFRESH SPATIAL INDEX +summary: 刷新空间索引以回填历史行,或在数据变更后修改索引。 +--- + +# REFRESH SPATIAL INDEX + +{{{ .lake }}} 会在 `SYNC` 模式下每次写入新数据时自动刷新空间索引。`REFRESH SPATIAL INDEX` 主要用于回填在声明索引之前已存在的行。 + +## 语法 {#syntax} + +```sql +REFRESH SPATIAL INDEX ON [.]
[LIMIT ] +``` + +| 参数 | 描述 | +|-----------|-------------| +| `` | 指定刷新索引期间要处理的最大行数。如果未指定,则会处理表中的所有行。 | + +## 示例 {#examples} + +```sql +-- Existing table with data loaded before the index was declared +CREATE TABLE IF NOT EXISTS stores ( + store_id INT, + location GEOMETRY +) ENGINE = FUSE; + +INSERT INTO stores VALUES + (1, TO_GEOMETRY('POINT(10 10)')), + (2, TO_GEOMETRY('POINT(20 20)')); + +-- Create the spatial index afterward +CREATE SPATIAL INDEX stores_location_idx ON stores(location); + +-- Backfill historical rows so the index covers earlier inserts +REFRESH SPATIAL INDEX stores_location_idx ON stores; + +-- Future inserts refresh automatically in SYNC mode +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/refresh-vector-index.md b/tidb-cloud-lake/sql/refresh-vector-index.md new file mode 100644 index 0000000000000..00168b923a469 --- /dev/null +++ b/tidb-cloud-lake/sql/refresh-vector-index.md @@ -0,0 +1,48 @@ +--- +title: REFRESH VECTOR INDEX +summary: 为在索引创建之前已插入的现有数据构建 Vector 索引。 +--- + +# REFRESH VECTOR INDEX + +为在索引创建之前已插入的现有数据构建 Vector 索引。 + +## 语法 {#syntax} + +```sql +REFRESH VECTOR INDEX ON [.] +``` + +## 何时使用 REFRESH {#when-to-use-refresh} + +`REFRESH VECTOR INDEX` **仅在一种特定场景下**需要使用:当你在一个**已经包含数据**的表上创建 Vector 索引时。 + +现有行(即在索引创建之前写入的行)不会被自动建立索引。你必须运行 `REFRESH VECTOR INDEX`,为这些预先存在的数据构建索引。刷新完成后,之后的所有数据写入都会自动生成索引。 + +## 示例 {#examples} + +### 示例:为现有数据建立索引 {#example-index-existing-data} + +```sql +-- Step 1: Create a table without an index +CREATE TABLE products ( + id INT, + name VARCHAR, + embedding VECTOR(4) +) ENGINE = FUSE; + +-- Step 2: Insert data (without index) +INSERT INTO products VALUES + (1, 'Product A', [0.1, 0.2, 0.3, 0.4]), + (2, 'Product B', [0.5, 0.6, 0.7, 0.8]), + (3, 'Product C', [0.9, 1.0, 1.1, 1.2]); + +-- Step 3: Create vector index on existing data +CREATE VECTOR INDEX idx_embedding ON products(embedding) distance='cosine'; + +-- Step 4: Refresh to build index for the 3 existing rows +REFRESH VECTOR INDEX idx_embedding ON products; + +-- Step 5: New insertions are automatically indexed (no refresh needed) +INSERT INTO products VALUES (4, 'Product D', [1.3, 1.4, 1.5, 1.6]); +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/refresh-virtual-column.md b/tidb-cloud-lake/sql/refresh-virtual-column.md new file mode 100644 index 0000000000000..c0d84f2b23113 --- /dev/null +++ b/tidb-cloud-lake/sql/refresh-virtual-column.md @@ -0,0 +1,51 @@ +--- +title: REFRESH VIRTUAL COLUMN +summary: {{{ .lake }}} 中的 `REFRESH VIRTUAL COLUMN` 命令用于显式触发为现有表创建虚拟列。虽然 {{{ .lake }}} 会自动管理新数据的虚拟列,但在某些特定场景下,仍需要手动刷新才能充分利用此功能。 +--- + +# REFRESH VIRTUAL COLUMN + +{{{ .lake }}} 中的 `REFRESH VIRTUAL COLUMN` 命令用于显式触发为现有表创建虚拟列。虽然 {{{ .lake }}} 会自动管理新数据的虚拟列,但在某些特定场景下,仍需要手动刷新才能充分利用此功能。 + +从 v1.2.832 开始,虚拟列默认启用。 + +## 何时使用 `REFRESH VIRTUAL COLUMN` {#when-to-use-refresh-virtual-column} + +- **功能启用前已存在的表:** 如果你的表中包含 `VARIANT` 数据,并且这些表是在虚拟列功能启用之前创建的(或者是在升级到支持自动创建虚拟列的版本之前创建的),则需要刷新虚拟列以启用查询加速。对于这些表中已经存在的数据,{{{ .lake }}} 不会自动创建虚拟列。 + +## 语法 {#syntax} + +```sql +REFRESH VIRTUAL COLUMN FOR
+``` + +## 示例 {#examples} + +以下示例为名为 `test` 的表刷新虚拟列: + +```sql +CREATE TABLE test(id int, val variant); + +INSERT INTO + test +VALUES + ( + 1, + '{"id":1,"name":"datalake"}' + ), + ( + 2, + '{"id":2,"name":"databricks"}' + ); + +REFRESH VIRTUAL COLUMN FOR test; + +SHOW VIRTUAL COLUMNS WHERE table = 'test' AND database = 'default'; +╭───────────────────────────────────────────────────────────────────────────────────────────────────╮ +│ database │ table │ source_column │ virtual_column_id │ virtual_column_name │ virtual_column_type │ +│ String │ String │ String │ UInt32 │ String │ String │ +├──────────┼────────┼───────────────┼───────────────────┼─────────────────────┼─────────────────────┤ +│ default │ test │ val │ 3000000000 │ ['id'] │ UInt64 │ +│ default │ test │ val │ 3000000001 │ ['name'] │ String │ +╰───────────────────────────────────────────────────────────────────────────────────────────────────╯ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/regexp-instr.md b/tidb-cloud-lake/sql/regexp-instr.md new file mode 100644 index 0000000000000..ec8b045fef55f --- /dev/null +++ b/tidb-cloud-lake/sql/regexp-instr.md @@ -0,0 +1,61 @@ +--- +title: REGEXP_INSTR +summary: 返回字符串 `expr` 中与模式 `pat` 指定的正则表达式匹配的子字符串的起始索引;如果没有匹配,则返回 `0`。如果 `expr` 或 `pat` 为 NULL,则返回值为 NULL。字符索引从 `1` 开始。 +--- + +# REGEXP_INSTR + +返回字符串 `expr` 中与模式 `pat` 指定的正则表达式匹配的子字符串的起始索引;如果没有匹配,则返回 `0`。如果 `expr` 或 `pat` 为 NULL,则返回值为 NULL。字符索引从 `1` 开始。 + +## 语法 {#syntax} + +```sql +REGEXP_INSTR(, ) +``` + +## 参数 {#arguments} + +| 参数 | 描述 | +|---------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| expr | 要进行匹配的字符串 expr | +| pat | 正则表达式 | +| pos | 可选。开始在 expr 中进行搜索的位置。如果省略,默认值为 1。 | +| occurrence | 可选。要搜索第几次出现的匹配。如果省略,默认值为 1。 | +| return_option | 可选。指定返回哪种类型的位置。如果该值为 0,REGEXP_INSTR() 返回匹配子字符串第一个字符的位置。如果该值为 1,REGEXP_INSTR() 返回匹配子字符串之后的位置。如果省略,默认值为 0。 | +| match_type | 可选。一个字符串,用于指定如何执行匹配。其含义与 REGEXP_LIKE() 中的说明相同。 | + +## 返回类型 {#return-type} + +返回一个数值类型的值。 + +## 示例 {#examples} + +```sql +SELECT REGEXP_INSTR('dog cat dog', 'dog'); ++------------------------------------+ +| REGEXP_INSTR('dog cat dog', 'dog') | ++------------------------------------+ +| 1 | ++------------------------------------+ + +SELECT REGEXP_INSTR('dog cat dog', 'dog', 2); ++---------------------------------------+ +| REGEXP_INSTR('dog cat dog', 'dog', 2) | ++---------------------------------------+ +| 9 | ++---------------------------------------+ + +SELECT REGEXP_INSTR('aa aaa aaaa', 'a{2}'); ++-------------------------------------+ +| REGEXP_INSTR('aa aaa aaaa', 'a{2}') | ++-------------------------------------+ +| 1 | ++-------------------------------------+ + +SELECT REGEXP_INSTR('aa aaa aaaa', 'a{4}'); ++-------------------------------------+ +| REGEXP_INSTR('aa aaa aaaa', 'a{4}') | ++-------------------------------------+ +| 8 | ++-------------------------------------+ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/regexp-like.md b/tidb-cloud-lake/sql/regexp-like.md new file mode 100644 index 0000000000000..15eaba0d1f5ca --- /dev/null +++ b/tidb-cloud-lake/sql/regexp-like.md @@ -0,0 +1,75 @@ +--- +title: REGEXP_LIKE +summary: REGEXP_LIKE 函数用于检查字符串是否匹配正则表达式。 +--- + +# REGEXP_LIKE + +REGEXP_LIKE 函数用于检查字符串是否匹配正则表达式。 + +## 语法 {#syntax} + +```sql +REGEXP_LIKE(, ) +``` + +## 参数 {#arguments} + +| 参数 | 描述 | +|----------------|-----------------------------------------------------------------------------------| +| `` | 要进行匹配的字符串 expr | +| `` | 正则表达式 | +| `[match_type]` | 可选。`match_type` 参数是一个字符串,用于指定如何执行匹配 | + +`match_type` 可以包含以下任意一个或多个字符: + +* `c`:大小写敏感匹配。 +* `i`:大小写不敏感匹配。 +* `m`:多行模式。识别字符串中的行终止符。默认行为是仅在字符串表达式的开头和结尾匹配行终止符。 +* `n`:`.` 字符可以匹配行终止符。默认情况下,`.` 的匹配会在行尾停止。 +* `u`:仅 Unix 行结束符。当前暂不支持。 + +## 返回类型 {#return-type} + +`BIGINT`:如果字符串 expr 与模式 pat 指定的正则表达式匹配,则返回 `1`,否则返回 `0`。如果 expr 或 pat 为 NULL,则返回值为 NULL。 + +## 示例 {#examples} + +```sql +SELECT REGEXP_LIKE('a', '^[a-d]'); ++----------------------------+ +| REGEXP_LIKE('a', '^[a-d]') | ++----------------------------+ +| 1 | ++----------------------------+ + +SELECT REGEXP_LIKE('abc', 'ABC'); ++---------------------------+ +| REGEXP_LIKE('abc', 'ABC') | ++---------------------------+ +| 1 | ++---------------------------+ + +SELECT REGEXP_LIKE('abc', 'ABC', 'c'); ++--------------------------------+ +| REGEXP_LIKE('abc', 'ABC', 'c') | ++--------------------------------+ +| 0 | ++--------------------------------+ + +SELECT REGEXP_LIKE('new*\n*line', 'new\\*.\\*line'); ++-------------------------------------------+ +| REGEXP_LIKE('new* +*line', 'new\*.\*line') | ++-------------------------------------------+ +| 0 | ++-------------------------------------------+ + +SELECT REGEXP_LIKE('new*\n*line', 'new\\*.\\*line', 'n'); ++------------------------------------------------+ +| REGEXP_LIKE('new* +*line', 'new\*.\*line', 'n') | ++------------------------------------------------+ +| 1 | ++------------------------------------------------+ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/regexp-replace.md b/tidb-cloud-lake/sql/regexp-replace.md new file mode 100644 index 0000000000000..a6c2ce5b65661 --- /dev/null +++ b/tidb-cloud-lake/sql/regexp-replace.md @@ -0,0 +1,54 @@ +--- +title: REGEXP_REPLACE +summary: 将字符串 `expr` 中与模式 `pat` 指定的正则表达式匹配的内容替换为替换字符串 `repl`,并返回结果字符串。如果 `expr`、`pat` 或 `repl` 为 NULL,则返回值为 NULL。 +--- + +# REGEXP_REPLACE + +将字符串 `expr` 中与模式 `pat` 指定的正则表达式匹配的内容替换为替换字符串 `repl`,并返回结果字符串。如果 `expr`、`pat` 或 `repl` 为 NULL,则返回值为 NULL。 + +## 语法 {#syntax} + +```sql +REGEXP_REPLACE(, , ) +``` + +## 参数 {#arguments} + +| 参数 | 描述 | +|------------|-------------------------------------------------------------------------------------------------------------------------| +| expr | 要匹配的字符串 expr | +| pat | 正则表达式 | +| repl | 替换字符串 | +| pos | 可选。开始在 expr 中搜索的位置。如果省略,默认值为 1。 | +| occurrence | 可选。要替换第几次出现的匹配项。如果省略,默认值为 0(表示“替换所有出现的匹配项”)。 | +| match_type | 可选。一个字符串,用于指定如何执行匹配。其含义与 REGEXP_LIKE() 中的说明相同。 | + +## 返回类型 {#return-type} + +`VARCHAR` + +## 示例 {#examples} + +```sql +SELECT REGEXP_REPLACE('a b c', 'b', 'X'); ++-----------------------------------+ +| REGEXP_REPLACE('a b c', 'b', 'X') | ++-----------------------------------+ +| a X c | ++-----------------------------------+ + +SELECT REGEXP_REPLACE('abc def ghi', '[a-z]+', 'X', 1, 3); ++----------------------------------------------------+ +| REGEXP_REPLACE('abc def ghi', '[a-z]+', 'X', 1, 3) | ++----------------------------------------------------+ +| abc def X | ++----------------------------------------------------+ + +SELECT REGEXP_REPLACE('周 周周 周周周', '周+', 'X', 3, 2); ++-----------------------------------------------------------+ +| REGEXP_REPLACE('周 周周 周周周', '周+', 'X', 3, 2) | ++-----------------------------------------------------------+ +| 周 周周 X | ++-----------------------------------------------------------+ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/regexp-split-array.md b/tidb-cloud-lake/sql/regexp-split-array.md new file mode 100644 index 0000000000000..f1e314d3ebc1e --- /dev/null +++ b/tidb-cloud-lake/sql/regexp-split-array.md @@ -0,0 +1,76 @@ +--- +title: REGEXP_SPLIT_TO_ARRAY +summary: 使用正则表达式模式切分字符串,并将各个片段作为数组返回。 +--- + +# REGEXP_SPLIT_TO_ARRAY + +使用正则表达式模式切分字符串,并将各个片段作为数组返回。 + +## 语法 {#syntax} + +```sql +REGEXP_SPLIT_TO_ARRAY(string, pattern [, flags text]) +``` + +| 参数 | 描述 | +|--------------|----------------------------------------------------------------| +| `string` | 要切分的输入字符串(VARCHAR 类型) | +| `pattern` | 用于切分的正则表达式模式(VARCHAR 类型) | +| `flags text` | 用于修改正则表达式行为的标记字符串。 | + +**支持的 `flags` 参数:** + +通过组合以下字符,提供灵活的正则表达式配置选项,以控制匹配行为: + +* `i`(大小写不敏感):模式匹配时忽略大小写。 +* `c`(大小写敏感):模式匹配区分大小写(默认行为)。 +* `n` 或 `m`(多行):启用多行模式。在此模式下,`^` 和 `$` 分别匹配字符串的开头和结尾,也匹配每一行的开头和结尾;点号 `.` 不匹配换行符。 +* `s`(单行):启用单行模式(也称为 dot-matches-newline)。在此模式下,点号 `.` 匹配任意字符,包括换行符。 +* `x`(忽略空白):忽略模式中的空白字符(提高模式可读性)。 +* `q`(字面量):将 `pattern` 视为字面字符串,而不是正则表达式。 + +## 示例 {#examples} + +### 基本切分 {#basic-splitting} + +```sql +SELECT REGEXP_SPLIT_TO_ARRAY('apple,orange,banana', ','); +┌───────────────────────────────────────────┐ +│ ["apple","orange","banana"] │ +└───────────────────────────────────────────┘ +``` + +### 复杂分隔符 {#complex-delimiters} + +```sql +SELECT REGEXP_SPLIT_TO_ARRAY('2023-01-01T14:30:00', '[-T:]'); +┌───────────────────────────────────────────────────────┐ +│ ["2023","01","01","14","30","00"] │ +└───────────────────────────────────────────────────────┘ +``` + +### 处理空元素 {#handling-empty-elements} + +```sql +SELECT REGEXP_SPLIT_TO_ARRAY('a,,b,,,c', ',+'); +┌───────────────────────────────────┐ +│ ["a","b","c"] │ +└───────────────────────────────────┘ +``` + +### 使用 flag text {#with-flag-text} + +```sql +SELECT regexp_split_to_array('One_Two_Three', '[_-]', 'i') + +╭─────────────────────────────────────────────────────╮ +│ ['One','Two','Three'] │ +╰─────────────────────────────────────────────────────╯ + +``` + +## 另请参阅 {#see-also} + +- [SPLIT](/tidb-cloud-lake/sql/split.md):用于简单的字符串切分 +- [REGEXP_SPLIT_TO_TABLE](/tidb-cloud-lake/sql/regexp-split-table.md):将字符串切分为表 \ No newline at end of file diff --git a/tidb-cloud-lake/sql/regexp-split-table.md b/tidb-cloud-lake/sql/regexp-split-table.md new file mode 100644 index 0000000000000..d56610240fa07 --- /dev/null +++ b/tidb-cloud-lake/sql/regexp-split-table.md @@ -0,0 +1,88 @@ +--- +title: REGEXP_SPLIT_TO_TABLE +summary: 使用正则表达式模式切分字符串,并将每个片段作为表返回。 +--- + +# REGEXP_SPLIT_TO_TABLE + +使用正则表达式模式切分字符串,并将每个片段作为表返回。 + +## 语法 {#syntax} + +```sql +REGEXP_SPLIT_TO_TABLE(string, pattern [, flags text]) +``` + +| 参数 | 描述 | +|--------------|----------------------------------------------------------------| +| `string` | 要切分的输入字符串(VARCHAR 类型) | +| `pattern` | 用于切分的正则表达式模式(VARCHAR 类型) | +| `flags text` | 用于修改正则表达式行为的标记字符串。 | + +**支持的 `flags` 参数:** + +通过组合以下字符,提供灵活的正则表达式配置选项,以控制匹配行为: + +* `i`(不区分大小写):模式匹配时忽略大小写。 +* `c`(大小写敏感):模式匹配区分大小写(默认行为)。 +* `n` 或 `m`(多行):启用多行模式。在此模式下,`^` 和 `$` 分别匹配字符串的开头和结尾,也匹配每一行的开头和结尾;点号 `.` 不匹配换行符。 +* `s`(单行):启用单行模式(也称为 dot-matches-newline)。在此模式下,点号 `.` 可以匹配任意字符,包括换行符。 +* `x`(忽略空白):忽略模式中的空白字符(提高模式可读性)。 +* `q`(字面量):将 `pattern` 视为字面量字符串,而不是正则表达式。 + +## 示例 {#examples} + +### 基本行生成 {#basic-row-generation} + +```sql +SELECT REGEXP_SPLIT_TO_TABLE('one,two,three', ','); +┌─────────┐ +│ one │ +│ two │ +│ three │ +└─────────┘ +``` + +### 日志解析 {#log-parsing} + +```sql +SELECT REGEXP_SPLIT_TO_TABLE('ERR:404:File Not Found', ':'); +┌──────────────────┐ +│ ERR │ +│ 404 │ +│ File Not Found │ +└──────────────────┘ +``` + +### 使用 flag text {#with-flag-text} + +```sql +SELECT regexp_split_to_table('One_Two_Three', '[_-]', 'i') + +╭────────╮ +│ One │ +│ Two │ +│ Three │ +╰────────╯ + +``` + +### 嵌套用法 {#nested-usage} + +```sql +WITH data AS ( + SELECT 'id=123,name=John' AS kv_pairs +) +SELECT + REGEXP_SPLIT_TO_TABLE(kv_pairs, ',') AS pair +FROM data; +┌──────────────┐ +│ id=123 │ +│ name=John │ +└──────────────┘ +``` + +## 另请参阅 {#see-also} + +- [SPLIT](/tidb-cloud-lake/sql/split.md):用于简单字符串切分 +- [REGEXP_SPLIT_TO_ARRAY](/tidb-cloud-lake/sql/regexp-split-array.md):将字符串切分为数组 \ No newline at end of file diff --git a/tidb-cloud-lake/sql/regexp-substr.md b/tidb-cloud-lake/sql/regexp-substr.md new file mode 100644 index 0000000000000..cb8fb092987c0 --- /dev/null +++ b/tidb-cloud-lake/sql/regexp-substr.md @@ -0,0 +1,82 @@ +--- +title: REGEXP_SUBSTR +summary: 返回字符串 `expr` 中与模式 `pat` 指定的正则表达式匹配的子字符串;如果没有匹配项,则返回 NULL。如果 expr 或 pat 为 NULL,则返回值为 NULL。 +--- + +# REGEXP_SUBSTR + +返回字符串 `expr` 中与模式 `pat` 指定的正则表达式匹配的子字符串;如果没有匹配项,则返回 NULL。如果 expr 或 pat 为 NULL,则返回值为 NULL。 + +- REGEXP_SUBSTR 不支持提取捕获组(由括号 `()` 定义的子模式)。它返回整个匹配到的子字符串,而不是特定的捕获组。 + +```sql +SELECT REGEXP_SUBSTR('abc123', '(\w+)(\d+)'); +-- Returns 'abc123' (the entire match), not 'abc' or '123'. + +-- Alternative Solution: Use string functions like SUBSTRING and REGEXP_INSTR to manually extract the desired portion of the string: +SELECT SUBSTRING('abc123', 1, REGEXP_INSTR('abc123', '\d+') - 1); +-- Returns 'abc' (extracts the part before the digits). +SELECT SUBSTRING('abc123', REGEXP_INSTR('abc123', '\d+')); +-- Returns '123' (extracts the digits). +``` + +- REGEXP_SUBSTR 不支持 `e` 参数(在 Snowflake 中用于提取捕获组),也不支持用于指定返回哪个捕获组的 `group_num` 参数。 + +```sql +SELECT REGEXP_SUBSTR('abc123', '(\w+)(\d+)', 1, 1, 'e', 1); +-- Error: {{{ .lake }}} does not support the 'e' parameter or capture group extraction. + +-- Alternative Solution: Use string functions like SUBSTRING and LOCATE to manually extract the desired substring, or preprocess the data with external tools (e.g., Python) to extract capture groups before querying. +SELECT SUBSTRING( + REGEXP_SUBSTR('letters:abc,numbers:123', 'letters:[a-z]+,numbers:[0-9]+'), + LOCATE('letters:', 'letters:abc,numbers:123') + 8, + LOCATE(',', 'letters:abc,numbers:123') - (LOCATE('letters:', 'letters:abc,numbers:123') + 8) +); +-- Returns 'abc' +``` + +## 语法 {#syntax} + +```sql +REGEXP_SUBSTR(, ) +``` + +## 参数 {#arguments} + +| 参数 | 描述 | +|------------|-----------------------------------------------------------------------------------------------------------| +| expr | 要匹配的字符串 expr | +| pat | 正则表达式 | +| pos | 可选。在 expr 中开始搜索的位置。如果省略,默认值为 1。 | +| occurrence | 可选。要搜索匹配项的第几次出现。如果省略,默认值为 1。 | +| match_type | 可选。一个字符串,用于指定如何执行匹配。其含义与 REGEXP_LIKE() 中的说明相同。 | + +## 返回类型 {#return-type} + +`VARCHAR` + +## 示例 {#examples} + +```sql +SELECT REGEXP_SUBSTR('abc def ghi', '[a-z]+'); ++----------------------------------------+ +| REGEXP_SUBSTR('abc def ghi', '[a-z]+') | ++----------------------------------------+ +| abc | ++----------------------------------------+ + +SELECT REGEXP_SUBSTR('abc def ghi', '[a-z]+', 1, 3); ++----------------------------------------------+ +| REGEXP_SUBSTR('abc def ghi', '[a-z]+', 1, 3) | ++----------------------------------------------+ +| ghi | ++----------------------------------------------+ + +SELECT REGEXP_SUBSTR('周 周周 周周周 周周周周', '周+', 2, 3); ++------------------------------------------------------------------+ +| REGEXP_SUBSTR('周 周周 周周周 周周周周', '周+', 2, 3) | ++------------------------------------------------------------------+ +| 周周周周 | ++------------------------------------------------------------------+ + +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/regexp.md b/tidb-cloud-lake/sql/regexp.md new file mode 100644 index 0000000000000..16023e7d697ae --- /dev/null +++ b/tidb-cloud-lake/sql/regexp.md @@ -0,0 +1,30 @@ +--- +title: REGEXP +summary: 如果字符串 `` 与 `` 指定的正则表达式匹配,则返回 `true`,否则返回 `false`。 +--- + +# REGEXP + +如果字符串 `` 与 `` 指定的正则表达式匹配,则返回 `true`,否则返回 `false`。 + +## 语法 {#syntax} + +```sql + REGEXP +``` + +## 别名 {#aliases} + +- [RLIKE](/tidb-cloud-lake/sql/rlike.md) + +## 示例 {#examples} + +```sql +SELECT 'datalake' REGEXP 'd*', 'datalake' RLIKE 'd*'; + +┌────────────────────────────────────────────────────┐ +│ ('datalake' regexp 'd*') │ ('datalake' rlike 'd*') │ +├──────────────────────────┼─────────────────────────┤ +│ true │ true │ +└────────────────────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/remove-nullable.md b/tidb-cloud-lake/sql/remove-nullable.md new file mode 100644 index 0000000000000..c1d5048d5cd47 --- /dev/null +++ b/tidb-cloud-lake/sql/remove-nullable.md @@ -0,0 +1,8 @@ +--- +title: REMOVE_NULLABLE +summary: ASSUME_NOT_NULL 的别名。 +--- + +# REMOVE_NULLABLE + +[ASSUME_NOT_NULL](/tidb-cloud-lake/sql/assume-not-null.md) 的别名。 \ No newline at end of file diff --git a/tidb-cloud-lake/sql/remove-stage-files.md b/tidb-cloud-lake/sql/remove-stage-files.md new file mode 100644 index 0000000000000..e4ac65c01ce33 --- /dev/null +++ b/tidb-cloud-lake/sql/remove-stage-files.md @@ -0,0 +1,45 @@ +--- +title: REMOVE STAGE FILES +summary: 从 stage 中移除文件。 +--- + +# REMOVE STAGE FILES + +从 stage 中移除文件。 + +另请参阅: + +- [LIST STAGE FILES](/tidb-cloud-lake/sql/list-stage-files.md):列出 stage 中的文件。 +- [PRESIGN](/tidb-cloud-lake/sql/presign.md):{{{ .lake }}} 建议使用 Presigned URL 方法将文件上传到 stage。 + +## 语法 {#syntax} + +```sql +REMOVE { userStage | internalStage | externalStage } [ PATTERN = '' ] +``` + +其中: + +### internalStage {#internalstage} + +```sql +internalStage ::= @[/] +``` + +### externalStage {#externalstage} + +```sql +externalStage ::= @[/] +``` + +### PATTERN = 'regex_pattern' {#pattern-regex-pattern} + +用单引号括起来的正则表达式模式字符串,用于筛选要移除的 stage 文件。它匹配 `@[/]` 之后的文件路径部分。参见 [使用 PATTERN 过滤 stage 文件](/tidb-cloud-lake/guides/stage-overview.md#filtering-staged-files-with-pattern)。 + +## 示例 {#examples} + +以下命令会从名为 *playground* 的 stage 中移除所有名称匹配模式 *'ontime.*'* 的文件: + +```sql +REMOVE @playground PATTERN = 'ontime.*' +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/rename-dictionary.md b/tidb-cloud-lake/sql/rename-dictionary.md new file mode 100644 index 0000000000000..a30f68df0bf96 --- /dev/null +++ b/tidb-cloud-lake/sql/rename-dictionary.md @@ -0,0 +1,34 @@ +--- +title: RENAME DICTIONARY +summary: 重命名字典。 +--- + +# RENAME DICTIONARY + +重命名字典。 + +## 语法 {#syntax} + +```sql +RENAME DICTIONARY [ IF EXISTS ] + [ . ][ . ] + TO [ . ][ . ] +``` + +## 参数 {#parameters} + +| 参数 | 描述 | +|-----------|-------------| +| `IF EXISTS` | 可选。如果源字典不存在,则抑制报错。 | +| `` | 当前字典名称。 | +| `` | 新的字典名称。 | + +## 示例 {#examples} + +```sql +RENAME DICTIONARY user_info TO user_profile; +``` + +```sql +RENAME DICTIONARY IF EXISTS default.user_info TO analytics.user_profile; +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/rename-table.md b/tidb-cloud-lake/sql/rename-table.md new file mode 100644 index 0000000000000..3d6addb70ba7a --- /dev/null +++ b/tidb-cloud-lake/sql/rename-table.md @@ -0,0 +1,42 @@ +--- +title: RENAME TABLE +summary: 更改表的名称。 +--- + +# RENAME TABLE + +更改表的名称。 + +## 语法 {#syntax} + +```sql +ALTER TABLE [ IF EXISTS ] RENAME TO +``` + +## 示例 {#examples} + +```sql +CREATE TABLE test(a INT); +``` + +```sql +SHOW TABLES; ++------+ +| name | ++------+ +| test | ++------+ +``` + +```sql +ALTER TABLE `test` RENAME TO `new_test`; +``` + +```sql +SHOW TABLES; ++----------+ +| name | ++----------+ +| new_test | ++----------+ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/rename-workload-group.md b/tidb-cloud-lake/sql/rename-workload-group.md new file mode 100644 index 0000000000000..3a4dd3be1d11b --- /dev/null +++ b/tidb-cloud-lake/sql/rename-workload-group.md @@ -0,0 +1,22 @@ +--- +title: RENAME WORKLOAD GROUP +summary: 将现有的 workload group 重命名为新名称。 +--- + +# RENAME WORKLOAD GROUP + +将现有的 workload group 重命名为新名称。 + +## 语法 {#syntax} + +```sql +RENAME WORKLOAD GROUP TO +``` + +## 示例 {#examples} + +以下示例将 `test_workload_group_1` 重命名为 `test_workload_group`: + +```sql +RENAME WORKLOAD GROUP test_workload_group_1 TO test_workload_group; +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/repeat.md b/tidb-cloud-lake/sql/repeat.md new file mode 100644 index 0000000000000..f0f052a179c3e --- /dev/null +++ b/tidb-cloud-lake/sql/repeat.md @@ -0,0 +1,46 @@ +--- +title: REPEAT +summary: 返回一个由字符串 str 重复 count 次组成的字符串。如果 count 小于 1,则返回空字符串。如果 str 或 count 为 NULL,则返回 NULL。 +--- + +# REPEAT + +返回一个由字符串 str 重复 count 次组成的字符串。如果 count 小于 1,则返回空字符串。如果 str 或 count 为 NULL,则返回 NULL。 + +## 语法 {#syntax} + +```sql +REPEAT(, ) +``` + +## 参数 {#arguments} + +| 参数 | 描述 | +|-----------|-------------| +| `` | 字符串。 | +| `` | 数字。 | + +## 示例 {#examples} + +```sql +SELECT REPEAT('datalake', 3); ++--------------------------+ +| REPEAT('datalake', 3) | ++--------------------------+ +| datalakedatalakedatalake | ++--------------------------+ + +SELECT REPEAT('datalake', 0); ++-----------------------+ +| REPEAT('datalake', 0) | ++-----------------------+ +| | ++-----------------------+ + +SELECT REPEAT('datalake', NULL); ++--------------------------+ +| REPEAT('datalake', NULL) | ++--------------------------+ +| NULL | ++--------------------------+ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/replace-sql.md b/tidb-cloud-lake/sql/replace-sql.md new file mode 100644 index 0000000000000..fd826d14858c7 --- /dev/null +++ b/tidb-cloud-lake/sql/replace-sql.md @@ -0,0 +1,37 @@ +--- +title: REPLACE +summary: 返回字符串 str,其中字符串 from_str 的所有出现位置都被替换为字符串 to_str。 +--- + +# REPLACE + +返回字符串 str,其中字符串 from_str 的所有出现位置都被替换为字符串 to_str。 + +## 语法 {#syntax} + +```sql +REPLACE(, , ) +``` + +## 参数 {#arguments} + +| 参数 | 描述 | +|--------------|------------------| +| `` | 该字符串。 | +| `` | 源字符串。 | +| `` | 目标字符串。 | + +## 返回类型 {#return-type} + +`VARCHAR` + +## 示例 {#examples} + +```sql +SELECT REPLACE('www.mysql.com', 'w', 'Ww'); ++-------------------------------------+ +| REPLACE('www.mysql.com', 'w', 'Ww') | ++-------------------------------------+ +| WwWwWw.mysql.com | ++-------------------------------------+ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/replace.md b/tidb-cloud-lake/sql/replace.md new file mode 100644 index 0000000000000..af2c971d439f1 --- /dev/null +++ b/tidb-cloud-lake/sql/replace.md @@ -0,0 +1,184 @@ +--- +title: REPLACE +summary: REPLACE INTO 可以使用以下数据来源,向表中插入多行新数据;如果这些行已存在,则修改现有行。 +--- + +# REPLACE + +> **Note:** +> +> 于 v1.1.55 中引入。 + +`REPLACE INTO` 可以使用以下数据来源,向表中插入多行新数据;如果这些行已存在,则修改现有行: + +- 直接值 + +- 查询结果 + +- stage 文件:{{{ .lake }}} 支持通过 `REPLACE INTO` 语句将 stage 文件中的数据替换到表中。这是通过 {{{ .lake }}} 查询 [查询 Stage 文件](/tidb-cloud-lake/sql/stage.md) 并随后将查询结果写入表中来实现的。 + +> **Tip:** +> +> {{{ .lake }}} 通过原子操作确保数据完整性。插入、修改、替换和删除操作要么全部成功,要么全部失败。 + +## 语法 {#syntax} + +```sql +REPLACE INTO [ ( [ , ... ] ) ] + ON () ... +``` + +当在表中找到指定的冲突键时,`REPLACE INTO` 会修改现有行;如果冲突键不存在,则插入新行。冲突键是表中的一个列或多个列的组合,用于唯一标识一行,并用于在执行 `REPLACE INTO` 语句时判断是插入新行还是修改现有行。示例如下: + +```sql +CREATE TABLE employees ( + employee_id INT, + employee_name VARCHAR(100), + employee_salary DECIMAL(10, 2), + employee_email VARCHAR(255) +); + +-- This REPLACE INTO inserts a new row +REPLACE INTO employees (employee_id, employee_name, employee_salary, employee_email) +ON (employee_email) +VALUES (123, 'John Doe', 50000, 'john.doe@example.com'); + +-- This REPLACE INTO updates the inserted row +REPLACE INTO employees (employee_id, employee_name, employee_salary, employee_email) +ON (employee_email) +VALUES (123, 'John Doe', 60000, 'john.doe@example.com'); +``` + +## 分布式 REPLACE INTO {#distributed-replace-into} + +`REPLACE INTO` 支持在集群环境中进行分布式执行。你可以通过将 `ENABLE_DISTRIBUTED_REPLACE_INTO` 设置为 `1` 来启用分布式 `REPLACE INTO`。这有助于提升集群环境中的数据加载性能和扩展性。 + +```sql +SET enable_distributed_replace_into = 1; +``` + +## 示例 {#examples} + +### 示例 1:使用直接值进行替换 {#example-1-replace-with-direct-values} + +以下示例使用直接值替换数据: + +```sql +CREATE TABLE employees(id INT, name VARCHAR, salary INT); + +REPLACE INTO employees (id, name, salary) ON (id) +VALUES (1, 'John Doe', 50000); + +SELECT * FROM Employees; ++------+----------+--------+ +| id | name | salary | ++------+----------+--------+ +| 1 | John Doe | 50000 | ++------+----------+--------+ +``` + +### 示例 2:使用查询结果进行替换 {#example-2-replace-with-query-results} + +以下示例使用查询结果替换数据: + +```sql +CREATE TABLE employees(id INT, name VARCHAR, salary INT); + +CREATE TABLE temp_employees(id INT, name VARCHAR, salary INT); + +INSERT INTO temp_employees (id, name, salary) VALUES (1, 'John Doe', 60000); + +REPLACE INTO employees (id, name, salary) ON (id) +SELECT id, name, salary FROM temp_employees WHERE id = 1; + +SELECT * FROM Employees; ++------+----------+--------+ +| id | name | salary | ++------+----------+--------+ +| 1 | John Doe | 60000 | ++------+----------+--------+ +``` + +### 示例 3:使用 stage 文件进行替换 {#example-3-replace-with-staged-files} + +以下示例演示如何使用 stage 文件中的数据替换表中的现有数据。 + +1. 创建一个名为 `sample` 的表 + + ```sql + CREATE TABLE sample + ( + id INT, + city VARCHAR, + score INT, + country VARCHAR DEFAULT 'China' + ); + + INSERT INTO sample + (id, city, score) + VALUES + (1, 'Chengdu', 66); + ``` + +2. 设置一个包含示例数据的内部 stage + + 首先,创建一个名为 `mystage` 的 stage。然后,将示例数据加载到该 stage 中。 + + ```sql + CREATE STAGE mystage; + + COPY INTO @mystage + FROM + ( + SELECT * + FROM + ( + VALUES + (1, 'Chengdu', 80), + (3, 'Chongqing', 90), + (6, 'Hangzhou', 92), + (9, 'Hong Kong', 88) + ) + ) + FILE_FORMAT = (TYPE = PARQUET); + ``` + +3. 使用 `REPLACE INTO` 和 stage 中的 Parquet 文件替换现有数据 + + > **Tip:** + > + > 你可以使用 [COPY INTO](/tidb-cloud-lake/sql/copy-into-table.md) 命令中提供的 `FILE_FORMAT` 和 `COPY_OPTIONS` 来指定文件格式以及各种与复制相关的设置。 + + ```sql + REPLACE INTO sample + (id, city, score) + ON + (Id) + SELECT + $1, $2, $3 + FROM + @mystage + (FILE_FORMAT => 'parquet'); + ``` + +4. 验证数据替换结果 + +现在,你可以查询 `sample` 表来查看变更: + +```sql +SELECT * FROM sample; +``` + +结果应如下所示: + +```sql +┌─────────────────────────────────────────────────────────────────────────┐ +│ id │ city │ score │ country │ +│ Nullable(Int32) │ Nullable(String) │ Nullable(Int32) │ Nullable(String) │ +├─────────────────┼──────────────────┼─────────────────┼──────────────────┤ +│ 1 │ Chengdu │ 80 │ China │ +│ 3 │ Chongqing │ 90 │ China │ +│ 6 │ Hangzhou │ 92 │ China │ +│ 9 │ Hong Kong │ 88 │ China │ +└─────────────────────────────────────────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/result-scan.md b/tidb-cloud-lake/sql/result-scan.md new file mode 100644 index 0000000000000..ad5ae6c334267 --- /dev/null +++ b/tidb-cloud-lake/sql/result-scan.md @@ -0,0 +1,58 @@ +--- +title: RESULT_SCAN +summary: 通过查询 ID 检索先前查询的缓存结果。 +--- + +# RESULT_SCAN + +通过查询 ID 检索先前查询的缓存结果。 + +另请参阅:[system.query_cache](/tidb-cloud-lake/sql/system-query-cache.md) + +## 语法 {#syntax} + +```sql +RESULT_SCAN('' | LAST_QUERY_ID()) +``` + +## 示例 {#examples} + +以下示例展示了如何启用查询结果缓存,并运行一个其结果将被缓存的查询: + +```bash +# Enable the query result cache feature +mysql> SET enable_query_result_cache = 1; +Query OK, 0 rows affected (0.01 sec) + +# Cache all queries regardless of how fast they execute +mysql> SET query_result_cache_min_execute_secs = 0; +Query OK, 0 rows affected (0.01 sec) + +# Execute a query and cache its result +mysql> SELECT * FROM t1 ORDER BY a; ++------+ +| a | ++------+ +| 1 | +| 2 | +| 3 | ++------+ +3 rows in set (0.02 sec) +Read 0 rows, 0.00 B in 0.006 sec., 0 rows/sec., 0.00 B/sec. +``` + +结果被缓存后,你可以使用 `RESULT_SCAN` 检索该结果,而无需重新运行查询: + +```bash +# Retrieve the cached result of the previous query using its query ID +mysql> SELECT * FROM RESULT_SCAN(LAST_QUERY_ID()) ORDER BY a; ++------+ +| a | ++------+ +| 1 | +| 2 | +| 3 | ++------+ +3 rows in set (0.02 sec) +Read 3 rows, 13.00 B in 0.006 sec., 464.06 rows/sec., 1.96 KiB/sec. +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/retention.md b/tidb-cloud-lake/sql/retention.md new file mode 100644 index 0000000000000..2961d71911e1a --- /dev/null +++ b/tidb-cloud-lake/sql/retention.md @@ -0,0 +1,71 @@ +--- +title: RETENTION +summary: 聚合函数。 +--- + +# RETENTION + +聚合函数 + +`RETENTION()` 函数接受一组条件作为参数,参数个数可以是 1 到 32 个,类型为 UInt8,用于指示某个事件是否满足特定条件。 + +任意条件都可以作为参数指定(与 `WHERE` 中类似)。 + +除第一个条件外,其余条件按配对方式生效:如果第一个和第二个条件都为 true,则第二个结果为 true;如果第一个和第三个条件都为 true,则第三个结果为 true;以此类推。 + +## 语法 {#syntax} + +```sql +RETENTION( , , ..., ); +``` + +## 参数 {#arguments} + +| 参数 | 描述 | +|-----------|---------------------------------------------| +| `` | 返回布尔结果的表达式 | + +## 返回类型 {#return-type} + +返回由 1 或 0 组成的数组。 + +## 示例 {#example} + +**创建表并插入示例数据** + +```sql +CREATE TABLE user_events ( + id INT, + user_id INT, + event_date DATE, + event_type VARCHAR +); + +INSERT INTO user_events (id, user_id, event_date, event_type) +VALUES (1, 1, '2022-01-01', 'signup'), + (2, 1, '2022-01-02', 'login'), + (3, 2, '2022-01-01', 'signup'), + (4, 2, '2022-01-03', 'purchase'), + (5, 3, '2022-01-01', 'signup'), + (6, 3, '2022-01-02', 'login'); +``` + +**查询示例:基于 signup、login 和 purchase 事件计算用户留存** + +```sql +SELECT + user_id, + RETENTION(event_type = 'signup', event_type = 'login', event_type = 'purchase') AS retention +FROM user_events +GROUP BY user_id; +``` + +**结果** + +```sql +| user_id | retention | +|---------|-----------| +| 1 | [1, 1, 0] | +| 2 | [1, 0, 1] | +| 3 | [1, 1, 0] | +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/reverse.md b/tidb-cloud-lake/sql/reverse.md new file mode 100644 index 0000000000000..e761bdca57b3e --- /dev/null +++ b/tidb-cloud-lake/sql/reverse.md @@ -0,0 +1,35 @@ +--- +title: REVERSE +summary: 返回字符串 str,其字符顺序与原字符串相反。 +--- + +# REVERSE + +返回字符串 str,其字符顺序与原字符串相反。 + +## 语法 {#syntax} + +```sql +REVERSE() +``` + +## 参数 {#arguments} + +| 参数 | 描述 | +|-----------|-------------------| +| `` | 字符串值。 | + +## 返回类型 {#return-type} + +`VARCHAR` + +## 示例 {#examples} + +```sql +SELECT REVERSE('abc'); ++----------------+ +| REVERSE('abc') | ++----------------+ +| cba | ++----------------+ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/revoke.md b/tidb-cloud-lake/sql/revoke.md new file mode 100644 index 0000000000000..5f37d46793471 --- /dev/null +++ b/tidb-cloud-lake/sql/revoke.md @@ -0,0 +1,243 @@ +--- +title: REVOKE +summary: 回收特定数据库对象的权限、角色和所有权。这包括。 +--- + +# REVOKE + +回收特定数据库对象的权限、角色和所有权。这包括: + +- 从角色回收权限。 +- 从用户或其他角色中移除角色。 + +另请参阅: + +- [GRANT](/tidb-cloud-lake/sql/grant.md) +- [SHOW GRANTS](/tidb-cloud-lake/sql/show-grants.md) + +> **Note:** +> +> 使用 `REVOKE` 修改权限或角色后,运行 [SYSTEM FLUSH PRIVILEGES](/tidb-cloud-lake/sql/system-flush-privileges.md) 以立即将更新广播到每个查询节点。 + +## 语法 {#syntax} + +### 回收权限 {#revoking-privileges} + +```sql +REVOKE { + schemaObjectPrivileges | ALL [ PRIVILEGES ] ON + } +FROM ROLE +``` + +其中: + +```sql +schemaObjectPrivileges ::= +-- For TABLE + { SELECT | INSERT } + +-- For SCHEMA + { CREATE | DROP | ALTER } + +-- For USER + { CREATE USER } + +-- For ROLE + { CREATE ROLE} + +-- For STAGE + { READ, WRITE } + +-- For UDF + { USAGE } + +-- For MASKING POLICY (account-level privileges) + { CREATE MASKING POLICY | APPLY MASKING POLICY } + +-- For ROW ACCESS POLICY (account-level privileges) + { CREATE ROW ACCESS POLICY | APPLY ROW ACCESS POLICY } +``` + +```sql +privileges_level ::= + *.* + | db_name.* + | db_name.tbl_name + | STAGE + | UDF + | MASKING POLICY + | ROW ACCESS POLICY +``` + +### 回收 Masking Policy 权限 {#revoking-masking-policy-privileges} + +```sql +REVOKE APPLY ON MASKING POLICY FROM ROLE +REVOKE ALL [ PRIVILEGES ] ON MASKING POLICY FROM ROLE +REVOKE OWNERSHIP ON MASKING POLICY FROM ROLE '' +``` + +使用这些形式可以移除对单个 masking policy 的访问。全局 `CREATE MASKING POLICY` 和 `APPLY MASKING POLICY` 权限使用带有 `ON *.*` 的标准语法进行回收。 + +### 回收 Row Access Policy 权限 {#revoking-row-access-policy-privileges} + +```sql +REVOKE APPLY ON ROW ACCESS POLICY FROM ROLE +REVOKE ALL [ PRIVILEGES ] ON ROW ACCESS POLICY FROM ROLE +REVOKE OWNERSHIP ON ROW ACCESS POLICY FROM ROLE '' +``` + +使用这些形式可以回收对特定 row access policy 的访问。对全局 `CREATE ROW ACCESS POLICY` 和 `APPLY ROW ACCESS POLICY` 权限的回收,可通过针对 `ON *.*` 的标准语法完成。 + +### 回收角色 {#revoking-role} + +```sql +-- Revoke a role from a user +REVOKE ROLE FROM + +-- Revoke a role from a role +REVOKE ROLE FROM ROLE +``` + +## 示例 {#examples} + +### 示例 1:从角色回收权限 {#example-1-revoking-privileges-from-a-role} + +创建一个角色: + +```sql +CREATE ROLE user1_role; +``` + +将 `default` 数据库中所有现有表的 `SELECT,INSERT` 权限授予角色 `user1_role`: + +```sql +GRANT SELECT,INSERT ON default.* TO ROLE user1_role; +``` + +```sql +SHOW GRANTS FOR ROLE user1_role; ++---------------------------------------------------------+ +| Grants | ++---------------------------------------------------------+ +| GRANT SELECT,INSERT ON 'default'.* TO ROLE 'user1_role' | ++---------------------------------------------------------+ +``` + +从角色 `user1_role` 回收 `INSERT` 权限: + +```sql +REVOKE INSERT ON default.* FROM ROLE user1_role; +``` + +```sql +SHOW GRANTS FOR ROLE user1_role; ++---------------------------------------------------+ +| Grants | ++---------------------------------------------------+ +| GRANT SELECT ON 'default'.* TO 'user1_role' | ++---------------------------------------------------+ +``` + +### 示例 2:从另一个角色回收权限 {#example-2-revoking-privileges-from-another-role} + +将 `mydb` 数据库中所有现有表的 `SELECT,INSERT` 权限授予角色 `role1`: + +创建角色: + +```sql +CREATE ROLE role1; +``` + +向该角色授予权限: + +```sql +GRANT SELECT,INSERT ON mydb.* TO ROLE role1; +``` + +显示该角色的授权信息: + +```sql +SHOW GRANTS FOR ROLE role1; ++--------------------------------------------+ +| Grants | ++--------------------------------------------+ +| GRANT SELECT,INSERT ON 'mydb'.* TO 'role1' | ++--------------------------------------------+ +``` + +从角色 `role1` 回收 `INSERT` 权限: + +```sql +REVOKE INSERT ON mydb.* FROM ROLE role1; +``` + +```sql +SHOW GRANTS FOR ROLE role1; ++-------------------------------------+ +| Grants | ++-------------------------------------+ +| GRANT SELECT ON 'mydb'.* TO 'role1' | ++-------------------------------------+ +``` + +### 示例 3:从用户回收角色 {#example-3-revoking-a-role-from-a-user} + +```sql +REVOKE ROLE role1 FROM USER user1; +``` + +```sql +SHOW GRANTS FOR user1; +``` + +> **提示:** +> +> 为什么在执行 revoke 后,`default_role` 仍然显示? +> +> `default_role` 是用户属性,不是授权。`REVOKE` 会移除角色成员关系,但不会重置 `default_role`。如下所示: +> +> ```sql +> CREATE ROLE analyst; +> CREATE USER bob IDENTIFIED BY 'password123' WITH DEFAULT_ROLE = 'analyst'; +> GRANT ROLE analyst TO bob; +> +> DESC USER bob; +> +------+----------+----------------------+--------------+---------+ +> | name | hostname | auth_type | default_role | roles | +> +------+----------+----------------------+--------------+---------+ +> | bob | % | double_sha1_password | analyst | analyst | +> +------+----------+----------------------+--------------+---------+ +> +> REVOKE ROLE analyst FROM bob; +> +> DESC USER bob; +> +------+----------+----------------------+--------------+-------+ +> | name | hostname | auth_type | default_role | roles | +> +------+----------+----------------------+--------------+-------+ +> | bob | % | double_sha1_password | analyst | | +> +------+----------+----------------------+--------------+-------+ +> ``` +> +> 注意,`roles` 现在为空,但 `default_role` 仍然保留。该用户不再拥有 `analyst` 的权限。要清理该属性,请执行 `ALTER USER bob WITH DEFAULT_ROLE = 'public'`。 + +### 示例 4:回收 Masking Policy 权限 {#example-4-revoking-masking-policy-privileges} + +```sql +-- Remove per-policy access from a role +REVOKE APPLY ON MASKING POLICY email_mask FROM ROLE pii_readers; + +-- Revoke the ability to create masking policies at the account level +REVOKE CREATE MASKING POLICY ON *.* FROM ROLE security_admin; +``` + +### 示例 5:回收 Row Access Policy 权限 {#example-5-revoking-row-access-policy-privileges} + +```sql +-- Remove per-policy access from a role +REVOKE APPLY ON ROW ACCESS POLICY rap_region FROM ROLE apac_only; + +-- Revoke the ability to create row access policies globally +REVOKE CREATE ROW ACCESS POLICY ON *.* FROM ROLE row_policy_admin; +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/right.md b/tidb-cloud-lake/sql/right.md new file mode 100644 index 0000000000000..e4cc3f06c4693 --- /dev/null +++ b/tidb-cloud-lake/sql/right.md @@ -0,0 +1,36 @@ +--- +title: RIGHT +summary: 返回字符串 str 最右侧的 len 个字符;如果任一参数为 NULL,则返回 NULL。 +--- + +# RIGHT + +返回字符串 str 最右侧的 len 个字符;如果任一参数为 NULL,则返回 NULL。 + +## 语法 {#syntax} + +```sql +RIGHT(, ); +``` + +## 参数 {#arguments} + +| 参数 | 描述 | +|-----------|----------------------------------------------------------| +| `` | 要从中提取字符的主字符串 | +| `` | 字符个数 | + +## 返回类型 {#return-type} + +`VARCHAR` + +## 示例 {#examples} + +```sql +SELECT RIGHT('foobarbar', 4); ++-----------------------+ +| RIGHT('foobarbar', 4) | ++-----------------------+ +| rbar | ++-----------------------+ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/rlike.md b/tidb-cloud-lake/sql/rlike.md new file mode 100644 index 0000000000000..949f2c161f163 --- /dev/null +++ b/tidb-cloud-lake/sql/rlike.md @@ -0,0 +1,8 @@ +--- +title: RLIKE +summary: REGEXP 的别名。 +--- + +# RLIKE + +[REGEXP](/tidb-cloud-lake/sql/regexp.md) 的别名。 \ No newline at end of file diff --git a/tidb-cloud-lake/sql/rollback.md b/tidb-cloud-lake/sql/rollback.md new file mode 100644 index 0000000000000..fbf7cc6f6bddd --- /dev/null +++ b/tidb-cloud-lake/sql/rollback.md @@ -0,0 +1,18 @@ +--- +title: ROLLBACK +summary: 撤销事务期间所做的所有更改。BEGIN 和 COMMIT/ROLLBACK 必须配合使用,用于启动事务,然后保存或撤销该事务。 +--- + +# ROLLBACK + +撤销事务期间所做的所有更改。[BEGIN](/tidb-cloud-lake/sql/begin.md) 和 [COMMIT](/tidb-cloud-lake/sql/commit.md)/ROLLBACK 必须配合使用,用于启动事务,然后保存或撤销该事务。 + +## 语法 {#syntax} + +```sql +ROLLBACK +``` + +## 示例 {#examples} + +参见 [示例](/tidb-cloud-lake/sql/begin.md#examples)。 \ No newline at end of file diff --git a/tidb-cloud-lake/sql/round.md b/tidb-cloud-lake/sql/round.md new file mode 100644 index 0000000000000..ccdaf09d43173 --- /dev/null +++ b/tidb-cloud-lake/sql/round.md @@ -0,0 +1,33 @@ +--- +title: ROUND +summary: 将参数 x 四舍五入到 d 位小数。舍入算法取决于 x 的数据类型。如果未指定,d 默认为 0。d 可以为负数,这会使值 x 的小数点左侧第 d 位及其左侧的数字变为零。d 的最大绝对值为 30;超过 30(或 -30)的位数会被截断。 +--- + +# ROUND + +将参数 x 四舍五入到 d 位小数。舍入算法取决于 x 的数据类型。如果未指定,d 默认为 0。d 可以为负数,这会使值 x 的小数点左侧第 d 位及其左侧的数字变为零。d 的最大绝对值为 30;超过 30(或 -30)的位数会被截断。 + +在计算中使用此函数的结果时,请注意,由于其返回数据类型为 DOUBLE,可能会出现精度问题,从而影响最终准确性: + +```sql +SELECT ROUND(4/7, 4) - ROUND(3/7, 4); -- Result: 0.14280000000000004 +SELECT ROUND(4/7, 4)::DECIMAL(8,4) - ROUND(3/7, 4)::DECIMAL(8,4); -- Result: 0.1428 +``` + +## 语法 {#syntax} + +```sql +ROUND( ) +``` + +## 示例 {#examples} + +```sql +SELECT ROUND(0.123, 2); + +┌─────────────────┐ +│ round(0.123, 2) │ +├─────────────────┤ +│ 0.12 │ +└─────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/row-access-policy-overview.md b/tidb-cloud-lake/sql/row-access-policy-overview.md new file mode 100644 index 0000000000000..d9b74af892b27 --- /dev/null +++ b/tidb-cloud-lake/sql/row-access-policy-overview.md @@ -0,0 +1,26 @@ +--- +title: 行访问策略概览 +summary: "按功能组织的 {{{ .lake }}} 中行访问策略操作综合概览,便于参考。" +--- + +# 行访问策略概览 + +本页提供 {{{ .lake }}} 中行访问策略操作的综合概览,并按功能进行组织,便于参考。 + +## 行访问策略管理 {#row-access-policy-management} + +| 命令 | 描述 | +|---------|-------------| +| [CREATE ROW ACCESS POLICY](/tidb-cloud-lake/sql/create-row-access-policy.md) | 创建行级过滤策略 | +| [DESCRIBE ROW ACCESS POLICY](/tidb-cloud-lake/sql/desc-row-access-policy.md) | 显示行访问策略的详细信息 | +| [DROP ROW ACCESS POLICY](/tidb-cloud-lake/sql/drop-row-access-policy.md) | 删除行访问策略 | + +## 相关主题 {#related-topics} + +- [行访问策略](/tidb-cloud-lake/guides/row-access-policy.md) +- [ALTER TABLE](/tidb-cloud-lake/sql/alter-table.md#row-access-policy-operations) +- [POLICY_REFERENCES](/tidb-cloud-lake/sql/policy-references.md) + +> **注意:** +> +> 行访问策略会在查询时过滤行。受保护的表仅返回策略表达式计算结果为 `TRUE` 的行。 \ No newline at end of file diff --git a/tidb-cloud-lake/sql/row-number.md b/tidb-cloud-lake/sql/row-number.md new file mode 100644 index 0000000000000..dbd4e5056c269 --- /dev/null +++ b/tidb-cloud-lake/sql/row-number.md @@ -0,0 +1,102 @@ +--- +title: ROW_NUMBER +summary: 为分区内的每一行分配一个从 1 开始的连续编号。 +--- + +# ROW_NUMBER + +为分区内的每一行分配一个从 1 开始的连续编号。 + +## 语法 {#syntax} + +```sql +ROW_NUMBER() +OVER ( + [ PARTITION BY partition_expression ] + ORDER BY sort_expression [ ASC | DESC ] +) +``` + +**参数:** + +- `PARTITION BY`:可选。将行划分为多个分区 +- `ORDER BY`:必需。确定行编号的顺序 +- `ASC | DESC`:可选。排序方向(默认值:ASC) + +**说明:** + +- 返回从 1 开始的连续整数型编号 +- 每个分区都会从 1 开始重新编号 +- 常用于排名和分页 + +## 示例 {#examples} + +```sql +-- Create sample data +CREATE TABLE scores ( + student VARCHAR(20), + subject VARCHAR(20), + score INT +); + +INSERT INTO scores VALUES + ('Alice', 'Math', 95), + ('Alice', 'English', 87), + ('Alice', 'Science', 92), + ('Bob', 'Math', 78), + ('Bob', 'English', 85), + ('Bob', 'Science', 80), + ('Charlie', 'Math', 88), + ('Charlie', 'English', 90), + ('Charlie', 'Science', 85); +``` + +**为所有行依次编号(即使分数相同也是如此):** + +```sql +SELECT student, subject, score, + ROW_NUMBER() OVER (ORDER BY score DESC, student, subject) AS row_num +FROM scores +ORDER BY score DESC, student, subject; +``` + +结果: + +``` +student | subject | score | row_num +--------+---------+-------+-------- +Alice | Math | 95 | 1 +Alice | Science | 92 | 2 +Charlie | English | 90 | 3 +Charlie | Math | 88 | 4 +Alice | English | 87 | 5 +Bob | English | 85 | 6 +Charlie | Science | 85 | 7 +Bob | Science | 80 | 8 +Bob | Math | 78 | 9 +``` + +**在每个 student 内部分别编号(用于分页或 top-N):** + +```sql +SELECT student, subject, score, + ROW_NUMBER() OVER (PARTITION BY student ORDER BY score DESC) AS subject_rank +FROM scores +ORDER BY student, score DESC; +``` + +结果: + +``` +student | subject | score | subject_rank +--------+---------+-------+------------- +Alice | Math | 95 | 1 +Alice | Science | 92 | 2 +Alice | English | 87 | 3 +Bob | English | 85 | 1 +Bob | Science | 80 | 2 +Bob | Math | 78 | 3 +Charlie | English | 90 | 1 +Charlie | Math | 88 | 2 +Charlie | Science | 85 | 3 +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/rows-between.md b/tidb-cloud-lake/sql/rows-between.md new file mode 100644 index 0000000000000..19bfd2a23fc23 --- /dev/null +++ b/tidb-cloud-lake/sql/rows-between.md @@ -0,0 +1,334 @@ +--- +title: ROWS BETWEEN +summary: 使用基于行的边界为窗口函数定义窗口框架。 +--- + +# ROWS BETWEEN + +使用基于行的边界为窗口函数定义窗口框架。 + +## 概述 {#overview} + +`ROWS BETWEEN` 子句用于指定在窗口函数计算中应包含哪些行到窗口框架中。它允许你定义滑动窗口、累积计算以及其他基于行的聚合。 + +## 语法 {#syntax} + +```sql +FUNCTION() OVER ( + [ PARTITION BY partition_expression ] + [ ORDER BY sort_expression ] + ROWS BETWEEN frame_start AND frame_end +) +``` + +### 框架边界 {#frame-boundaries} + +| 边界 | 描述 | 示例 | +|----------|-------------|---------| +| `UNBOUNDED PRECEDING` | 分区起始位置 | `ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW` | +| `n PRECEDING` | 当前行之前的 n 行 | `ROWS BETWEEN 2 PRECEDING AND CURRENT ROW` | +| `CURRENT ROW` | 当前行 | `ROWS BETWEEN CURRENT ROW AND CURRENT ROW` | +| `n FOLLOWING` | 当前行之后的 n 行 | `ROWS BETWEEN CURRENT ROW AND 2 FOLLOWING` | +| `UNBOUNDED FOLLOWING` | 分区结束位置 | `ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING` | + +## ROWS 与 RANGE 的对比 {#rows-vs-range} + +| 方面 | ROWS | RANGE | +|--------|------|-------| +| **定义** | 物理行数 | 逻辑值范围 | +| **边界** | 行位置 | 基于值的位置 | +| **并列值** | 每一行相互独立 | 相同值共享同一个框架 | +| **性能** | 通常更快 | 存在重复值时可能更慢 | +| **使用场景** | 移动平均、运行总计 | 基于值的窗口、百分位计算 | + +## 示例 {#examples} + +### 示例数据 {#sample-data} + +```sql +CREATE OR REPLACE TABLE sales ( + sale_date DATE, + product VARCHAR(20), + amount DECIMAL(10,2) +); + +INSERT INTO sales VALUES + ('2024-01-01', 'A', 100.00), + ('2024-01-02', 'A', 150.00), + ('2024-01-03', 'A', 200.00), + ('2024-01-04', 'A', 250.00), + ('2024-01-05', 'A', 300.00), + ('2024-01-01', 'B', 50.00), + ('2024-01-02', 'B', 75.00), + ('2024-01-03', 'B', 100.00), + ('2024-01-04', 'B', 125.00), + ('2024-01-05', 'B', 150.00); +``` + +### 1. 运行总计(累积求和) {#1-running-total-cumulative-sum} + +```sql +SELECT sale_date, product, amount, + SUM(amount) OVER ( + PARTITION BY product + ORDER BY sale_date + ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW + ) AS running_total +FROM sales +ORDER BY product, sale_date; +``` + +结果: + +``` +sale_date | product | amount | running_total +------------+---------+--------+-------------- +2024-01-01 | A | 100.00 | 100.00 +2024-01-02 | A | 150.00 | 250.00 +2024-01-03 | A | 200.00 | 450.00 +2024-01-04 | A | 250.00 | 700.00 +2024-01-05 | A | 300.00 | 1000.00 +2024-01-01 | B | 50.00 | 50.00 +2024-01-02 | B | 75.00 | 125.00 +2024-01-03 | B | 100.00 | 225.00 +2024-01-04 | B | 125.00 | 350.00 +2024-01-05 | B | 150.00 | 500.00 +``` + +### 2. 移动平均(3 天窗口) {#2-moving-average-3-day-window} + +```sql +SELECT sale_date, product, amount, + AVG(amount) OVER ( + PARTITION BY product + ORDER BY sale_date + ROWS BETWEEN 2 PRECEDING AND CURRENT ROW + ) AS moving_avg_3day +FROM sales +ORDER BY product, sale_date; +``` + +结果: + +``` +sale_date | product | amount | moving_avg_3day +------------+---------+--------+---------------- +2024-01-01 | A | 100.00 | 100.00 +2024-01-02 | A | 150.00 | 125.00 -- (100+150)/2 +2024-01-03 | A | 200.00 | 150.00 -- (100+150+200)/3 +2024-01-04 | A | 250.00 | 200.00 -- (150+200+250)/3 +2024-01-05 | A | 300.00 | 250.00 -- (200+250+300)/3 +``` + +### 3. 居中窗口(当前行 + 前 1 行 + 后 1 行) {#3-centered-window-current-1-before-1-after} + +```sql +SELECT sale_date, product, amount, + SUM(amount) OVER ( + PARTITION BY product + ORDER BY sale_date + ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING + ) AS centered_sum +FROM sales +ORDER BY product, sale_date; +``` + +结果: + +``` +sale_date | product | amount | centered_sum +------------+---------+--------+------------- +2024-01-01 | A | 100.00 | 250.00 -- (100+150) +2024-01-02 | A | 150.00 | 450.00 -- (100+150+200) +2024-01-03 | A | 200.00 | 600.00 -- (150+200+250) +2024-01-04 | A | 250.00 | 750.00 -- (200+250+300) +2024-01-05 | A | 300.00 | 550.00 -- (250+300) +``` + +### 4. 面向未来的窗口 {#4-future-looking-window} + +```sql +SELECT sale_date, product, amount, + MIN(amount) OVER ( + PARTITION BY product + ORDER BY sale_date + ROWS BETWEEN CURRENT ROW AND 2 FOLLOWING + ) AS min_next_3days +FROM sales +ORDER BY product, sale_date; +``` + +结果: + +``` +sale_date | product | amount | min_next_3days +------------+---------+--------+--------------- +2024-01-01 | A | 100.00 | 100.00 -- min(100,150,200) +2024-01-02 | A | 150.00 | 150.00 -- min(150,200,250) +2024-01-03 | A | 200.00 | 200.00 -- min(200,250,300) +2024-01-04 | A | 250.00 | 250.00 -- min(250,300) +2024-01-05 | A | 300.00 | 300.00 -- min(300) +``` + +### 5. 完整分区窗口 {#5-full-partition-window} + +```sql +SELECT sale_date, product, amount, + MAX(amount) OVER ( + PARTITION BY product + ORDER BY sale_date + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS max_in_partition, + MIN(amount) OVER ( + PARTITION BY product + ORDER BY sale_date + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS min_in_partition +FROM sales +ORDER BY product, sale_date; +``` + +结果: + +``` +sale_date | product | amount | max_in_partition | min_in_partition +------------+---------+--------+------------------+----------------- +2024-01-01 | A | 100.00 | 300.00 | 100.00 +2024-01-02 | A | 150.00 | 300.00 | 100.00 +2024-01-03 | A | 200.00 | 300.00 | 100.00 +2024-01-04 | A | 250.00 | 300.00 | 100.00 +2024-01-05 | A | 300.00 | 300.00 | 100.00 +``` + +## 常见模式 {#common-patterns} + +### 累积计算 {#running-calculations} + +**语法示例(不是完整语句):** + +```sql +-- Running total +SUM(column) OVER (ORDER BY sort_col ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) + +-- Running average +AVG(column) OVER (ORDER BY sort_col ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) + +-- Running count +COUNT(*) OVER (ORDER BY sort_col ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) +``` + +**完整示例:** + +```sql +-- Running total with actual table +SELECT sale_date, product, amount, + SUM(amount) OVER ( + ORDER BY sale_date + ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW + ) AS running_total +FROM sales +ORDER BY sale_date; +``` + +### 滑动窗口 {#moving-windows} + +**语法示例:** + +```sql +-- 3-period moving average +AVG(column) OVER (ORDER BY sort_col ROWS BETWEEN 2 PRECEDING AND CURRENT ROW) + +-- 5-period moving sum +SUM(column) OVER (ORDER BY sort_col ROWS BETWEEN 4 PRECEDING AND CURRENT ROW) + +-- Centered 3-period window +AVG(column) OVER (ORDER BY sort_col ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING) +``` + +**完整示例:** + +```sql +-- 3-day moving average +SELECT sale_date, amount, + AVG(amount) OVER ( + ORDER BY sale_date + ROWS BETWEEN 2 PRECEDING AND CURRENT ROW + ) AS moving_avg_3day +FROM sales +ORDER BY sale_date; +``` + +### 有界窗口 {#bounded-windows} + +**语法示例:** + +```sql +-- First 3 rows of partition +SUM(column) OVER (ORDER BY sort_col ROWS BETWEEN UNBOUNDED PRECEDING AND 2 FOLLOWING) + +-- Last 3 rows of partition +SUM(column) OVER (ORDER BY sort_col ROWS BETWEEN 2 PRECEDING AND UNBOUNDED FOLLOWING) + +-- Fixed window of 5 rows +AVG(column) OVER (ORDER BY sort_col ROWS BETWEEN 2 PRECEDING AND 2 FOLLOWING) +``` + +**完整示例:** + +```sql +-- Fixed 5-row window average +SELECT sale_date, amount, + AVG(amount) OVER ( + ORDER BY sale_date + ROWS BETWEEN 2 PRECEDING AND 2 FOLLOWING + ) AS avg_5row_window +FROM sales +ORDER BY sale_date; +``` + +## 最佳实践 {#best-practices} + +1. 当你需要精确基于行的窗口时,**对物理行数使用 ROWS** +2. 使用 ROWS BETWEEN 时,**始终包含 ORDER BY**(UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING 除外) +3. 对于大窗口,**考虑性能** - 较小的窗口效率更高 +4. **处理边界情况** - 在分区边界处,窗口可能会更小 +5. **结合 PARTITION BY 使用**,以进行按组计算 +6. **理解边界行为** - 在分区边缘,窗口会收缩 + +### 边界行为示例 {#boundary-behavior-examples} + +**分区边缘处的居中窗口:** + +```sql +-- For row 1: ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING +-- Actual window: CURRENT ROW AND 1 FOLLOWING (no preceding row exists) + +-- For last row: ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING +-- Actual window: 1 PRECEDING AND CURRENT ROW (no following row exists) +``` + +**开始位置的移动平均值:** + +```sql +-- For row 1: ROWS BETWEEN 2 PRECEDING AND CURRENT ROW +-- Actual window: CURRENT ROW only (no preceding rows) + +-- For row 2: ROWS BETWEEN 2 PRECEDING AND CURRENT ROW +-- Actual window: 1 PRECEDING AND CURRENT ROW (only 1 preceding row exists) +``` + +这是正常行为 - 窗口框架会根据分区边界处可用的行进行调整。 + +## 限制 {#limitations} + +1. **n 必须是非负整数型** - 不能使用负值或表达式 +2. 大多数窗口框架都**需要 ORDER BY**(完整分区除外) +3. **框架边界必须有序** - start_bound <= end_bound +4. **不能任意混用 PRECEDING 和 FOLLOWING** - 必须构成有效窗口 + +## 另请参阅 {#see-also} + +- [窗口函数概览](/tidb-cloud-lake/sql/window-functions-overview.md) +- [RANGE BETWEEN](/tidb-cloud-lake/sql/range-between.md) - 基于值的窗口框架 +- [聚合函数](/tidb-cloud-lake/sql/aggregate-functions.md) - 可使用窗口框架的聚合函数 +- [FIRST_VALUE](/tidb-cloud-lake/sql/first-value.md) - 带框架的窗口函数示例 \ No newline at end of file diff --git a/tidb-cloud-lake/sql/rpad.md b/tidb-cloud-lake/sql/rpad.md new file mode 100644 index 0000000000000..cf3d6d37aa766 --- /dev/null +++ b/tidb-cloud-lake/sql/rpad.md @@ -0,0 +1,44 @@ +--- +title: RPAD +summary: 返回字符串 str,在其右侧使用字符串 padstr 填充,直到长度达到 len 个字符。如果 str 的长度大于 len,则返回值会被截短为 len 个字符。 +--- + +# RPAD + +返回字符串 str,在其右侧使用字符串 padstr 填充,直到长度达到 len 个字符。如果 str 的长度大于 len,则返回值会被截短为 len 个字符。 + +## 语法 {#syntax} + +```sql +RPAD(, , ) +``` + +## 参数 {#arguments} + +| 参数 | 描述 | +|------------|--------------| +| `` | 字符串。 | +| `` | 长度。 | +| `` | 填充字符串。 | + +## 返回类型 {#return-type} + +`VARCHAR` + +## 示例 {#examples} + +```sql +SELECT RPAD('hi',5,'?'); ++--------------------+ +| RPAD('hi', 5, '?') | ++--------------------+ +| hi??? | ++--------------------+ + +SELECT RPAD('hi',1,'?'); ++--------------------+ +| RPAD('hi', 1, '?') | ++--------------------+ +| h | ++--------------------+ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/rtrim.md b/tidb-cloud-lake/sql/rtrim.md new file mode 100644 index 0000000000000..0f3f125fba53a --- /dev/null +++ b/tidb-cloud-lake/sql/rtrim.md @@ -0,0 +1,31 @@ +--- +title: RTRIM +summary: 从字符串右侧移除指定 trim 字符串中出现的所有字符。 +--- + +# RTRIM + +从字符串右侧移除指定 trim 字符串中出现的所有字符。 + +另请参阅: + +- [TRIM_TRAILING](/tidb-cloud-lake/sql/trim-trailing.md) +- [LTRIM](/tidb-cloud-lake/sql/ltrim.md) + +## 语法 {#syntax} + +```sql +RTRIM(, ) +``` + +## 示例 {#examples} + +```sql +SELECT RTRIM('datalakexx', 'x'), RTRIM('datalakexx', 'xy'); + +┌──────────────────────────────────────────────────────┐ +│ rtrim('datalakexx', 'x') │ rtrim('datalakexx', 'xy') │ +├──────────────────────────┼───────────────────────────┤ +│ datalake │ datalake │ +└──────────────────────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/score.md b/tidb-cloud-lake/sql/score.md new file mode 100644 index 0000000000000..24f711cf9d5bc --- /dev/null +++ b/tidb-cloud-lake/sql/score.md @@ -0,0 +1,62 @@ +--- +title: SCORE +summary: 返回由倒排索引搜索条件匹配到的行的相关性得分。 +--- + +# SCORE + +`SCORE()` 返回倒排索引搜索为当前行分配的相关性得分。请将其与 `WHERE` 子句中的 [MATCH](/tidb-cloud-lake/sql/match.md) 或 [QUERY](/tidb-cloud-lake/sql/query.md) 一起使用。 + +> **注意:** +> +> {{{ .lake }}} 的 SCORE 函数受 Elasticsearch 的 [SCORE](https://www.elastic.co/guide/en/elasticsearch/reference/current/sql-functions-search.html#sql-functions-search-score) 启发。 + +## 语法 {#syntax} + +```sql +SCORE() +``` + +## 示例 {#examples} + +### 示例:为 MATCH 准备文本注释 {#example-prepare-text-notes-for-match} + +```sql +CREATE OR REPLACE TABLE frame_notes ( + id INT, + camera STRING, + summary STRING, + tags STRING, + INVERTED INDEX idx_notes (summary, tags) +); + +INSERT INTO frame_notes VALUES + (1, 'dashcam_front', + 'Green light at Market & 5th with pedestrian entering the crosswalk', + 'downtown commute green-light pedestrian'), + (2, 'dashcam_front', + 'Vehicle stopped at Mission & 6th red traffic light with cyclist ahead', + 'stop urban red-light cyclist'), + (3, 'dashcam_front', + 'School zone caution sign in SOMA with pedestrian waiting near crosswalk', + 'school-zone caution pedestrian'); +``` + +### 示例:为 MATCH 结果评分 {#example-score-match-results} + +```sql +SELECT summary, SCORE() +FROM frame_notes +WHERE MATCH('summary^2, tags', 'traffic light red', 'operator=AND') +ORDER BY SCORE() DESC; +``` + +### 示例:为 QUERY 结果评分 {#example-score-query-results} + +复用 [QUERY](/tidb-cloud-lake/sql/query.md) 示例中的 `frames` 表: + +```sql +SELECT id, SCORE() +FROM frames +WHERE QUERY('meta.detections.label:pedestrian^3 AND meta.scene.time_of_day:day'); +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/second.md b/tidb-cloud-lake/sql/second.md new file mode 100644 index 0000000000000..97cdb0562cbc3 --- /dev/null +++ b/tidb-cloud-lake/sql/second.md @@ -0,0 +1,37 @@ +--- +title: TO_SECOND +summary: 将带时间的日期(timestamp/datetime)转换为一个 UInt8 数字,表示分钟中的秒数(0-59)。 +--- + +# TO_SECOND + +将带时间的日期(timestamp/datetime)转换为一个 UInt8 数字,表示分钟中的秒数(0-59)。 + +## 语法 {#syntax} + +```sql +TO_SECOND() +``` + +## 参数 {#arguments} + +| 参数 | 描述 | +|-----------|-------------| +| `` | 时间戳 | + +## 返回类型 {#return-type} + +`TINYINT` + +## 示例 {#examples} + +```sql +SELECT + to_second('2023-11-12 09:38:18.165575'); + +┌─────────────────────────────────────────┐ +│ to_second('2023-11-12 09:38:18.165575') │ +├─────────────────────────────────────────┤ +│ 18 │ +└─────────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/seconds.md b/tidb-cloud-lake/sql/seconds.md new file mode 100644 index 0000000000000..0489d6ca9b34c --- /dev/null +++ b/tidb-cloud-lake/sql/seconds.md @@ -0,0 +1,36 @@ +--- +title: TO_SECONDS +summary: 将指定的秒数转换为 Interval 类型。 +--- + +# TO_SECONDS + +将指定的秒数转换为 Interval 类型。 + +- 接受正整数、零和负整数作为输入。 + +## 语法 {#syntax} + +```sql +TO_SECONDS() +``` + +## 别名 {#aliases} + +- [EPOCH](/tidb-cloud-lake/sql/epoch.md) + +## 返回类型 {#return-type} + +Interval(格式为 `hh:mm:ss`)。 + +## 示例 {#examples} + +```sql +SELECT TO_SECONDS(2), TO_SECONDS(0), TO_SECONDS((- 2)); + +┌─────────────────────────────────────────────────┐ +│ to_seconds(2) │ to_seconds(0) │ to_seconds(- 2) │ +├───────────────┼───────────────┼─────────────────┤ +│ 0:00:02 │ 00:00:00 │ -0:00:02 │ +└─────────────────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/select.md b/tidb-cloud-lake/sql/select.md new file mode 100644 index 0000000000000..661a22d97fe5f --- /dev/null +++ b/tidb-cloud-lake/sql/select.md @@ -0,0 +1,527 @@ +--- +title: SELECT +summary: 从表中检索数据。 +--- + +# SELECT + +从表中检索数据。 + +## 语法 {#syntax} + +```sql +[WITH] +SELECT + [ALL | DISTINCT] + [ TOP ] + | [[AS] ] | $ [, ...] | * + COLUMNS + [EXCLUDE ( [, , , ...] ) ] + [FROM table_references] + [AT ...] + [WHERE ] + [GROUP BY {{ | | | }, + ... | }] + [HAVING ] + [ORDER BY { | | | } [ASC | DESC], + [ NULLS { FIRST | LAST }] + [LIMIT ] + [OFFSET ] + [IGNORE_RESULT] +``` + +- `SELECT` 语句还支持直接查询 stage 中的文件。语法和示例请参见[使用 {{{ .lake }}} 高效进行数据转换](/tidb-cloud-lake/sql/stage.md)。 + +- 本页示例中使用 `numbers(N)` 表进行测试。该表只有一个 UInt64 列(名为 `number`),包含从 0 到 N-1 的整数。 + +## SELECT 子句 {#select-clause} + +### AS 关键字 {#as-keyword} + +在 {{{ .lake }}} 中,你可以使用 `AS` 关键字为列指定别名。这样可以在 SQL 语句和查询结果中为列提供更具描述性且更易理解的名称: + +- {{{ .lake }}} 建议在创建列别名时尽量避免使用特殊字符。不过,如果某些场景下确实需要使用特殊字符,则应将别名用反引号括起来,例如:`SELECT price AS \`$CA\` FROM ...` + +- {{{ .lake }}} 会自动将别名转换为小写。例如,如果你将某列的别名设为 *Total*,那么它在结果中会显示为 *total*。如果你希望保留大小写,请将别名用反引号括起来:`\`Total\``。 + +```sql +SELECT number AS Total FROM numbers(3); ++--------+ +| total | ++--------+ +| 0 | +| 1 | +| 2 | ++--------+ + +SELECT number AS `Total` FROM numbers(3); ++--------+ +| Total | ++--------+ +| 0 | +| 1 | +| 2 | ++--------+ +``` + +如果你在 `SELECT` 子句中为某列指定了别名,那么在该别名定义之后,你可以在 `WHERE`、`GROUP BY` 和 `HAVING` 子句中引用该别名,也可以在 `SELECT` 子句自身中引用它。 + +```sql +SELECT number * 2 AS a, a * 2 AS double FROM numbers(3) WHERE (a + 1) % 3 = 0; ++---+--------+ +| a | double | ++---+--------+ +| 2 | 4 | ++---+--------+ + +SELECT MAX(number) AS b, number % 3 AS c FROM numbers(100) GROUP BY c HAVING b > 8; ++----+---+ +| b | c | ++----+---+ +| 99 | 0 | +| 97 | 1 | +| 98 | 2 | ++----+---+ +``` + +如果你为某列指定的别名与列名相同,那么 `WHERE` 和 `GROUP BY` 子句会将该别名识别为列名;但是,`HAVING` 子句会将其识别为别名本身。 + +```sql +SELECT number * 2 AS number FROM numbers(3) +WHERE (number + 1) % 3 = 0 +GROUP BY number +HAVING number > 5; + ++--------+ +| number | ++--------+ +| 10 | +| 16 | ++--------+ +``` + +### EXCLUDE 关键字 {#exclude-keyword} + +按列名从结果中排除一个或多个列。该关键字通常与 `SELECT * ...` 一起使用,用于从结果中排除少量列,而不是检索所有列。 + +```sql +SELECT * FROM allemployees ORDER BY id; + +--- +| id | firstname | lastname | gender | +|----|-----------|----------|--------| +| 1 | Ryan | Tory | M | +| 2 | Oliver | Green | M | +| 3 | Noah | Shuster | M | +| 4 | Lily | McMeant | F | +| 5 | Macy | Lee | F | + +-- 从结果中排除 "id" 列 +SELECT * EXCLUDE id FROM allemployees; + +--- +| firstname | lastname | gender | +|-----------|----------|--------| +| Noah | Shuster | M | +| Ryan | Tory | M | +| Oliver | Green | M | +| Lily | McMeant | F | +| Macy | Lee | F | + +-- 从结果中排除 "id" 和 "lastname" 列 +SELECT * EXCLUDE (id,lastname) FROM allemployees; + +--- +| firstname | gender | +|-----------|--------| +| Oliver | M | +| Ryan | M | +| Lily | F | +| Noah | M | +| Macy | F | +``` + +### COLUMNS 关键字 {#columns-keyword} + +COLUMNS 关键字提供了一种灵活的列选择机制,可基于字面量正则表达式模式和 lambda 表达式来选择列。 + +```sql +CREATE TABLE employee ( + employee_id INT, + employee_name VARCHAR(255), + department VARCHAR(50), + salary DECIMAL(10, 2) +); + +INSERT INTO employee VALUES +(1, 'Alice', 'HR', 60000.00), +(2, 'Bob', 'IT', 75000.00), +(3, 'Charlie', 'Marketing', 50000.00), +(4, 'David', 'Finance', 80000.00); + +-- Select columns with names starting with 'employee' +SELECT COLUMNS('employee.*') FROM employee; + +┌────────────────────────────────────┐ +│ employee_id │ employee_name │ +├─────────────────┼──────────────────┤ +│ 1 │ Alice │ +│ 2 │ Bob │ +│ 3 │ Charlie │ +│ 4 │ David │ +└────────────────────────────────────┘ + +-- Select columns where the name contains the substring 'name' +SELECT COLUMNS(x -> x LIKE '%name%') FROM employee; + +┌──────────────────┐ +│ employee_name │ +├──────────────────┤ +│ Alice │ +│ Bob │ +│ Charlie │ +│ David │ +└──────────────────┘ +``` + +COLUMNS 关键字还可以与 EXCLUDE 一起使用,以在查询结果中显式排除特定列。 + +```sql +-- Select all columns excluding 'salary' from the 'employee' table +SELECT COLUMNS(* EXCLUDE salary) FROM employee; + +┌───────────────────────────────────────────────────────┐ +│ employee_id │ employee_name │ department │ +├─────────────────┼──────────────────┼──────────────────┤ +│ 1 │ Alice │ HR │ +│ 2 │ Bob │ IT │ +│ 3 │ Charlie │ Marketing │ +│ 4 │ David │ Finance │ +└───────────────────────────────────────────────────────┘ +``` + +### 列位置 {#column-position} + +通过使用 $N,你可以表示 SELECT 子句中的某一列。例如,$2 表示第二列: + +```sql +CREATE TABLE IF NOT EXISTS t1(a int, b varchar); +INSERT INTO t1 VALUES (1, 'a'), (2, 'b'); +SELECT a, $2 FROM t1; + ++---+-------+ +| a | $2 | ++---+-------+ +| 1 | a | +| 2 | b | ++---+-------+ +``` + +### 检索所有列 {#retrieving-all-columns} + +`SELECT *` 语句用于从表或查询结果中检索所有列。这是一种便捷方式,无需指定单独的列名即可获取完整的数据集。 + +以下示例返回 my_table 中的所有列: + +```sql +SELECT * FROM my_table; +``` + +{{{ .lake }}} 对 SQL 语法进行了扩展,允许查询以 `FROM
` 开始,而无需显式使用 `SELECT *`: + +```sql +FROM my_table; +``` + +这等价于: + +```sql +SELECT * FROM my_table; +``` + +## FROM 子句 {#from-clause} + +SELECT 语句中的 FROM 子句用于指定要查询数据的源表或源表集合。你也可以将 FROM 子句放在 SELECT 子句之前,以提高代码可读性,尤其是在处理较长的 SELECT 列表或希望快速识别所选列来源时。 + +```sql +-- The following two statements are equivalent: + +-- Statement 1: Using SELECT clause with FROM clause +SELECT number FROM numbers(3); + +-- Statement 2: Equivalent representation with FROM clause preceding SELECT clause +FROM numbers(3) SELECT number; + ++--------+ +| number | ++--------+ +| 0 | +| 1 | +| 2 | ++--------+ +``` + +FROM 子句还可以指定一个位置,从而支持直接查询来自各种来源的数据,而无需先将其加载到表中。更多信息,参见[查询 stage 文件](/tidb-cloud-lake/sql/stage.md)。 + +## AT 子句 {#at-clause} + +AT 子句使你能够查询数据的历史版本。更多信息,参见 [AT](/tidb-cloud-lake/sql/at.md)。 + +## WHERE 子句 {#where-clause} + +```sql +SELECT number FROM numbers(3) WHERE number > 1; ++--------+ +| number | ++--------+ +| 2 | ++--------+ +``` + +## GROUP BY 子句 {#group-by-clause} + +```sql +--Group the rows of the result set by column alias +SELECT number%2 as c1, number%3 as c2, MAX(number) FROM numbers(10000) GROUP BY c1, c2; ++------+------+-------------+ +| c1 | c2 | MAX(number) | ++------+------+-------------+ +| 1 | 2 | 9995 | +| 1 | 1 | 9997 | +| 0 | 2 | 9998 | +| 0 | 1 | 9994 | +| 0 | 0 | 9996 | +| 1 | 0 | 9999 | ++------+------+-------------+ + +--Group the rows of the result set by column position in the SELECT list +SELECT number%2 as c1, number%3 as c2, MAX(number) FROM numbers(10000) GROUP BY 1, 2; ++------+------+-------------+ +| c1 | c2 | MAX(number) | ++------+------+-------------+ +| 1 | 2 | 9995 | +| 1 | 1 | 9997 | +| 0 | 2 | 9998 | +| 0 | 1 | 9994 | +| 0 | 0 | 9996 | +| 1 | 0 | 9999 | ++------+------+-------------+ + +``` + +## HAVING 子句 {#having-clause} + +```sql +SELECT + number % 2 as c1, + number % 3 as c2, + MAX(number) as max +FROM + numbers(10000) +GROUP BY + c1, c2 +HAVING + max > 9996; + ++------+------+------+ +| c1 | c2 | max | ++------+------+------+ +| 1 | 0 | 9999 | +| 1 | 1 | 9997 | +| 0 | 2 | 9998 | ++------+------+------+ +``` + +## ORDER BY 子句 {#order-by-clause} + +```sql +--Sort by column name in ascending order. +SELECT number FROM numbers(5) ORDER BY number ASC; ++--------+ +| number | ++--------+ +| 0 | +| 1 | +| 2 | +| 3 | +| 4 | ++--------+ + +--Sort by column name in descending order. +SELECT number FROM numbers(5) ORDER BY number DESC; ++--------+ +| number | ++--------+ +| 4 | +| 3 | +| 2 | +| 1 | +| 0 | ++--------+ + +--Sort by column alias. +SELECT number%2 AS c1, number%3 AS c2 FROM numbers(5) ORDER BY c1 ASC, c2 DESC; ++------+------+ +| c1 | c2 | ++------+------+ +| 0 | 2 | +| 0 | 1 | +| 0 | 0 | +| 1 | 1 | +| 1 | 0 | ++------+------+ + +--Sort by column position in the SELECT list +SELECT * FROM t1 ORDER BY 2 DESC; ++------+------+ +| a | b | ++------+------+ +| 2 | 3 | +| 1 | 2 | ++------+------+ + +SELECT a FROM t1 ORDER BY 1 DESC; ++------+ +| a | ++------+ +| 2 | +| 1 | ++------+ + +--Sort with the NULLS FIRST or LAST option. + +CREATE TABLE t_null ( + number INTEGER +); + +INSERT INTO t_null VALUES (1); +INSERT INTO t_null VALUES (2); +INSERT INTO t_null VALUES (3); +INSERT INTO t_null VALUES (NULL); +INSERT INTO t_null VALUES (NULL); + +--{{{ .lake }}} considers NULL values larger than any non-NULL values. +--The NULL values appear last in the following example that sorts the results in ascending order: + +SELECT number FROM t_null order by number ASC; ++--------+ +| number | ++--------+ +| 1 | +| 2 | +| 3 | +| NULL | +| NULL | ++--------+ + +-- To make the NULL values appear first in the preceding example, use the NULLS FIRST option: + +SELECT number FROM t_null order by number ASC nulls first; ++--------+ +| number | ++--------+ +| NULL | +| NULL | +| 1 | +| 2 | +| 3 | ++--------+ + +-- Use the NULLS LAST option to make the NULL values appear last in descending order: + +SELECT number FROM t_null order by number DESC nulls last; ++--------+ +| number | ++--------+ +| 3 | +| 2 | +| 1 | +| NULL | +| NULL | ++--------+ +``` + +## LIMIT 子句 {#limit-clause} + +```sql +SELECT number FROM numbers(1000000000) LIMIT 1; ++--------+ +| number | ++--------+ +| 0 | ++--------+ + +SELECT number FROM numbers(100000) ORDER BY number LIMIT 2 OFFSET 10; ++--------+ +| number | ++--------+ +| 10 | +| 11 | ++--------+ +``` + +为了优化大结果集查询的性能,{{{ .lake }}} 默认启用了 `lazy_read_threshold` 选项,默认值为 1,000。该选项专门用于包含 LIMIT 子句的查询。启用 `lazy_read_threshold` 后,当查询中指定的 LIMIT 数量小于或等于你设置的阈值时,将触发该优化。要禁用此选项,请将其设置为 0。 + +
+ 工作原理 +
该优化可提升同时包含 ORDER BY 子句和 LIMIT 子句的查询性能。启用后,如果查询中的 LIMIT 数量小于指定阈值,则只会获取并排序 ORDER BY 子句中涉及的列,而不是整个结果集。

系统获取并排序 ORDER BY 子句中涉及的列后,会应用 LIMIT 约束,从已排序的结果集中选出所需数量的行。随后,系统将这个受限的行集作为查询结果返回。该方法通过仅获取和排序必要的列来减少资源消耗,并通过将处理的行数限制在所需子集内,进一步优化查询执行。
+
+ +```sql +SELECT * FROM hits WHERE URL LIKE '%google%' ORDER BY EventTime LIMIT 10 ignore_result; +Empty set (0.300 sec) + +set lazy_read_threshold=0; +Query OK, 0 rows affected (0.004 sec) + +SELECT * FROM hits WHERE URL LIKE '%google%' ORDER BY EventTime LIMIT 10 ignore_result; +Empty set (0.897 sec) +``` + +## OFFSET 子句 {#offset-clause} + +```sql +SELECT number FROM numbers(5) ORDER BY number OFFSET 2; ++--------+ +| number | ++--------+ +| 2 | +| 3 | +| 4 | ++--------+ +``` + +## IGNORE_RESULT {#ignore-result} + +不输出结果集。 + +```sql +SELECT number FROM numbers(2); ++--------+ +| number | ++--------+ +| 0 | +| 1 | ++--------+ + +SELECT number FROM numbers(2) IGNORE_RESULT; +-- Empty set +``` + +## 嵌套子查询 {#nested-sub-selects} + +SELECT 语句可以嵌套在查询中。 + +``` +SELECT ... [SELECT ...[SELECT [...]]] +``` + +```sql +SELECT MIN(number) FROM (SELECT number%3 AS number FROM numbers(10)) GROUP BY number%2; ++-------------+ +| min(number) | ++-------------+ +| 1 | +| 0 | ++-------------+ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/sequence-functions-overview.md b/tidb-cloud-lake/sql/sequence-functions-overview.md new file mode 100644 index 0000000000000..0dc823d02eb66 --- /dev/null +++ b/tidb-cloud-lake/sql/sequence-functions-overview.md @@ -0,0 +1,14 @@ +--- +title: 序列函数 +summary: 本节提供 {{{ .lake }}} 中序列函数的参考信息。序列函数可用于操作序列对象,这些对象会生成唯一的、自增的数值。 +--- + +# 序列函数 + +本节提供 {{{ .lake }}} 中序列函数的参考信息。序列函数可用于操作序列对象,这些对象会生成唯一的、自增的数值。 + +## 可用的序列函数 {#available-sequence-functions} + +| 函数 | 描述 | 示例 | +|----------|-------------|--------| +| [NEXTVAL](/tidb-cloud-lake/sql/nextval.md) | 获取序列中的下一个值 | `NEXTVAL(my_sequence)` | \ No newline at end of file diff --git a/tidb-cloud-lake/sql/sequence.md b/tidb-cloud-lake/sql/sequence.md new file mode 100644 index 0000000000000..b089131a7de21 --- /dev/null +++ b/tidb-cloud-lake/sql/sequence.md @@ -0,0 +1,26 @@ +--- +title: 序列 +summary: 本页按功能分类,全面概述了 {{{ .lake }}} 中的序列操作,便于快速查阅。 +--- + +# 序列 + +本页按功能分类,全面概述了 {{{ .lake }}} 中的序列操作,便于快速查阅。 + +## 序列管理 {#sequence-management} + +| Command | 描述 | +|---------|-------------| +| [CREATE SEQUENCE](/tidb-cloud-lake/sql/create-sequence.md) | 创建新的序列生成器 | +| [DROP SEQUENCE](/tidb-cloud-lake/sql/drop-sequence.md) | 删除序列生成器 | + +## 序列信息 {#sequence-information} + +| Command | 描述 | +|---------|-------------| +| [DESC SEQUENCE](/tidb-cloud-lake/sql/desc-sequence.md) | 显示序列的详细信息 | +| [SHOW SEQUENCES](/tidb-cloud-lake/sql/show-sequences.md) | 列出当前或指定数据库中的所有序列 | + +> **注意:** +> +> {{{ .lake }}} 中的序列用于按顺序生成唯一的数值,通常用于主键或其他唯一标识符。 \ No newline at end of file diff --git a/tidb-cloud-lake/sql/set-cache-capacity.md b/tidb-cloud-lake/sql/set-cache-capacity.md new file mode 100644 index 0000000000000..6363bfd99c273 --- /dev/null +++ b/tidb-cloud-lake/sql/set-cache-capacity.md @@ -0,0 +1,48 @@ +--- +title: SYSTEM$SET_CACHE_CAPACITY +summary: 在运行时调整指定缓存的容量。 +--- + +# SYSTEM$SET_CACHE_CAPACITY + +在运行时为指定名称的缓存设置最大容量。更改会立即生效,但**不会持久化**——重启后,缓存会恢复为配置文件中的值。 + +另请参阅:[system.caches](/tidb-cloud-lake/sql/system-caches.md)。 + +## 语法 {#syntax} + +```sql +CALL system$set_cache_capacity('', ) +``` + +| 参数 | 描述 | +|--------------|--------------------------------------------------------------------------| +| cache_name | 缓存名称(参见 [system.caches](/tidb-cloud-lake/sql/system-caches.md) 中的缓存列表) | +| new_capacity | 新的容量值。单位(数量或字节)取决于缓存类型。 | + +## 注意事项 {#notes} + +- 如果新容量**大于**当前值,则会保留现有缓存条目。 +- 如果新容量**小于**当前值,则可能会根据 LRU 策略逐出条目。 +- 更改**不会持久化**。重启后,容量会恢复为配置文件中的值。 +- `disk_cache_column_data` 不能使用此命令调整。 + +## 示例 {#examples} + +将 bloom index metadata cache 设置为 5000 个条目: + +```sql +CALL system$set_cache_capacity('memory_cache_bloom_index_file_meta_data', 5000); + +┌────────────────────────┬────────┐ +│ node │ result │ +├────────────────────────┼────────┤ +│ Gwo2DYOLZ9zAdYbGTWY9y6 │ Ok │ +└────────────────────────┴────────┘ +``` + +为测试禁用 partition pruning cache: + +```sql +CALL system$set_cache_capacity('memory_cache_prune_partitions', 0); +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/set-cluster-key.md b/tidb-cloud-lake/sql/set-cluster-key.md new file mode 100644 index 0000000000000..5e02de58c0e8c --- /dev/null +++ b/tidb-cloud-lake/sql/set-cluster-key.md @@ -0,0 +1,35 @@ +--- +title: SET CLUSTER KEY +summary: 在创建表时设置 cluster key。 +--- + +# SET CLUSTER KEY + +在创建表时设置 cluster key。 + +cluster key 用于通过将数据在物理上聚集在一起来提升查询性能。例如,当你将某一列设置为表的 cluster key 时,表数据将按照你设置的列在物理上进行有序的排列。如果你的大多数查询都按该列进行过滤,这将最大化查询性能。 + +> **Note:** +> +> 对于字符串列,cluster 统计信息仅使用前 8 个字节。你可以使用 substring 来提供足够的基数。 + +另请参阅: + +* [ALTER CLUSTER KEY](/tidb-cloud-lake/sql/alter-cluster-key.md) +* [DROP CLUSTER KEY](/tidb-cloud-lake/sql/drop-cluster-key.md) + +## 语法 {#syntax} + +```sql +CREATE TABLE ... CLUSTER BY ( [ , ... ] ) +``` + +## 示例 {#examples} + +以下命令创建按列进行聚集的表: + +```sql +CREATE TABLE t1(a int, b int) CLUSTER BY(b,a); + +CREATE TABLE t2(a int, b string) CLUSTER BY(SUBSTRING(b, 5, 6)); +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/set-operators-sql.md b/tidb-cloud-lake/sql/set-operators-sql.md new file mode 100644 index 0000000000000..7e7e90460a9e1 --- /dev/null +++ b/tidb-cloud-lake/sql/set-operators-sql.md @@ -0,0 +1,163 @@ +--- +title: 集合运算符 +summary: 集合运算符将两个查询的结果组合为单个结果。{{{ .lake }}} 支持以下集合运算符。 +--- + +# 集合运算符 + +集合运算符将两个查询的结果组合为单个结果。{{{ .lake }}} 支持以下集合运算符: + +- [INTERSECT](#intersect) +- [EXCEPT](#except) +- [UNION [ALL]](#union-all) + +## INTERSECT {#intersect} + +返回两个查询都选中的所有去重行。 + +### 语法 {#syntax} + +```sql +SELECT column1 , column2 .... +FROM table_names +WHERE condition + +INTERSECT + +SELECT column1 , column2 .... +FROM table_names +WHERE condition +``` + +### 示例 {#example} + +```sql +create table t1(a int, b int); +create table t2(c int, d int); + +insert into t1 values(1, 2), (2, 3), (3 ,4), (2, 3); +insert into t2 values(2,2), (3, 5), (7 ,8), (2, 3), (3, 4); + +select * from t1 intersect select * from t2; +``` + +输出: + +```sql +2|3 +3|4 +``` + +## EXCEPT {#except} + +返回第一个查询选中但第二个查询未选中的所有去重行。 + +### 语法 {#syntax} + +```sql +SELECT column1 , column2 .... +FROM table_names +WHERE condition + +EXCEPT + +SELECT column1 , column2 .... +FROM table_names +WHERE condition +``` + +### 示例 {#example} + +```sql +create table t1(a int, b int); +create table t2(c int, d int); + +insert into t1 values(1, 2), (2, 3), (3 ,4), (2, 3); +insert into t2 values(2,2), (3, 5), (7 ,8), (2, 3), (3, 4); + +select * from t1 except select * from t2; +``` + +输出: + +```sql +1|2 +``` + +## UNION [ALL] {#union-all} + +将两个或多个结果集中的行组合在一起。每个结果集必须返回相同数量的列,并且对应列必须具有相同或兼容的数据类型。 + +在组合结果集时,该命令默认会去除重复行。若要包含重复行,请使用 **UNION ALL**。 + +### 语法 {#syntax} + +```sql +SELECT column1 , column2 ... +FROM table_names +WHERE condition + +UNION [ALL] + +SELECT column1 , column2 ... +FROM table_names +WHERE condition + +[UNION [ALL] + +SELECT column1 , column2 ... +FROM table_names +WHERE condition]... + +[ORDER BY ...] +``` + +### 示例 {#example} + +```sql +CREATE TABLE support_team + ( + NAME STRING, + salary UINT32 + ); + +CREATE TABLE hr_team + ( + NAME STRING, + salary UINT32 + ); + +INSERT INTO support_team +VALUES ('Alice', + 1000), + ('Bob', + 3000), + ('Carol', + 5000); + +INSERT INTO hr_team +VALUES ('Davis', + 1000), + ('Eva', + 4000); + +-- The following code returns the employees in both teams who are paid less than 2,000 dollars: + +SELECT NAME AS SelectedEmployee, + salary +FROM support_team +WHERE salary < 2000 +UNION +SELECT NAME AS SelectedEmployee, + salary +FROM hr_team +WHERE salary < 2000 +ORDER BY selectedemployee DESC; +``` + +输出: + +```sql +Davis|1000 +Alice|1000 +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/set-role.md b/tidb-cloud-lake/sql/set-role.md new file mode 100644 index 0000000000000..ae011d41863c8 --- /dev/null +++ b/tidb-cloud-lake/sql/set-role.md @@ -0,0 +1,42 @@ +--- +title: SET ROLE +summary: 切换会话的活动角色。你可以使用 [SHOW ROLES](/tidb-cloud-lake/sql/show-roles.md) 命令查看当前活动角色,其中 `is_current` 字段表示活动角色。有关活动角色和次要角色的更多信息,请参阅 [活动角色和次要角色](/tidb-cloud-lake/guides/roles.md#active-role--secondary-roles)。 +--- + +# SET ROLE + +切换会话的活动角色。你可以使用 [SHOW ROLES](/tidb-cloud-lake/sql/show-roles.md) 命令查看当前活动角色,其中 `is_current` 字段表示活动角色。有关活动角色和次要角色的更多信息,请参阅 [活动角色和次要角色](/tidb-cloud-lake/guides/roles.md#active-role--secondary-roles)。 + +另请参阅:[SET SECONDARY ROLES](/tidb-cloud-lake/sql/set-secondary-roles.md) + +## 语法 {#syntax} + +```sql +SET ROLE +``` + +## 示例 {#examples} + +```sql +SHOW ROLES; + +┌───────────────────────────────────────────────────────┐ +│ name │ inherited_roles │ is_current │ is_default │ +├───────────┼─────────────────┼────────────┼────────────┤ +│ developer │ 0 │ false │ false │ +│ public │ 0 │ false │ false │ +│ writer │ 0 │ true │ true │ +└───────────────────────────────────────────────────────┘ + +SET ROLE developer; + +SHOW ROLES; + +┌───────────────────────────────────────────────────────┐ +│ name │ inherited_roles │ is_current │ is_default │ +├───────────┼─────────────────┼────────────┼────────────┤ +│ developer │ 0 │ true │ false │ +│ public │ 0 │ false │ false │ +│ writer │ 0 │ false │ true │ +└───────────────────────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/set-secondary-roles.md b/tidb-cloud-lake/sql/set-secondary-roles.md new file mode 100644 index 0000000000000..64d4db6429dd1 --- /dev/null +++ b/tidb-cloud-lake/sql/set-secondary-roles.md @@ -0,0 +1,88 @@ +--- +title: SET SECONDARY ROLES +summary: 为当前会话激活所有次要角色。这意味着授予用户的所有次要角色都将处于激活状态,从而扩展用户的权限。有关活动角色和次要角色的更多信息,请参阅 Active Role & Secondary Roles。 +--- + +# SET SECONDARY ROLES + +为当前会话激活所有次要角色。这意味着授予用户的所有次要角色都将处于激活状态,从而扩展用户的权限。有关活动角色和次要角色的更多信息,请参阅 [活动角色和次要角色](/tidb-cloud-lake/guides/roles.md#active-role--secondary-roles)。 + +另请参阅:[SET ROLE](/tidb-cloud-lake/sql/set-role.md) + +## 语法 {#syntax} + +```sql +SET SECONDARY ROLES { ALL | NONE } +``` + +| 参数 | 默认值 | 描述 | +|-----------|---------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| ALL | 是 | 为当前会话激活授予用户的所有次要角色,以及活动角色。这使用户能够使用与所有次要角色关联的权限。 | +| NONE | 否 | 为当前会话停用所有次要角色,这意味着只有活动角色的权限处于激活状态。这会将用户的权限限制为仅由活动角色授予的权限。 | + +## 示例 {#examples} + +本示例展示了次要角色如何工作,以及如何激活/停用它们。 + +1. 以用户 root 创建角色。 + + 首先,创建两个角色:`admin` 和 `analyst`: + + ```sql + CREATE ROLE admin; + + CREATE ROLE analyst; + ``` + +2. 授予权限。 + + 接下来,为每个角色授予一些权限。例如,为 `admin` 角色授予创建数据库的能力,为 `analyst` 角色授予从表中查询数据的能力: + + ```sql + GRANT CREATE DATABASE ON *.* TO ROLE admin; + + GRANT SELECT ON *.* TO ROLE analyst; + ``` + +3. 创建用户。 + + 现在,创建一个用户: + + ```sql + CREATE USER 'user1' IDENTIFIED BY 'password'; + ``` + +4. 分配角色。 + + 将这两个角色都分配给该用户: + + ```sql + GRANT ROLE admin TO 'user1'; + + GRANT ROLE analyst TO 'user1'; + ``` + +5. 设置活动角色。 + + 现在,以 `user1` 身份登录到 {{{ .lake }}},然后将活动角色设置为 `analyst`。 + + ```sql + SET ROLE analyst; + ``` + + 默认情况下,所有次要角色都会被激活,因此我们可以创建一个新数据库: + + ```sql + CREATE DATABASE my_db; + ``` + +6. 停用次要角色。 + +活动角色 `analyst` 不具有 CREATE DATABASE 权限。当所有次要角色都被停用时,创建新数据库将失败。 + +```sql +SET SECONDARY ROLES NONE; + +CREATE DATABASE my_db2; +error: APIError: ResponseError with 1063: Permission denied: privilege [CreateDatabase] is required on *.* for user 'user1'@'%' with roles [analyst,public] +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/set-tag.md b/tidb-cloud-lake/sql/set-tag.md new file mode 100644 index 0000000000000..5c09b3f984f2a --- /dev/null +++ b/tidb-cloud-lake/sql/set-tag.md @@ -0,0 +1,94 @@ +--- +title: SET TAG and UNSET TAG +summary: 为数据库对象分配或移除标签。 +--- + +# SET TAG and UNSET TAG + +为数据库对象分配或移除标签。标签必须先使用 [CREATE TAG](/tidb-cloud-lake/sql/create-tag.md) 创建,然后才能分配。 + +另请参阅:[CREATE TAG](/tidb-cloud-lake/sql/create-tag.md)、[TAG_REFERENCES](/tidb-cloud-lake/sql/tag-references.md)。 + +## 语法 {#syntax} + +```sql +-- Assign tags +ALTER { DATABASE | TABLE | VIEW | STAGE | CONNECTION + | USER | ROLE | STREAM | FUNCTION | PROCEDURE } + [ IF EXISTS ] + SET TAG = '' [, = '' ...] + +-- Remove tags +ALTER { DATABASE | TABLE | VIEW | STAGE | CONNECTION + | USER | ROLE | STREAM | FUNCTION | PROCEDURE } + [ IF EXISTS ] + UNSET TAG [, ...] +``` + +## 支持的对象类型 {#supported-object-types} + +| 对象类型 | 对象名称格式 | 示例 | +|-------------|-------------------|---------| +| DATABASE | `` | `ALTER DATABASE mydb SET TAG env = 'prod'` | +| TABLE | `[.]
` | `ALTER TABLE mydb.users SET TAG env = 'prod'` | +| VIEW | `[.]` | `ALTER VIEW mydb.active_users SET TAG env = 'prod'` | +| STAGE | `` | `ALTER STAGE my_stage SET TAG env = 'prod'` | +| CONNECTION | `` | `ALTER CONNECTION my_conn SET TAG env = 'prod'` | +| USER | `''` | `ALTER USER 'alice' SET TAG env = 'prod'` | +| ROLE | `` | `ALTER ROLE analyst SET TAG env = 'prod'` | +| STREAM | `[.]` | `ALTER STREAM mydb.my_stream SET TAG env = 'prod'` | +| FUNCTION | `` | `ALTER FUNCTION my_udf SET TAG env = 'prod'` | +| PROCEDURE | `()` | `ALTER PROCEDURE my_proc(INT) SET TAG env = 'prod'` | + +> **注意:** +> +> - 如果标签定义了 `ALLOWED_VALUES`,则该值必须是允许值之一。 +> - 对不存在的标签名执行 `UNSET TAG` 会返回错误,除非对象本身不存在且指定了 `IF EXISTS`。 +> - 对于 PROCEDURE,必须在对象名称中包含参数类型签名。 + +## 示例 {#examples} + +### 为数据库和表添加标签 {#tag-a-database-and-table} + +```sql +CREATE TAG env ALLOWED_VALUES = ('dev', 'staging', 'prod'); +CREATE TAG owner; + +ALTER DATABASE default SET TAG env = 'prod'; +ALTER TABLE default.my_table SET TAG env = 'staging', owner = 'team_a'; +``` + +### 为 stage 和 connection 添加标签 {#tag-a-stage-and-connection} + +```sql +ALTER STAGE data_stage SET TAG env = 'dev', owner = 'data_team'; +ALTER CONNECTION my_s3 SET TAG env = 'prod'; +``` + +### 为视图添加标签 {#tag-a-view} + +```sql +ALTER VIEW default.active_users SET TAG env = 'prod', owner = 'analytics'; +``` + +### 为用户和角色添加标签 {#tag-a-user-and-role} + +```sql +ALTER USER 'alice' SET TAG env = 'prod', owner = 'security'; +ALTER ROLE analyst SET TAG env = 'dev'; +``` + +### 为 UDF 和存储过程添加标签 {#tag-a-udf-and-procedure} + +```sql +ALTER FUNCTION my_udf SET TAG env = 'dev'; +ALTER PROCEDURE my_proc(DECIMAL(10,2)) SET TAG env = 'prod'; +``` + +### 移除标签 {#remove-tags} + +```sql +ALTER TABLE default.my_table UNSET TAG env, owner; +ALTER STAGE data_stage UNSET TAG env; +ALTER USER 'alice' UNSET TAG env, owner; +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/set-var.md b/tidb-cloud-lake/sql/set-var.md new file mode 100644 index 0000000000000..d1535630efe83 --- /dev/null +++ b/tidb-cloud-lake/sql/set-var.md @@ -0,0 +1,127 @@ +--- +title: SET_VAR +summary: SET_VAR 用于在单条 SQL 语句中指定优化器 hint,从而对该语句的执行计划进行更细粒度的控制。这包括。 +--- + +# SET_VAR + +SET_VAR 用于在单条 SQL 语句中指定优化器 hint,从而对该语句的执行计划进行更细粒度的控制。这包括: + +> **Note:** +> +> SET_VAR 将在即将发布的版本中被弃用。建议改用 [SETTINGS 子句](/tidb-cloud-lake/sql/settings-clause.md)。 + +- 临时配置设置,仅在 SQL 语句执行期间生效。需要注意的是,使用 SET_VAR 指定的设置只会影响当前正在执行语句的结果,不会对整体数据库配置产生任何持久影响。有关可通过 SET_VAR 配置的可用设置列表,请参阅 [SHOW SETTINGS](/tidb-cloud-lake/sql/show-settings.md)。如需了解其工作方式,请参阅以下示例: + + - [示例 1:临时设置时区](#example-1-temporarily-set-timezone) + - [示例 2:控制 COPY INTO 的并行处理](#example-2-control-parallel-processing-for-copy-into) + +- 使用标签 *deduplicate_label* 控制 [INSERT](/tidb-cloud-lake/sql/insert.md)、[UPDATE](/tidb-cloud-lake/sql/update.md) 或 [REPLACE](/tidb-cloud-lake/sql/replace.md) 操作的去重行为。对于 SQL 语句中带有 deduplicate_label 的这些操作,{{{ .lake }}} 只执行第一条语句,后续具有相同 deduplicate_label 值的语句都会被忽略,无论这些语句原本打算进行何种数据修改。请注意,一旦设置了 deduplicate_label,它将在 24 小时内持续生效。要了解 deduplicate_label 如何帮助去重,请参阅 [示例 3:设置去重标签](#example-3-set-deduplicate-label)。 + +另请参阅: + +- [SETTINGS 子句](/tidb-cloud-lake/sql/settings-clause.md) +- [SET](/tidb-cloud-lake/sql/set.md) + +## 语法 {#syntax} + +```sql +/*+ SET_VAR(key=value) SET_VAR(key=value) ... */ +``` + +- 该 hint 必须紧跟在作为 SQL 语句开头的 [SELECT](/tidb-cloud-lake/sql/select.md)、[INSERT](/tidb-cloud-lake/sql/insert.md)、[UPDATE](/tidb-cloud-lake/sql/update.md)、[REPLACE](/tidb-cloud-lake/sql/replace.md)、[MERGE](/tidb-cloud-lake/sql/merge.md)、[DELETE](/tidb-cloud-lake/sql/dml.md) 或 [COPY](/tidb-cloud-lake/sql/copy-into-table.md) (INTO) 关键字之后。 +- 一个 SET_VAR 只能包含一个 Key=Value 对,这意味着你只能通过一个 SET_VAR 配置一个设置。不过,你可以使用多个 SET_VAR hint 来配置多个设置。 + - 如果多个 SET_VAR hint 包含相同的 key,则第一个 Key=Value 对会生效。 + - 如果某个 key 解析或绑定失败,则所有 hint 都会被忽略。 + +## 示例 {#examples} + +### 示例 1:临时设置时区 {#example-1-temporarily-set-timezone} + +```sql +root@localhost> SELECT TIMEZONE(); + +SELECT + TIMEZONE(); + +┌────────────┐ +│ timezone() │ +│ String │ +├────────────┤ +│ UTC │ +└────────────┘ + +1 row in 0.011 sec. Processed 1 rows, 1B (91.23 rows/s, 91B/s) + +root@localhost> SELECT /*+SET_VAR(timezone='America/Toronto') */ TIMEZONE(); + +SELECT + /*+SET_VAR(timezone='America/Toronto') */ + TIMEZONE(); + +┌─────────────────┐ +│ timezone() │ +│ String │ +├─────────────────┤ +│ America/Toronto │ +└─────────────────┘ + +1 row in 0.023 sec. Processed 1 rows, 1B (43.99 rows/s, 43B/s) + +root@localhost> SELECT TIMEZONE(); + +SELECT + TIMEZONE(); + +┌────────────┐ +│ timezone() │ +│ String │ +├────────────┤ +│ UTC │ +└────────────┘ + +1 row in 0.010 sec. Processed 1 rows, 1B (104.34 rows/s, 104B/s) +``` + +### 示例 2:控制 COPY INTO 的并行处理 {#example-2-control-parallel-processing-for-copy-into} + +在 {{{ .lake }}} 中,*max_threads* 设置指定了可用于执行请求的最大线程数。默认情况下,该值通常设置为与机器上可用的 CPU 核心数一致。 + +使用 COPY INTO 将数据加载到 {{{ .lake }}} 时,你可以通过在 COPY INTO 命令中注入 hint 并设置 *max_threads* 参数来控制并行处理能力。例如: + +```sql +COPY /*+ set_var(max_threads=6) */ INTO mytable FROM @mystage/ pattern='.*[.]parq' FILE_FORMAT=(TYPE=parquet); +``` + +### 示例 3:设置去重标签 {#example-3-set-deduplicate-label} + +```sql +CREATE TABLE t1(a Int, b bool); +INSERT /*+ SET_VAR(deduplicate_label='datalake') */ INTO t1 (a, b) VALUES(1, false); +SELECT * FROM t1; + +a|b| +-+-+ +1|0| + +UPDATE /*+ SET_VAR(deduplicate_label='datalake') */ t1 SET a = 20 WHERE b = false; +SELECT * FROM t1; + +a|b| +-+-+ +1|0| + +REPLACE /*+ SET_VAR(deduplicate_label='datalake') */ INTO t1 on(a,b) VALUES(40, false); +SELECT * FROM t1; + +a|b| +-+-+ +1|0| + +MERGE /*+ SET_VAR(deduplicate_label='datalake') */ INTO t1 using t2 on t1.a = t2.a when matched then update *; +SELECT * FROM t1; + +a|b| +-+-+ +1|0| +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/set-variable.md b/tidb-cloud-lake/sql/set-variable.md new file mode 100644 index 0000000000000..caa7ed9fde832 --- /dev/null +++ b/tidb-cloud-lake/sql/set-variable.md @@ -0,0 +1,100 @@ +--- +title: SET VARIABLE +summary: 在会话中设置一个或多个 SQL 变量的值。这些值可以是简单常量、表达式、查询结果或数据库对象。变量会在整个会话期间持续存在,并可在后续查询中使用。 +--- + +# SET VARIABLE + +在会话中设置一个或多个 SQL 变量的值。这些值可以是简单常量、表达式、查询结果或数据库对象。变量会在整个会话期间持续存在,并可在后续查询中使用。 + +## 语法 {#syntax} + +```sql +-- Set one variable +SET VARIABLE = + +-- Set more than one variable +SET VARIABLE (, , ...) = (, , ...) + +-- Set multiple variables from a query result +SET VARIABLE (, , ...) = +``` + +## 访问变量 {#accessing-variables} + +可以使用美元符号语法访问变量:`$variable_name` + +## 示例 {#examples} + +### 设置单个变量 {#setting-a-single-variable} + +```sql +-- Sets variable a to the string 'datalake' +SET VARIABLE a = 'datalake'; + +-- Access the variable +SELECT $a; +┌─────────┐ +│ $a │ +├─────────┤ +│ datalake│ +└─────────┘ +``` + +### 设置多个变量 {#setting-multiple-variables} + +```sql +-- Sets variable x to 'xx' and y to 'yy' +SET VARIABLE (x, y) = ('xx', 'yy'); + +-- Access multiple variables +SELECT $x, $y; +┌────┬────┐ +│ $x │ $y │ +├────┼────┤ +│ xx │ yy │ +└────┴────┘ +``` + +### 从查询结果设置变量 {#setting-variables-from-query-results} + +```sql +-- Sets variable a to 3 and b to 55 +SET VARIABLE (a, b) = (SELECT 3, 55); + +-- Access the variables +SELECT $a, $b; +┌────┬────┐ +│ $a │ $b │ +├────┼────┤ +│ 3 │ 55 │ +└────┴────┘ +``` + +### 动态表引用 {#dynamic-table-references} + +变量可以与 `IDENTIFIER()` 函数一起使用,以动态引用数据库对象: + +```sql +-- Create a sample table +CREATE OR REPLACE TABLE monthly_sales(empid INT, amount INT, month TEXT) AS SELECT 1, 2, '3'; + +-- Set a variable 't' to the name of the table 'monthly_sales' +SET VARIABLE t = 'monthly_sales'; + +-- Access the variable directly +SELECT $t; +┌──────────────┐ +│ $t │ +├──────────────┤ +│ monthly_sales│ +└──────────────┘ + +-- Use IDENTIFIER to dynamically reference the table name stored in the variable 't' +SELECT * FROM IDENTIFIER($t); +┌───────┬────────┬───────┐ +│ empid │ amount │ month │ +├───────┼────────┼───────┤ +│ 1 │ 2 │ 3 │ +└───────┴────────┴───────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/set.md b/tidb-cloud-lake/sql/set.md new file mode 100644 index 0000000000000..d76ca2ea4e138 --- /dev/null +++ b/tidb-cloud-lake/sql/set.md @@ -0,0 +1,45 @@ +--- +title: SET +summary: 更改当前会话的系统设置值。要显示所有当前设置,请使用 SHOW SETTINGS。 +--- + +# SET + +更改当前会话的系统设置值。要显示所有当前设置,请使用 [SHOW SETTINGS](/tidb-cloud-lake/sql/show-settings.md)。 + +另请参阅: + +- [SETTINGS 子句](/tidb-cloud-lake/sql/settings-clause.md) +- [SET_VAR](/tidb-cloud-lake/sql/set-var.md) +- [UNSET](/tidb-cloud-lake/sql/unset.md) + +## 语法 {#syntax} + +```sql +SET [ SESSION | GLOBAL ] = +``` + +| 参数 | 描述 | +|-----------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| SESSION | 在会话级别应用设置更改。如果省略,则默认在会话级别应用。 | +| GLOBAL | 在全局级别应用设置更改,而不仅限于当前会话。有关设置级别的更多信息,请参阅 [设置级别](/tidb-cloud-lake/sql/show-settings.md#setting-levels)。 | + +## 示例 {#examples} + +以下示例将 `max_memory_usage` 设置为 `4 GB`: + +```sql +SET max_memory_usage = 1024*1024*1024*4; +``` + +以下示例将 `max_threads` 设置为 `4`: + +```sql +SET max_threads = 4; +``` + +以下示例将 `max_threads` 设置为 `4`,并将其更改为全局级别设置: + +```sql +SET GLOBAL max_threads = 4; +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/settings-clause.md b/tidb-cloud-lake/sql/settings-clause.md new file mode 100644 index 0000000000000..1edf30a0a1765 --- /dev/null +++ b/tidb-cloud-lake/sql/settings-clause.md @@ -0,0 +1,116 @@ +--- +title: SETTINGS 子句 +summary: SETTINGS 子句用于配置会影响其前置 SQL 语句执行行为的特定设置。要查看 {{{ .lake }}} 中可用的设置及其值,请使用 SHOW SETTINGS。 +--- + +# SETTINGS 子句 + +SETTINGS 子句用于配置会影响其前置 SQL 语句执行行为的特定设置。要查看 {{{ .lake }}} 中可用的设置及其值,请使用 [SHOW SETTINGS](/tidb-cloud-lake/sql/show-settings.md)。 + +另请参阅:[SET](/tidb-cloud-lake/sql/set.md) + +## 语法 {#syntax} + +```sql +SETTINGS ( = [, = , ...] ) +``` + +## 支持的语句 {#supported-statements} + +SETTINGS 子句可用于以下 SQL 语句: + +- [SELECT](/tidb-cloud-lake/sql/select.md) +- [INSERT](/tidb-cloud-lake/sql/insert.md) +- [INSERT(多表)](/tidb-cloud-lake/sql/insert-multi-table.md) +- [MERGE](/tidb-cloud-lake/sql/merge.md) +- [`COPY INTO
`](/tidb-cloud-lake/sql/copy-into-table.md) +- [`COPY INTO `](/tidb-cloud-lake/sql/copy-into-location.md) +- [UPDATE](/tidb-cloud-lake/sql/update.md) +- [DELETE](/tidb-cloud-lake/sql/delete.md) +- [CREATE TABLE](/tidb-cloud-lake/sql/create-table.md) +- [EXPLAIN](/tidb-cloud-lake/sql/explain.md) + +## 示例 {#examples} + +以下示例演示了如何在 SELECT 查询中使用 SETTINGS 子句调整 timezone 参数,从而影响 `now()` 的显示结果: + +```sql +-- When no timezone is set, {{{ .lake }}} defaults to UTC, so now() returns the current UTC timestamp +SELECT timezone(), now(); + +┌─────────────────────────────────────────┐ +│ timezone() │ now() │ +│ String │ Timestamp │ +├────────────┼────────────────────────────┤ +│ UTC │ 2024-11-04 19:42:28.424925 │ +└─────────────────────────────────────────┘ + +-- By setting the timezone to Asia/Shanghai, the now() function returns the local time in Shanghai, which is 8 hours ahead of UTC. +SETTINGS (timezone = 'Asia/Shanghai') SELECT timezone(), now(); + +┌────────────────────────────────────────────┐ +│ timezone() │ now() │ +├───────────────┼────────────────────────────┤ +│ Asia/Shanghai │ 2024-11-05 03:42:42.209404 │ +└────────────────────────────────────────────┘ + +-- Setting the timezone to America/Toronto adjusts the now() output to the local time in Toronto, reflecting the Eastern Time Zone (UTC-5 or UTC-4 during daylight saving time). +SETTINGS (timezone = 'America/Toronto') SELECT timezone(), now(); + +┌──────────────────────────────────────────────┐ +│ timezone() │ now() │ +│ String │ Timestamp │ +├─────────────────┼────────────────────────────┤ +│ America/Toronto │ 2024-11-04 14:42:48.353577 │ +└──────────────────────────────────────────────┘ +``` + +以下示例演示了如何使用 date_format_style 设置在 MySQL 和 Oracle 日期格式样式之间切换: + +```sql +-- Default MySQL style date formatting +SELECT to_string('2024-04-05'::DATE, '%b'); + +┌────────────────────────────────┐ +│ to_string('2024-04-05', '%b') │ +├────────────────────────────────┤ +│ Apr │ +└────────────────────────────────┘ + +-- Oracle style date formatting +SETTINGS (date_format_style = 'Oracle') SELECT to_string('2024-04-05'::DATE, 'MON'); + +┌────────────────────────────────┐ +│ to_string('2024-04-05', 'MON') │ +├────────────────────────────────┤ +│ Apr │ +└────────────────────────────────┘ +``` + +以下示例展示了 week_start 设置如何影响与周相关的日期函数: + +```sql +-- Default week_start = 1 (Monday as first day of week) +SELECT date_trunc(WEEK, to_date('2024-04-03')); -- Wednesday + +┌────────────────────────────────────────┐ +│ date_trunc(WEEK, to_date('2024-04-03')) │ +├────────────────────────────────────────┤ +│ 2024-04-01 │ +└────────────────────────────────────────┘ + +-- Setting week_start = 0 (Sunday as first day of week) +SETTINGS (week_start = 0) SELECT date_trunc(WEEK, to_date('2024-04-03')); -- Wednesday + +┌────────────────────────────────────────┐ +│ date_trunc(WEEK, to_date('2024-04-03')) │ +├────────────────────────────────────────┤ +│ 2024-03-31 │ +└────────────────────────────────────────┘ +``` + +以下示例允许 COPY INTO 操作最多使用 100 个线程进行并行处理: + +```sql +SETTINGS (max_threads = 100) COPY INTO ... +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/sha-functions.md b/tidb-cloud-lake/sql/sha-functions.md new file mode 100644 index 0000000000000..756b7a304a613 --- /dev/null +++ b/tidb-cloud-lake/sql/sha-functions.md @@ -0,0 +1,26 @@ +--- +title: SHA2 +summary: 计算 SHA-2 系列的散列函数(SHA-224、SHA-256、SHA-384 和 SHA-512)。如果散列长度不是允许的值之一,则返回值为 NULL。否则,函数结果是一个包含所需位数的散列值,以十六进制数字字符串表示。 +--- + +# SHA2 + +计算 SHA-2 系列的散列函数(SHA-224、SHA-256、SHA-384 和 SHA-512)。如果散列长度不是允许的值之一,则返回值为 NULL。否则,函数结果是一个包含所需位数的散列值,以十六进制数字字符串表示。 + +## 语法 {#syntax} + +```sql +SHA2(, ) +``` + +## 示例 {#examples} + +```sql +SELECT SHA2('1234567890', 0); + +┌──────────────────────────────────────────────────────────────────┐ +│ sha2('1234567890', 0) │ +├──────────────────────────────────────────────────────────────────┤ +│ c775e7b757ede630cd0aa1113bd102661ab38829ca52a6422ab782862f268646 │ +└──────────────────────────────────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/sha-sql.md b/tidb-cloud-lake/sql/sha-sql.md new file mode 100644 index 0000000000000..ae6d7dbe09983 --- /dev/null +++ b/tidb-cloud-lake/sql/sha-sql.md @@ -0,0 +1,8 @@ +--- +title: SHA1 +summary: SHA 的别名。 +--- + +# SHA1 + +[SHA](/tidb-cloud-lake/sql/sha.md) 的别名。 \ No newline at end of file diff --git a/tidb-cloud-lake/sql/sha.md b/tidb-cloud-lake/sql/sha.md new file mode 100644 index 0000000000000..ca152bf3a4fd8 --- /dev/null +++ b/tidb-cloud-lake/sql/sha.md @@ -0,0 +1,30 @@ +--- +title: SHA +summary: 按照 RFC 3174(Secure Hash Algorithm)中的描述,计算字符串的 SHA-1 160 位校验和。如果参数为 NULL,则返回值为 40 个十六进制数字组成的字符串或 NULL。 +--- + +# SHA + +按照 RFC 3174(Secure Hash Algorithm)中的描述,计算字符串的 SHA-1 160 位校验和。如果参数为 NULL,则返回值为 40 个十六进制数字组成的字符串或 NULL。 + +## 语法 {#syntax} + +```sql +SHA() +``` + +## 别名 {#aliases} + +- [SHA1](/tidb-cloud-lake/sql/sha.md) + +## 示例 {#examples} + +```sql +SELECT SHA('1234567890'), SHA1('1234567890'); + +┌─────────────────────────────────────────────────────────────────────────────────────┐ +│ sha('1234567890') │ sha1('1234567890') │ +├──────────────────────────────────────────┼──────────────────────────────────────────┤ +│ 01b307acba4f54f55aafc33bb06bbbf6ca803e9a │ 01b307acba4f54f55aafc33bb06bbbf6ca803e9a │ +└─────────────────────────────────────────────────────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/show-catalogs.md b/tidb-cloud-lake/sql/show-catalogs.md new file mode 100644 index 0000000000000..ae38b442268e3 --- /dev/null +++ b/tidb-cloud-lake/sql/show-catalogs.md @@ -0,0 +1,20 @@ +--- +title: SHOW CATALOGS +summary: 列出 catalogs。 +--- + +# SHOW CATALOGS + +列出 catalogs。 + +## 语法 {#syntax} + +```sql +SHOW CATALOGS [ LIKE '' | WHERE ] +``` + +## 示例 {#example} + +```sql +SHOW CATALOGS; +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/show-columns.md b/tidb-cloud-lake/sql/show-columns.md new file mode 100644 index 0000000000000..86eaa3ab9c1d3 --- /dev/null +++ b/tidb-cloud-lake/sql/show-columns.md @@ -0,0 +1,56 @@ +--- +title: SHOW COLUMNS +summary: 显示给定表中列的信息。 +--- + +# SHOW COLUMNS + +显示给定表中列的信息。 + +> **Tip:** +> +> [DESCRIBE TABLE](/tidb-cloud-lake/sql/describe-table.md) 也可以提供表中列的类似信息,但信息较少。 + +## 语法 {#syntax} + +```sql +SHOW [ FULL ] COLUMNS + {FROM | IN} tbl_name + [ {FROM | IN} db_name ] + [ LIKE '' | WHERE ] +``` + +当包含可选关键字 FULL 时,{{{ .lake }}} 会在结果中为表中的每一列额外返回排序规则、权限和注释信息。 + +## 示例 {#examples} + +```sql +CREATE TABLE books + ( + price FLOAT Default 0.00, + pub_time DATETIME Default '1900-01-01', + author VARCHAR + ); + +SHOW COLUMNS FROM books FROM default; + +Field |Type |Null|Default |Extra|Key| +--------+---------+----+------------+-----+---+ +author |VARCHAR |NO | | | | +price |FLOAT |NO |0.00 | | | +pub_time|TIMESTAMP|NO |'1900-01-01'| | | + +SHOW FULL COLUMNS FROM books; + +Field |Type |Null|Default |Extra|Key|Collation|Privileges|Comment| +--------+---------+----+------------+-----+---+---------+----------+-------+ +author |VARCHAR |NO | | | | | | | +price |FLOAT |NO |0.00 | | | | | | +pub_time|TIMESTAMP|NO |'1900-01-01'| | | | | | + +SHOW FULL COLUMNS FROM books LIKE 'a%' + +Field |Type |Null|Default|Extra|Key|Collation|Privileges|Comment| +------+-------+----+-------+-----+---+---------+----------+-------+ +author|VARCHAR|NO | | | | | | | +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/show-connections.md b/tidb-cloud-lake/sql/show-connections.md new file mode 100644 index 0000000000000..0cb506956daea --- /dev/null +++ b/tidb-cloud-lake/sql/show-connections.md @@ -0,0 +1,26 @@ +--- +title: SHOW CONNECTIONS +summary: 显示所有可用连接的列表。 +--- + +# SHOW CONNECTIONS + +显示所有可用连接的列表。 + +## 语法 {#syntax} + +```sql +SHOW CONNECTIONS +``` + +## 示例 {#examples} + +```sql +SHOW CONNECTIONS; + +┌────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ +│ name │ storage_type │ storage_params │ +├─────────┼──────────────┼───────────────────────────────────────────────────────────────────────────────────┤ +│ toronto │ s3 │ access_key_id= secret_access_key= │ +└────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/show-create-catalog.md b/tidb-cloud-lake/sql/show-create-catalog.md new file mode 100644 index 0000000000000..dac6c4e8879dd --- /dev/null +++ b/tidb-cloud-lake/sql/show-create-catalog.md @@ -0,0 +1,14 @@ +--- +title: SHOW CREATE CATALOG +summary: 显示 catalog 定义信息。 +--- + +# SHOW CREATE CATALOG + +显示 catalog 定义信息。 + +## 语法 {#syntax} + +```sql +SHOW CREATE CATALOG +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/show-create-database.md b/tidb-cloud-lake/sql/show-create-database.md new file mode 100644 index 0000000000000..51d3177bdb748 --- /dev/null +++ b/tidb-cloud-lake/sql/show-create-database.md @@ -0,0 +1,25 @@ +--- +title: SHOW CREATE DATABASE +summary: 显示用于创建指定数据库的 CREATE DATABASE 语句。 +--- + +# SHOW CREATE DATABASE + +显示用于创建指定数据库的 CREATE DATABASE 语句。 + +## 语法 {#syntax} + +```sql +SHOW CREATE DATABASE database_name +``` + +## 示例 {#examples} + +```sql +SHOW CREATE DATABASE default; ++----------+---------------------------+ +| Database | Create Database | ++----------+---------------------------+ +| default | CREATE DATABASE `default` | ++----------+---------------------------+ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/show-create-dictionary.md b/tidb-cloud-lake/sql/show-create-dictionary.md new file mode 100644 index 0000000000000..306ddf3474b51 --- /dev/null +++ b/tidb-cloud-lake/sql/show-create-dictionary.md @@ -0,0 +1,63 @@ +--- +title: SHOW CREATE DICTIONARY +summary: 显示用于创建字典的 SQL 语句。 +--- + +# SHOW CREATE DICTIONARY + +显示用于创建字典的 SQL 语句。 + +## 语法 {#syntax} + +```sql +SHOW CREATE DICTIONARY [ . ][ . ] +``` + +## 参数 {#parameters} + +| 参数 | 描述 | +|-----------|-------------| +| `` | 字典名称。你可以使用 catalog 名称和 database 名称对其进行限定。 | + +## 输出 {#output} + +结果包含字典名称以及重建后的 `CREATE DICTIONARY` 语句。 + +返回的 SQL 中会对敏感的源选项(例如 `password`)进行掩码处理。 + +## 示例 {#examples} + +```sql +CREATE DICTIONARY user_info +( + user_id UInt64, + user_name String, + user_email String +) +PRIMARY KEY user_id +SOURCE( + mysql( + host = '127.0.0.1' + port = '3306' + username = 'root' + password = 'root' + db = 'app' + table = 'users' + ) +) +COMMENT 'User dictionary from MySQL'; + +SHOW CREATE DICTIONARY user_info; + +*************************** 1. row *************************** + Dictionary: user_info +Create Dictionary: CREATE DICTIONARY user_info +( + user_id BIGINT UNSIGNED NULL, + user_name VARCHAR NULL, + user_email VARCHAR NULL +) +PRIMARY KEY user_id +SOURCE(mysql(db='app' host='127.0.0.1' password='[HIDDEN]' port='3306' table='users' username='root')) +COMMENT 'User dictionary from MySQL' +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/show-create-table.md b/tidb-cloud-lake/sql/show-create-table.md new file mode 100644 index 0000000000000..8038fb5801613 --- /dev/null +++ b/tidb-cloud-lake/sql/show-create-table.md @@ -0,0 +1,40 @@ +--- +title: SHOW CREATE TABLE +summary: 显示指定表的 CREATE TABLE 语句。要在结果中包含 Fuse Engine 选项,请将 hide_options_in_show_create_table 设置为 0。 +--- + +# SHOW CREATE TABLE + +显示指定表的 CREATE TABLE 语句。要在结果中包含 Fuse Engine 选项,请将 `hide_options_in_show_create_table` 设置为 `0`。 + +## 语法 {#syntax} + +```sql +SHOW CREATE TABLE [ . ] +``` + +## 示例 {#examples} + +以下示例展示了如何通过将 `hide_options_in_show_create_table` 设置为 `0` 来显示完整的 CREATE TABLE 语句,包括 Fuse Engine 选项: + +```sql +CREATE TABLE fuse_table (a int); + +SHOW CREATE TABLE fuse_table; + +-[ RECORD 1 ]----------------------------------- + Table: fuse_table +Create Table: CREATE TABLE fuse_table ( + a INT NULL +) ENGINE=FUSE + +SET hide_options_in_show_create_table=0; + +SHOW CREATE TABLE fuse_table; + +-[ RECORD 1 ]----------------------------------- + Table: fuse_table +Create Table: CREATE TABLE fuse_table ( + a INT NULL +) ENGINE=FUSE COMPRESSION='lz4' DATA_RETENTION_PERIOD_IN_HOURS='240' STORAGE_FORMAT='native' +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/show-databases.md b/tidb-cloud-lake/sql/show-databases.md new file mode 100644 index 0000000000000..7048c01221fc2 --- /dev/null +++ b/tidb-cloud-lake/sql/show-databases.md @@ -0,0 +1,53 @@ +--- +title: SHOW DATABASES +summary: 显示实例中存在的数据库列表。 +--- + +# SHOW DATABASES + +显示实例中存在的数据库列表。 + +另请参阅:[system.databases](/tidb-cloud-lake/sql/system-databases.md) + +## 语法 {#syntax} + +```sql +SHOW [ FULL ] DATABASES + [ LIKE '' | WHERE ] +``` + +| 参数 | 描述 | +|-----------|-----------------------------------------------------------------------------------------------------------------------------| +| FULL | 列出包含附加信息的结果。更多详情请参阅[示例](#examples)。 | +| LIKE | 使用大小写敏感的模式匹配按名称过滤结果。 | +| WHERE | 使用 WHERE 子句中的表达式过滤结果。 | + +## 示例 {#examples} + +```sql +SHOW DATABASES; + +┌──────────────────────┐ +│ databases_in_default │ +├──────────────────────┤ +│ canada │ +│ china │ +│ default │ +│ information_schema │ +│ system │ +│ test │ +└──────────────────────┘ + +SHOW FULL DATABASES; + +┌───────────────────────────────────────────────────┐ +│ catalog │ owner │ databases_in_default │ +├─────────┼──────────────────┼──────────────────────┤ +│ default │ account_admin │ canada │ +│ default │ account_admin │ china │ +│ default │ NULL │ default │ +│ default │ NULL │ information_schema │ +│ default │ NULL │ system │ +│ default │ account_admin │ test │ +└───────────────────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/show-dictionaries.md b/tidb-cloud-lake/sql/show-dictionaries.md new file mode 100644 index 0000000000000..7d099d3360f31 --- /dev/null +++ b/tidb-cloud-lake/sql/show-dictionaries.md @@ -0,0 +1,71 @@ +--- +title: SHOW DICTIONARIES +summary: 列出当前或指定数据库中的字典。 +--- + +# SHOW DICTIONARIES + +列出当前或指定数据库中的字典。 + +## 语法 {#syntax} + +```sql +SHOW DICTIONARIES [ FROM | IN ] + [ LIMIT ] + [ LIKE '' | WHERE ] +``` + +## 参数 {#parameters} + +| 参数 | 描述 | +|-----------|-------------| +| `FROM ` / `IN ` | 可选。列出指定数据库中的字典。 | +| `LIMIT ` | 可选。限制返回的行数。 | +| `LIKE ''` | 可选。按模式过滤字典名称。 | +| `WHERE ` | 可选。使用表达式过滤结果集。 | + +## 示例 {#examples} + +```sql +CREATE DICTIONARY user_info +( + user_id UInt64, + user_name String, + user_email String +) +PRIMARY KEY user_id +SOURCE( + mysql( + host = '127.0.0.1' + port = '3306' + username = 'root' + password = 'root' + db = 'app' + table = 'users' + ) +) +COMMENT 'User dictionary from MySQL'; + +CREATE DICTIONARY cache +( + key String, + value String +) +PRIMARY KEY key +SOURCE( + redis( + host = '127.0.0.1' + port = '6379' + ) +) +COMMENT 'cache dictionary from Redis'; + +SHOW DICTIONARIES; +╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ +│ database │ dictionary │ key_names │ key_types │ attribute_names │ attribute_types │ source │ comment │ +│ String │ String │ Array(String) │ Array(String) │ Array(String) │ Array(String) │ String │ String │ +├──────────┼────────────┼───────────────┼──────────────────────────┼────────────────────────────┼─────────────────────────────────┼─────────────────────────────────────────────────────────────────────────────────────────┼─────────────────────────────┤ +│ default │ cache │ ["key"] │ ["VARCHAR NULL"] │ ["value"] │ ["VARCHAR NULL"] │ redis(host=127.0.0.1 port=6379) │ cache dictionary from Redis │ +│ default │ user_info │ ["user_id"] │ ["BIGINT UNSIGNED NULL"] │ ["user_name","user_email"] │ ["VARCHAR NULL","VARCHAR NULL"] │ mysql(db=app host=127.0.0.1 password=[hidden] port=3306 table=users username=root) │ User dictionary from MySQL │ +╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/show-drop-databases.md b/tidb-cloud-lake/sql/show-drop-databases.md new file mode 100644 index 0000000000000..940f293857a1d --- /dev/null +++ b/tidb-cloud-lake/sql/show-drop-databases.md @@ -0,0 +1,44 @@ +--- +title: SHOW DROP DATABASES +summary: 列出所有数据库;如果数据库已被删除,则同时显示其删除时间戳,便于用户查看已删除的数据库及其详细信息。 +--- + +# SHOW DROP DATABASES + +列出所有数据库;如果数据库已被删除,则同时显示其删除时间戳,便于用户查看已删除的数据库及其详细信息。 + +- 只有仍处于数据保留时间内的已删除数据库才能被找回。 +- 建议使用管理员用户,例如 `root`。如果你使用的是 {{{ .lake }}},请使用具有 `account_admin` 角色的用户来查询已删除的数据库。 + +另请参阅:[system.databases_with_history](/tidb-cloud-lake/sql/system-databases-with-history.md) + +## 语法 {#syntax} + +```sql +SHOW DROP DATABASES + [ FROM ] + [ LIKE '' | WHERE ] +``` + +## 示例 {#examples} + +```sql +-- Create a new database named my_db +CREATE DATABASE my_db; + +-- Drop the database my_db +DROP DATABASE my_db; + +-- If a database has been dropped, dropped_on shows the deletion time; +-- If it is still active, dropped_on is NULL. +SHOW DROP DATABASES; + +┌─────────────────────────────────────────────────────────────────────────────────┐ +│ catalog │ name │ database_id │ dropped_on │ +├─────────┼────────────────────┼─────────────────────┼────────────────────────────┤ +│ default │ default │ 1 │ NULL │ +│ default │ information_schema │ 4611686018427387906 │ NULL │ +│ default │ my_db │ 114 │ 2024-11-15 02:44:46.207120 │ +│ default │ system │ 4611686018427387905 │ NULL │ +└─────────────────────────────────────────────────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/show-drop-tables.md b/tidb-cloud-lake/sql/show-drop-tables.md new file mode 100644 index 0000000000000..4aab8785905cc --- /dev/null +++ b/tidb-cloud-lake/sql/show-drop-tables.md @@ -0,0 +1,42 @@ +--- +title: SHOW DROP TABLES +summary: 列出当前或指定数据库中已删除的表。 +--- + +# SHOW DROP TABLES + +列出当前或指定数据库中已删除的表。 + +另请参阅:[system.tables_with_history](/tidb-cloud-lake/sql/system-tables-with-history.md) + +## 语法 {#syntax} + +```sql +SHOW DROP TABLES [ FROM ] [ LIKE '' | WHERE ] +``` + +## 示例 {#examples} + +```sql +USE database1; + +-- List dropped tables in the current database +SHOW DROP TABLES; + +-- List dropped tables in the "default" database +SHOW DROP TABLES FROM default; + +Name |Value | +--------------------+-----------------------------+ +tables |t1 | +table_type |BASE TABLE | +database |default | +catalog |default | +engine |FUSE | +create_time |2023-06-13 08:43:36.556 +0000| +drop_time |2023-07-19 04:39:18.536 +0000| +num_rows |2 | +data_size |34 | +data_compressed_size|330 | +index_size |464 | +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/show-fields.md b/tidb-cloud-lake/sql/show-fields.md new file mode 100644 index 0000000000000..c7a9922576c86 --- /dev/null +++ b/tidb-cloud-lake/sql/show-fields.md @@ -0,0 +1,37 @@ +--- +title: SHOW FIELDS +summary: 显示给定表中各列的信息。等同于 DESCRIBE TABLE。 +--- + +# SHOW FIELDS + +显示给定表中各列的信息。等同于 [DESCRIBE TABLE](/tidb-cloud-lake/sql/describe-table.md)。 + +> **Tip:** +> +> [SHOW COLUMNS](/tidb-cloud-lake/sql/show-columns.md) 提供与之类似但更详细的表列信息。 + +## 语法 {#syntax} + +```sql +SHOW FIELDS FROM [ . ] +``` + +## 示例 {#examples} + +```sql +CREATE TABLE books + ( + price FLOAT Default 0.00, + pub_time DATETIME Default '1900-01-01', + author VARCHAR + ); + +SHOW FIELDS FROM books; + +Field |Type |Null|Default |Extra| +--------+---------+----+----------------------------+-----+ +price |FLOAT |YES |0 | | +pub_time|TIMESTAMP|YES |'1900-01-01 00:00:00.000000'| | +author |VARCHAR |YES |NULL | | +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/show-file-formats.md b/tidb-cloud-lake/sql/show-file-formats.md new file mode 100644 index 0000000000000..d167c1404d86c --- /dev/null +++ b/tidb-cloud-lake/sql/show-file-formats.md @@ -0,0 +1,26 @@ +--- +title: SHOW FILE FORMATS +summary: 返回已创建的文件格式列表。 +--- + +# SHOW FILE FORMATS + +返回已创建的文件格式列表。 + +## 语法 {#syntax} + +```sql +SHOW FILE FORMATS; +``` + +## 示例 {#examples} + +```sql +SHOW FILE FORMATS; + ++---------------+------------------------------------------------------------------------------------------------------------------------+ +| name | format_options | ++---------------+------------------------------------------------------------------------------------------------------------------------+ +| my_custom_csv | TYPE = CSV FIELD_DELIMITER = '\t' RECORD_DELIMITER = '\n' QUOTE = '\"' ESCAPE = '' SKIP_HEADER = 0 NAN_DISPLAY = 'NaN' | ++---------------+------------------------------------------------------------------------------------------------------------------------+ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/show-functions.md b/tidb-cloud-lake/sql/show-functions.md new file mode 100644 index 0000000000000..6b0c0edb26db0 --- /dev/null +++ b/tidb-cloud-lake/sql/show-functions.md @@ -0,0 +1,67 @@ +--- +title: SHOW FUNCTIONS +summary: 列出当前支持的内置标量函数和聚合函数。 +--- + +# SHOW FUNCTIONS + +列出当前支持的内置标量函数和聚合函数。 + +另请参阅:[system.functions](/tidb-cloud-lake/sql/system-functions.md) + +## 语法 {#syntax} + +```sql +SHOW FUNCTIONS [LIKE '' | WHERE ] | [LIMIT ] +``` + +## 示例 {#example} + +```sql +SHOW FUNCTIONS; + ++-------------------------+--------------+---------------------------+ +| name | is_aggregate | description | ++-------------------------+--------------+---------------------------+ +| != | 0 | | +| % | 0 | | +| * | 0 | | +| + | 0 | | +| - | 0 | | +| / | 0 | | +| < | 0 | | +| <= | 0 | | +| <> | 0 | | +| = | 0 | | ++-------------------------+--------------+---------------------------+ +``` + +显示以 `"today"` 开头的函数: + +```sql +SHOW FUNCTIONS LIKE 'today%'; + ++--------------+--------------+-------------+ +| name | is_aggregate | description | ++--------------+--------------+-------------+ +| today | 0 | | +| todayofmonth | 0 | | +| todayofweek | 0 | | +| todayofyear | 0 | | ++--------------+--------------+-------------+ +``` + +使用 `WHERE` 显示以 `"today"` 开头的函数: + +```sql +SHOW FUNCTIONS WHERE name LIKE 'today%'; + ++--------------+--------------+-------------+ +| name | is_aggregate | description | ++--------------+--------------+-------------+ +| today | 0 | | +| todayofmonth | 0 | | +| todayofweek | 0 | | +| todayofyear | 0 | | ++--------------+--------------+-------------+ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/show-grants-sql.md b/tidb-cloud-lake/sql/show-grants-sql.md new file mode 100644 index 0000000000000..58f8c594e9cbf --- /dev/null +++ b/tidb-cloud-lake/sql/show-grants-sql.md @@ -0,0 +1,138 @@ +--- +title: SHOW_GRANTS +summary: 列出授予角色的权限、授予用户的角色分配,或特定对象上的权限。 +--- + +# SHOW_GRANTS + +列出授予角色的权限、授予用户的角色分配,或特定对象上的权限。 + +另请参阅:[SHOW GRANTS](/tidb-cloud-lake/sql/show-grants.md) + +## 语法 {#syntax} + +```sql +SHOW_GRANTS('role', '') +SHOW_GRANTS('user', '') +SHOW_GRANTS('stage', '') +SHOW_GRANTS('udf', '') +SHOW_GRANTS('table', '', '', '') +SHOW_GRANTS('database', '', '') +``` + +## 配置 `enable_expand_roles` 设置 {#configuring-enable-expand-roles-setting} + +`enable_expand_roles` 设置用于控制 SHOW_GRANTS 函数在显示权限时是否展开角色继承。 + +- `enable_expand_roles=1`(默认): + + - SHOW_GRANTS 会递归展开继承的权限,这意味着如果某个角色被授予了另一个角色,它将显示所有继承而来的权限。 + - 用户还会看到通过其已分配角色授予的所有权限。 + +- `enable_expand_roles=0`: + + - SHOW_GRANTS 仅显示直接分配给指定角色或用户的权限。 + - 不过,结果仍会包含 GRANT ROLE 语句,以表明角色继承关系。 + +例如,角色 `a` 在 `t1` 上具有 `SELECT` 权限,角色 `b` 在 `t2` 上具有 `SELECT` 权限: + +```sql +SELECT grants FROM show_grants('role', 'a') ORDER BY object_id; + +┌──────────────────────────────────────────────────────┐ +│ grants │ +├──────────────────────────────────────────────────────┤ +│ GRANT SELECT ON 'default'.'default'.'t1' TO ROLE `a` │ +└──────────────────────────────────────────────────────┘ + +SELECT grants FROM show_grants('role', 'b') ORDER BY object_id; + +┌──────────────────────────────────────────────────────┐ +│ grants │ +├──────────────────────────────────────────────────────┤ +│ GRANT SELECT ON 'default'.'default'.'t2' TO ROLE `b` │ +└──────────────────────────────────────────────────────┘ +``` + +如果你将角色 `b` 授予角色 `a`,然后再次查看角色 `a` 的授权信息,就可以看到 `t2` 上的 `SELECT` 权限现在也包含在角色 `a` 中: + +```sql +GRANT ROLE b TO ROLE a; +``` + +```sql +SELECT grants FROM show_grants('role', 'a') ORDER BY object_id; + +┌──────────────────────────────────────────────────────┐ +│ grants │ +├──────────────────────────────────────────────────────┤ +│ GRANT SELECT ON 'default'.'default'.'t1' TO ROLE `a` │ +│ GRANT SELECT ON 'default'.'default'.'t2' TO ROLE `a` │ +└──────────────────────────────────────────────────────┘ +``` + +如果你将 `enable_expand_roles` 设置为 `0`,然后再次查看角色 `a` 的授权信息,结果将显示 `GRANT ROLE` 语句,而不是列出从角色 `b` 继承的具体权限: + +```sql +SET enable_expand_roles=0; +``` + +```sql +SELECT grants FROM show_grants('role', 'a') ORDER BY object_id; + +┌──────────────────────────────────────────────────────┐ +│ grants │ +├──────────────────────────────────────────────────────┤ +│ GRANT SELECT ON 'default'.'default'.'t1' TO ROLE `a` │ +│ GRANT ROLE b to ROLE `a` │ +│ GRANT ROLE public to ROLE `a` │ +└──────────────────────────────────────────────────────┘ +``` + +## 示例 {#examples} + +本示例说明如何列出用户的授权信息、授予角色的权限,以及特定对象上的权限。 + +```sql +-- Create a new user +CREATE USER 'user1' IDENTIFIED BY 'password'; + +-- Create a new role +CREATE ROLE analyst; + +-- Grant the analyst role to the user +GRANT ROLE analyst TO 'user1'; + +-- Create a stage +CREATE STAGE my_stage; + +-- Grant privileges on the stage to the role +GRANT READ ON STAGE my_stage TO ROLE analyst; + +-- List grants for the user +SELECT * FROM SHOW_GRANTS('user', 'user1'); + +┌───────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ +│ privileges │ object_name │ object_id │ grant_to │ name │ grants │ +├────────────┼─────────────┼──────────────────┼──────────┼────────┼─────────────────────────────────────────────┤ +│ Read │ my_stage │ NULL │ USER │ user1 │ GRANT Read ON STAGE my_stage TO 'user1'@'%' │ +└───────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ + +-- List privileges granted to the role +SELECT * FROM SHOW_GRANTS('role', 'analyst'); + +┌───────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ +│ privileges │ object_name │ object_id │ grant_to │ name │ grants │ +├────────────┼─────────────┼──────────────────┼──────────┼─────────┼────────────────────────────────────────────────┤ +│ Read │ my_stage │ NULL │ ROLE │ analyst │ GRANT Read ON STAGE my_stage TO ROLE `analyst` │ +└───────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ + +-- List privileges granted on the stage +SELECT * FROM SHOW_GRANTS('stage', 'my_stage'); + +┌─────────────────────────────────────────────────────────────────────────────────────┐ +│ privileges │ object_name │ object_id │ grant_to │ name │ grants │ +├────────────┼─────────────┼──────────────────┼──────────┼─────────┼──────────────────┤ +│ Read │ my_stage │ NULL │ ROLE │ analyst │ │ +└─────────────────────────────────────────────────────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/show-grants.md b/tidb-cloud-lake/sql/show-grants.md new file mode 100644 index 0000000000000..de314b449ab87 --- /dev/null +++ b/tidb-cloud-lake/sql/show-grants.md @@ -0,0 +1,95 @@ +--- +title: SHOW GRANTS +summary: 列出授予角色的权限、授予用户的角色分配,或特定对象上的权限。 +--- + +# SHOW GRANTS + +列出授予角色的权限、授予用户的角色分配,或特定对象上的权限。 + +另请参阅: + +- [SHOW_GRANTS](/tidb-cloud-lake/sql/show-grants.md) +- [GRANT](/tidb-cloud-lake/sql/grant.md) +- [REVOKE](/tidb-cloud-lake/sql/revoke.md) + +## 语法 {#syntax} + +```sql +-- List grants for a user +SHOW GRANTS FOR [ LIKE '' | WHERE | LIMIT ] + +-- List privileges granted to a role +SHOW GRANTS FOR ROLE [ LIKE '' | WHERE | LIMIT ] + +-- List privileges granted on an object +SHOW GRANTS ON { STAGE | TABLE | DATABASE | UDF | MASKING POLICY | ROW ACCESS POLICY } [ LIKE '' | WHERE | LIMIT ] + +-- Lists all users and roles that have been directly granted role_name. +SHOW GRANTS OF ROLE + +``` + +## 示例 {#examples} + +以下示例展示了如何列出用户的授权、授予角色的权限,以及特定对象上的权限。 + +```sql +-- Create a new user +CREATE USER 'user1' IDENTIFIED BY 'password'; + +-- Create a new role +CREATE ROLE analyst; + +-- Grant the analyst role to the user +GRANT ROLE analyst TO 'user1'; + +-- Create a database +CREATE DATABASE my_db; + +-- Grant privileges on the database to the role +GRANT OWNERSHIP ON my_db.* TO ROLE analyst; + +-- List privileges granted to the user +SHOW GRANTS FOR user1; + +┌────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ +│ privileges │ object_name │ object_id │ grant_to │ name │ grants │ +├────────────┼─────────────┼──────────────────┼──────────┼────────┼──────────────────────────────────────────────────────┤ +│ ROLE │ NULL │ NULL │ USER │ user1 │ GRANT ROLE analyst TO 'user1'@'%' │ +└────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ + +-- List privileges granted to the role +SHOW GRANTS FOR ROLE analyst; + +┌─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ +│ privileges │ object_name │ object_id │ grant_to │ name │ grants │ +├────────────┼─────────────┼──────────────────┼──────────┼─────────┼──────────────────────────────────────────────────────────┤ +│ OWNERSHIP │ my_db │ 16 │ ROLE │ analyst │ GRANT OWNERSHIP ON 'default'.'my_db'.* TO ROLE `analyst` │ +└─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ +-- List privileges granted on the database +SHOW GRANTS ON DATABASE my_db; + +┌─────────────────────────────────────────────────────────────────────────────────────┐ +│ privileges │ object_name │ object_id │ grant_to │ name │ grants ├────────────┼─────────────┼──────────────────┼──────────┼─────────┼──────────────────┤ +│ OWNERSHIP │ my_db │ 16 │ ROLE │ analyst │ │ +└─────────────────────────────────────────────────────────────────────────────────────┘ + +-- Lists all users and roles that have been directly granted role_name. +-- This command displays only the direct grantees of role_name. +-- This means it lists users and roles that have explicitly received the role through a GRANT ROLE role_name TO statement. +-- It does not show users or roles that acquire role_name indirectly via role hierarchies or inheritance. +SHOW GRANTS OF ROLE analyst + +╭─────────────────────────────────────╮ +│ role │ granted_to │ grantee_name │ +│ String │ String │ String │ +├─────────┼────────────┼──────────────┤ +│ analyst │ USER │ user1 │ +╰─────────────────────────────────────╯ + +SHOW GRANTS ON MASKING POLICY email_mask; + +-- Inspect row access policy privileges +SHOW GRANTS ON ROW ACCESS POLICY rap_region; +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/show-indexes.md b/tidb-cloud-lake/sql/show-indexes.md new file mode 100644 index 0000000000000..06f4b457eb1f5 --- /dev/null +++ b/tidb-cloud-lake/sql/show-indexes.md @@ -0,0 +1,32 @@ +--- +title: SHOW INDEXES +summary: 显示已创建的索引。等价于 SELECT * FROM system.indexes。 +--- + +# SHOW INDEXES + +显示已创建的索引。等价于 `SELECT * FROM system.indexes`。 + +另请参阅:[system.indexes](/tidb-cloud-lake/sql/system-indexes.md) + +## 语法 {#syntax} + +```sql +SHOW INDEXES [LIKE '' | WHERE ] | [LIMIT ] +``` + +## 示例 {#example} + +```sql +CREATE TABLE t1(a int,b int); + +CREATE AGGREGATING INDEX agg_idx AS SELECT avg(a), abs(sum(b)), abs(b) AS bs FROM t1 GROUP BY bs; + +SHOW INDEXES; + +┌──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ +│ name │ type │ original │ definition │ created_on │ updated_on │ +├─────────┼─────────────┼──────────────────────────────────────────────────────────────────────┼────────────────────────────────────────────────────────────────────────────────────┼────────────────────────────┼─────────────────────┤ +│ agg_idx │ AGGREGATING │ SELECT avg(a), abs(sum(b)), abs(b) AS bs FROM default.t1 GROUP BY bs │ SELECT abs(b) AS bs, COUNT(), COUNT(a), SUM(a), SUM(b) FROM default.t1 GROUP BY bs │ 2024-01-29 07:15:34.856234 │ NULL │ +└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/show-locks.md b/tidb-cloud-lake/sql/show-locks.md new file mode 100644 index 0000000000000..e958c4f5c7526 --- /dev/null +++ b/tidb-cloud-lake/sql/show-locks.md @@ -0,0 +1,64 @@ +--- +title: SHOW LOCKS +summary: 提供当前正在持有表锁的活跃事务列表,可以显示当前用户在其所有会话中的锁,或 {{{ .lake }}} 系统内所有用户的锁。锁是一种同步机制,用于限制对共享资源(如表)的访问,确保 {{{ .lake }}} 系统中的进程或线程之间以有序且受控的方式进行交互,从而维护数据一致性并防止冲突。 +--- + +# SHOW LOCKS + +提供当前正在持有表锁的活跃事务列表,可以显示当前用户在其所有会话中的锁,或 {{{ .lake }}} 系统内所有用户的锁。锁是一种同步机制,用于限制对共享资源(如表)的访问,确保 {{{ .lake }}} 系统中的进程或线程之间以有序且受控的方式进行交互,从而维护数据一致性并防止冲突。 + +[UPDATE](/tidb-cloud-lake/sql/update.md)、[DELETE](/tidb-cloud-lake/sql/delete.md)、[OPTIMIZE TABLE](/tidb-cloud-lake/sql/optimize-table.md)、[RECLUSTER TABLE](/tidb-cloud-lake/sql/recluster-table.md) 和 [ALTER TABLE](/tidb-cloud-lake/sql/alter-table.md#column-operations) 等操作都可能导致系统中出现表锁。表锁功能默认启用。发生资源冲突时,你可以使用该命令查看具体详情。若要禁用此功能,请执行 `set enable_table_lock=0;`。 + +## 语法 {#syntax} + +```sql +SHOW LOCKS [IN ACCOUNT] [WHERE ] +``` + +| 参数 | 描述 | +|------------|-----------------------------------------------------------------------------------------------------------------------------------------------------| +| IN ACCOUNT | 显示 {{{ .lake }}} 系统内所有用户的锁信息。如果省略该选项,则命令返回当前用户在所有会话中的锁。 | +| WHERE | 根据状态筛选锁;有效值包括 `HOLDING` 和 `WAITING`。 | + +## 输出 {#output} + +该命令以表格形式返回锁信息,包含以下列: + +| 列 | 描述 | +|-------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| table_id | 与该锁关联的表的内部 ID。 | +| revision | 表示发起该锁的事务版本的修订号。从 0 开始,该数字会随着后续每个事务递增,从而在所有事务之间建立完整的顺序。 | +| type | 锁的类型,例如 `TABLE`。 | +| status | 锁的状态,例如 `HOLDING` 或 `WAITING`。 | +| user | 与该锁关联的用户。 | +| node | 持有该锁的查询节点标识符。 | +| query_id | 与该锁相关的查询会话 ID。在发生死锁或锁持有时间过长时,可使用它来 [KILL](/tidb-cloud-lake/sql/kill.md) 查询。 | +| created_on | 发起该锁的事务创建时的时间戳。 | +| acquired_on | 获取该锁时的时间戳。 | +| extra_info | 与该锁相关的附加信息(如果有)。 | + +## 示例 {#examples} + +```sql +SHOW LOCKS IN ACCOUNT; ++----------+----------+-------+---------+------+------------------------+--------------------------------------+----------------------------+----------------------------+------------+ +| table_id | revision | type | status | user | node | query_id | created_on | acquired_on | extra_info | ++----------+----------+-------+---------+------+------------------------+--------------------------------------+----------------------------+----------------------------+------------+ +| 57 | 4517 | TABLE | HOLDING | root | xzi6pRbLUYasuA9QFB36m6 | d7989971-d5ec-4764-8e37-afe38ebc13e2 | 2023-12-13 09:56:47.295684 | 2023-12-13 09:56:47.310805 | | ++----------+----------+-------+---------+------+------------------------+--------------------------------------+----------------------------+----------------------------+------------+ + +SHOW LOCKS; ++----------+----------+-------+---------+------+------------------------+--------------------------------------+----------------------------+----------------------------+------------+ +| table_id | revision | type | status | user | node | query_id | created_on | acquired_on | extra_info | ++----------+----------+-------+---------+------+------------------------+--------------------------------------+----------------------------+----------------------------+------------+ +| 57 | 4517 | TABLE | HOLDING | root | xzi6pRbLUYasuA9QFB36m6 | d7989971-d5ec-4764-8e37-afe38ebc13e2 | 2023-12-13 09:56:47.295684 | 2023-12-13 09:56:47.310805 | | +| 57 | 4521 | TABLE | WAITING | zzq | xzi6pRbLUYasuA9QFB36m6 | 4bc78044-d4fc-4fe1-a5c5-ff6ab1e3e372 | 2023-12-13 09:56:48.419774 | NULL | | ++----------+----------+-------+---------+------+------------------------+--------------------------------------+----------------------------+----------------------------+------------+ + +SHOW LOCKS WHERE STATUS = 'HOLDING'; ++----------+----------+-------+---------+------+------------------------+--------------------------------------+----------------------------+----------------------------+------------+ +| table_id | revision | type | status | user | node | query_id | created_on | acquired_on | extra_info | ++----------+----------+-------+---------+------+------------------------+--------------------------------------+----------------------------+----------------------------+------------+ +| 57 | 4517 | TABLE | HOLDING | root | xzi6pRbLUYasuA9QFB36m6 | d7989971-d5ec-4764-8e37-afe38ebc13e2 | 2023-12-13 09:56:47.295684 | 2023-12-13 09:56:47.310805 | | ++----------+----------+-------+---------+------+------------------------+--------------------------------------+----------------------------+----------------------------+------------+ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/show-metrics.md b/tidb-cloud-lake/sql/show-metrics.md new file mode 100644 index 0000000000000..1e573b046792d --- /dev/null +++ b/tidb-cloud-lake/sql/show-metrics.md @@ -0,0 +1,31 @@ +--- +title: SHOW METRICS +summary: 显示系统指标列表。 +--- + +# SHOW METRICS + +显示[系统指标](/tidb-cloud-lake/sql/system-metrics.md)列表。 + +## 语法 {#syntax} + +```sql +SHOW METRICS [LIKE '' | WHERE ] | [LIMIT ] +``` + +## 示例 {#examples} + +```sql +SHOW METRICS; ++-----------------------------------+---------+--------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| metric | kind | labels | value | ++-----------------------------------+---------+--------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| session_connect_numbers | counter | {} | 1.0 | +| optimizer_optimize_usedtime_sum | untyped | {} | 0.000438079 | +| optimizer_optimize_usedtime_count | untyped | {} | 1.0 | +| parser_parse_usedtime_sum | untyped | {} | 0.000254307 | +| parser_parse_usedtime_count | untyped | {} | 2.0 | +| optimizer_optimize_usedtime | summary | {} | [{"quantile":0.0,"count":0.000438079},{"quantile":0.5,"count":0.000438079},{"quantile":0.9,"count":0.000438079},{"quantile":0.95,"count":0.000438079},{"quantile":0.99,"count":0.000438079},{"quantile":0.999,"count":0.000438079},{"quantile":1.0,"count":0.000438079}] | +| parser_parse_usedtime | summary | {} | [{"quantile":0.0,"count":0.000107972},{"quantile":0.5,"count":0.000107972},{"quantile":0.9,"count":0.000107972},{"quantile":0.95,"count":0.000107972},{"quantile":0.99,"count":0.000107972},{"quantile":0.999,"count":0.000107972},{"quantile":1.0,"count":0.000107972}] | ++-----------------------------------+---------+--------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/show-network-policies.md b/tidb-cloud-lake/sql/show-network-policies.md new file mode 100644 index 0000000000000..c38587d926861 --- /dev/null +++ b/tidb-cloud-lake/sql/show-network-policies.md @@ -0,0 +1,25 @@ +--- +title: SHOW NETWORK POLICIES +summary: 显示 {{{ .lake }}} 中所有现有网络策略的列表。它会提供可用网络策略的信息,包括其名称,以及是否配置了允许或阻止的 IP 地址列表。 +--- + +# SHOW NETWORK POLICIES + +显示 {{{ .lake }}} 中所有现有网络策略的列表。它会提供可用网络策略的信息,包括其名称,以及是否配置了允许或阻止的 IP 地址列表。 + +## 语法 {#syntax} + +```sql +SHOW NETWORK POLICIES +``` + +## 示例 {#examples} + +```sql +SHOW NETWORK POLICIES; + +Name |Allowed Ip List |Blocked Ip List|Comment | +------------+----------------+---------------+------------+ +test_policy |192.168.1.0/24 |192.168.1.99 |test comment| +test_policy1|192.168.100.0/24| | | +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/show-password-policies.md b/tidb-cloud-lake/sql/show-password-policies.md new file mode 100644 index 0000000000000..a6ddc02097116 --- /dev/null +++ b/tidb-cloud-lake/sql/show-password-policies.md @@ -0,0 +1,29 @@ +--- +title: SHOW PASSWORD POLICIES +summary: 显示 {{{ .lake }}} 中所有现有密码策略的列表。 +--- + +# SHOW PASSWORD POLICIES + +显示 {{{ .lake }}} 中所有现有密码策略的列表。 + +## 语法 {#syntax} + +```sql +SHOW PASSWORD POLICIES [ LIKE '' ] +``` + +## 示例 {#examples} + +```sql +CREATE PASSWORD POLICY SecureLogin + PASSWORD_MIN_LENGTH = 10; + +SHOW PASSWORD POLICIES; + +┌──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ +│ name │ comment │ options │ +├─────────────┼─────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤ +│ SecureLogin │ │ MIN_LENGTH=10, MAX_LENGTH=256, MIN_UPPER_CASE_CHARS=1, MIN_LOWER_CASE_CHARS=1, MIN_NUMERIC_CHARS=1, MIN_SPECIAL_CHARS=0, MIN_AGE_DAYS=0, MAX_AGE_DAYS=90, MAX_RETRIES=5, LOCKOUT_TIME_MINS=15, HISTORY=0 │ +└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/show-procedures.md b/tidb-cloud-lake/sql/show-procedures.md new file mode 100644 index 0000000000000..0d5445fc50f15 --- /dev/null +++ b/tidb-cloud-lake/sql/show-procedures.md @@ -0,0 +1,26 @@ +--- +title: SHOW PROCEDURES +summary: 返回系统中所有存储过程的列表。 +--- + +# SHOW PROCEDURES + +返回系统中所有存储过程的列表。 + +## 语法 {#syntax} + +```sql +SHOW PROCEDURES +``` + +## 示例 {#examples} + +```sql +SHOW PROCEDURES; + +┌────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ +│ name │ procedure_id │ arguments │ comment │ description │ created_on │ +├──────────────────┼──────────────┼─────────────────────────────────────────────────────────┼──────────────────────────────┼────────────────────────┼────────────────────────────┤ +│ convert_kg_to_lb │ 2104 │ convert_kg_to_lb(Decimal(4, 2)) RETURN (Decimal(10, 2)) │ Converts kilograms to pounds │ user-defined procedure │ 2024-11-07 04:12:25.243143 │ +└────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/show-processlist.md b/tidb-cloud-lake/sql/show-processlist.md new file mode 100644 index 0000000000000..47f7ad6a5a4ff --- /dev/null +++ b/tidb-cloud-lake/sql/show-processlist.md @@ -0,0 +1,28 @@ +--- +title: SHOW PROCESSLIST +summary: {{{ .lake }}} 进程列表显示了服务器内已执行线程集合当前正在执行的操作。 +--- + +# SHOW PROCESSLIST + +{{{ .lake }}} 进程列表显示了服务器内已执行线程集合当前正在执行的操作。 + +另请参阅:[KILL](/tidb-cloud-lake/sql/kill.md) + +## 语法 {#syntax} + +```sql +SHOW PROCESSLIST [LIKE '' | WHERE ] | [LIMIT ] +``` + +## 示例 {#examples} + +```sql +SHOW PROCESSLIST; ++--------------------------------------+-------+-----------------+------+-------+----------+-------------------------------------------------+--------------+------------------------+-------------------------+-------------------------+--------------------------+---------------------+------+ +| id | type | host | user | state | database | extra_info | memory_usage | dal_metrics_read_bytes | dal_metrics_write_bytes | scan_progress_read_rows | scan_progress_read_bytes | mysql_connection_id | time | ++--------------------------------------+-------+-----------------+------+-------+----------+-------------------------------------------------+--------------+------------------------+-------------------------+-------------------------+--------------------------+---------------------+------+ +| c1152483-de11-4375-bfe3-a35ad2ae9311 | MySQL | 127.0.0.1:57636 | root | Query | default | select sum(number) from numbers(10000000000000) | 0 | 0 | 0 | 816930000 | 6535440000 | 9 | 4 | +| ed21393e-6b6b-4efe-b333-1643f531e8ac | MySQL | 127.0.0.1:57637 | root | Query | system | show processlist | 0 | 0 | 0 | 0 | 0 | 10 | 0 | ++--------------------------------------+-------+-----------------+------+-------+----------+-------------------------------------------------+--------------+------------------------+-------------------------+-------------------------+--------------------------+---------------------+------+ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/show-roles.md b/tidb-cloud-lake/sql/show-roles.md new file mode 100644 index 0000000000000..6e1e7e17dbb54 --- /dev/null +++ b/tidb-cloud-lake/sql/show-roles.md @@ -0,0 +1,39 @@ +--- +title: SHOW ROLES +summary: 列出分配给当前用户的所有角色。 +--- + +# SHOW ROLES + +列出分配给当前用户的所有角色。 + +## 语法 {#syntax} + +```sql +SHOW ROLES +``` + +## 输出 {#output} + +该命令以表格形式返回结果,包含以下列: + +| 列名 | 描述 | +|-----------------|----------------------------------| +| name | 角色名称。 | +| inherited_roles | 当前角色继承的角色数量。 | +| is_current | 指示该角色当前是否处于激活状态。 | +| is_default | 指示该角色是否为用户的默认角色。 | + +## 示例 {#examples} + +```sql +SHOW ROLES; + +┌───────────────────────────────────────────────────────┐ +│ name │ inherited_roles │ is_current │ is_default │ +├───────────┼─────────────────┼────────────┼────────────┤ +│ developer │ 0 │ false │ false │ +│ public │ 0 │ false │ false │ +│ writer │ 0 │ true │ true │ +└───────────────────────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/show-sequences.md b/tidb-cloud-lake/sql/show-sequences.md new file mode 100644 index 0000000000000..cdff569865944 --- /dev/null +++ b/tidb-cloud-lake/sql/show-sequences.md @@ -0,0 +1,66 @@ +--- +title: SHOW SEQUENCES +summary: 返回已创建的序列列表。 +--- + +# SHOW SEQUENCES + +返回已创建的序列列表。 + +## 语法 {#syntax} + +```sql +SHOW SEQUENCES [ LIKE '' | WHERE ] +``` + +| 参数 | 描述 | +|-----------|-----------------------------------------------------------------------------------------------------------------------------| +| LIKE | 使用大小写敏感的模式匹配按名称过滤结果。 | +| WHERE | 使用 WHERE 子句中的表达式过滤结果。你可以基于结果集中的任意列进行过滤,例如 `name`、`start`、`interval`、`current`、`created_on`、`updated_on` 或 `comment`。例如:`WHERE start > 0` 或 `WHERE name LIKE 's%'`。 | + +## 示例 {#examples} + +```sql +-- Create a sequence +CREATE SEQUENCE seq; + +-- Show all sequences +SHOW SEQUENCES; + +╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ +│ name │ start │ interval │ current │ created_on │ updated_on │ comment │ +├────────┼────────┼──────────┼─────────┼────────────────────────────┼────────────────────────────┼──────────────────┤ +│ seq │ 1 │ 1 │ 1 │ 2025-05-20 02:48:49.749338 │ 2025-05-20 02:48:49.749338 │ NULL │ +╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ + +-- Use the sequence in an INSERT statement +CREATE TABLE tmp(a int, b uint64, c int); +INSERT INTO tmp select 10,nextval(seq),20 from numbers(3); + +-- Show sequences after usage +SHOW SEQUENCES; + +╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ +│ name │ start │ interval │ current │ created_on │ updated_on │ comment │ +├────────┼────────┼──────────┼─────────┼────────────────────────────┼────────────────────────────┼──────────────────┤ +│ seq │ 1 │ 1 │ 4 │ 2025-05-20 02:48:49.749338 │ 2025-05-20 02:49:14.302917 │ NULL │ +╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ + +-- Filter sequences using WHERE clause +SHOW SEQUENCES WHERE start > 0; + +╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ +│ name │ start │ interval │ current │ created_on │ updated_on │ comment │ +├────────┼────────┼──────────┼─────────┼────────────────────────────┼────────────────────────────┼──────────────────┤ +│ seq │ 1 │ 1 │ 4 │ 2025-05-20 02:48:49.749338 │ 2025-05-20 02:49:14.302917 │ NULL │ +╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ + +-- Filter sequences by name pattern +SHOW SEQUENCES LIKE 's%'; + +╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ +│ name │ start │ interval │ current │ created_on │ updated_on │ comment │ +├────────┼────────┼──────────┼─────────┼────────────────────────────┼────────────────────────────┼──────────────────┤ +│ seq │ 1 │ 1 │ 4 │ 2025-05-20 02:48:49.749338 │ 2025-05-20 02:49:14.302917 │ NULL │ +╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/show-settings.md b/tidb-cloud-lake/sql/show-settings.md new file mode 100644 index 0000000000000..d2e8dd5b81d50 --- /dev/null +++ b/tidb-cloud-lake/sql/show-settings.md @@ -0,0 +1,49 @@ +--- +title: SHOW SETTINGS +summary: "{{{ .lake }}} 提供了多种系统设置,使你能够控制 {{{ .lake }}} 的工作方式。此命令会显示可用系统设置的当前值、默认值以及设置级别。要修改某个设置,请使用 SET 或 UNSET 命令。" +--- + +# SHOW SETTINGS + +{{{ .lake }}} 提供了多种系统设置,使你能够控制 {{{ .lake }}} 的工作方式。此命令会显示可用系统设置的当前值、默认值以及[设置级别](#setting-levels)。要修改某个设置,请使用 [SET](/tidb-cloud-lake/sql/set.md) 或 [UNSET](/tidb-cloud-lake/sql/unset.md) 命令。 + +- {{{ .lake }}} 的某些行为无法通过系统设置进行更改;你在使用 {{{ .lake }}} 时必须将这些行为考虑在内。例如: + - {{{ .lake }}} 会将字符串编码为 UTF-8 字符集。 + - {{{ .lake }}} 对数组使用从 1 开始的编号约定。 +- {{{ .lake }}} 将系统设置存储在系统表 [system.settings](/tidb-cloud-lake/sql/system-settings.md) 中。 + +## 语法 {#syntax} + +```sql +SHOW SETTINGS [LIKE '' | WHERE ] | [LIMIT ] +``` + +## 设置级别 {#setting-levels} + +每个 {{{ .lake }}} 设置都具有一个级别,可以是 Global、Default 或 Session。下表说明了各个级别之间的区别: + +| 级别 | 说明 | +|------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| Global | 具有此级别的设置会写入 meta service,并影响同一租户中的所有集群。在此级别进行的更改具有全局影响,并会应用于由多个集群共享的整个数据库环境。 | +| Default | 具有此级别的设置是单个查询实例的服务默认值。在此级别进行的更改只会影响应用该默认值的查询实例。 | +| Session | 具有此级别的设置仅限于单个请求或会话。它们的作用域最小,仅适用于当前正在进行的特定会话或请求,从而提供按会话自定义设置的方式。 | + +## 示例 {#examples} + +> **注意:** +> +> 由于 {{{ .lake }}} 会不时修改系统设置,此示例可能不会显示最新结果。要查看 {{{ .lake }}} 中最新的系统设置,请在你的 {{{ .lake }}} 实例中执行 `SHOW SETTINGS;`。 + +```sql +SHOW SETTINGS LIMIT 5; + +┌───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ +│ name │ value │ default │ range │ level │ description │ type │ +├─────────────────────────────────────────────┼────────┼─────────┼──────────┼─────────┼────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┼────────┤ +│ acquire_lock_timeout │ 15 │ 15 │ None │ DEFAULT │ Sets the maximum timeout in seconds for acquire a lock. │ UInt64 │ +│ aggregate_spilling_bytes_threshold_per_proc │ 0 │ 0 │ None │ DEFAULT │ Sets the maximum amount of memory in bytes that an aggregator can use before spilling data to storage during query execution. │ UInt64 │ +│ aggregate_spilling_memory_ratio │ 0 │ 0 │ [0, 100] │ DEFAULT │ Sets the maximum memory ratio in bytes that an aggregator can use before spilling data to storage during query execution. │ UInt64 │ +│ auto_compaction_imperfect_blocks_threshold │ 50 │ 50 │ None │ DEFAULT │ Threshold for triggering auto compaction. This occurs when the number of imperfect blocks in a snapshot exceeds this value after write operations. │ UInt64 │ +│ collation │ utf8 │ utf8 │ ["utf8"] │ DEFAULT │ Sets the character collation. Available values include "utf8". │ String │ +└───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/show-stages.md b/tidb-cloud-lake/sql/show-stages.md new file mode 100644 index 0000000000000..bb933caaf3660 --- /dev/null +++ b/tidb-cloud-lake/sql/show-stages.md @@ -0,0 +1,26 @@ +--- +title: SHOW STAGES +summary: 返回已创建的 stage 列表。输出列表不包括用户 stage。 +--- + +# SHOW STAGES + +返回已创建的 stage 列表。输出列表不包括用户 stage。 + +## 语法 {#syntax} + +```sql +SHOW STAGES; +``` + +## 示例 {#examples} + +```sql +SHOW STAGES; + +┌───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ +│ name │ stage_type │ storage_type │ url │ endpoint │ has_credentials │ has_encryption_key │ storage_params │ file_format_options │ creator │ created_on │ comment │ owner │ +├──────┼────────────┼──────────────┼──────┼──────────┼─────────────────┼────────────────────┼────────────────┼─────────────────────┼─────────┼────────────────────────────┼─────────┼───────────────┤ +│ eric │ Internal │ NULL │ NULL │ NULL │ false │ false │ NULL │ {"compression":...} │ root@% │ 2026-06-16 22:21:19.000000 │ │ account_admin │ +└───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/show-statistics.md b/tidb-cloud-lake/sql/show-statistics.md new file mode 100644 index 0000000000000..fa06ef8af56c4 --- /dev/null +++ b/tidb-cloud-lake/sql/show-statistics.md @@ -0,0 +1,89 @@ +--- +title: SHOW STATISTICS +summary: 显示表及其列的统计信息。统计信息通过提供数据分布、行数和不同值等信息,帮助查询优化器对查询执行计划做出更优决策。 +--- + +# SHOW STATISTICS + +显示表及其列的统计信息。统计信息通过提供数据分布、行数和不同值等信息,帮助查询优化器对查询执行计划做出更优决策。 + +{{{ .lake }}} 会在数据插入期间自动生成统计信息。你可以使用此命令检查这些统计信息,并将其与实际数据进行比较,以识别可能影响查询性能的差异。 + +## 语法 {#syntax} + +```sql +SHOW STATISTICS [ FROM DATABASE | FROM TABLE . ] +``` + +| 参数 | 描述 | +|-----------|-----------------------------------------------------------------------------------------------------------------------------| +| FROM DATABASE | 显示指定数据库中所有表的统计信息。 | +| FROM TABLE | 仅显示指定表的统计信息。 | + +如果未指定参数,该命令会返回当前数据库中所有表的统计信息。 + +## 输出列 {#output-columns} + +该命令会为每个表中的每一列返回以下列: + +| 列 | 描述 | +|--------|-----------------------------------------------------------------------------------------------------------------------------| +| database | 数据库名称。 | +| table | 表名称。 | +| column_name | 列名称。 | +| stats_row_count | 统计信息中累计考虑的行数。由于统计信息会在插入时更新,但不会在删除时递减,因此该数值可能会**大于** actual_row_count。 | +| actual_row_count | 当前快照下表中的实际行数。 | +| distinct_count | 通过 HyperLogLog 计算得到的不同值(NDV)估算数量。 | +| null_count | 列中 NULL 值的数量。 | +| avg_size | 列中每个值的平均大小(以字节为单位)。 | + +## 示例 {#examples} + +### 显示当前数据库的统计信息 {#show-statistics-for-current-database} + +```sql +CREATE DATABASE test_db; +USE test_db; + +CREATE TABLE t1 (id INT, name VARCHAR(50)); +INSERT INTO t1 VALUES (1, 'Alice'), (2, 'Bob'); + +SHOW STATISTICS; +``` + +输出: + +``` +database table column_name stats_row_count actual_row_count distinct_count null_count avg_size +test_db t1 id 2 2 2 0 4 +test_db t1 name 2 2 2 0 16 +``` + +### 显示指定表的统计信息 {#show-statistics-for-a-specific-table} + +```sql +CREATE TABLE t2 (age INT, city VARCHAR(50)); +INSERT INTO t2 VALUES (25, 'New York'), (30, 'London'); + +SHOW STATISTICS FROM TABLE test_db.t2; +``` + +输出: + +``` +database table column_name stats_row_count actual_row_count distinct_count null_count avg_size +test_db t2 age 2 2 2 0 4 +test_db t2 city 2 2 2 0 19 +``` + +### 显示数据库中所有表的统计信息 {#show-statistics-for-all-tables-in-a-database} + +```sql +SHOW STATISTICS FROM DATABASE test_db; +``` + +这将显示 `test_db` 数据库中所有表(`t1` 和 `t2`)的统计信息。 + +## 相关命令 {#related-commands} + +- [SHOW TABLE STATUS](/tidb-cloud-lake/sql/show-table-status.md):显示表的状态信息 \ No newline at end of file diff --git a/tidb-cloud-lake/sql/show-streams.md b/tidb-cloud-lake/sql/show-streams.md new file mode 100644 index 0000000000000..a0aea3257e91a --- /dev/null +++ b/tidb-cloud-lake/sql/show-streams.md @@ -0,0 +1,53 @@ +--- +title: SHOW STREAMS +summary: 列出与特定数据库关联的 streams。 +--- + +# SHOW STREAMS + +列出与特定数据库关联的 streams。 + +## 语法 {#syntax} + +```sql +SHOW [ FULL ] STREAMS + [ { FROM | IN } ] + [ LIKE '' | WHERE ] +``` + +| 参数 | 描述 | +|-----------|----------------------------------------------------------------------------------------------| +| FULL | 列出包含附加信息的结果。更多详情请参见[示例](#examples)。 | +| FROM / IN | 指定一个数据库。如果省略,该命令返回当前数据库中的结果。 | +| LIKE | 使用大小写敏感的模式匹配并结合 `%` 通配符来过滤 stream 名称。 | +| WHERE | 使用 WHERE 子句中的表达式来过滤 stream 名称。 | + +## 示例 {#examples} + +以下示例显示属于当前数据库的 streams: + +```sql +SHOW STREAMS; + +┌──────────────────────────────────────────────────────────┐ +│ Streams_in_default │ table_on │ mode │ +├────────────────────┼───────────────────────┼─────────────┤ +│ order_changes │ default.orders │ append_only │ +│ s_append_only │ default.t_append_only │ append_only │ +│ s_standard │ default.t_standard │ standard │ +└──────────────────────────────────────────────────────────┘ +``` + +以下示例显示当前数据库中 streams 的详细信息: + +```sql +SHOW FULL STREAMS; + +┌─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ +│ created_on │ name │ database │ catalog │ table_on │ owner │ comment │ mode │ invalid_reason │ +├────────────────────────────┼───────────────┼──────────┼─────────┼───────────────────────┼──────────────────┼─────────┼─────────────┼────────────────┤ +│ 2024-05-12 14:28:33.886271 │ order_changes │ default │ default │ default.orders │ NULL │ │ append_only │ │ +│ 2024-05-12 14:35:05.992050 │ s_append_only │ default │ default │ default.t_append_only │ NULL │ │ append_only │ │ +│ 2024-05-12 14:35:05.981121 │ s_standard │ default │ default │ default.t_standard │ NULL │ │ standard │ │ +└─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/show-table-functions.md b/tidb-cloud-lake/sql/show-table-functions.md new file mode 100644 index 0000000000000..5fbb3e84ac723 --- /dev/null +++ b/tidb-cloud-lake/sql/show-table-functions.md @@ -0,0 +1,61 @@ +--- +title: SHOW TABLE FUNCTIONS +summary: 显示当前支持的表函数列表。 +--- + +# SHOW TABLE FUNCTIONS + +显示当前支持的表函数列表。 + +## 语法 {#syntax} + +```sql +SHOW TABLE_FUNCTIONS [LIKE '' | WHERE ] | [LIMIT ] +``` + +## 示例 {#example} + +```sql +SHOW TABLE_FUNCTIONS; ++------------------------+ +| name | ++------------------------+ +| numbers | +| numbers_mt | +| numbers_local | +| fuse_snapshot | +| fuse_segment | +| fuse_block | +| fuse_statistic | +| clustering_information | +| sync_crash_me | +| async_crash_me | +| infer_schema | ++------------------------+ +``` + +显示以 `"number"` 开头的表函数: + +```sql +SHOW TABLE_FUNCTIONS LIKE 'number%'; ++---------------+ +| name | ++---------------+ +| numbers | +| numbers_mt | +| numbers_local | ++---------------+ +``` + +使用 `WHERE` 显示以 `"number"` 开头的表函数: + +```sql +SHOW TABLE_FUNCTIONS WHERE name LIKE 'number%'; ++---------------+ +| name | ++---------------+ +| numbers | +| numbers_mt | +| numbers_local | ++---------------+ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/show-table-status.md b/tidb-cloud-lake/sql/show-table-status.md new file mode 100644 index 0000000000000..73306ce99b9ed --- /dev/null +++ b/tidb-cloud-lake/sql/show-table-status.md @@ -0,0 +1,60 @@ +--- +title: SHOW TABLE STATUS +summary: 显示数据库中各个表的状态。状态信息包括表的各种物理大小和时间戳,详见“示例”。 +--- + +# SHOW TABLE STATUS + +显示数据库中各个表的状态。状态信息包括表的各种物理大小和时间戳,详见[示例](#examples)。 + +## 语法 {#syntax} + +```sql +SHOW TABLE STATUS + [ {FROM | IN} ] + [ LIKE 'pattern' | WHERE expr ] +``` + +| 参数 | 描述 | +|-----------|-----------------------------------------------------------------------------------------------------------------------------| +| FROM / IN | 指定一个数据库。如果省略,则该命令返回当前数据库中的结果。 | +| LIKE | 使用大小写敏感的模式匹配按表名过滤结果。 | +| WHERE | 使用 WHERE 子句中的表达式过滤结果。 | + +## 示例 {#examples} + +以下示例显示当前数据库中各个表的状态,提供名称、引擎、行数以及其他相关信息等详细内容: + +```sql +SHOW TABLE STATUS; + +name |engine|version|row_format|rows|avg_row_length|data_length|max_data_length|index_length|data_free|auto_increment|create_time |update_time|check_time|collation|checksum|comment|cluster_by| +-------+------+-------+----------+----+--------------+-----------+---------------+------------+---------+--------------+-----------------------------+-----------+----------+---------+--------+-------+----------+ +books |FUSE | 0| | 2| | 160| | 713| | |2023-09-25 06:40:47.237 +0000| | | | | | | +mytable|FUSE | 0| | 5| | 40| | 1665| | |2023-08-28 07:53:05.455 +0000| | | | | |((a + 1)) | +ontime |FUSE | 0| | 199| | 147981| | 22961| | |2023-09-19 07:04:06.414 +0000| | | | | | | +``` + +以下示例显示当前数据库中名称以 `'my'` 开头的表的状态: + +```sql +SHOW TABLE STATUS LIKE 'my%'; + +name |engine|version|row_format|rows|avg_row_length|data_length|max_data_length|index_length|data_free|auto_increment|create_time |update_time|check_time|collation|checksum|comment|cluster_by| +-------+------+-------+----------+----+--------------+-----------+---------------+------------+---------+--------------+-----------------------------+-----------+----------+---------+--------+-------+----------+ +mytable|FUSE | 0| | 5| | 40| | 1665| | |2023-08-28 07:53:05.455 +0000| | | | | |((a + 1)) | +``` + +以下示例显示当前数据库中行数大于 100 的表的状态: + +> **注意:** +> +> 使用 SHOW TABLE STATUS 查询时,请注意某些列名(例如 `"rows"`)可能会被解释为 SQL 关键字,从而导致错误。为避免此问题,请始终使用反引号将列名括起来,如本示例所示。这样可以确保在 SQL 查询中,列名被视为标识符而不是关键字。 + +```sql +SHOW TABLE STATUS WHERE `rows` > 100; + +name |engine|version|row_format|rows|avg_row_length|data_length|max_data_length|index_length|data_free|auto_increment|create_time |update_time|check_time|collation|checksum|comment|cluster_by| +------+------+-------+----------+----+--------------+-----------+---------------+------------+---------+--------------+-----------------------------+-----------+----------+---------+--------+-------+----------+ +ontime|FUSE | 0| | 199| | 147981| | 22961| | |2023-09-19 07:04:06.414 +0000| | | | | | | +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/show-tables.md b/tidb-cloud-lake/sql/show-tables.md new file mode 100644 index 0000000000000..06fed642353b4 --- /dev/null +++ b/tidb-cloud-lake/sql/show-tables.md @@ -0,0 +1,118 @@ +--- +title: SHOW TABLES +summary: 列出当前数据库或指定数据库中的表。 +--- + +# SHOW TABLES + +列出当前数据库或指定数据库中的表。 + +> **Note:** +> +> 从 1.2.415 版本开始,SHOW TABLES 命令的结果中不再包含视图。要显示视图,请改用 [SHOW VIEWS](/tidb-cloud-lake/sql/show-views.md)。 + +另请参阅:[system.tables](/tidb-cloud-lake/sql/system-tables.md) + +## 语法 {#syntax} + +```sql +SHOW [ FULL ] TABLES + [ {FROM | IN} ] + [ HISTORY ] + [ LIKE '' | WHERE ] +``` + +| 参数 | 描述 | +|-----------|-----------------------------------------------------------------------------------------------------------------------------| +| FULL | 列出结果并附带额外信息。更多详情请参见[示例](#examples)。 | +| FROM / IN | 指定数据库。如果省略,该命令返回当前数据库中的结果。 | +| HISTORY | 显示保留时间内(默认 24 小时)被删除表的时间戳。如果某个表尚未被删除,则 `drop_time` 的值为 NULL。 | +| LIKE | 使用大小写敏感的模式匹配按名称过滤结果。 | +| WHERE | 使用 WHERE 子句中的表达式过滤结果。 | + +## 示例 {#examples} + +以下示例列出当前数据库(默认)的所有表名: + +```sql +SHOW TABLES; + +┌───────────────────┐ +│ Tables_in_default │ +├───────────────────┤ +│ books │ +│ mytable │ +│ ontime │ +│ products │ +└───────────────────┘ +``` + +以下示例列出所有表及其附加信息: + +```sql +SHOW FULL TABLES; + +┌──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ +│ tables │ table_type │ database │ catalog │ owner │ engine │ cluster_by │ create_time │ num_rows │ data_size │ data_compressed_size │ index_size │ +├──────────┼────────────┼──────────┼─────────┼──────────────────┼────────┼────────────┼────────────────────────────┼──────────────────┼──────────────────┼──────────────────────┼──────────────────┤ +│ books │ BASE TABLE │ default │ default │ account_admin │ FUSE │ │ 2024-01-16 03:53:15.354132 │ 0 │ 0 │ 0 │ 0 │ +│ mytable │ BASE TABLE │ default │ default │ account_admin │ FUSE │ │ 2024-01-16 03:53:27.968505 │ 0 │ 0 │ 0 │ 0 │ +│ ontime │ BASE TABLE │ default │ default │ account_admin │ FUSE │ │ 2024-01-16 03:53:42.052399 │ 0 │ 0 │ 0 │ 0 │ +│ products │ BASE TABLE │ default │ default │ account_admin │ FUSE │ │ 2024-01-16 03:54:00.883985 │ 0 │ 0 │ 0 │ 0 │ +└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ +``` + +以下示例演示了当存在可选参数 HISTORY 时,结果将包含已删除的表: + +```sql +DROP TABLE products; + +SHOW TABLES; + +┌───────────────────┐ +│ Tables_in_default │ +├───────────────────┤ +│ books │ +│ mytable │ +│ ontime │ +└───────────────────┘ + +SHOW TABLES HISTORY; + +┌────────────────────────────────────────────────┐ +│ Tables_in_default │ drop_time │ +├───────────────────┼────────────────────────────┤ +│ books │ NULL │ +│ mytable │ NULL │ +│ ontime │ NULL │ +│ products │ 2024-01-16 03:55:47.900362 │ +└────────────────────────────────────────────────┘ +``` + +以下示例列出名称以字符串 "time" 结尾的表: + +```sql +SHOW TABLES LIKE '%time'; + +┌───────────────────┐ +│ Tables_in_default │ +├───────────────────┤ +│ ontime │ +└───────────────────┘ + +-- CASE-SENSITIVE pattern matching. +-- No results will be returned if you code the previous statement like this: +SHOW TABLES LIKE '%TIME'; +``` + +以下示例列出数据大小大于 1,000 字节的表: + +```sql +SHOW TABLES WHERE data_size > 1000 ; + +┌───────────────────┐ +│ Tables_in_default │ +├───────────────────┤ +│ ontime │ +└───────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/show-tags.md b/tidb-cloud-lake/sql/show-tags.md new file mode 100644 index 0000000000000..4f11a2fc8521c --- /dev/null +++ b/tidb-cloud-lake/sql/show-tags.md @@ -0,0 +1,57 @@ +--- +title: SHOW TAGS +summary: 列出当前租户中的标签定义。 +--- + +# SHOW TAGS + +列出当前租户中的标签定义。你也可以通过 `system.tags` 表查询标签定义。 + +另请参阅:[CREATE TAG](/tidb-cloud-lake/sql/create-tag.md)、[DROP TAG](/tidb-cloud-lake/sql/drop-tag.md)。 + +## 语法 {#syntax} + +```sql +SHOW TAGS [ LIKE '' | WHERE ] [ LIMIT ] +``` + +## 输出列 {#output-columns} + +| 列 | 描述 | +|------------------|------------------------------------------------------| +| `name` | 标签名称 | +| `allowed_values` | 允许的值列表;如果允许任意值,则为 NULL | +| `comment` | 标签描述 | +| `created_on` | 创建时间戳 | + +## 示例 {#examples} + +显示所有标签: + +```sql +SHOW TAGS; +``` + +按名称模式筛选标签: + +```sql +SHOW TAGS LIKE 'env%'; +``` + +使用 WHERE 条件筛选: + +```sql +SHOW TAGS WHERE comment IS NOT NULL; +``` + +限制结果数量: + +```sql +SHOW TAGS LIMIT 5; +``` + +使用系统表的等价查询: + +```sql +SELECT * FROM system.tags; +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/show-tasks.md b/tidb-cloud-lake/sql/show-tasks.md new file mode 100644 index 0000000000000..5205acd0b95af --- /dev/null +++ b/tidb-cloud-lake/sql/show-tasks.md @@ -0,0 +1,63 @@ +--- +title: SHOW TASKS +summary: 列出当前角色可见的任务。 +--- + +# SHOW TASKS + +列出当前角色可见的任务。 + +**NOTICE:** 此命令开箱即用仅适用于 {{{ .lake }}}。对于自托管部署,请配置 Cloud Control 以查询任务。 + +## 语法 {#syntax} + +```sql +SHOW TASKS [LIKE '' | WHERE ] +``` + +| 参数 | 描述 | +|-----------|-------------| +| LIKE | 使用大小写敏感的模式匹配和 `%` 通配符过滤任务名称。 | +| WHERE | 使用输出列上的表达式过滤结果集。 | + +### 输出 {#output} + +`SHOW TASKS` 返回以下列: + +- `created_on`:任务创建时的时间戳。 +- `name`:任务名称。 +- `id`:内部任务标识符。 +- `owner`:拥有该任务的角色。 +- `comment`:可选注释。 +- `warehouse`:分配给任务的计算集群 (Warehouse)。 +- `schedule`:间隔或 CRON 调度(如果存在)。 +- `state`:当前状态(`Started` 或 `Suspended`)。 +- `definition`:任务运行的 SQL。 +- `condition_text`:任务的 WHEN 条件。 +- `after`:DAG 中上游任务的逗号分隔列表。 +- `suspend_task_after_num_failures`:挂起前允许连续失败的次数。 +- `error_integration`:失败时使用的通知集成。 +- `next_schedule_time`:下一次计划运行的时间戳。 +- `last_committed_on`:上次修改任务定义时的时间戳。 +- `last_suspended_on`:任务上次被挂起时的时间戳(如果有)。 +- `session_parameters`:任务运行时应用的会话参数。 + +## 示例 {#examples} + +列出当前角色可用的所有任务: + +```sql +SHOW TASKS; ++----------------------------+---------------+------+---------------+---------+-----------+---------------------------------+----------+-------------------------------------------+------------------------+---------+-------------------------------------+-------------------+----------------------------+----------------------------+----------------------------+---------------------------------------------------+ +| created_on | name | id | owner | comment | warehouse | schedule | state | definition | condition_text | after | suspend_task_after_num_failures | error_integration | next_schedule_time | last_committed_on | last_suspended_on | session_parameters | ++----------------------------+---------------+------+---------------+---------+-----------+---------------------------------+----------+-------------------------------------------+------------------------+---------+-------------------------------------+-------------------+----------------------------+----------------------------+----------------------------+---------------------------------------------------+ +| 2024-07-01 08:00:00.000000 | ingest_sales | 101 | ACCOUNTADMIN | NULL | etl_wh | CRON 0 5 * * * * TIMEZONE UTC | Started | COPY INTO sales FROM @stage PATTERN '.*' | STREAM_STATUS('s1') | | 3 | slack_errors | 2024-07-01 08:05:00.000000 | 2024-07-01 08:00:00.000000 | NULL | {"enable_query_result_cache":"1"} | +| 2024-07-01 09:00:00.000000 | hourly_checks | 102 | SYSADMIN | health | etl_wh | INTERVAL 3600 SECOND | Suspended | CALL run_health_check() | | ingest_sales | NULL | NULL | 2024-07-01 10:00:00.000000 | 2024-07-01 09:05:00.000000 | 2024-07-01 09:10:00.000000 | {"query_result_cache_min_execute_secs":"5"} | ++----------------------------+---------------+------+---------------+---------+-----------+---------------------------------+----------+-------------------------------------------+------------------------+---------+-------------------------------------+-------------------+----------------------------+----------------------------+----------------------------+---------------------------------------------------+ +``` + +仅显示名称以 `ingest_` 开头的任务: + +```sql +SHOW TASKS LIKE 'ingest_%'; +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/show-user-functions-sql.md b/tidb-cloud-lake/sql/show-user-functions-sql.md new file mode 100644 index 0000000000000..a850858d68c13 --- /dev/null +++ b/tidb-cloud-lake/sql/show-user-functions-sql.md @@ -0,0 +1,30 @@ +--- +title: SHOW USER FUNCTIONS +summary: 列出系统中现有的用户定义函数和外部函数。等价于 `SELECT name, is_aggregate, description, arguments, language FROM system.user_functions....` +--- + +# SHOW USER FUNCTIONS + +列出系统中现有的用户定义函数和外部函数。等价于 `SELECT name, is_aggregate, description, arguments, language FROM system.user_functions ...`。 + +另请参阅:[system.user_functions](/tidb-cloud-lake/sql/system-user-functions.md) + +## 语法 {#syntax} + +```sql +SHOW USER FUNCTIONS [LIKE '' | WHERE ] | [LIMIT ] +``` + +## 示例 {#example} + +```sql +SHOW USER FUNCTIONS; + +┌─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ +│ name │ is_aggregate │ description │ arguments │ language │ +├────────────────┼───────────────────┼─────────────┼───────────────────────────────────────────────────────────┼──────────┤ +│ binary_reverse │ NULL │ │ {"arg_types":["Binary NULL"],"return_type":"Binary NULL"} │ python │ +│ echo │ NULL │ │ {"arg_types":["String NULL"],"return_type":"String NULL"} │ python │ +│ isnotempty │ NULL │ │ {"parameters":["p"]} │ SQL │ +└─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/show-user-functions.md b/tidb-cloud-lake/sql/show-user-functions.md new file mode 100644 index 0000000000000..12c9309a8a269 --- /dev/null +++ b/tidb-cloud-lake/sql/show-user-functions.md @@ -0,0 +1,39 @@ +--- +title: SHOW USER FUNCTIONS +summary: 列出所有用户定义函数,包括标量函数、表函数、嵌入式函数和外部函数。 +--- + +# SHOW USER FUNCTIONS + +列出所有用户定义函数,包括标量函数、表函数、嵌入式函数和外部函数。 + +## 语法 {#syntax} + +```sql +SHOW USER FUNCTIONS +``` + +## 输出列 {#output-columns} + +| 列 | 描述 | +|--------|-------------| +| `name` | 函数名称 | +| `is_aggregate` | 是否为聚合函数(对于 UDF 为 NULL) | +| `description` | 如果提供,则为函数描述 | +| `arguments` | JSON 格式的函数参数 | +| `language` | 编程语言:SQL、python、javascript、wasm 或 external | +| `created_on` | 函数创建时间戳 | + +## 示例 {#examples} + +```sql +SHOW USER FUNCTIONS; + +┌──────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ +│ name │ is_aggregate │ description │ arguments │ language │ created_on │ +│ String │ Nullable(Boolean) │ String │ Variant │ String │ Timestamp │ +├────────┼───────────────────┼─────────────┼───────────────────────────────┼──────────┼────────────────────────────┤ +│ get_v1 │ NULL │ │ {"parameters":["input_json"]} │ SQL │ 2024-11-18 23:20:28.432842 │ +│ get_v2 │ NULL │ │ {"parameters":["input_json"]} │ SQL │ 2024-11-18 23:21:46.838744 │ +└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/show-users.md b/tidb-cloud-lake/sql/show-users.md new file mode 100644 index 0000000000000..e8006c24d723f --- /dev/null +++ b/tidb-cloud-lake/sql/show-users.md @@ -0,0 +1,45 @@ +--- +title: SHOW USERS +summary: 列出系统中的所有 SQL 用户。如果你使用的是 {{{ .lake }}},此命令还会显示你所在组织中用于登录 {{{ .lake }}} 的用户账户(电子邮件地址)。 +--- + +# SHOW USERS + +列出系统中的所有 SQL 用户。如果你使用的是 {{{ .lake }}},此命令还会显示你所在组织中用于登录 {{{ .lake }}} 的用户账户(电子邮件地址)。 + +## 语法 {#syntax} + +```sql +SHOW USERS +``` + +## 示例 {#examples} + +```sql +CREATE NETWORK POLICY my_network_policy ALLOWED_IP_LIST=('192.168.100.0/24'); + +CREATE PASSWORD POLICY my_password_policy + PASSWORD_MIN_LENGTH = 12 + PASSWORD_MAX_LENGTH = 24 + PASSWORD_MIN_UPPER_CASE_CHARS = 2 + PASSWORD_MIN_LOWER_CASE_CHARS = 2 + PASSWORD_MIN_NUMERIC_CHARS = 2 + PASSWORD_MIN_SPECIAL_CHARS = 2 + PASSWORD_MIN_AGE_DAYS = 1 + PASSWORD_MAX_AGE_DAYS = 30 + PASSWORD_MAX_RETRIES = 3 + PASSWORD_LOCKOUT_TIME_MINS = 30 + PASSWORD_HISTORY = 5 + COMMENT = 'test comment'; + +CREATE USER eric IDENTIFIED BY '123ABCabc$$123' WITH SET PASSWORD POLICY='my_password_policy', SET NETWORK POLICY='my_network_policy'; + +SHOW USERS; + +┌─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ +│ name │ hostname │ auth_type │ is_configured │ default_role │ roles │ disabled │ network_policy │ password_policy │ must_change_password │ +├────────┼──────────┼──────────────────────┼───────────────┼───────────────┼───────────────┼──────────┼───────────────────┼────────────────────┼──────────────────────┤ +│ eric │ % │ double_sha1_password │ NO │ │ │ false │ my_network_policy │ my_password_policy │ NULL │ +│ root │ % │ no_password │ YES │ account_admin │ account_admin │ false │ NULL │ NULL │ NULL │ +└─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/show-variables-sql.md b/tidb-cloud-lake/sql/show-variables-sql.md new file mode 100644 index 0000000000000..8239520cc9250 --- /dev/null +++ b/tidb-cloud-lake/sql/show-variables-sql.md @@ -0,0 +1,31 @@ +--- +title: SHOW_VARIABLES +summary: 显示所有会话变量及其详细信息,例如名称、值和类型。 +--- + +# SHOW_VARIABLES + +显示所有会话变量及其详细信息,例如名称、值和类型。 + +另请参阅:[SHOW VARIABLES](/tidb-cloud-lake/sql/show-variables.md) + +## 语法 {#syntax} + +```sql +SHOW_VARIABLES() +``` + +## 示例 {#examples} + +```sql +SELECT name, value, type FROM SHOW_VARIABLES(); + +┌──────────────────────────┐ +│ name │ value │ type │ +├────────┼────────┼────────┤ +│ y │ 'yy' │ String │ +│ b │ 55 │ UInt8 │ +│ x │ 'xx' │ String │ +│ a │ 3 │ UInt8 │ +└──────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/show-variables.md b/tidb-cloud-lake/sql/show-variables.md new file mode 100644 index 0000000000000..322799fe27fa6 --- /dev/null +++ b/tidb-cloud-lake/sql/show-variables.md @@ -0,0 +1,41 @@ +--- +title: SHOW VARIABLES +summary: 显示所有会话变量及其详细信息,例如名称、值和类型。 +--- + +# SHOW VARIABLES + +显示所有会话变量及其详细信息,例如名称、值和类型。 + +另请参阅:[SHOW_VARIABLES](/tidb-cloud-lake/sql/show-variables.md) + +## 语法 {#syntax} + +```sql +SHOW VARIABLES [ LIKE '' | WHERE ] +``` + +## 示例 {#examples} + +以下示例列出了所有会话变量及其值和类型: + +```sql +SHOW VARIABLES; + +┌──────────────────────────┐ +│ name │ value │ type │ +├────────┼────────┼────────┤ +│ a │ 3 │ UInt8 │ +│ b │ 55 │ UInt8 │ +│ x │ 'xx' │ String │ +│ y │ 'yy' │ String │ +└──────────────────────────┘ +``` + +要筛选并仅返回名为 `a` 的变量,请使用以下任一查询: + +```sql +SHOW VARIABLES LIKE 'a'; + +SHOW VARIABLES WHERE name = 'a'; +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/show-views.md b/tidb-cloud-lake/sql/show-views.md new file mode 100644 index 0000000000000..f2c6821f64b76 --- /dev/null +++ b/tidb-cloud-lake/sql/show-views.md @@ -0,0 +1,59 @@ +--- +title: SHOW VIEWS +summary: 返回指定数据库中的视图名称列表;如果未提供数据库名称,则返回当前数据库中的视图名称列表。 +--- + +# SHOW VIEWS + +返回指定数据库中的视图名称列表;如果未提供数据库名称,则返回当前数据库中的视图名称列表。 + +## 语法 {#syntax} + +```sql +SHOW [ FULL ] VIEWS + [ { FROM | IN } ] + [ HISTORY ] + [ LIKE '' | WHERE ] +``` + +| 参数 | 描述 | +|-----------|----------------------------------------------------------------------------------------------| +| FULL | 返回包含附加信息的结果。更多详情请参见[示例](#examples)。 | +| FROM / IN | 指定一个数据库。如果省略,则该命令返回当前数据库中的结果。 | +| HISTORY | 显示保留时间内(默认 24 小时)被删除视图的时间戳。如果某个视图尚未被删除,则 `drop_time` 的值为 NULL。 | +| LIKE | 使用带有 `%` 通配符的大小写敏感模式匹配来过滤视图名称。 | +| WHERE | 使用 WHERE 子句中的表达式来过滤视图名称。 | + +## 示例 {#examples} + +```sql +SHOW VIEWS; + +┌───────────────────────────────────────────────────────────────────┐ +│ Views_in_default │ view_query │ +├──────────────────┼────────────────────────────────────────────────┤ +│ books_view │ SELECT id, title, genre FROM default.books │ +│ users_view │ SELECT username, email, age FROM default.users │ +└───────────────────────────────────────────────────────────────────┘ + +SHOW FULL VIEWS; + +┌───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ +│ views │ database │ catalog │ owner │ engine │ create_time │ view_query │ +├────────────┼──────────┼─────────┼──────────────────┼────────┼────────────────────────────┼────────────────────────────────────────────────┤ +│ books_view │ default │ default │ NULL │ VIEW │ 2024-04-14 23:29:52.916989 │ SELECT id, title, genre FROM default.books │ +│ users_view │ default │ default │ NULL │ VIEW │ 2024-04-14 23:31:02.918994 │ SELECT username, email, age FROM default.users │ +└───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ + +-- Delete the view 'books_view' +DROP VIEW books_view; + +SHOW VIEWS HISTORY; + +┌────────────────────────────────────────────────────────────────────────────────────────────────┐ +│ Views_in_default │ view_query │ drop_time │ +├──────────────────┼────────────────────────────────────────────────┼────────────────────────────┤ +│ books_view │ SELECT id, title, genre FROM default.books │ 2024-04-15 02:29:56.051081 │ +│ users_view │ SELECT username, email, age FROM default.users │ NULL │ +└────────────────────────────────────────────────────────────────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/show-virtual-columns.md b/tidb-cloud-lake/sql/show-virtual-columns.md new file mode 100644 index 0000000000000..1064b1b421470 --- /dev/null +++ b/tidb-cloud-lake/sql/show-virtual-columns.md @@ -0,0 +1,47 @@ +--- +title: SHOW VIRTUAL COLUMNS +summary: 显示系统中已创建的虚拟列。等同于 SELECT * FROM system.virtual_columns。 +--- + +# SHOW VIRTUAL COLUMNS + +显示系统中已创建的虚拟列。等同于 `SELECT * FROM system.virtual_columns`。 + +从 v1.2.832 开始,默认启用虚拟列。 + +另请参阅:[system.virtual_columns](/tidb-cloud-lake/sql/system-virtual-columns.md) + +## 首选语法 {#preferred-syntax} + +使用该命令最简单且最实用的形式来查看特定表,或列出所有虚拟列: + +```sql +SHOW VIRTUAL COLUMNS [WHERE table = '' AND database = ''] +``` + +## 示例 {#example} + +```sql +CREATE TABLE test(id int, val variant); + +INSERT INTO + test +VALUES + ( + 1, + '{"id":1,"name":"datalake"}' + ), + ( + 2, + '{"id":2,"name":"databricks"}' + ); + +SHOW VIRTUAL COLUMNS WHERE table = 'test' AND database = 'default'; +╭───────────────────────────────────────────────────────────────────────────────────────────────────╮ +│ database │ table │ source_column │ virtual_column_id │ virtual_column_name │ virtual_column_type │ +│ String │ String │ String │ UInt32 │ String │ String │ +├──────────┼────────┼───────────────┼───────────────────┼─────────────────────┼─────────────────────┤ +│ default │ test │ val │ 3000000000 │ ['id'] │ UInt64 │ +│ default │ test │ val │ 3000000001 │ ['name'] │ String │ +╰───────────────────────────────────────────────────────────────────────────────────────────────────╯ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/show-warehouses.md b/tidb-cloud-lake/sql/show-warehouses.md new file mode 100644 index 0000000000000..572078246cc21 --- /dev/null +++ b/tidb-cloud-lake/sql/show-warehouses.md @@ -0,0 +1,56 @@ +--- +title: SHOW WAREHOUSES +summary: 列出当前租户可见的所有计算集群。 +--- + +# SHOW WAREHOUSES + +列出当前租户可见的所有计算集群。 + +## 语法 {#syntax} + +```sql +SHOW WAREHOUSES [ LIKE '' ] [ ] +``` + +| 参数 | 描述 | +| ------------------------ | -------------------------------------------------------------------------------------------------------------------------- | +| `LIKE ''` | 可选。使用 SQL `LIKE` 语义过滤计算集群名称(`%` 匹配任意字符序列,`_` 匹配任意单个字符)。 | +| `` | 可选。当省略 `LIKE` 但后面跟随一个字面量时,该字面量会被视为 `LIKE ''`。 | + +## 输出列 {#output-columns} + +| 列 | 描述 | +| ------------------- | ----------------------------------------- | +| `name` | 计算集群名称 | +| `state` | 当前状态(例如 Running、Suspended) | +| `size` | 计算集群大小 | +| `auto_suspend` | 自动挂起超时时间(秒) | +| `auto_resume` | 是否启用自动恢复 | +| `min_cluster_count` | 自动扩缩容的最小集群数 | +| `max_cluster_count` | 自动扩缩容的最大集群数 | +| `role` | 计算集群角色 | +| `comment` | 用户定义的注释 | +| `tags` | JSON 格式字符串表示的计算集群标签 | +| `created_by` | 创建者 | +| `created_on` | 创建时间戳 | + +## 示例 {#examples} + +列出所有计算集群: + +```sql +SHOW WAREHOUSES; +``` + +列出匹配某个模式的计算集群: + +```sql +SHOW WAREHOUSES LIKE '%prod%'; +``` + +在不使用 `LIKE` 的情况下使用字面量: + +```sql +SHOW WAREHOUSES 'nightly-etl'; +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/show-workers.md b/tidb-cloud-lake/sql/show-workers.md new file mode 100644 index 0000000000000..806478abba090 --- /dev/null +++ b/tidb-cloud-lake/sql/show-workers.md @@ -0,0 +1,52 @@ +--- +title: SHOW WORKERS +summary: 使用 SHOW WORKERS 列出 worker 及其元信息。 +--- + +# SHOW WORKERS + +> **注意:** +> +> 于 v1.3.0 中引入。 + +列出当前租户中的 worker。 + +> **注意:** +> +> 此命令要求启用 cloud control。 + +## 语法 {#syntax} + +```sql +SHOW WORKERS +``` + +## 输出 {#output} + +`SHOW WORKERS` 返回以下列: + +| 列名 | 描述 | +|--------|-------------| +| `name` | Worker 名称 | +| `tags` | JSON 格式的 Worker 标签 | +| `options` | JSON 格式的 Worker 选项 | +| `created_at` | Worker 创建时间戳 | +| `updated_at` | Worker 修改时间戳 | + +## 示例 {#examples} + +```sql +SHOW WORKERS; +``` + +示例输出: + +```text +read_env,{},"{""auto_resume"":""true"",""auto_suspend"":""300"",""max_cluster_count"":""3"",""min_cluster_count"":""1"",""size"":""small""}",2026-04-23T11:40:27.942797+00:00,2026-04-23T11:40:27.942797+00:00 +``` + +## 相关主题 {#related-topics} + +- [CREATE WORKER](/tidb-cloud-lake/sql/create-worker.md) - 创建 worker +- [ALTER WORKER](/tidb-cloud-lake/sql/alter-worker.md) - 修改 worker 的标签、选项或状态 +- [DROP WORKER](/tidb-cloud-lake/sql/drop-worker.md) - 删除 worker \ No newline at end of file diff --git a/tidb-cloud-lake/sql/show-workload-groups.md b/tidb-cloud-lake/sql/show-workload-groups.md new file mode 100644 index 0000000000000..4ba2efb92726f --- /dev/null +++ b/tidb-cloud-lake/sql/show-workload-groups.md @@ -0,0 +1,27 @@ +--- +title: SHOW WORKLOAD GROUPS +summary: 返回所有现有 workload group 及其配额的列表。 +--- + +# SHOW WORKLOAD GROUPS + +返回所有现有 workload group 及其配额的列表。 + +## 语法 {#syntax} + +```sql +SHOW WORKLOAD GROUPS +``` + +## 示例 {#examples} + +```sql +SHOW WORKLOAD GROUPS + +┌────────────────────────────────────────────────────────────────────────────────────────────┐ +│ name │ cpu_quota │ memory_quota │ query_timeout │ max_concurrency │ query_queued_timeout │ +│ String │ String │ String │ String │ String │ String │ +├────────┼───────────┼──────────────┼───────────────┼─────────────────┼──────────────────────┤ +│ test │ 30% │ │ 15s │ │ │ +└────────────────────────────────────────────────────────────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/sign.md b/tidb-cloud-lake/sql/sign.md new file mode 100644 index 0000000000000..5231a8ab73105 --- /dev/null +++ b/tidb-cloud-lake/sql/sign.md @@ -0,0 +1,26 @@ +--- +title: SIGN +summary: 根据 `x` 是负数、零还是正数,返回参数的符号 -1、0 或 1;如果参数为 NULL,则返回 NULL。 +--- + +# SIGN + +根据 `x` 是负数、零还是正数,返回参数的符号 -1、0 或 1;如果参数为 NULL,则返回 NULL。 + +## 语法 {#syntax} + +```sql +SIGN( ) +``` + +## 示例 {#examples} + +```sql +SELECT SIGN(0); + +┌─────────┐ +│ sign(0) │ +├─────────┤ +│ 0 │ +└─────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/sin.md b/tidb-cloud-lake/sql/sin.md new file mode 100644 index 0000000000000..e9460343e8cbb --- /dev/null +++ b/tidb-cloud-lake/sql/sin.md @@ -0,0 +1,26 @@ +--- +title: SIN +summary: 返回 `x` 的正弦值,其中 `x` 以弧度为单位。 +--- + +# SIN + +返回 `x` 的正弦值,其中 `x` 以弧度为单位。 + +## 语法 {#syntax} + +```sql +SIN( ) +``` + +## 示例 {#examples} + +```sql +SELECT SIN(90); + +┌────────────────────┐ +│ sin(90) │ +├────────────────────┤ +│ 0.8939966636005579 │ +└────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/siphash-sql.md b/tidb-cloud-lake/sql/siphash-sql.md new file mode 100644 index 0000000000000..5106897e3a905 --- /dev/null +++ b/tidb-cloud-lake/sql/siphash-sql.md @@ -0,0 +1,30 @@ +--- +title: SIPHASH64 +summary: 生成一个 64 位 SipHash 哈希值。 +--- + +# SIPHASH64 + +生成一个 64 位 [SipHash](https://en.wikipedia.org/wiki/SipHash) 哈希值。 + +## 语法 {#syntax} + +```sql +SIPHASH64() +``` + +## 别名 {#aliases} + +- [SIPHASH](/tidb-cloud-lake/sql/siphash.md) + +## 示例 {#examples} + +```sql +SELECT SIPHASH('1234567890'), SIPHASH64('1234567890'); + +┌─────────────────────────────────────────────────┐ +│ siphash('1234567890') │ siphash64('1234567890') │ +├───────────────────────┼─────────────────────────┤ +│ 18110648197875983073 │ 18110648197875983073 │ +└─────────────────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/siphash.md b/tidb-cloud-lake/sql/siphash.md new file mode 100644 index 0000000000000..aed6a8c6226ed --- /dev/null +++ b/tidb-cloud-lake/sql/siphash.md @@ -0,0 +1,8 @@ +--- +title: SIPHASH +summary: SIPHASH64 的别名。 +--- + +# SIPHASH + +[SIPHASH64](/tidb-cloud-lake/sql/siphash.md) 的别名。 \ No newline at end of file diff --git a/tidb-cloud-lake/sql/skewness.md b/tidb-cloud-lake/sql/skewness.md new file mode 100644 index 0000000000000..9b35b69720e22 --- /dev/null +++ b/tidb-cloud-lake/sql/skewness.md @@ -0,0 +1,60 @@ +--- +title: SKEWNESS +summary: 聚合函数。 +--- + +# SKEWNESS + +聚合函数。 + +`SKEWNESS()` 函数返回所有输入值的偏度。 + +## 语法 {#syntax} + +```sql +SKEWNESS() +``` + +## 参数 {#arguments} + +| 参数 | 描述 | +|-----------| ----------- | +| `` | 任意数值表达式 | + +## 返回类型 {#return-type} + +可为空的 Float64。 + +## 示例 {#example} + +**创建表并插入示例数据** + +```sql +CREATE TABLE temperature_data ( + id INT, + city_id INT, + temperature FLOAT +); + +INSERT INTO temperature_data (id, city_id, temperature) +VALUES (1, 1, 60), + (2, 1, 65), + (3, 1, 62), + (4, 2, 70), + (5, 2, 75); +``` + +**查询演示:计算温度数据的偏度** + +```sql +SELECT SKEWNESS(temperature) AS temperature_skewness +FROM temperature_data; +``` + +**结果** + +```sql +| temperature_skewness | +|----------------------| +| 0.68 | +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/sleep.md b/tidb-cloud-lake/sql/sleep.md new file mode 100644 index 0000000000000..0d80c3ebfc10f --- /dev/null +++ b/tidb-cloud-lake/sql/sleep.md @@ -0,0 +1,39 @@ +--- +title: SLEEP +summary: 在每个数据块上休眠 `seconds` 秒。 +--- + +# SLEEP + +在每个数据块上休眠 `seconds` 秒。 + +> **注意:** +> +> 仅用于需要 sleep 的测试场景。 + +## 语法 {#syntax} + +```sql +SLEEP(seconds) +``` + +## 参数 {#arguments} + +| 参数 | 描述 | +| ----------- | ----------- | +| seconds | 必须是任意非负数或 float 的常数列。| + +## 返回类型 {#return-type} + +UInt8 + +## 示例 {#examples} + +```sql +SELECT sleep(2); ++----------+ +| sleep(2) | ++----------+ +| 0 | ++----------+ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/slice.md b/tidb-cloud-lake/sql/slice.md new file mode 100644 index 0000000000000..1c2084a939571 --- /dev/null +++ b/tidb-cloud-lake/sql/slice.md @@ -0,0 +1,30 @@ +--- +title: SLICE +summary: 按索引(从 1 开始)从数组中提取一个切片。 +--- + +# SLICE + +按索引(从 1 开始)从数组中提取一个切片。 + +## 语法 {#syntax} + +```sql +SLICE( , [, ] ) +``` + +## 别名 {#aliases} + +- [ARRAY_SLICE](/tidb-cloud-lake/sql/array-slice.md) + +## 示例 {#examples} + +```sql +SELECT ARRAY_SLICE([1, 21, 32, 4], 2, 3), SLICE([1, 21, 32, 4], 2, 3); + +┌─────────────────────────────────────────────────────────────────┐ +│ array_slice([1, 21, 32, 4], 2, 3) │ slice([1, 21, 32, 4], 2, 3) │ +├───────────────────────────────────┼─────────────────────────────┤ +│ [21,32] │ [21,32] │ +└─────────────────────────────────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/soundex.md b/tidb-cloud-lake/sql/soundex.md new file mode 100644 index 0000000000000..533d414f2bb49 --- /dev/null +++ b/tidb-cloud-lake/sql/soundex.md @@ -0,0 +1,74 @@ +--- +title: SOUNDEX +summary: 为字符串生成 Soundex 代码。 +--- + +# SOUNDEX + +为字符串生成 Soundex 代码。 + +- Soundex 代码由一个字母和三个数字组成。{{{ .lake }}} 的实现会返回超过 4 位的结果,但你可以对结果使用 [SUBSTR](/tidb-cloud-lake/sql/substr.md) 以获取标准的 Soundex 代码。 +- 字符串中所有非字母字符都会被忽略。 +- 除非是首字母,否则 A-Z 范围之外的所有国际字母字符都会被忽略。 + +> **Tip:** +> +> Soundex 会根据字符串用英语发音时的读音,将字母数字字符串转换为一个四字符代码。更多信息,参见 + +另请参阅:[SOUNDS LIKE](/tidb-cloud-lake/sql/sounds-like.md) + +## 语法 {#syntax} + +```sql +SOUNDEX() +``` + +## 参数 {#arguments} + +| 参数 | 描述 | +|-----------|-------------| +| str | 字符串。 | + +## 返回类型 {#return-type} + +返回 VARCHAR 类型的代码或 NULL 值。 + +## 示例 {#examples} + +```sql +SELECT SOUNDEX('Datalake'); + +--- +D42 + +-- All non-alphabetic characters in the string are ignored. +SELECT SOUNDEX('Datalake!');; + +--- +D42 + +-- All international alphabetic characters outside the A-Z range are ignored unless they're the first letter. +SELECT SOUNDEX('Datalake,你好'); + +--- +D42 + +SELECT SOUNDEX('你好,Datalake'); + +--- +你342 + +-- SUBSTR the result to get a standard Soundex code. +SELECT SOUNDEX('Datalake Cloud'),SUBSTR(SOUNDEX('Datalake Cloud'),1,4); + +soundex('datalake cloud')|substring(soundex('datalake cloud') from 1 for 4)| +-------------------------+-------------------------------------------------+ +D42243 |D422 | + +SELECT SOUNDEX(NULL); ++-------------------------------------+ +| `SOUNDEX(NULL)` | ++-------------------------------------+ +| | ++-------------------------------------+ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/sounds-like.md b/tidb-cloud-lake/sql/sounds-like.md new file mode 100644 index 0000000000000..b5a1ab22d599b --- /dev/null +++ b/tidb-cloud-lake/sql/sounds-like.md @@ -0,0 +1,70 @@ +--- +title: SOUNDS LIKE +summary: 通过两个字符串的 Soundex 代码比较它们的发音。Soundex 是一种语音算法,会生成一个表示字符串发音的代码,从而可以根据发音而非拼写对字符串进行近似匹配。{{{ .lake }}} 提供了 [SOUNDEX](/tidb-cloud-lake/sql/soundex.md) 函数,用于从字符串中获取 Soundex 代码。 +--- + +# SOUNDS LIKE + +通过两个字符串的 Soundex 代码比较它们的发音。Soundex 是一种语音算法,会生成一个表示字符串发音的代码,从而可以根据发音而非拼写对字符串进行近似匹配。{{{ .lake }}} 提供了 [SOUNDEX](/tidb-cloud-lake/sql/soundex.md) 函数,用于从字符串中获取 Soundex 代码。 + +SOUNDS LIKE 常用于 SQL 查询的 WHERE 子句中,通过模糊字符串匹配来缩小结果行范围,例如用于姓名和地址。参见 [示例](#examples) 中的 [过滤行](#filtering-rows)。 + +> **Note:** +> +> 虽然该函数可用于近似字符串匹配,但需要注意的是,它并不总是准确。Soundex 算法基于英语发音规则,对于其他语言或方言的字符串可能效果不佳。 + +## 语法 {#syntax} + +```sql + SOUNDS LIKE +``` + +## 参数 {#arguments} + +| 参数 | 描述 | +|-----------|-------------| +| str1, 2 | 要比较的字符串。 | + +## 返回类型 {#return-type} + +如果两个字符串的 Soundex 代码相同(即它们听起来相似),则返回 Boolean 值 1;否则返回 0。 + +## 示例 {#examples} + +### 比较字符串 {#comparing-strings} + +```sql +SELECT 'two' SOUNDS LIKE 'too' +---- +1 + +SELECT CONCAT('A', 'B') SOUNDS LIKE 'AB'; +---- +1 + +SELECT 'Monday' SOUNDS LIKE 'Sunday'; +---- +0 +``` + +### 过滤行 {#filtering-rows} + +```sql +SELECT * FROM employees; + +id|first_name|last_name|age| +--+----------+---------+---+ + 0|John |Smith | 35| + 0|Mark |Smythe | 28| + 0|Johann |Schmidt | 51| + 0|Eric |Doe | 30| + 0|Sue |Johnson | 45| + +SELECT * FROM employees +WHERE first_name SOUNDS LIKE 'John'; + +id|first_name|last_name|age| +--+----------+---------+---+ + 0|John |Smith | 35| + 0|Johann |Schmidt | 51| +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/space.md b/tidb-cloud-lake/sql/space.md new file mode 100644 index 0000000000000..7e7f5368736a8 --- /dev/null +++ b/tidb-cloud-lake/sql/space.md @@ -0,0 +1,35 @@ +--- +title: SPACE +summary: 返回一个由 N 个空格字符组成的字符串。 +--- + +# SPACE + +返回一个由 N 个空格字符组成的字符串。 + +## 语法 {#syntax} + +```sql +SPACE(); +``` + +## 参数 {#arguments} + +| 参数 | 描述 | +|-----------|----------------------| +| `` | 空格的数量 | + +## 返回类型 {#return-type} + +字符串数据类型值。 + +## 示例 {#examples} + +```sql +SELECT SPACE(20) ++----------------------+ +| SPACE(20) | ++----------------------+ +| | ++----------------------+ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/spatial-index-overview.md b/tidb-cloud-lake/sql/spatial-index-overview.md new file mode 100644 index 0000000000000..904a550f1a02f --- /dev/null +++ b/tidb-cloud-lake/sql/spatial-index-overview.md @@ -0,0 +1,39 @@ +--- +title: 空间索引 +summary: 空间索引可加速对 `GEOMETRY` 列的空间谓词过滤。 +--- + +# 空间索引 + +{{{ .lake }}} 中的空间索引可加速对 `GEOMETRY` 列的空间谓词过滤。它们专为 Fuse 表设计,并帮助优化器在计算精确空间函数之前先裁剪数据块。 + +> **Tip:** +> +> 空间索引会自动维护创建索引后写入的数据。对于创建索引前表中已存在的数据,如果你需要回填现有行,请使用 `REFRESH SPATIAL INDEX`。 + +## 空间索引管理 {#spatial-index-management} + +| Command | 描述 | +|---------|-------------| +| [CREATE SPATIAL INDEX](/tidb-cloud-lake/sql/create-spatial-index.md) | 在一个或多个 `GEOMETRY` 列上创建新的空间索引 | +| [REFRESH SPATIAL INDEX](/tidb-cloud-lake/sql/refresh-spatial-index.md) | 为创建索引前已存在的行回填空间索引数据 | +| [DROP SPATIAL INDEX](/tidb-cloud-lake/sql/drop-spatial-index.md) | 从表中删除空间索引 | + +## 支持的谓词 {#supported-predicates} + +{{{ .lake }}} 可以使用空间索引来加速基于以下空间谓词构建的查询: + +- `ST_CONTAINS` +- `ST_INTERSECTS` +- `ST_WITHIN` +- `ST_DWITHIN` + +## 限制 {#limitations} + +- 空间索引支持用于 Fuse 表。 +- 建立索引的列必须是 `GEOMETRY` 类型。 +- 不支持 `GEOGRAPHY` 列。 + +## 相关主题 {#related-topics} + +- [地理空间函数](/tidb-cloud-lake/sql/geospatial-functions.md) \ No newline at end of file diff --git a/tidb-cloud-lake/sql/split-part.md b/tidb-cloud-lake/sql/split-part.md new file mode 100644 index 0000000000000..d813d6f6c570a --- /dev/null +++ b/tidb-cloud-lake/sql/split-part.md @@ -0,0 +1,67 @@ +--- +title: SPLIT_PART +summary: 使用指定的分隔符切分字符串,并返回指定的部分。 +--- + +# SPLIT_PART + +使用指定的分隔符切分字符串,并返回指定的部分。 + +另请参阅:[SPLIT](/tidb-cloud-lake/sql/split.md) + +## 语法 {#syntax} + +```sql +SPLIT_PART('', '', '') +``` + +*position* 参数用于指定要返回哪一部分。它使用从 1 开始的索引,同时也接受正数、负数或 0: + +- 如果 *position* 是正数,则返回从左到右对应位置的部分;如果该部分不存在,则返回 NULL。 +- 如果 *position* 是负数,则返回从右到左对应位置的部分;如果该部分不存在,则返回 NULL。 +- 如果 *position* 为 0,则按 1 处理,即返回字符串的第一部分。 + +## 返回类型 {#return-type} + +字符串。当输入字符串、分隔符或 position 中任一值为 NULL 时,SPLIT_PART 返回 NULL。 + +## 示例 {#examples} + +```sql +-- 使用空格作为分隔符 +-- SPLIT_PART 返回指定的部分。 +SELECT SPLIT_PART('Datalake Cloud', ' ', 1); + +split_part('datalake cloud', ' ', 1)| +------------------------------------+ +Datalake | + +-- 使用空字符串作为分隔符,或使用输入字符串中不存在的分隔符 +-- SPLIT_PART 返回整个输入字符串。 +SELECT SPLIT_PART('Datalake Cloud', '', 1); + +split_part('datalake cloud', '', 1)| +-----------------------------------+ +Datalake Cloud | + +SELECT SPLIT_PART('Datalake Cloud', ',', 1); + +split_part('datalake cloud', ',', 1)| +------------------------------------+ +Datalake Cloud | + +-- 使用 ' '(tab)作为分隔符 +-- SPLIT_PART 返回各个字段。 +SELECT SPLIT_PART('2023-10-19 15:30:45 INFO Log message goes here', ' ', 3); + +split_part('2023-10-19 15:30:45 info log message goes here', ' ', 3)| +--------------------------------------------------------------------------+ +Log message goes here | + +-- 由于指定的部分完全不存在,SPLIT_PART 返回空字符串。 +SELECT SPLIT_PART('2023-10-19 15:30:45 INFO Log message goes here', ' ', 4); + +split_part('2023-10-19 15:30:45 info log message goes here', ' ', 4)| +--------------------------------------------------------------------------+ + | +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/split.md b/tidb-cloud-lake/sql/split.md new file mode 100644 index 0000000000000..edd8197cdcd84 --- /dev/null +++ b/tidb-cloud-lake/sql/split.md @@ -0,0 +1,55 @@ +--- +title: SPLIT +summary: 使用指定的分隔符切分字符串,并将结果部分作为数组返回。 +--- + +# SPLIT + +使用指定的分隔符切分字符串,并将结果部分作为数组返回。 + +另请参阅:[SPLIT_PART](/tidb-cloud-lake/sql/split-part.md) + +## 语法 {#syntax} + +```sql +SPLIT('', '') +``` + +## 返回类型 {#return-type} + +字符串数组。当输入字符串或分隔符任一为 NULL 时,SPLIT 返回 NULL。 + +## 示例 {#examples} + +```sql +-- 使用空格作为分隔符 +-- SPLIT 返回一个包含两个部分的数组。 +SELECT SPLIT('Datalake Cloud', ' '); + +split('datalake cloud', ' ')| +----------------------------+ +['Datalake','Cloud'] | + +-- 使用空字符串作为分隔符,或使用输入字符串中不存在的分隔符 +-- SPLIT 返回一个仅包含整个输入字符串作为单个部分的数组。 +SELECT SPLIT('Datalake Cloud', ''); + +split('datalake cloud', '')| +---------------------------+ +['Datalake Cloud'] | + +SELECT SPLIT('Datalake Cloud', ','); + +split('datalake cloud', ',')| +----------------------------+ +['Datalake Cloud'] | + +-- 使用 ' '(tab)作为分隔符 +-- SPLIT 返回一个包含时间戳、日志等级和消息的数组。 + +SELECT SPLIT('2023-10-19 15:30:45 INFO Log message goes here', ' '); + +split('2023-10-19 15:30:45\tinfo\tlog message goes here', '\t')| +---------------------------------------------------------------+ +['2023-10-19 15:30:45','INFO','Log message goes here'] | +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/sql-dialects-conformance.md b/tidb-cloud-lake/sql/sql-dialects-conformance.md new file mode 100644 index 0000000000000..f265a4226d303 --- /dev/null +++ b/tidb-cloud-lake/sql/sql-dialects-conformance.md @@ -0,0 +1,201 @@ +--- +title: SQL 方言与一致性 +summary: 本页介绍 {{{ .lake }}} 支持的 SQL 方言,以及它对 SQL 标准的符合情况,重点说明 SQL:2011 特性及其在 {{{ .lake }}} 中的支持状态。 +--- + +# SQL 方言与一致性 + +本页介绍 {{{ .lake }}} 支持的 SQL 方言,以及它对 SQL 标准的符合情况,重点说明 SQL:2011 特性及其在 {{{ .lake }}} 中的支持状态。 + +## 支持的 SQL 方言 {#supported-sql-dialects} + +SQL 方言是指结构化查询语言(Structured Query Language)的一种特定变体或风格。{{{ .lake }}} 默认支持 `PostgreSQL` 方言,并且可以灵活切换到其他受支持的方言。有关支持的方言及其简要说明,请参见下表: + +| 方言 | 简介 | 了解更多 | +|---------------|--------------------------------------------------------------------------------------------------|------------------------------| +| `PostgreSQL` | 默认支持的方言,常用于企业环境 | | +| `MySQL` | 开源数据库管理系统 | | +| `Hive` | 用于大数据处理的数据仓库 | | +| `Prql` | PRQL 是一种现代数据转换语言——可作为简单、强大且支持管道式处理的 SQL 替代方案 | | +| `Experimental`| 用于测试和研究的实验性方言 | N/A | + +如需在支持的 SQL 方言之间切换,或显示当前方言,请使用 `sql_dialect` 设置: + +```sql title='Examples:' +-- Set SQL dialect to PRQL +SET sql_dialect = 'Prql'; + +-- Display current dialect +SHOW SETTINGS LIKE 'sql_dialect'; +``` + +## SQL 一致性摘要 {#sql-conformance-summary} + +{{{ .lake }}} 致力于遵循 SQL 标准,尤其支持 ISO/IEC 9075:2011,也称为 SQL:2011。虽然这并不是一份完整的符合性声明,但 {{{ .lake }}} 已实现 SQL 标准要求的许多特性,只是在语法或函数上通常存在一些细微差异。本页概述了 {{{ .lake }}} 对 SQL:2011 标准的符合程度。 + +| Feature ID | 功能名称 | 是否支持 | 说明 | +|:----------: |:------------------------------------------------------------------------------------------------------------------------: |:----------: |:------------------------------------------------------------------------------------------------------------: | +| **E011** | **数值数据类型** | Yes | | +| E011-01 | INTEGER 和 SMALLINT 数据类型 | Yes | | +| E011-02 | REAL、DOUBLE PRECISION 和 FLOAT 数据类型 | Yes | | +| E011-03 | DECIMAL 和 NUMERIC 数据类型 | Yes | | +| E011-04 | 算术运算符 | Yes | | +| E011-05 | 数值比较 | Yes | | +| E011-06 | 数值数据类型之间的隐式类型转换 | Yes | | +| **E021** | **字符字符串类型** | Partial | | +| E021-01 | CHARACTER 数据类型 | No | 不支持定长字符串类型 | +| E021-02 | CHARACTER VARYING 数据类型 | Yes | | +| E021-03 | 字符字面量 | Yes | | +| E021-04 | CHARACTER_LENGTH 函数 | Yes | | +| E021-05 | OCTET_LENGTH 函数 | Yes | | +| E021-06 | SUBSTRING | Yes | | +| E021-07 | 字符串拼接 | Yes | | +| E021-08 | UPPER 和 LOWER 函数 | Yes | | +| E021-09 | TRIM 函数 | Yes | | +| E021-10 | 定长和变长字符字符串类型之间的隐式类型转换 | No | 不支持定长字符串类型 | +| E021-11 | POSITION 函数 | Yes | | +| E021-12 | 字符比较 | Yes | | +| **E031** | **标识符** | Yes | | +| E031-01 | 定界标识符 | Yes | | +| E031-02 | 小写标识符 | Yes | | +| E031-03 | 尾随下划线 | Yes | | +| **E051** | **基本查询规范** | Partial | | +| E051-01 | SELECT DISTINCT | Yes | | +| E051-02 | GROUP BY 子句 | Yes | | +| E051-04 | GROUP BY 可以包含未出现在 SELECT 列表中的列 | Yes | | +| E051-05 | 可以重命名选择项 | Yes | | +| E051-06 | HAVING 子句 | Yes | | +| E051-07 | select 列表中的限定 * | No | | +| E051-08 | FROM 子句中的相关名称 | Yes | | +| E051-09 | 在 FROM 子句中重命名列 | No | | +| **E061** | **基本谓词和搜索条件** | Partial | | +| E061-01 | 比较谓词 | Yes | | +| E061-02 | BETWEEN 谓词 | Yes | | +| E061-03 | 带值列表的 IN 谓词 | Yes | | +| E061-04 | LIKE 谓词 | Yes | | +| E061-05 | LIKE 谓词:ESCAPE 子句 | No | | +| E061-06 | NULL 谓词 | Yes | | +| E061-07 | 量化比较谓词 | Yes | | +| E061-08 | EXISTS 谓词 | Yes | | +| E061-09 | 比较谓词中的子查询 | Yes | | +| E061-11 | IN 谓词中的子查询 | Yes | | +| E061-12 | 量化比较谓词中的子查询 | Yes | | +| E061-13 | 相关子查询 | Yes | | +| E061-14 | 搜索条件 | Yes | | +| **E071** | **基本查询表达式** | Partial | | +| E071-01 | UNION DISTINCT 表运算符 | Yes | | +| E071-02 | UNION ALL 表运算符 | Yes | | +| E071-03 | EXCEPT DISTINCT 表运算符 | Yes | | +| E071-05 | 通过表运算符组合的列不需要具有完全相同的数据类型 | Partial | 仅允许可进行隐式强制转换的数据类型列通过表运算符进行组合。 | +| E071-06 | 子查询中的表运算符 | Yes | | +| **E081** | **基本权限** | Partial | | +| E081-01 | 表级 SELECT 权限 | Yes | | +| E081-02 | DELETE 权限 | Yes | | +| E081-03 | 表级 INSERT 权限 | Yes | | +| E081-04 | 表级 UPDATE 权限 | Yes | | +| E081-05 | 列级 UPDATE 权限 | No | | +| E081-06 | 表级 REFERENCES 权限 | No | | +| E081-07 | 列级 REFERENCES 权限 | No | | +| E081-08 | WITH GRANT OPTION | No | | +| E081-09 | USAGE 权限 | No | | +| E081-10 | EXECUTE 权限 | No | | +| **E091** | **集合函数** | Yes | | +| E091-01 | AVG | Yes | | +| E091-02 | COUNT | Yes | | +| E091-03 | MAX | Yes | | +| E091-04 | MIN | Yes | | +| E091-05 | SUM | Yes | | +| E091-06 | ALL 量词 | Yes | | +| E091-07 | DISTINCT 量词 | Partial | 当前,{{{ .lake }}} 支持 COUNT(DISTINCT ...) 和 SELECT DISTINCT ... 查询。 | +| **E101** | **基本数据操作** | Partial | | +| E101-01 | INSERT 语句 | Yes | | +| E101-03 | 搜索式 UPDATE 语句 | Yes | | +| E101-04 | 搜索式 DELETE 语句 | Yes | | +| **E111** | **单行 SELECT 语句** | Yes | | +| **E121** | **基本游标支持** | Partial | | +| E121-01 | DECLARE CURSOR | No | | +| E121-02 | ORDER BY 列不必出现在 select 列表中 | Yes | | +| E121-03 | ORDER BY 子句中的值表达式 | Yes | | +| E121-04 | OPEN 语句 | No | | +| E121-06 | 定位 UPDATE 语句 | No | | +| E121-07 | 定位 DELETE 语句 | No | | +| E121-08 | CLOSE 语句 | No | | +| E121-10 | FETCH 语句:隐式 NEXT | No | | +| E121-17 | WITH HOLD 游标 | No | | +| **E131** | **空值支持(以空值代替值)** | Yes | | +| **E141** | **基本完整性约束** | No | | +| E141-01 | NOT NULL 约束 | Yes | {{{ .lake }}} 中的默认行为:所有列都允许为空。 | +| E141-02 | NOT NULL 列的 UNIQUE 约束 | No | | +| E141-03 | PRIMARY KEY 约束 | No | | +| E141-04 | 基本 FOREIGN KEY 约束,引用删除动作和引用修改动作的默认值均为 NO ACTION | No | | +| E141-06 | CHECK 约束 | No | | +| E141-07 | 列默认值 | Yes | | +| E141-08 | 在 PRIMARY KEY 上推导 NOT NULL | No | | +| E141-10 | 外键中的名称可以按任意顺序指定 | No | | +| **E151** | **事务支持** | Partial | | +| E151-01 | COMMIT 语句 | Partial | {{{ .lake }}} 仅支持对每条单独 DML 语句使用隐式事务。 | +| E151-02 | ROLLBACK 语句 | No | | +| **E152** | **基本 SET TRANSACTION 语句** | No | | +| E152-01 | SET TRANSACTION 语句:ISOLATION LEVEL SERIALIZABLE 子句 | No | | +| E152-02 | SET TRANSACTION 语句:READ ONLY 和 READ WRITE 子句 | No | | +| **E153** | **带子查询的可修改查询** | Yes | | +| **E161** | **使用前导双减号的 SQL 注释** | Yes | | +| **E171** | **SQLSTATE 支持** | No | | +| **E182** | **主机语言绑定** | No | | +| **F031** | **基本模式操作** | Yes | | +| F031-01 | 用于创建持久基表的 CREATE TABLE 语句 | Yes | | +| F031-02 | CREATE VIEW 语句 | Yes | | +| F031-03 | GRANT 语句 | Partial | | +| F031-04 | ALTER TABLE 语句:ADD COLUMN 子句 | Yes | | +| F031-13 | DROP TABLE 语句:RESTRICT 子句 | Partial | | +| F031-16 | DROP VIEW 语句:RESTRICT 子句 | Partial | | +| F031-19 | REVOKE 语句:RESTRICT 子句 | Partial | | +| **F041** | **基本连接表** | Yes | | +| F041-01 | 内连接(但不一定要求使用 INNER 关键字) | Yes | | +| F041-02 | INNER 关键字 | Yes | | +| F041-03 | LEFT OUTER JOIN | Yes | | +| F041-04 | RIGHT OUTER JOIN | Yes | | +| F041-05 | 外连接可以嵌套 | Yes | | +| F041-07 | 左外连接或右外连接中的内表也可以用于内连接 | Yes | | +| F041-08 | 支持所有比较运算符(而不仅仅是 =) | Yes | | +| **F051** | **基本日期和时间** | Partial | | +| F051-01 | DATE 数据类型(包括支持 DATE 字面量) | Yes | | +| F051-02 | TIME 数据类型(包括支持 TIME 字面量),小数秒精度至少为 0 | No | | +| F051-03 | TIMESTAMP 数据类型(包括支持 TIMESTAMP 字面量),小数秒精度至少为 0 和 6 | Yes | | +| F051-04 | DATE、TIME 和 TIMESTAMP 数据类型上的比较谓词 | Yes | | +| F051-05 | datetime 类型与字符字符串类型之间的显式 CAST | Yes | | +| F051-06 | CURRENT_DATE | Yes | | +| F051-07 | LOCALTIME | Yes | | +| F051-08 | LOCALTIMESTAMP | Yes | | +| **F081** | **视图中的 UNION 和 EXCEPT** | Yes | | +| **F131** | **分组操作** | Yes | | +| F131-01 | 在带分组视图的查询中支持 WHERE、GROUP BY 和 HAVING 子句 | Yes | | +| F131-02 | 在带分组视图的查询中支持多表 | Yes | | +| F131-03 | 在带分组视图的查询中支持集合函数 | Yes | | +| F131-04 | 带 GROUP BY 和 HAVING 子句以及分组视图的子查询 | Yes | | +| F131-05 | 带 GROUP BY 和 HAVING 子句以及分组视图的单行 SELECT | Yes | | +| **F181** | **多模块支持** | No | | +| **F201** | **CAST 函数** | Yes | | +| **F221** | **显式默认值** | No | | +| **F261** | **CASE 表达式** | Yes | | +| F261-01 | 简单 CASE | Yes | | +| F261-02 | 搜索式 CASE | Yes | | +| F261-03 | NULLIF | Yes | | +| F261-04 | COALESCE | Yes | | +| **F311** | **模式定义语句** | Partial | | +| F311-01 | CREATE SCHEMA | Yes | | +| F311-02 | 用于持久基表的 CREATE TABLE | Yes | | +| F311-03 | CREATE VIEW | Yes | | +| F311-04 | CREATE VIEW:WITH CHECK OPTION | No | | +| F311-05 | GRANT 语句 | Partial | | +| **F471** | **标量子查询值** | Yes | | +| **F481** | **扩展的 NULL 谓词** | Yes | | +| **F812** | **基本标记** | No | | +| **S011** | **不同数据类型** | No | | +| **T321** | **基本 SQL 调用例程** | No | | +| T321-01 | 无重载的用户定义函数 | Yes | | +| T321-02 | 无重载的用户定义存储过程 | No | | +| T321-03 | 函数调用 | Yes | | +| T321-04 | CALL 语句 | No | | +| T321-05 | RETURN 语句 | No | | +| **T631** | **带单个列表元素的 IN 谓词** | Yes | | \ No newline at end of file diff --git a/tidb-cloud-lake/sql/sql-function-reference.md b/tidb-cloud-lake/sql/sql-function-reference.md new file mode 100644 index 0000000000000..2a4e03075a8ac --- /dev/null +++ b/tidb-cloud-lake/sql/sql-function-reference.md @@ -0,0 +1,93 @@ +--- +title: SQL 函数参考 +summary: "{{{ .lake }}} 提供了适用于各类数据处理场景的全面 SQL 函数。函数按重要性和使用频率进行组织。" +--- + +# SQL 函数参考 + +{{{ .lake }}} 提供了适用于各类数据处理场景的全面 SQL 函数。函数按重要性和使用频率进行组织。 + +> **提示:** +> +> **找不到你需要的函数?** 如果下面的内置函数都无法覆盖你的逻辑需求,你可以使用 [用户定义函数(UDF)](/tidb-cloud-lake/sql/user-defined-function.md) 定义自己的函数。UDF 允许你使用 SQL 表达式、Python 或 JavaScript 实现自定义标量函数、聚合函数和表函数,然后像调用任何内置函数一样调用它们。参见下文的[使用 User-Defined Functions 扩展](#extending-with-user-defined-functions)。 + +## 核心数据函数 {#core-data-functions} + +| 类别 | 描述 | +|----------|-------------| +| [数值函数](/tidb-cloud-lake/sql/numeric-functions.md) | 数学运算与计算 | +| [字符串函数](/tidb-cloud-lake/sql/string-functions-overview.md) | 文本处理与字符串处理 | +| [日期和时间函数](/tidb-cloud-lake/sql/date-time-functions.md) | 日期、时间和时态操作 | +| [转换函数](/tidb-cloud-lake/sql/conversion-functions.md) | 类型转换与数据格式转换 | +| [条件函数](/tidb-cloud-lake/sql/conditional-functions.md) | 逻辑与控制流操作 | + +## 分析函数 {#analytics-functions} + +| 类别 | 描述 | +|----------|-------------| +| [聚合函数](/tidb-cloud-lake/sql/aggregate-functions.md) | 跨多行的统计计算 | +| [窗口函数](/tidb-cloud-lake/sql/window-functions-overview.md) | 使用窗口操作进行高级分析 | + +## 结构化与半结构化数据 {#structured-semi-structured-data} + +| 类别 | 描述 | +|----------|-------------| +| [结构化和半结构化函数](/tidb-cloud-lake/sql/structured-semi-structured-functions.md) | JSON、数组、对象和嵌套数据处理 | + +## 搜索函数 {#search-functions} + +| 类别 | 描述 | +|----------|-------------| +| [全文搜索函数](/tidb-cloud-lake/sql/full-text-search-functions.md) | 全文搜索与相关性评分 | + +## 向量函数 {#vector-functions} + +| 类别 | 描述 | +|----------|-------------| +| [向量函数](/tidb-cloud-lake/sql/vector-functions.md) | 向量相似度与距离计算 | + +## 地理空间函数 {#geospatial-functions} + +| 类别 | 描述 | +|----------|-------------| +| [Geospatial Functions](/tidb-cloud-lake/sql/geospatial-functions.md) | 几何、GeoHash 和 H3 空间操作 | + +## 数据管理 {#data-management} + +| 类别 | 描述 | +|----------|-------------| +| [表函数](/tidb-cloud-lake/sql/table-functions.md) | 文件检查、数据生成和系统信息 | +| [系统函数](/tidb-cloud-lake/sql/system-functions.md) | 系统信息与管理操作 | +| [上下文函数](/tidb-cloud-lake/sql/context-functions.md) | 当前会话、用户和数据库信息 | + +## 安全性与完整性 {#security-integrity} + +| 类别 | 描述 | +|----------|-------------| +| [散列函数](/tidb-cloud-lake/sql/hash-functions.md) | 数据散列与完整性验证 | +| [位图函数](/tidb-cloud-lake/sql/bitmap-functions.md) | 高性能位图操作与分析 | +| [UUID 函数](/tidb-cloud-lake/sql/uuid-functions.md) | 通用唯一标识符生成 | +| [IP 地址函数](/tidb-cloud-lake/sql/ip-address-functions.md) | 网络地址处理与验证 | + +## 实用函数 {#utility-functions} + +| 类别 | 描述 | +|----------|-------------| +| [区间函数](/tidb-cloud-lake/sql/interval-functions.md) | 时间单位转换与区间创建 | +| [序列函数](/tidb-cloud-lake/sql/sequence-functions-overview.md) | 自增序列值生成 | +| [数据匿名化函数](/tidb-cloud-lake/sql/data-anonymization-functions.md) | 数据脱敏与匿名化工具 | +| [测试函数](/tidb-cloud-lake/sql/test-functions.md) | 测试与调试工具 | +| [其他函数](/tidb-cloud-lake/sql/other-functions.md) | 其他辅助函数与工具 | + +## 使用 User-Defined Functions 扩展 {#extending-with-user-defined-functions} + +当上述内置函数无法覆盖你的特定逻辑时,可以使用 [用户定义函数(UDF)](/tidb-cloud-lake/sql/user-defined-function.md) 定义自己的函数。创建后,UDF 在查询中的调用方式与内置函数完全相同。 + +| 函数类型 | 适用场景 | +| --------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------- | +| [标量函数 (SQL)](/tidb-cloud-lake/sql/create-scalar-function.md) | 你希望在多个查询中复用某个 SQL 表达式(如数学计算、字符串格式化)。 | +| [标量函数 (Python/JavaScript)](/tidb-cloud-lake/sql/create-scalar-function.md) | 你的逻辑需要控制流、外部库或高级算法。 | +| [聚合函数](/tidb-cloud-lake/sql/create-aggregate-function.md) | 你需要内置聚合函数无法表达的自定义聚合。 | +| [表函数](/tidb-cloud-lake/sql/create-table-function.md) | 你希望使用可复用、带参数的查询来返回结果集。 | + +如需了解 UDF 类型和语法的完整对比,请参见 [用户定义函数](/tidb-cloud-lake/sql/user-defined-function.md)。 \ No newline at end of file diff --git a/tidb-cloud-lake/sql/sql-identifiers.md b/tidb-cloud-lake/sql/sql-identifiers.md new file mode 100644 index 0000000000000..9f8d6ac9c067e --- /dev/null +++ b/tidb-cloud-lake/sql/sql-identifiers.md @@ -0,0 +1,181 @@ +--- +title: SQL 标识符 +summary: SQL 标识符是在 {{{ .lake }}} 中用于不同元素的名称,例如表、视图和数据库。 +--- + +# SQL 标识符 + +SQL 标识符是在 {{{ .lake }}} 中用于不同元素的名称,例如表、视图和数据库。 + +## 不带引号和双引号标识符 {#unquoted-double-quoted-identifiers} + +不带引号的标识符以字母(A-Z、a-z)或下划线(“_”)开头,并且可以由字母、下划线、数字(0-9)或美元符号(“$”)组成。 + +```text title='Examples:' +mydatalake +MyDatalake1 +My$datalake +_my_datalake +``` + +双引号标识符可以包含更广泛的字符,例如数字(0-9)、特殊字符(如句点(.)、单引号(')、感叹号(!)、at 符号(@)、井号(#)、美元符号($)、百分号(%)、插入符号(^)和与号(&))、扩展 ASCII 和非 ASCII 字符,以及空格。 + +```text title='Examples:' +"MyDatalake" +"my.datalake" +"my datalake" +"My 'Datalake'" +"1_datalake" +"$Datalake" +``` + +请注意,使用双反引号(``)或双引号(")是等价的: + +```text title='Examples:' +`MyDatalake` +`my.datalake` +`my datalake` +`My 'Datalake'` +`1_datalake` +`$Datalake` +``` + +## 标识符大小写规则 {#identifier-casing-rules} + +默认情况下,{{{ .lake }}} 会将不带引号的标识符以小写形式存储,而双引号标识符则按输入时的形式存储。换句话说,{{{ .lake }}} 默认将数据库、表和列等对象名称视为大小写不敏感。如果你希望 {{{ .lake }}} 将它们视为大小写敏感,请使用双引号。 + +> **注意:** +> +> 默认情况下,{{{ .lake }}} 遵循 PostgreSQL 风格的标识符大小写规则:不带引号的标识符会折叠为小写,而双引号标识符会保留其精确大小写并且大小写敏感。此行为由以下两个设置控制: +> +> - `unquoted_ident_case_sensitive`:默认值为 `0`,因此不带引号的标识符大小写不敏感,并会折叠为小写。将其设置为 `1` 会保留不带引号标识符的大小写,使其变为大小写敏感。 +> - `quoted_ident_case_sensitive`:默认值为 `1`,因此双引号标识符会保留字符大小写并且大小写敏感。将其设置为 `0` 会使双引号标识符变为大小写不敏感。 +> +> 如果你更希望使用 MySQL 风格的行为,即无论是否加引号标识符都大小写不敏感,请将 `unquoted_ident_case_sensitive` 和 `quoted_ident_case_sensitive` 都设置为 `0`。 + +### 为什么 `SELECT *` 可以工作,而 `SELECT ` 会失败 {#why-select-works-but-select-fails} + +一个常见的困惑来源是:某个表的列是在保留大小写的引号(双引号或反引号)下创建的,例如 `"Employee_ID"`。在默认设置下,`SELECT *` 可以返回数据,但按列名引用时,无论你使用什么大小写形式都会失败: + +```sql +-- Columns created with the case preserved +CREATE TABLE xxxTable ("Employee_ID" INT, "Department" VARCHAR); +INSERT INTO xxxTable VALUES (1, 'Eng'); + +-- Works: no column is referenced by name +SELECT * FROM xxxTable; + +-- Fails: unquoted names are folded to lowercase (employee_id / department), +-- which do not match the stored "Employee_ID" / "Department" +SELECT Employee_ID FROM xxxTable; +SELECT employee_id FROM xxxTable; + +-- Works: double quotes preserve the case and match the stored column name +SELECT "Employee_ID" FROM xxxTable; +``` + +这是因为 `unquoted_ident_case_sensitive` 的默认值为 `0`,因此 `Employee_ID` 和 `employee_id` 都会被解析为 `employee_id`,而该列并不存在。要确认列名的实际大小写,请运行 `DESC xxxTable;` 或 `SHOW CREATE TABLE xxxTable;`。 + +为避免这种情况,你可以在引用列时使用与创建时完全一致大小写的双引号;或者更推荐的做法是,在创建数据库、表和列时仅使用小写字母、数字和下划线(不加引号)。 + +以下示例演示了 {{{ .lake }}} 在创建和列出数据库时如何处理标识符的大小写: + +```sql +-- Create a database named "datalake" +CREATE DATABASE datalake; + +-- Attempt to create a database named "Datalake" +CREATE DATABASE Datalake; + +>> SQL Error [1105] [HY000]: DatabaseAlreadyExists. Code: 2301, Text = Database 'datalake' already exists. + +-- Create a database named "Datalake" +CREATE DATABASE "Datalake"; + +-- List all databases +SHOW DATABASES; + +databases_in_default| +--------------------+ +Datalake | +datalake | +default | +information_schema | +system | +``` + +以下示例演示了 {{{ .lake }}} 如何处理表名和列名的大小写,突出显示了其默认的大小写敏感行为,以及如何使用双引号区分大小写不同的标识符: + +```sql +-- Create a table named "datalake" +CREATE TABLE datalake (a INT); +DESC datalake; + +Field|Type|Null|Default|Extra| +-----+----+----+-------+-----+ +a |INT |YES |NULL | | + +-- Attempt to create a table named "Datalake" +CREATE TABLE Datalake (a INT); + +>> SQL Error [1105] [HY000]: TableAlreadyExists. Code: 2302, Text = Table 'datalake' already exists. + +-- Attempt to create a table with one column named "a" and the other one named "A" +CREATE TABLE "Datalake" (a INT, A INT); + +>> SQL Error [1105] [HY000]: BadArguments. Code: 1006, Text = Duplicated column name: a. + +-- Double quote the column names +CREATE TABLE "Datalake" ("a" INT, "A" INT); +DESC "Datalake"; + +Field|Type|Null|Default|Extra| +-----+----+----+-------+-----+ +a |INT |YES |NULL | | +A |INT |YES |NULL | | +``` + +## 字符串标识符 {#string-identifiers} + +在 {{{ .lake }}} 中,处理文本和日期等字符串项时,标准做法是将它们用单引号(')括起来。 + +```sql +INSERT INTO weather VALUES ('San Francisco', 46, 50, 0.25, '1994-11-27'); + +SELECT 'Datalake'; + +'datalake'| +----------+ +Datalake | + +SELECT "Datalake"; + +>> SQL Error [1105] [HY000]: SemanticError. Code: 1065, Text = error: + --> SQL:1:73 + | +1 | /* ApplicationName=DBeaver 23.2.0 - SQLEditor */ SELECT "Datalake" + | ^^^^^^^^^^ column Datalake doesn't exist, do you mean 'Datalake'? +``` + +默认情况下,{{{ .lake }}} 的 SQL 方言为 `PostgreSQL`: + +```sql +SHOW SETTINGS LIKE '%sql_dialect%'; + +name |value |default |level |description |type | +-----------+----------+----------+-------+---------------------------------------------------------------------------------+------+ +sql_dialect|PostgreSQL|PostgreSQL|SESSION|Sets the SQL dialect. Available values include "PostgreSQL", "MySQL", and "Hive".|String| +``` + +你可以将其更改为 `MySQL` 以启用双引号(`"`): + +```sql +SET sql_dialect='MySQL'; + +SELECT "demo"; ++--------+ +| 'demo' | ++--------+ +| demo | ++--------+ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/sql-statements-overview.md b/tidb-cloud-lake/sql/sql-statements-overview.md new file mode 100644 index 0000000000000..d6eb612e2ef42 --- /dev/null +++ b/tidb-cloud-lake/sql/sql-statements-overview.md @@ -0,0 +1,19 @@ +--- +title: SQL 语句概览 +summary: 这些主题提供 {{{ .lake }}} 中各种 SQL 命令的参考信息。 +--- + +# SQL 语句概览 + +这些主题提供 {{{ .lake }}} 中各种 SQL 命令的参考信息。 + +## 命令类别 {#command-categories} + +| 类别 | 描述 | +|----------|-------------| +| **[DDL 命令](/tidb-cloud-lake/sql/ddl.md)** | 数据定义语言 - 创建、修改和删除数据库对象 | +| **[DML 命令](/tidb-cloud-lake/sql/dml.md)** | 数据操作语言 - 插入、修改、删除和复制数据 | +| **[查询语法](/tidb-cloud-lake/sql/query-syntax.md)** | SELECT 语句组件 - FROM、WHERE、GROUP BY、JOIN 等 | +| **[查询运算符](/tidb-cloud-lake/sql/query-operators.md)** | 算术、比较、逻辑及其他运算符 | +| **[EXPLAIN 命令](/tidb-cloud-lake/sql/explain-commands.md)** | 查询分析和优化工具 | +| **[管理命令](/tidb-cloud-lake/sql/administration-commands.md)** | 系统监控、配置和维护 | \ No newline at end of file diff --git a/tidb-cloud-lake/sql/sql-statements-reference.md b/tidb-cloud-lake/sql/sql-statements-reference.md new file mode 100644 index 0000000000000..9cf59c158bcbb --- /dev/null +++ b/tidb-cloud-lake/sql/sql-statements-reference.md @@ -0,0 +1,8 @@ +--- +title: SQL 语句参考 +summary: 本页已迁移至 SQL 语句概览。 +--- + +# SQL 语句参考 + +本页已迁移至 [SQL 语句概览](/tidb-cloud-lake/sql/sql-statements-overview.md)。 \ No newline at end of file diff --git a/tidb-cloud-lake/sql/sql-variables.md b/tidb-cloud-lake/sql/sql-variables.md new file mode 100644 index 0000000000000..fb1a16737630a --- /dev/null +++ b/tidb-cloud-lake/sql/sql-variables.md @@ -0,0 +1,59 @@ +--- +title: SQL 变量 +summary: SQL 变量允许你在会话中存储和管理临时数据,使脚本更具动态性和可复用性。 +--- + +# SQL 变量 + +SQL 变量允许你在会话中存储和管理临时数据,使脚本更具动态性和可复用性。 + +## 变量命令 {#variable-commands} + +| 命令 | 描述 | +|---------|-------------| +| [SET VARIABLE](/tidb-cloud-lake/sql/set-variable.md) | 创建或修改会话变量或用户变量。 | +| [UNSET VARIABLE](/tidb-cloud-lake/sql/unset-variable.md) | 删除用户定义的变量。 | +| [SHOW VARIABLES](/tidb-cloud-lake/sql/show-variables.md) | 显示系统变量和用户变量的当前值。 | + +SHOW VARIABLES 命令还有一个对应的表函数 [`SHOW_VARIABLES`](/tidb-cloud-lake/sql/show-variables.md),它以表格形式返回相同的信息,以便进行更丰富的过滤和查询。 + +## 使用变量进行查询 {#querying-with-variables} + +你可以在语句中引用变量,以实现动态值替换或在运行时构建对象名称。 + +### 使用 `$` 和 `getvariable()` 访问变量 {#accessing-variables-with-and-getvariable} + +使用 `$` 符号或 `getvariable()` 函数,可以将变量值直接嵌入查询中。 + +```sql title='Example:' +-- Set a variable to use as a filter value +SET VARIABLE threshold = 100; + +-- Use the variable in a query with $ +SELECT * FROM sales WHERE amount > $threshold; + +-- Alternatively, use the getvariable() function +SELECT * FROM sales WHERE amount > getvariable('threshold'); +``` + +### 使用 `IDENTIFIER` 访问对象 {#accessing-objects-with-identifier} + +`IDENTIFIER` 关键字允许你引用名称存储在变量中的数据库对象,从而实现灵活的查询构造。(注意:LakeSQL 目前尚不支持 `IDENTIFIER`。) + +```sql title='Example:' +-- Create a table with sales data +CREATE TABLE sales_data (region TEXT, sales_amount INT, month TEXT) AS +SELECT 'North', 5000, 'January' UNION ALL +SELECT 'South', 3000, 'January'; + +select * from sales_data; + +-- Set variables for the table name and column name +SET VARIABLE table_name = 'sales_data'; +SET VARIABLE column_name = 'sales_amount'; + +-- Use IDENTIFIER to dynamically reference the table and column in the query +SELECT region, IDENTIFIER($column_name) +FROM IDENTIFIER($table_name) +WHERE IDENTIFIER($column_name) > 4000; +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/sqrt.md b/tidb-cloud-lake/sql/sqrt.md new file mode 100644 index 0000000000000..a2f57caade9ac --- /dev/null +++ b/tidb-cloud-lake/sql/sqrt.md @@ -0,0 +1,26 @@ +--- +title: SQRT +summary: 返回非负数 `x` 的平方根。对于负数输入,返回 Nan。 +--- + +# SQRT + +返回非负数 `x` 的平方根。对于负数输入,返回 Nan。 + +## 语法 {#syntax} + +```sql +SQRT( ) +``` + +## 示例 {#examples} + +```sql +SELECT SQRT(4); + +┌─────────┐ +│ sqrt(4) │ +├─────────┤ +│ 2 │ +└─────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/st-area.md b/tidb-cloud-lake/sql/st-area.md new file mode 100644 index 0000000000000..5b9fcafd6e81e --- /dev/null +++ b/tidb-cloud-lake/sql/st-area.md @@ -0,0 +1,56 @@ +--- +title: ST_AREA +summary: 返回 GEOMETRY 或 GEOGRAPHY 对象的面积。对于 GEOMETRY 输入,该函数基于 [shoelace formula](https://en.wikipedia.org/wiki/Shoelace_formula) 计算平面面积。对于 GEOGRAPHY 输入,该函数使用 [Karney (2013)](https://arxiv.org/pdf/1109.4448.pdf) 中描述的方法,在地球椭球模型上测量测地面积。 +--- + +# ST_AREA + +返回 GEOMETRY 或 GEOGRAPHY 对象的面积。对于 GEOMETRY 输入,该函数基于 [shoelace formula](https://en.wikipedia.org/wiki/Shoelace_formula) 计算平面面积。对于 GEOGRAPHY 输入,该函数使用 [Karney (2013)](https://arxiv.org/pdf/1109.4448.pdf) 中描述的方法,在地球椭球模型上测量测地面积。 + +## 语法 {#syntax} + +```sql +ST_AREA() +``` + +## 参数 {#arguments} + +| 参数 | 描述 | +|---------------------------|-----------------------------------------------------------------| +| `` | 该参数必须是 GEOMETRY 或 GEOGRAPHY 类型的表达式。 | + +## 返回类型 {#return-type} + +Double。 + +## 示例 {#examples} + +### GEOMETRY 示例 {#geometry-examples} + +```sql +SELECT + ST_AREA( + TO_GEOMETRY('POLYGON((0 0, 1 0, 1 1, 0 1, 0 0))') + ) AS area + +┌──────┐ +│ area │ +├──────┤ +│ 1.0 │ +└──────┘ +``` + +### GEOGRAPHY 示例 {#geography-examples} + +```sql +SELECT + ST_AREA( + TO_GEOGRAPHY('POLYGON((0 0, 1 0, 1 1, 0 1, 0 0))') + ) AS area + +╭────────────────────╮ +│ area │ +├────────────────────┤ +│ 12308778361.469452 │ +╰────────────────────╯ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/st-asbinary.md b/tidb-cloud-lake/sql/st-asbinary.md new file mode 100644 index 0000000000000..9663c052ae2c6 --- /dev/null +++ b/tidb-cloud-lake/sql/st-asbinary.md @@ -0,0 +1,8 @@ +--- +title: ST_ASBINARY +summary: ST_ASWKB 的别名。 +--- + +# ST_ASBINARY + +[ST_ASWKB](/tidb-cloud-lake/sql/st-aswkb.md) 的别名。 \ No newline at end of file diff --git a/tidb-cloud-lake/sql/st-asewkb.md b/tidb-cloud-lake/sql/st-asewkb.md new file mode 100644 index 0000000000000..10364be55a092 --- /dev/null +++ b/tidb-cloud-lake/sql/st-asewkb.md @@ -0,0 +1,73 @@ +--- +title: ST_ASEWKB +summary: 将 GEOMETRY 或 GEOGRAPHY 对象转换为 EWKB(extended well-known-binary) 格式表示。 +--- + +# ST_ASEWKB + +将 GEOMETRY 或 GEOGRAPHY 对象转换为 [EWKB(extended well-known-binary)](https://postgis.net/docs/ST_GeomFromEWKB.html) 格式表示。 + +## 语法 {#syntax} + +```sql +ST_ASEWKB() +``` + +## 参数 {#arguments} + +| 参数 | 描述 | +|--------------|------------------------------------------------------| +| `` | 该参数必须是 GEOMETRY 或 GEOGRAPHY 类型的表达式。 | + +## 返回类型 {#return-type} + +Binary。 + +## 示例 {#examples} + +### GEOMETRY 示例 {#geometry-examples} + +```sql +SELECT + ST_ASEWKB( + ST_GEOMETRYFROMWKT( + 'SRID=4326;LINESTRING(400000 6000000, 401000 6010000)' + ) + ) AS pipeline_ewkb; + +┌────────────────────────────────────────────────────────────────────────────────────────────┐ +│ pipeline_ewkb │ +├────────────────────────────────────────────────────────────────────────────────────────────┤ +│ 0102000020E61000000200000000000000006A18410000000060E3564100000000A07918410000000024ED5641 │ +└────────────────────────────────────────────────────────────────────────────────────────────┘ + +SELECT + ST_ASEWKB( + ST_GEOMETRYFROMWKT( + 'SRID=4326;POINT(-122.35 37.55)' + ) + ) AS pipeline_ewkb; + +┌────────────────────────────────────────────────────┐ +│ pipeline_ewkb │ +├────────────────────────────────────────────────────┤ +│ 0101000020E61000006666666666965EC06666666666C64240 │ +└────────────────────────────────────────────────────┘ +``` + +### GEOGRAPHY 示例 {#geography-examples} + +```sql +SELECT + ST_ASEWKB( + ST_GEOGFROMWKT( + 'SRID=4326;POINT(-122.35 37.55)' + ) + ) AS pipeline_ewkb; + +╭────────────────────────────────────────────────────╮ +│ pipeline_ewkb │ +├────────────────────────────────────────────────────┤ +│ 0101000020E61000006666666666965EC06666666666C64240 │ +╰────────────────────────────────────────────────────╯ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/st-asewkt.md b/tidb-cloud-lake/sql/st-asewkt.md new file mode 100644 index 0000000000000..7330c136d425d --- /dev/null +++ b/tidb-cloud-lake/sql/st-asewkt.md @@ -0,0 +1,73 @@ +--- +title: ST_ASEWKT +summary: 将 GEOMETRY 或 GEOGRAPHY 对象转换为 EWKT(extended well-known-text) 格式表示。 +--- + +# ST_ASEWKT + +将 GEOMETRY 或 GEOGRAPHY 对象转换为 [EWKT(extended well-known-text)](https://postgis.net/docs/ST_GeomFromEWKT.html) 格式表示。 + +## 语法 {#syntax} + +```sql +ST_ASEWKT() +``` + +## 参数 {#arguments} + +| 参数 | 描述 | +|--------------|------------------------------------------------------| +| `` | 该参数必须是 GEOMETRY 或 GEOGRAPHY 类型的表达式。 | + +## 返回类型 {#return-type} + +字符串。 + +## 示例 {#examples} + +### GEOMETRY 示例 {#geometry-examples} + +```sql +SELECT + ST_ASEWKT( + ST_GEOMETRYFROMWKT( + 'SRID=4326;LINESTRING(400000 6000000, 401000 6010000)' + ) + ) AS pipeline_ewkt; + +┌─────────────────────────────────────────────────────┐ +│ pipeline_ewkt │ +├─────────────────────────────────────────────────────┤ +│ SRID=4326;LINESTRING(400000 6000000,401000 6010000) │ +└─────────────────────────────────────────────────────┘ + +SELECT + ST_ASEWKT( + ST_GEOMETRYFROMWKT( + 'SRID=4326;POINT(-122.35 37.55)' + ) + ) AS pipeline_ewkt; + +┌────────────────────────────────┐ +│ pipeline_ewkt │ +├────────────────────────────────┤ +│ SRID=4326;POINT(-122.35 37.55) │ +└────────────────────────────────┘ +``` + +### GEOGRAPHY 示例 {#geography-examples} + +```sql +SELECT + ST_ASEWKT( + ST_GEOGFROMWKT( + 'SRID=4326;POINT(-122.35 37.55)' + ) + ) AS pipeline_ewkt; + +╭────────────────────────────────╮ +│ pipeline_ewkt │ +├────────────────────────────────┤ +│ SRID=4326;POINT(-122.35 37.55) │ +╰────────────────────────────────╯ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/st-asgeojson.md b/tidb-cloud-lake/sql/st-asgeojson.md new file mode 100644 index 0000000000000..fccb2dee53cf3 --- /dev/null +++ b/tidb-cloud-lake/sql/st-asgeojson.md @@ -0,0 +1,60 @@ +--- +title: ST_ASGEOJSON +summary: 将 GEOMETRY 或 GEOGRAPHY 对象转换为 GeoJSON 表示形式。 +--- + +# ST_ASGEOJSON + +将 GEOMETRY 或 GEOGRAPHY 对象转换为 [GeoJSON](https://geojson.org/) 表示形式。 + +## 语法 {#syntax} + +```sql +ST_ASGEOJSON() +``` + +## 参数 {#arguments} + +| 参数 | 描述 | +|--------------|------------------------------------------------------| +| `` | 该参数必须是 GEOMETRY 或 GEOGRAPHY 类型的表达式。 | + +## 返回类型 {#return-type} + +Variant。 + +## 示例 {#examples} + +### GEOMETRY 示例 {#geometry-examples} + +```sql +SELECT + ST_ASGEOJSON( + ST_GEOMETRYFROMWKT( + 'SRID=4326;LINESTRING(400000 6000000, 401000 6010000)' + ) + ) AS pipeline_geojson; + +┌─────────────────────────────────────────────────────────────────────────┐ +│ pipeline_geojson │ +├─────────────────────────────────────────────────────────────────────────┤ +│ {"coordinates":[[400000,6000000],[401000,6010000]],"type":"LineString"} │ +└─────────────────────────────────────────────────────────────────────────┘ +``` + +### GEOGRAPHY 示例 {#geography-examples} + +```sql +SELECT + ST_ASGEOJSON( + ST_GEOGFROMWKT( + 'SRID=4326;POINT(-122.35 37.55)' + ) + ) AS pipeline_geojson; + +╭────────────────────────────────────────────────╮ +│ pipeline_geojson │ +├────────────────────────────────────────────────┤ +│ {"coordinates":[-122.35,37.55],"type":"Point"} │ +╰────────────────────────────────────────────────╯ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/st-astext.md b/tidb-cloud-lake/sql/st-astext.md new file mode 100644 index 0000000000000..f3d9743d2c9ed --- /dev/null +++ b/tidb-cloud-lake/sql/st-astext.md @@ -0,0 +1,8 @@ +--- +title: ST_ASTEXT +summary: ST_ASWKT 的别名。 +--- + +# ST_ASTEXT + +[ST_ASWKT](/tidb-cloud-lake/sql/st-aswkt.md) 的别名。 \ No newline at end of file diff --git a/tidb-cloud-lake/sql/st-aswkb.md b/tidb-cloud-lake/sql/st-aswkb.md new file mode 100644 index 0000000000000..5bbebd898763b --- /dev/null +++ b/tidb-cloud-lake/sql/st-aswkb.md @@ -0,0 +1,77 @@ +--- +title: ST_ASWKB +summary: 将 GEOMETRY 或 GEOGRAPHY 对象转换为 WKB(well-known-binary) 格式表示。 +--- + +# ST_ASWKB + +将 GEOMETRY 或 GEOGRAPHY 对象转换为 [WKB(well-known-binary)](https://en.wikipedia.org/wiki/Well-known_text_representation_of_geometry#Well-known_binary) 格式表示。 + +## 语法 {#syntax} + +```sql +ST_ASWKB() +``` + +## 别名 {#aliases} + +- [ST_ASBINARY](/tidb-cloud-lake/sql/st-asbinary.md) + +## 参数 {#arguments} + +| 参数 | 描述 | +|--------------|------------------------------------------------------| +| `` | 该参数必须是 GEOMETRY 或 GEOGRAPHY 类型的表达式。 | + +## 返回类型 {#return-type} + +Binary。 + +## 示例 {#examples} + +### GEOMETRY 示例 {#geometry-examples} + +```sql +SELECT + ST_ASWKB( + ST_GEOMETRYFROMWKT( + 'SRID=4326;LINESTRING(400000 6000000, 401000 6010000)' + ) + ) AS pipeline_wkb; + +┌────────────────────────────────────────────────────────────────────────────────────┐ +│ pipeline_wkb │ +├────────────────────────────────────────────────────────────────────────────────────┤ +│ 01020000000200000000000000006A18410000000060E3564100000000A07918410000000024ED5641 │ +└────────────────────────────────────────────────────────────────────────────────────┘ + +SELECT + ST_ASBINARY( + ST_GEOMETRYFROMWKT( + 'SRID=4326;POINT(-122.35 37.55)' + ) + ) AS pipeline_wkb; + +┌────────────────────────────────────────────┐ +│ pipeline_wkb │ +├────────────────────────────────────────────┤ +│ 01010000006666666666965EC06666666666C64240 │ +└────────────────────────────────────────────┘ +``` + +### GEOGRAPHY 示例 {#geography-examples} + +```sql +SELECT + ST_ASWKB( + ST_GEOGFROMWKT( + 'SRID=4326;POINT(-122.35 37.55)' + ) + ) AS pipeline_wkb; + +╭────────────────────────────────────────────╮ +│ pipeline_wkb │ +├────────────────────────────────────────────┤ +│ 01010000006666666666965EC06666666666C64240 │ +╰────────────────────────────────────────────╯ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/st-aswkt.md b/tidb-cloud-lake/sql/st-aswkt.md new file mode 100644 index 0000000000000..940f804139543 --- /dev/null +++ b/tidb-cloud-lake/sql/st-aswkt.md @@ -0,0 +1,77 @@ +--- +title: ST_ASWKT +summary: 将 GEOMETRY 或 GEOGRAPHY 对象转换为 WKT(well-known-text) 格式表示。 +--- + +# ST_ASWKT + +将 GEOMETRY 或 GEOGRAPHY 对象转换为 [WKT(well-known-text)](https://en.wikipedia.org/wiki/Well-known_text_representation_of_geometry) 格式表示。 + +## 语法 {#syntax} + +```sql +ST_ASWKT() +``` + +## 别名 {#aliases} + +- [ST_ASTEXT](/tidb-cloud-lake/sql/st-astext.md) + +## 参数 {#arguments} + +| 参数 | 描述 | +|--------------|------------------------------------------------------| +| `` | 该参数必须是 GEOMETRY 或 GEOGRAPHY 类型的表达式。 | + +## 返回类型 {#return-type} + +字符串。 + +## 示例 {#examples} + +### GEOMETRY 示例 {#geometry-examples} + +```sql +SELECT + ST_ASWKT( + ST_GEOMETRYFROMWKT( + 'SRID=4326;LINESTRING(400000 6000000, 401000 6010000)' + ) + ) AS pipeline_wkt; + +┌───────────────────────────────────────────┐ +│ pipeline_wkt │ +├───────────────────────────────────────────┤ +│ LINESTRING(400000 6000000,401000 6010000) │ +└───────────────────────────────────────────┘ + +SELECT + ST_ASTEXT( + ST_GEOMETRYFROMWKT( + 'SRID=4326;POINT(-122.35 37.55)' + ) + ) AS pipeline_wkt; + +┌──────────────────────┐ +│ pipeline_wkt │ +├──────────────────────┤ +│ POINT(-122.35 37.55) │ +└──────────────────────┘ +``` + +### GEOGRAPHY 示例 {#geography-examples} + +```sql +SELECT + ST_ASWKT( + ST_GEOGFROMWKT( + 'SRID=4326;POINT(-122.35 37.55)' + ) + ) AS pipeline_wkt; + +╭──────────────────────╮ +│ pipeline_wkt │ +├──────────────────────┤ +│ POINT(-122.35 37.55) │ +╰──────────────────────╯ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/st-azimuth.md b/tidb-cloud-lake/sql/st-azimuth.md new file mode 100644 index 0000000000000..a67ae39b35b78 --- /dev/null +++ b/tidb-cloud-lake/sql/st-azimuth.md @@ -0,0 +1,69 @@ +--- +title: ST_AZIMUTH +summary: 返回从一个 Point 到另一个 Point 的线段的方位角(以弧度表示),从正 Y 轴(北)开始按顺时针方向测量。如果两个点相同,则返回 NULL。 +--- + +# ST_AZIMUTH + +返回从一个 Point 到另一个 Point 的线段的方位角(以弧度表示),从正 Y 轴(北)开始按顺时针方向测量。如果两个点相同,则返回 NULL。 + +## 语法 {#syntax} + +```sql +ST_AZIMUTH(, ) +``` + +## 参数 {#arguments} + +| 参数 | 描述 | +|------------|------------------------------------------------------| +| `` | 类型为 Point 的 GEOMETRY 表达式(起点)。 | +| `` | 类型为 Point 的 GEOMETRY 表达式(目标点)。 | + +> **注意:** +> +> 两个参数都必须是 Point 几何对象。其他类型会产生错误。 + +## 返回类型 {#return-type} + +Double(可为空)。 + +## 示例 {#examples} + +```sql +-- Due north (along positive Y-axis): 0 radians +SELECT ST_AZIMUTH(TO_GEOMETRY('POINT(0 0)'), TO_GEOMETRY('POINT(0 1)')); + +┌────────┐ +│ result │ +├────────┤ +│ 0.0 │ +└────────┘ + +-- Due east: π/2 radians +SELECT ST_AZIMUTH(TO_GEOMETRY('POINT(0 0)'), TO_GEOMETRY('POINT(1 0)')); + +┌─────────────┐ +│ result │ +├─────────────┤ +│ 1.570796327 │ +└─────────────┘ + +-- Due south: π radians +SELECT ST_AZIMUTH(TO_GEOMETRY('POINT(0 1)'), TO_GEOMETRY('POINT(0 0)')); + +┌─────────────┐ +│ result │ +├─────────────┤ +│ 3.141592654 │ +└─────────────┘ + +-- Identical points: NULL +SELECT ST_AZIMUTH(TO_GEOMETRY('POINT(0 0)'), TO_GEOMETRY('POINT(0 0)')); + +┌────────┐ +│ result │ +├────────┤ +│ NULL │ +└────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/st-buffer.md b/tidb-cloud-lake/sql/st-buffer.md new file mode 100644 index 0000000000000..48a1b92a00368 --- /dev/null +++ b/tidb-cloud-lake/sql/st-buffer.md @@ -0,0 +1,75 @@ +--- +title: ST_BUFFER +summary: 返回一个 GEOMETRY,表示与输入几何对象距离小于或等于指定距离的所有点。结果为 MultiPolygon 或 NULL。 +--- + +# ST_BUFFER + +返回一个 GEOMETRY,表示与输入几何对象距离小于或等于指定距离的所有点。结果为 MultiPolygon 或 NULL。 + +## 语法 {#syntax} + +```sql +ST_BUFFER(, ) +``` + +## 参数 {#arguments} + +| 参数 | 描述 | +|--------------|-----------------------------------------------------------------------------| +| `` | 一个 GEOMETRY 表达式。不支持 GeometryCollection。 | +| `` | 缓冲距离。单位与输入几何对象的坐标系一致。 | + +> **注意:** +> +> - 对于 Point、MultiPoint、LineString 和 MultiLineString:使用 distance 的绝对值(负值与正值行为相同)。 +> - 对于 Polygon 和 MultiPolygon:正 distance 表示膨胀,负 distance 表示收缩。 +> - 当结果为空时返回 NULL(例如,Point 的 distance 为 0,或 Polygon 收缩后面积降为 0 以下)。 +> - 对于 distance 为 0 的 Polygon:返回包装为 MultiPolygon 的该 Polygon。 +> - 输出中会保留 SRID。 + +## 返回类型 {#return-type} + +Geometry(可为空)。 + +## 示例 {#examples} + +```sql +-- Buffer a point (produces a polygon approximating a circle) +SELECT ST_BUFFER(TO_GEOMETRY('POINT(0 0)'), 1) IS NOT NULL; + +┌────────┐ +│ result │ +├────────┤ +│ true │ +└────────┘ + +-- Zero distance on a polygon returns itself as MultiPolygon +SELECT ST_ASWKT( + ST_BUFFER(TO_GEOMETRY('POLYGON((0 0, 4 0, 4 4, 0 4, 0 0))'), 0) +); + +┌─────────────────────────────────────────────────┐ +│ result │ +├─────────────────────────────────────────────────┤ +│ MULTIPOLYGON(((0 0,4 0,4 4,0 4,0 0))) │ +└─────────────────────────────────────────────────┘ + +-- Zero distance on a point returns NULL +SELECT ST_ASWKT(ST_BUFFER(TO_GEOMETRY('POINT(0 0)'), 0)); + +┌────────┐ +│ result │ +├────────┤ +│ NULL │ +└────────┘ + +-- SRID is preserved +SELECT ST_SRID(ST_BUFFER(ST_GEOMETRYFROMWKT('POINT(0 0)', 4326), 1)); + +┌────────┐ +│ result │ +├────────┤ +│ 4326 │ +└────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/st-centroid.md b/tidb-cloud-lake/sql/st-centroid.md new file mode 100644 index 0000000000000..9cda10ab1ded2 --- /dev/null +++ b/tidb-cloud-lake/sql/st-centroid.md @@ -0,0 +1,48 @@ +--- +title: ST_CENTROID +summary: 返回 GEOMETRY 对象的质心。 +--- + +# ST_CENTROID + +返回 GEOMETRY 对象的质心。 + +此函数仅支持 GEOMETRY 值。 + +## 语法 {#syntax} + +```sql +ST_CENTROID() +``` + +## 参数 {#arguments} + +| 参数 | 描述 | +|--------------|--------------------------------------------------------| +| `` | 该参数必须是 GEOMETRY 类型的表达式。 | + +## 返回类型 {#return-type} + +GEOMETRY。 + +## 示例 {#examples} + +```sql +SELECT ST_ASWKT(ST_CENTROID(TO_GEOMETRY('POINT(1 2)'))); + +╭──────────────────────────────────────────────────╮ +│ st_aswkt(st_centroid(to_geometry('POINT(1 2)'))) │ +├──────────────────────────────────────────────────┤ +│ POINT(1 2) │ +╰──────────────────────────────────────────────────╯ +``` + +```sql +SELECT ST_ASWKT(ST_CENTROID(TO_GEOMETRY('LINESTRING(0 0, 2 0)'))); + +╭────────────────────────────────────────────────────────────╮ +│ st_aswkt(st_centroid(to_geometry('LINESTRING(0 0, 2 0)'))) │ +├────────────────────────────────────────────────────────────┤ +│ POINT(1 0) │ +╰────────────────────────────────────────────────────────────╯ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/st-collect.md b/tidb-cloud-lake/sql/st-collect.md new file mode 100644 index 0000000000000..4dafa9a1ad865 --- /dev/null +++ b/tidb-cloud-lake/sql/st-collect.md @@ -0,0 +1,49 @@ +--- +title: ST_COLLECT +summary: 将多个 GEOMETRY 值收集为单个 GEOMETRY 结果。 +--- + +# ST_COLLECT + +将多个 GEOMETRY 值收集为单个 GEOMETRY 结果。 + +此函数仅支持 GEOMETRY。 + +## 语法 {#syntax} + +```sql +ST_COLLECT() +``` + +## 参数 {#arguments} + +| 参数 | 描述 | +|-----------|-------------| +| `` | 一个 GEOMETRY 类型的表达式。 | + +## 返回类型 {#return-type} + +GEOMETRY。根据输入不同,结果可以是 `MULTIPOINT`、`MULTILINESTRING`、`MULTIPOLYGON` 或 `GEOMETRYCOLLECTION`。 + +> **注意:** +> +> - 会忽略输入中的 NULL 行。 +> - 如果所有输入行均为 NULL,结果为 NULL。 +> - 如果输入的 GEOMETRY 值使用了不同的 SRID,该函数会返回错误。 + +## 示例 {#example} + +```sql +WITH data AS ( + SELECT TO_GEOMETRY('POINT(0 0)') AS g + UNION ALL + SELECT TO_GEOMETRY('LINESTRING(1 1,2 2)') +) +SELECT ST_ASWKT(ST_COLLECT(g)) FROM data; + +╭────────────────────────────────────────────────────╮ +│ st_aswkt(st_collect(g)) │ +├────────────────────────────────────────────────────┤ +│ GEOMETRYCOLLECTION(POINT(0 0),LINESTRING(1 1,2 2)) │ +╰────────────────────────────────────────────────────╯ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/st-contains.md b/tidb-cloud-lake/sql/st-contains.md new file mode 100644 index 0000000000000..214bcf988c448 --- /dev/null +++ b/tidb-cloud-lake/sql/st-contains.md @@ -0,0 +1,58 @@ +--- +title: ST_CONTAINS +summary: 如果第二个 GEOMETRY 对象完全位于第一个 GEOMETRY 对象内部,则返回 TRUE。 +--- + +# ST_CONTAINS + +如果第二个 GEOMETRY 对象完全位于第一个 GEOMETRY 对象内部,则返回 TRUE。 + +## 语法 {#syntax} + +```sql +ST_CONTAINS(, ) +``` + +## 参数 {#arguments} + +| 参数 | 描述 | +|---------------|----------------------------------------------------------------------| +| `` | 该参数必须是 GEOMETRY 对象类型的表达式,且不能是 GeometryCollection。 | +| `` | 该参数必须是 GEOMETRY 对象类型的表达式,且不能是 GeometryCollection。 | + +> **注意:** +> +> - 如果两个输入的 GEOMETRY 对象具有不同的 SRID,则该函数会报错。 + +## 返回类型 {#return-type} + +Boolean。 + +## 示例 {#examples} + +```sql +SELECT ST_CONTAINS(TO_GEOMETRY('POLYGON((-2 0, 0 2, 2 0, -2 0))'), TO_GEOMETRY('POLYGON((-1 0, 0 1, 1 0, -1 0))')) AS contains + +┌──────────┐ +│ contains │ +├──────────┤ +│ true │ +└──────────┘ + +SELECT ST_CONTAINS(TO_GEOMETRY('POLYGON((-2 0, 0 2, 2 0, -2 0))'), TO_GEOMETRY('LINESTRING(-1 1, 0 2, 1 1)')) AS contains + +┌──────────┐ +│ contains │ +├──────────┤ +│ false │ +└──────────┘ + +SELECT ST_CONTAINS(TO_GEOMETRY('POLYGON((-2 0, 0 2, 2 0, -2 0))'), TO_GEOMETRY('LINESTRING(-2 0, 0 0, 0 1)')) AS contains + +┌──────────┐ +│ contains │ +├──────────┤ +│ true │ +└──────────┘ + +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/st-convexhull.md b/tidb-cloud-lake/sql/st-convexhull.md new file mode 100644 index 0000000000000..f498857b0a9b1 --- /dev/null +++ b/tidb-cloud-lake/sql/st-convexhull.md @@ -0,0 +1,40 @@ +--- +title: ST_CONVEXHULL +summary: 返回 GEOMETRY 对象的凸包。 +--- + +# ST_CONVEXHULL + +返回 GEOMETRY 对象的凸包。 + +## 语法 {#syntax} + +```sql +ST_CONVEXHULL() +``` + +## 参数 {#arguments} + +| 参数 | 描述 | +|-------------|-------------------------------------------------------| +| `` | 该参数必须是 GEOMETRY 类型的表达式。 | + +## 返回类型 {#return-type} + +GEOMETRY。 + +## 示例 {#examples} + +```sql +SELECT ST_ASTEXT( + ST_CONVEXHULL( + TO_GEOMETRY('POLYGON((0 0, 2 0, 2 2, 0 2, 0 0))') + ) +) AS hull; + +╭────────────────────────────────╮ +│ hull │ +├────────────────────────────────┤ +│ POLYGON((2 0,2 2,0 2,0 0,2 0)) │ +╰────────────────────────────────╯ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/st-coveredby.md b/tidb-cloud-lake/sql/st-coveredby.md new file mode 100644 index 0000000000000..d0ca97af08a77 --- /dev/null +++ b/tidb-cloud-lake/sql/st-coveredby.md @@ -0,0 +1,64 @@ +--- +title: ST_COVEREDBY +summary: 如果第一个 GEOMETRY 对象中没有任何点位于第二个 GEOMETRY 对象之外,则返回 TRUE。 +--- + +# ST_COVEREDBY + +如果第一个 GEOMETRY 对象中没有任何点位于第二个 GEOMETRY 对象之外,则返回 TRUE。 + +另请参阅:[ST_COVERS](/tidb-cloud-lake/sql/st-covers.md) + +## 语法 {#syntax} + +```sql +ST_COVEREDBY(, ) +``` + +## 参数 {#arguments} + +| 参数 | 描述 | +|---------------|--------------------------------------| +| `` | 一个 GEOMETRY 表达式(被测试的对象)。 | +| `` | 一个 GEOMETRY 表达式(覆盖对象)。 | + +## 返回类型 {#return-type} + +布尔型。 + +## 示例 {#examples} + +```sql +SELECT ST_COVEREDBY( + TO_GEOMETRY('POINT(1 1)'), + TO_GEOMETRY('POLYGON((0 0, 3 0, 3 3, 0 3, 0 0))') +); + +┌────────┐ +│ result │ +├────────┤ +│ true │ +└────────┘ + +SELECT ST_COVEREDBY( + TO_GEOMETRY('POLYGON((1 1, 2 1, 2 2, 1 2, 1 1))'), + TO_GEOMETRY('POLYGON((0 0, 3 0, 3 3, 0 3, 0 0))') +); + +┌────────┐ +│ result │ +├────────┤ +│ true │ +└────────┘ + +SELECT ST_COVEREDBY( + TO_GEOMETRY('POINT(5 5)'), + TO_GEOMETRY('POLYGON((0 0, 3 0, 3 3, 0 3, 0 0))') +); + +┌────────┐ +│ result │ +├────────┤ +│ false │ +└────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/st-covers.md b/tidb-cloud-lake/sql/st-covers.md new file mode 100644 index 0000000000000..7d399f2bd81c6 --- /dev/null +++ b/tidb-cloud-lake/sql/st-covers.md @@ -0,0 +1,67 @@ +--- +title: ST_COVERS +summary: 如果第二个 GEOMETRY 对象中没有任何点位于第一个 GEOMETRY 对象之外,则返回 TRUE。 +--- + +# ST_COVERS + +如果第二个 GEOMETRY 对象中没有任何点位于第一个 GEOMETRY 对象之外,则返回 TRUE。 + +另请参阅:[ST_COVEREDBY](/tidb-cloud-lake/sql/st-coveredby.md) + +## 语法 {#syntax} + +```sql +ST_COVERS(, ) +``` + +## 参数 {#arguments} + +| 参数 | 描述 | +|---------------|----------------------------------------------| +| `` | 一个 GEOMETRY 表达式(覆盖对象)。 | +| `` | 一个 GEOMETRY 表达式(被测试的对象)。 | + +## 返回类型 {#return-type} + +布尔型。 + +## 示例 {#examples} + +```sql +-- A polygon covers a smaller polygon inside it +SELECT ST_COVERS( + TO_GEOMETRY('POLYGON((-2 0, 0 2, 2 0, -2 0))'), + TO_GEOMETRY('POLYGON((-1 0, 0 1, 1 0, -1 0))') +); + +┌────────┐ +│ result │ +├────────┤ +│ true │ +└────────┘ + +-- A polygon covers a linestring on its boundary +SELECT ST_COVERS( + TO_GEOMETRY('POLYGON((-2 0, 0 2, 2 0, -2 0))'), + TO_GEOMETRY('LINESTRING(-1 1, 0 2, 1 1)') +); + +┌────────┐ +│ result │ +├────────┤ +│ true │ +└────────┘ + +-- A point outside the polygon is not covered +SELECT ST_COVERS( + TO_GEOMETRY('POLYGON((0 0, 3 0, 3 3, 0 3, 0 0))'), + TO_GEOMETRY('POINT(5 5)') +); + +┌────────┐ +│ result │ +├────────┤ +│ false │ +└────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/st-difference.md b/tidb-cloud-lake/sql/st-difference.md new file mode 100644 index 0000000000000..748b34d46931b --- /dev/null +++ b/tidb-cloud-lake/sql/st-difference.md @@ -0,0 +1,43 @@ +--- +title: ST_DIFFERENCE +summary: 返回第一个 GEOMETRY 对象中未被第二个 GEOMETRY 对象覆盖的部分。 +--- + +# ST_DIFFERENCE + +返回第一个 GEOMETRY 对象中未被第二个 GEOMETRY 对象覆盖的部分。 + +该函数仅支持 GEOMETRY 值。 + +## 语法 {#syntax} + +```sql +ST_DIFFERENCE(, ) +``` + +## 参数 {#arguments} + +| 参数 | 描述 | +|---------------|--------------------------------------------------------| +| `` | 该参数必须是 GEOMETRY 类型的表达式。 | +| `` | 该参数必须是 GEOMETRY 类型的表达式。 | + +> **注意:** +> +> 如果两个输入的 GEOMETRY 对象具有不同的 SRID,该函数会报错。 + +## 返回类型 {#return-type} + +GEOMETRY。 + +## 示例 {#examples} + +```sql +SELECT ST_ASWKT(ST_DIFFERENCE(TO_GEOMETRY('POINT(0 0)'), TO_GEOMETRY('POINT(1 1)'))); + +╭───────────────────────────────────────────────────────────────────────────────╮ +│ st_aswkt(st_difference(to_geometry('POINT(0 0)'), to_geometry('POINT(1 1)'))) │ +├───────────────────────────────────────────────────────────────────────────────┤ +│ POINT(0 0) │ +╰───────────────────────────────────────────────────────────────────────────────╯ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/st-dimension.md b/tidb-cloud-lake/sql/st-dimension.md new file mode 100644 index 0000000000000..5cc634dcbfcb3 --- /dev/null +++ b/tidb-cloud-lake/sql/st-dimension.md @@ -0,0 +1,92 @@ +--- +title: ST_DIMENSION +summary: 返回几何对象的维度。GEOMETRY 或 GEOGRAPHY 对象的维度如下。 +--- + +# ST_DIMENSION + +返回几何对象的维度。GEOMETRY 或 GEOGRAPHY 对象的维度如下: + +| 地理空间对象类型 | 维度 | +|------------------------------|------------| +| 点 / 多点 | 0 | +| 线串 / 多线串 | 1 | +| 多边形 / 多多边形 | 2 | + +## 语法 {#syntax} + +```sql +ST_DIMENSION() +``` + +## 参数 {#arguments} + +| 参数 | 描述 | +|--------------|------------------------------------------------------| +| `` | 该参数必须是 GEOMETRY 或 GEOGRAPHY 类型的表达式。 | + +## 返回类型 {#return-type} + +UInt8。 + +## 示例 {#examples} + +### GEOMETRY 示例 {#geometry-examples} + +```sql +SELECT + ST_DIMENSION( + ST_GEOMETRYFROMWKT( + 'POINT(-122.306100 37.554162)' + ) + ) AS pipeline_dimension; + +┌────────────────────┐ +│ pipeline_dimension │ +├────────────────────┤ +│ 0 │ +└────────────────────┘ + +SELECT + ST_DIMENSION( + ST_GEOMETRYFROMWKT( + 'LINESTRING(-124.20 42.00, -120.01 41.99)' + ) + ) AS pipeline_dimension; + +┌────────────────────┐ +│ pipeline_dimension │ +├────────────────────┤ +│ 1 │ +└────────────────────┘ + +SELECT + ST_DIMENSION( + ST_GEOMETRYFROMWKT( + 'POLYGON((-124.20 42.00, -120.01 41.99, -121.1 42.01, -124.20 42.00))' + ) + ) AS pipeline_dimension; + +┌────────────────────┐ +│ pipeline_dimension │ +├────────────────────┤ +│ 2 │ +└────────────────────┘ +``` + +### GEOGRAPHY 示例 {#geography-examples} + +```sql +SELECT + ST_DIMENSION( + ST_GEOGFROMWKT( + 'LINESTRING(-124.20 42.00, -120.01 41.99)' + ) + ) AS pipeline_dimension; + +╭────────────────────╮ +│ pipeline_dimension │ +├────────────────────┤ +│ 1 │ +╰────────────────────╯ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/st-disjoint.md b/tidb-cloud-lake/sql/st-disjoint.md new file mode 100644 index 0000000000000..069e7ba543e29 --- /dev/null +++ b/tidb-cloud-lake/sql/st-disjoint.md @@ -0,0 +1,55 @@ +--- +title: ST_DISJOINT +summary: 如果两个 GEOMETRY 对象不相交,则返回 TRUE。 +--- + +# ST_DISJOINT + +如果两个 GEOMETRY 对象不相交,则返回 TRUE。 + +## 语法 {#syntax} + +```sql +ST_DISJOINT(, ) +``` + +## 参数 {#arguments} + +| 参数 | 描述 | +|---------------|---------------------------------------| +| `` | 该参数必须是 GEOMETRY 类型的表达式。 | +| `` | 该参数必须是 GEOMETRY 类型的表达式。 | + +> **注意:** +> +> 如果两个输入的 GEOMETRY 对象具有不同的 SRID,则该函数会报错。 + +## 返回类型 {#return-type} + +布尔值。 + +## 示例 {#examples} + +```sql +SELECT ST_DISJOINT( + TO_GEOMETRY('POINT(3 3)'), + TO_GEOMETRY('POLYGON((0 0, 2 0, 2 2, 0 2, 0 0))') +) AS disjoint; + +╭──────────╮ +│ disjoint │ +├──────────┤ +│ true │ +╰──────────╯ + +SELECT ST_DISJOINT( + TO_GEOMETRY('LINESTRING(0 0, 2 2)'), + TO_GEOMETRY('LINESTRING(0 2, 2 0)') +) AS disjoint; + +╭──────────╮ +│ disjoint │ +├──────────┤ +│ false │ +╰──────────╯ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/st-distance.md b/tidb-cloud-lake/sql/st-distance.md new file mode 100644 index 0000000000000..7392f587431d3 --- /dev/null +++ b/tidb-cloud-lake/sql/st-distance.md @@ -0,0 +1,64 @@ +--- +title: ST_DISTANCE +summary: 返回两个对象之间的最小距离。对于 GEOMETRY 输入,该函数使用欧几里得距离。对于 GEOGRAPHY 输入,该函数使用 haversine 距离。 +--- + +# ST_DISTANCE + +返回两个对象之间的最小距离。对于 GEOMETRY 输入,该函数使用[欧几里得距离](https://en.wikipedia.org/wiki/Euclidean_distance)。对于 GEOGRAPHY 输入,该函数使用 [haversine 距离](https://en.wikipedia.org/wiki/Haversine_formula)。 + +## 语法 {#syntax} + +```sql +ST_DISTANCE(, ) +``` + +## 参数 {#arguments} + +| 参数 | 描述 | +|---------------|-------------------------------------------------------------------------------| +| `` | 该参数必须是 GEOMETRY 或 GEOGRAPHY 类型的表达式,并且必须包含一个 Point。 | +| `` | 该参数必须是 GEOMETRY 或 GEOGRAPHY 类型的表达式,并且必须包含一个 Point。 | + +> **注意:** +> +> - 如果一个或多个输入点为 NULL,则返回 NULL。 +> - 如果两个输入的 GEOMETRY 或 GEOGRAPHY 对象具有不同的 SRID,则该函数会报错。 + +## 返回类型 {#return-type} + +Double。 + +## 示例 {#examples} + +### GEOMETRY 示例 {#geometry-examples} + +```sql +SELECT + ST_DISTANCE( + TO_GEOMETRY('POINT(0 0)'), + TO_GEOMETRY('POINT(1 1)') + ) AS distance + +┌─────────────┐ +│ distance │ +├─────────────┤ +│ 1.414213562 │ +└─────────────┘ +``` + +### GEOGRAPHY 示例 {#geography-examples} + +```sql +SELECT + ST_DISTANCE( + ST_GEOGFROMWKT('POINT(0 0)'), + ST_GEOGFROMWKT('POINT(1 0)') + ) AS distance + +╭──────────────────╮ +│ distance │ +├──────────────────┤ +│ 111195.080233533 │ +╰──────────────────╯ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/st-dwithin.md b/tidb-cloud-lake/sql/st-dwithin.md new file mode 100644 index 0000000000000..69ec89e35c85c --- /dev/null +++ b/tidb-cloud-lake/sql/st-dwithin.md @@ -0,0 +1,54 @@ +--- +title: ST_DWITHIN +summary: 返回两个 GEOMETRY 对象是否位于指定的欧几里得距离之内。 +--- + +# ST_DWITHIN + +返回两个 GEOMETRY 对象是否位于指定的欧几里得距离之内;如果是,则返回 TRUE。 + +该函数仅支持 GEOMETRY 值。 + +## 语法 {#syntax} + +```sql +ST_DWITHIN(, , ) +``` + +## 参数 {#arguments} + +| 参数 | 描述 | +|---------------|----------------------------------------------------------------------| +| `` | 该参数必须是 GEOMETRY 类型的表达式。 | +| `` | 该参数必须是 GEOMETRY 类型的表达式。 | +| `` | 最大欧几里得距离,必须是与 Float64 兼容的值。 | + +> **注意:** +> +> 如果两个输入的 GEOMETRY 对象具有不同的 SRID,该函数会报错。 + +## 返回类型 {#return-type} + +Boolean。 + +## 示例 {#examples} + +```sql +SELECT ST_DWITHIN(TO_GEOMETRY('POINT(0 0)'), TO_GEOMETRY('POINT(1 1)'), 1.5); + +╭───────────────────────────────────────────────────────────────────────╮ +│ st_dwithin(to_geometry('POINT(0 0)'), to_geometry('POINT(1 1)'), 1.5) │ +├───────────────────────────────────────────────────────────────────────┤ +│ true │ +╰───────────────────────────────────────────────────────────────────────╯ +``` + +```sql +SELECT ST_DWITHIN(TO_GEOMETRY('POINT(0 0)'), TO_GEOMETRY('LINESTRING(2 0, 2 2)'), 1.9); + +╭─────────────────────────────────────────────────────────────────────────────────╮ +│ st_dwithin(to_geometry('POINT(0 0)'), to_geometry('LINESTRING(2 0, 2 2)'), 1.9) │ +├─────────────────────────────────────────────────────────────────────────────────┤ +│ false │ +╰─────────────────────────────────────────────────────────────────────────────────╯ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/st-endpoint.md b/tidb-cloud-lake/sql/st-endpoint.md new file mode 100644 index 0000000000000..27e3990efc199 --- /dev/null +++ b/tidb-cloud-lake/sql/st-endpoint.md @@ -0,0 +1,60 @@ +--- +title: ST_ENDPOINT +summary: 返回 LineString 中最后一个 Point。 +--- + +# ST_ENDPOINT + +返回 LineString 中最后一个 Point。 + +## 语法 {#syntax} + +```sql +ST_ENDPOINT() +``` + +## 参数 {#arguments} + +| 参数 | 描述 | +|--------------|-----------------------------------------------------------------------------------| +| `` | 该参数必须是一个 GEOMETRY 或 GEOGRAPHY 类型的表达式,并且表示一个 LineString。 | + +## 返回类型 {#return-type} + +Geometry。 + +## 示例 {#examples} + +### GEOMETRY 示例 {#geometry-examples} + +```sql +SELECT + ST_ENDPOINT( + ST_GEOMETRYFROMWKT( + 'LINESTRING(1 1, 2 2, 3 3, 4 4)' + ) + ) AS pipeline_endpoint; + +┌───────────────────┐ +│ pipeline_endpoint │ +├───────────────────┤ +│ POINT(4 4) │ +└───────────────────┘ +``` + +### GEOGRAPHY 示例 {#geography-examples} + +```sql +SELECT + ST_ENDPOINT( + ST_GEOGFROMWKT( + 'LINESTRING(1 1, 2 2, 3 3, 4 4)' + ) + ) AS pipeline_endpoint; + +┌───────────────────┐ +│ pipeline_endpoint │ +├───────────────────┤ +│ POINT(4 4) │ +└───────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/st-envelope-agg.md b/tidb-cloud-lake/sql/st-envelope-agg.md new file mode 100644 index 0000000000000..f2b72de4ef8a3 --- /dev/null +++ b/tidb-cloud-lake/sql/st-envelope-agg.md @@ -0,0 +1,51 @@ +--- +title: ST_ENVELOPE_AGG +summary: 聚合多个 GEOMETRY 值,并返回覆盖所有非 NULL 输入的最小外接矩形。 +--- + +# ST_ENVELOPE_AGG + +聚合多个 GEOMETRY 值,并返回覆盖所有非 NULL 输入的最小外接矩形。 + +此函数仅支持 GEOMETRY。 + +## 语法 {#syntax} + +```sql +ST_ENVELOPE_AGG() +``` + +## 参数 {#arguments} + +| 参数 | 描述 | +| --------- | ----------- | +| `` | 一个 GEOMETRY 类型的表达式。 | + +## 返回类型 {#return-type} + +GEOMETRY。 + +> **注意:** +> +> - NULL 输入行会被忽略。 +> - 如果所有输入行均为 NULL,结果为 NULL。 +> - 如果输入的 GEOMETRY 值使用了不同的 SRID,该函数会返回错误。 + +## 示例 {#example} + +```sql +WITH data AS ( + SELECT TO_GEOMETRY('POINT(1 1)') AS g + UNION ALL + SELECT TO_GEOMETRY('POINT(4 2)') + UNION ALL + SELECT TO_GEOMETRY('POINT(2 5)') +) +SELECT ST_ASWKT(ST_ENVELOPE_AGG(g)) FROM data; + +╭────────────────────────────────╮ +│ st_aswkt(st_envelope_agg(g)) │ +├────────────────────────────────┤ +│ POLYGON((1 1,4 1,4 5,1 5,1 1)) │ +╰────────────────────────────────╯ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/st-envelope.md b/tidb-cloud-lake/sql/st-envelope.md new file mode 100644 index 0000000000000..f1525acbf852f --- /dev/null +++ b/tidb-cloud-lake/sql/st-envelope.md @@ -0,0 +1,39 @@ +--- +title: ST_ENVELOPE +summary: 以多边形形式返回 GEOMETRY 对象的最小外接矩形。 +--- + +# ST_ENVELOPE + +以多边形形式返回 GEOMETRY 对象的最小外接矩形。 + +该函数仅支持 GEOMETRY 值。 + +## 语法 {#syntax} + +```sql +ST_ENVELOPE() +``` + +## 参数 {#arguments} + +| 参数 | 描述 | +|--------------|--------------------------------------------------------| +| `` | 该参数必须是 GEOMETRY 类型的表达式。 | + +## 返回类型 {#return-type} + +GEOMETRY。 + +## 示例 {#examples} + +```sql +SELECT ST_ASWKT(ST_ENVELOPE(TO_GEOMETRY('LINESTRING(0 0, 2 3)'))); + +╭────────────────────────────────────────────────────────────╮ +│ st_aswkt(st_envelope(to_geometry('LINESTRING(0 0, 2 3)'))) │ +│ String │ +├────────────────────────────────────────────────────────────┤ +│ POLYGON((0 0,2 0,2 3,0 3,0 0)) │ +╰────────────────────────────────────────────────────────────╯ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/st-equals.md b/tidb-cloud-lake/sql/st-equals.md new file mode 100644 index 0000000000000..29ea4f829920c --- /dev/null +++ b/tidb-cloud-lake/sql/st-equals.md @@ -0,0 +1,55 @@ +--- +title: ST_EQUALS +summary: 如果两个 GEOMETRY 对象在空间上相等,则返回 TRUE。 +--- + +# ST_EQUALS + +如果两个 GEOMETRY 对象在空间上相等,则返回 TRUE。 + +## 语法 {#syntax} + +```sql +ST_EQUALS(, ) +``` + +## 参数 {#arguments} + +| 参数 | 描述 | +|---------------|---------------------------------------| +| `` | 该参数必须是 GEOMETRY 类型的表达式。 | +| `` | 该参数必须是 GEOMETRY 类型的表达式。 | + +> **注意:** +> +> 如果两个输入的 GEOMETRY 对象具有不同的 SRID,则该函数会报错。 + +## 返回类型 {#return-type} + +布尔值。 + +## 示例 {#examples} + +```sql +SELECT ST_EQUALS( + TO_GEOMETRY('POINT(1 1)'), + TO_GEOMETRY('POINT(1 1)') +) AS equals; + +╭────────╮ +│ equals │ +├────────┤ +│ true │ +╰────────╯ + +SELECT ST_EQUALS( + TO_GEOMETRY('POINT(1 1)'), + TO_GEOMETRY('POINT(1 2)') +) AS equals; + +╭────────╮ +│ equals │ +├────────┤ +│ false │ +╰────────╯ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/st-geogetryfromwkb.md b/tidb-cloud-lake/sql/st-geogetryfromwkb.md new file mode 100644 index 0000000000000..2e147423b3434 --- /dev/null +++ b/tidb-cloud-lake/sql/st-geogetryfromwkb.md @@ -0,0 +1,8 @@ +--- +title: ST_GEOGETRYFROMWKB +summary: ST_GEOGRAPHYFROMWKB 的别名。 +--- + +# ST_GEOGETRYFROMWKB + +[ST_GEOGRAPHYFROMWKB](/tidb-cloud-lake/sql/st-geographyfromwkb.md) 的别名。 \ No newline at end of file diff --git a/tidb-cloud-lake/sql/st-geogfromewkb.md b/tidb-cloud-lake/sql/st-geogfromewkb.md new file mode 100644 index 0000000000000..345bf1b9e55e8 --- /dev/null +++ b/tidb-cloud-lake/sql/st-geogfromewkb.md @@ -0,0 +1,8 @@ +--- +title: ST_GEOGFROMEWKB +summary: ST_GEOGRAPHYFROMWKB 的别名。 +--- + +# ST_GEOGFROMEWKB + +[ST_GEOGRAPHYFROMWKB](/tidb-cloud-lake/sql/st-geographyfromwkb.md) 的别名。 \ No newline at end of file diff --git a/tidb-cloud-lake/sql/st-geogfromgeohash.md b/tidb-cloud-lake/sql/st-geogfromgeohash.md new file mode 100644 index 0000000000000..275f805567ec5 --- /dev/null +++ b/tidb-cloud-lake/sql/st-geogfromgeohash.md @@ -0,0 +1,42 @@ +--- +title: ST_GEOGFROMGEOHASH +summary: 返回一个 GEOGRAPHY 对象,用于表示 geohash 边界所对应的多边形。 +--- + +# ST_GEOGFROMGEOHASH + +返回一个 GEOGRAPHY 对象,用于表示 [geohash](https://en.wikipedia.org/wiki/Geohash) 边界所对应的多边形。 + +## 语法 {#syntax} + +```sql +ST_GEOGFROMGEOHASH() +``` + +## 参数 {#arguments} + +| 参数 | 描述 | +|-------------|-----------------------------| +| `` | 该参数必须是一个 geohash。 | + +## 返回类型 {#return-type} + +Geography。 + +## 示例 {#examples} + +```sql +SELECT + ST_ASWKT( + ST_GEOGFROMGEOHASH( + '9q60y60rhs' + ) + ) AS pipeline_geography; + +╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ +│ pipeline_geography │ +│ String │ +├───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤ +│ POLYGON((-120.66229462623596 35.30029535293579,-120.66229462623596 35.30030071735382,-120.66230535507202 35.30030071735382,-120.66230535507202 35.30029535293579… │ +╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/st-geogfromtext.md b/tidb-cloud-lake/sql/st-geogfromtext.md new file mode 100644 index 0000000000000..53185b3937607 --- /dev/null +++ b/tidb-cloud-lake/sql/st-geogfromtext.md @@ -0,0 +1,8 @@ +--- +title: ST_GEOGFROMTEXT +summary: ST_GEOGRAPHYFROMWKT 的别名。 +--- + +# ST_GEOGFROMTEXT + +[ST_GEOGRAPHYFROMWKT](/tidb-cloud-lake/sql/st-geographyfromwkt.md) 的别名。 \ No newline at end of file diff --git a/tidb-cloud-lake/sql/st-geogfromwkb.md b/tidb-cloud-lake/sql/st-geogfromwkb.md new file mode 100644 index 0000000000000..f7b3fb589a841 --- /dev/null +++ b/tidb-cloud-lake/sql/st-geogfromwkb.md @@ -0,0 +1,8 @@ +--- +title: ST_GEOGFROMWKB +summary: ST_GEOGRAPHYFROMWKB 的别名。 +--- + +# ST_GEOGFROMWKB + +[ST_GEOGRAPHYFROMWKB](/tidb-cloud-lake/sql/st-geographyfromwkb.md) 的别名。 \ No newline at end of file diff --git a/tidb-cloud-lake/sql/st-geogfromwkt.md b/tidb-cloud-lake/sql/st-geogfromwkt.md new file mode 100644 index 0000000000000..93d44eb293195 --- /dev/null +++ b/tidb-cloud-lake/sql/st-geogfromwkt.md @@ -0,0 +1,8 @@ +--- +title: ST_GEOGFROMWKT +summary: `ST_GEOGRAPHYFROMWKT` 的别名。 +--- + +# ST_GEOGFROMWKT + +[ST_GEOGRAPHYFROMWKT](/tidb-cloud-lake/sql/st-geographyfromwkt.md) 的别名。 \ No newline at end of file diff --git a/tidb-cloud-lake/sql/st-geogpointfromgeohash.md b/tidb-cloud-lake/sql/st-geogpointfromgeohash.md new file mode 100644 index 0000000000000..a8fe1f8ae877c --- /dev/null +++ b/tidb-cloud-lake/sql/st-geogpointfromgeohash.md @@ -0,0 +1,42 @@ +--- +title: ST_GEOGPOINTFROMGEOHASH +summary: 返回一个 GEOGRAPHY 对象,表示 geohash 中心点对应的点。 +--- + +# ST_GEOGPOINTFROMGEOHASH + +返回一个 GEOGRAPHY 对象,表示 [geohash](https://en.wikipedia.org/wiki/Geohash) 中心点对应的点。 + +## 语法 {#syntax} + +```sql +ST_GEOGPOINTFROMGEOHASH() +``` + +## 参数 {#arguments} + +| 参数 | 描述 | +|-------------|---------------------------------| +| `` | 该参数必须是一个 geohash。 | + +## 返回类型 {#return-type} + +Geography。 + +## 示例 {#examples} + +```sql +SELECT + ST_ASWKT( + ST_GEOGPOINTFROMGEOHASH( + 's02equ0' + ) + ) AS pipeline_geography; + +╭──────────────────────────────────────────────╮ +│ pipeline_geography │ +│ String │ +├──────────────────────────────────────────────┤ +│ POINT(1.0004425048828125 2.0001983642578125) │ +╰──────────────────────────────────────────────╯ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/st-geographyfromewkt.md b/tidb-cloud-lake/sql/st-geographyfromewkt.md new file mode 100644 index 0000000000000..9434bfebede31 --- /dev/null +++ b/tidb-cloud-lake/sql/st-geographyfromewkt.md @@ -0,0 +1,8 @@ +--- +title: ST_GEOGRAPHYFROMEWKT +summary: ST_GEOGRAPHYFROMWKT 的别名。 +--- + +# ST_GEOGRAPHYFROMEWKT + +[ST_GEOGRAPHYFROMWKT](/tidb-cloud-lake/sql/st-geographyfromwkt.md) 的别名。 \ No newline at end of file diff --git a/tidb-cloud-lake/sql/st-geographyfromtext.md b/tidb-cloud-lake/sql/st-geographyfromtext.md new file mode 100644 index 0000000000000..89ee0ed381c11 --- /dev/null +++ b/tidb-cloud-lake/sql/st-geographyfromtext.md @@ -0,0 +1,8 @@ +--- +title: ST_GEOGRAPHYFROMTEXT +summary: ST_GEOGRAPHYFROMWKT 的别名。 +--- + +# ST_GEOGRAPHYFROMTEXT + +[ST_GEOGRAPHYFROMWKT](/tidb-cloud-lake/sql/st-geographyfromwkt.md) 的别名。 \ No newline at end of file diff --git a/tidb-cloud-lake/sql/st-geographyfromwkb.md b/tidb-cloud-lake/sql/st-geographyfromwkb.md new file mode 100644 index 0000000000000..fd38023094309 --- /dev/null +++ b/tidb-cloud-lake/sql/st-geographyfromwkb.md @@ -0,0 +1,66 @@ +--- +title: ST_GEOGRAPHYFROMWKB +summary: 解析 WKB(well-known-binary) 或 EWKB(extended well-known-binary) 输入,并返回一个 GEOGRAPHY 类型的值。 +--- + +# ST_GEOGRAPHYFROMWKB + +解析 [WKB(well-known-binary)](https://en.wikipedia.org/wiki/Well-known_text_representation_of_geometry#Well-known_binary) 或 [EWKB(extended well-known-binary)](https://postgis.net/docs/ST_GeomFromEWKB.html) 输入,并返回一个 GEOGRAPHY 类型的值。 + +## 语法 {#syntax} + +```sql +ST_GEOGRAPHYFROMWKB() +ST_GEOGRAPHYFROMWKB() +``` + +## 别名 {#aliases} + +- [ST_GEOGFROMWKB](/tidb-cloud-lake/sql/st-geogfromwkb.md) +- [ST_GEOGETRYFROMWKB](/tidb-cloud-lake/sql/st-geogetryfromwkb.md) +- [ST_GEOGFROMEWKB](/tidb-cloud-lake/sql/st-geogfromewkb.md) + +## 参数 {#arguments} + +| 参数 | 描述 | +|-------------|--------------------------------------------------------------------------------| +| `` | 该参数必须是十六进制格式的 WKB 或 EWKB 字符串表达式。 | +| `` | 该参数必须是 WKB 或 EWKB 格式的二进制表达式。 | + +> **注意:** +> +> GEOGRAPHY 输入仅支持 SRID 4326。 + +## 返回类型 {#return-type} + +Geography。 + +## 示例 {#examples} + +```sql +SELECT + ST_ASWKT( + ST_GEOGRAPHYFROMWKB( + '0101000020E6100000000000000000F03F0000000000000040' + ) + ) AS pipeline_geography; + +┌────────────────────┐ +│ pipeline_geography │ +├────────────────────┤ +│ POINT(1 2) │ +└────────────────────┘ + +SELECT + ST_ASWKT( + ST_GEOGRAPHYFROMWKB( + FROM_HEX('0101000000000000000000F03F0000000000000040') + ) + ) AS pipeline_geography; + +┌────────────────────┐ +│ pipeline_geography │ +├────────────────────┤ +│ POINT(1 2) │ +└────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/st-geographyfromwkt.md b/tidb-cloud-lake/sql/st-geographyfromwkt.md new file mode 100644 index 0000000000000..263a22ff8ab8b --- /dev/null +++ b/tidb-cloud-lake/sql/st-geographyfromwkt.md @@ -0,0 +1,65 @@ +--- +title: ST_GEOGRAPHYFROMWKT +summary: 解析 WKT(well-known-text) 或 EWKT(extended well-known-text) 输入,并返回一个 GEOGRAPHY 类型的值。 +--- + +# ST_GEOGRAPHYFROMWKT + +解析 [WKT(well-known-text)](https://en.wikipedia.org/wiki/Well-known_text_representation_of_geometry) 或 [EWKT(extended well-known-text)](https://postgis.net/docs/ST_GeomFromEWKT.html) 输入,并返回一个 GEOGRAPHY 类型的值。 + +## 语法 {#syntax} + +```sql +ST_GEOGRAPHYFROMWKT() +``` + +## 别名 {#aliases} + +- [ST_GEOGFROMWKT](/tidb-cloud-lake/sql/st-geogfromwkt.md) +- [ST_GEOGRAPHYFROMEWKT](/tidb-cloud-lake/sql/st-geographyfromewkt.md) +- [ST_GEOGRAPHYFROMTEXT](/tidb-cloud-lake/sql/st-geographyfromtext.md) +- [ST_GEOGFROMTEXT](/tidb-cloud-lake/sql/st-geogfromtext.md) + +## 参数 {#arguments} + +| 参数 | 描述 | +|-------------|-----------------------------------------------------------------| +| `` | 该参数必须是 WKT 或 EWKT 格式的字符串表达式。 | + +> **注意:** +> +> GEOGRAPHY 输入仅支持 SRID 4326。 + +## 返回类型 {#return-type} + +Geography。 + +## 示例 {#examples} + +```sql +SELECT + ST_ASWKT( + ST_GEOGRAPHYFROMWKT( + 'POINT(1 2)' + ) + ) AS pipeline_geography; + +┌────────────────────┐ +│ pipeline_geography │ +├────────────────────┤ +│ POINT(1 2) │ +└────────────────────┘ + +SELECT + ST_ASEWKT( + ST_GEOGRAPHYFROMWKT( + 'SRID=4326;POINT(1 2)' + ) + ) AS pipeline_geography; + +┌──────────────────────┐ +│ pipeline_geography │ +├──────────────────────┤ +│ SRID=4326;POINT(1 2) │ +└──────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/st-geohash.md b/tidb-cloud-lake/sql/st-geohash.md new file mode 100644 index 0000000000000..53758a0258848 --- /dev/null +++ b/tidb-cloud-lake/sql/st-geohash.md @@ -0,0 +1,75 @@ +--- +title: ST_GEOHASH +summary: 返回 GEOMETRY 或 GEOGRAPHY 值的 geohash 字符串,并支持可选的精度参数来控制结果粒度。 +--- + +# ST_GEOHASH + +返回 GEOMETRY 或 GEOGRAPHY 对象的 [geohash](https://en.wikipedia.org/wiki/Geohash)。geohash 是一个简短的 base32 字符串,用于标识世界上包含某个位置的测地矩形。可选的 precision 参数用于指定返回的 geohash 的 `precision`。例如,将 5 作为 `precision` 传入时,会返回一个更短的 geohash(长度为 5 个字符),其精度也更低。 + +## 语法 {#syntax} + +```sql +ST_GEOHASH( [, ]) +``` + +## 参数 {#arguments} + +| 参数 | 描述 | +|-----------------|---------------------------------------------------------------------------| +| `` | 该参数必须是 GEOMETRY 或 GEOGRAPHY 类型的表达式。 | +| `[precision]` | 可选。指定返回的 geohash 的精度,默认为 12。 | + +## 返回类型 {#return-type} + +字符串。 + +## 示例 {#examples} + +### GEOMETRY 示例 {#geometry-examples} + +```sql +SELECT + ST_GEOHASH( + ST_GEOMETRYFROMWKT( + 'POINT(-122.306100 37.554162)' + ) + ) AS pipeline_geohash; + +┌──────────────────┐ +│ pipeline_geohash │ +├──────────────────┤ +│ 9q9j8ue2v71y │ +└──────────────────┘ + +SELECT + ST_GEOHASH( + ST_GEOMETRYFROMWKT( + 'SRID=4326;POINT(-122.35 37.55)' + ), + 5 + ) AS pipeline_geohash; + +┌──────────────────┐ +│ pipeline_geohash │ +├──────────────────┤ +│ 9q8vx │ +└──────────────────┘ +``` + +### GEOGRAPHY 示例 {#geography-examples} + +```sql +SELECT + ST_GEOHASH( + ST_GEOGFROMWKT( + 'POINT(-122.306100 37.554162)' + ) + ) AS pipeline_geohash; + +┌──────────────────┐ +│ pipeline_geohash │ +├──────────────────┤ +│ 9q9j8ue2v71y │ +└──────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/st-geom-point.md b/tidb-cloud-lake/sql/st-geom-point.md new file mode 100644 index 0000000000000..da39875dee22b --- /dev/null +++ b/tidb-cloud-lake/sql/st-geom-point.md @@ -0,0 +1,8 @@ +--- +title: ST_GEOM_POINT +summary: ST_MAKEGEOMPOINT 的别名。 +--- + +# ST_GEOM_POINT + +[ST_MAKEGEOMPOINT](/tidb-cloud-lake/sql/st-makegeompoint.md) 的别名。 \ No newline at end of file diff --git a/tidb-cloud-lake/sql/st-geometryfromewkb.md b/tidb-cloud-lake/sql/st-geometryfromewkb.md new file mode 100644 index 0000000000000..ac76ac4308307 --- /dev/null +++ b/tidb-cloud-lake/sql/st-geometryfromewkb.md @@ -0,0 +1,8 @@ +--- +title: ST_GEOMETRYFROMEWKB +summary: ST_GEOMTRYFROMWKB 的别名。 +--- + +# ST_GEOMETRYFROMEWKB + +[ST_GEOMTRYFROMWKB](/tidb-cloud-lake/sql/st-geometryfromwkb.md) 的别名。 \ No newline at end of file diff --git a/tidb-cloud-lake/sql/st-geometryfromewkt.md b/tidb-cloud-lake/sql/st-geometryfromewkt.md new file mode 100644 index 0000000000000..6ec86419c3416 --- /dev/null +++ b/tidb-cloud-lake/sql/st-geometryfromewkt.md @@ -0,0 +1,8 @@ +--- +title: ST_GEOMETRYFROMEWKT +summary: ST_GEOMTRYFROMWKT 的别名。 +--- + +# ST_GEOMETRYFROMEWKT + +[ST_GEOMTRYFROMWKT](/tidb-cloud-lake/sql/st-geometryfromwkt.md) 的别名。 \ No newline at end of file diff --git a/tidb-cloud-lake/sql/st-geometryfromtext.md b/tidb-cloud-lake/sql/st-geometryfromtext.md new file mode 100644 index 0000000000000..2bf923fdb5d45 --- /dev/null +++ b/tidb-cloud-lake/sql/st-geometryfromtext.md @@ -0,0 +1,8 @@ +--- +title: ST_GEOMETRYFROMTEXT +summary: ST_GEOMETRYFROMWKT 的别名。 +--- + +# ST_GEOMETRYFROMTEXT + +[ST_GEOMETRYFROMWKT](/tidb-cloud-lake/sql/st-geometryfromwkt.md) 的别名。 \ No newline at end of file diff --git a/tidb-cloud-lake/sql/st-geometryfromwkb.md b/tidb-cloud-lake/sql/st-geometryfromwkb.md new file mode 100644 index 0000000000000..a6cdb1b83bfc3 --- /dev/null +++ b/tidb-cloud-lake/sql/st-geometryfromwkb.md @@ -0,0 +1,59 @@ +--- +title: ST_GEOMETRYFROMWKB +summary: 解析 WKB(well-known-binary) 或 EWKB(extended well-known-binary) 输入,并返回 GEOMETRY 类型的值。 +--- + +# ST_GEOMETRYFROMWKB + +解析 [WKB(well-known-binary)](https://en.wikipedia.org/wiki/Well-known_text_representation_of_geometry#Well-known_binary) 或 [EWKB(extended well-known-binary)](https://postgis.net/docs/ST_GeomFromEWKB.html) 输入,并返回 GEOMETRY 类型的值。 + +## 语法 {#syntax} + +```sql +ST_GEOMETRYFROMWKB(, []) +ST_GEOMETRYFROMWKB(, []) +``` + +## 别名 {#aliases} + +- [ST_GEOMFROMWKB](/tidb-cloud-lake/sql/st-geomfromwkb.md) +- [ST_GEOMETRYFROMEWKB](/tidb-cloud-lake/sql/st-geometryfromewkb.md) +- [ST_GEOMFROMEWKB](/tidb-cloud-lake/sql/st-geomfromewkb.md) + +## 参数 {#arguments} + +| 参数 | 描述 | +|-------------|--------------------------------------------------------------------------------| +| `` | 该参数必须是十六进制格式的 WKB 或 EWKB 字符串表达式。 | +| `` | 该参数必须是 WKB 或 EWKB 格式的二进制表达式。 | +| `` | 要使用的 SRID 的整数值。 | + +## 返回类型 {#return-type} + +Geometry。 + +## 示例 {#examples} + +```sql +SELECT + ST_GEOMETRYFROMWKB( + '0101000020797f000066666666a9cb17411f85ebc19e325641' + ) AS pipeline_geometry; + +┌────────────────────────────────────────┐ +│ pipeline_geometry │ +├────────────────────────────────────────┤ +│ SRID=32633;POINT(389866.35 5819003.03) │ +└────────────────────────────────────────┘ + +SELECT + ST_GEOMETRYFROMWKB( + FROM_HEX('0101000020797f000066666666a9cb17411f85ebc19e325641'), 4326 + ) AS pipeline_geometry; + +┌───────────────────────────────────────┐ +│ pipeline_geometry │ +├───────────────────────────────────────┤ +│ SRID=4326;POINT(389866.35 5819003.03) │ +└───────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/st-geometryfromwkt.md b/tidb-cloud-lake/sql/st-geometryfromwkt.md new file mode 100644 index 0000000000000..62387871c01b9 --- /dev/null +++ b/tidb-cloud-lake/sql/st-geometryfromwkt.md @@ -0,0 +1,60 @@ +--- +title: ST_GEOMETRYFROMWKT +summary: 解析 WKT(well-known-text) 或 EWKT(extended well-known-text) 输入,并返回 GEOMETRY 类型的值。 +--- + +# ST_GEOMETRYFROMWKT + +解析 [WKT(well-known-text)](https://en.wikipedia.org/wiki/Well-known_text_representation_of_geometry) 或 [EWKT(extended well-known-text)](https://postgis.net/docs/ST_GeomFromEWKT.html) 输入,并返回 GEOMETRY 类型的值。 + +## 语法 {#syntax} + +```sql +ST_GEOMETRYFROMWKT(, []) +``` + +## 别名 {#aliases} + +- [ST_GEOMFROMWKT](/tidb-cloud-lake/sql/st-geomfromwkt.md) +- [ST_GEOMETRYFROMEWKT](/tidb-cloud-lake/sql/st-geometryfromewkt.md) +- [ST_GEOMFROMEWKT](/tidb-cloud-lake/sql/st-geomfromewkt.md) +- [ST_GEOMFROMTEXT](/tidb-cloud-lake/sql/st-geomfromtext.md) +- [ST_GEOMETRYFROMTEXT](/tidb-cloud-lake/sql/st-geometryfromtext.md) + +## 参数 {#arguments} + +| 参数 | 描述 | +|-------------|-------------------------------------------------------------| +| `` | 该参数必须是 WKT 或 EWKT 格式的字符串表达式。 | +| `` | 要使用的 SRID 的整数型值。 | + +## 返回类型 {#return-type} + +Geometry。 + +## 示例 {#examples} + +```sql +SELECT + ST_GEOMETRYFROMWKT( + 'POINT(1820.12 890.56)' + ) AS pipeline_geometry; + +┌───────────────────────┐ +│ pipeline_geometry │ +├───────────────────────┤ +│ POINT(1820.12 890.56) │ +└───────────────────────┘ + +SELECT + ST_GEOMETRYFROMWKT( + 'POINT(1820.12 890.56)', 4326 + ) AS pipeline_geometry; + +┌─────────────────────────────────┐ +│ pipeline_geometry │ +│ Geometry │ +├─────────────────────────────────┤ +│ SRID=4326;POINT(1820.12 890.56) │ +└─────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/st-geomfromewkb.md b/tidb-cloud-lake/sql/st-geomfromewkb.md new file mode 100644 index 0000000000000..c0e2f7a06535e --- /dev/null +++ b/tidb-cloud-lake/sql/st-geomfromewkb.md @@ -0,0 +1,8 @@ +--- +title: ST_GEOMFROMEWKB +summary: ST_GEOMTRYFROMWKB 的别名。 +--- + +# ST_GEOMFROMEWKB + +[ST_GEOMTRYFROMWKB](/tidb-cloud-lake/sql/st-geometryfromwkb.md) 的别名。 \ No newline at end of file diff --git a/tidb-cloud-lake/sql/st-geomfromewkt.md b/tidb-cloud-lake/sql/st-geomfromewkt.md new file mode 100644 index 0000000000000..4a5631bf10ebf --- /dev/null +++ b/tidb-cloud-lake/sql/st-geomfromewkt.md @@ -0,0 +1,8 @@ +--- +title: ST_GEOMFROMEWKT +summary: ST_GEOMTRYFROMWKT 的别名。 +--- + +# ST_GEOMFROMEWKT + +[ST_GEOMTRYFROMWKT](/tidb-cloud-lake/sql/st-geometryfromwkt.md) 的别名。 \ No newline at end of file diff --git a/tidb-cloud-lake/sql/st-geomfromgeohash.md b/tidb-cloud-lake/sql/st-geomfromgeohash.md new file mode 100644 index 0000000000000..e39863a1af516 --- /dev/null +++ b/tidb-cloud-lake/sql/st-geomfromgeohash.md @@ -0,0 +1,39 @@ +--- +title: ST_GEOMFROMGEOHASH +summary: 返回一个 GEOMETRY 对象,用于表示 geohash 边界的多边形。 +--- + +# ST_GEOMFROMGEOHASH + +返回一个 GEOMETRY 对象,用于表示 [geohash](https://en.wikipedia.org/wiki/Geohash) 边界的多边形。 + +## 语法 {#syntax} + +```sql +ST_GEOMFROMGEOHASH() +``` + +## 参数 {#arguments} + +| 参数 | 描述 | +|-------------|-------------------------| +| `` | 该参数必须是一个 geohash。 | + +## 返回类型 {#return-type} + +Geometry。 + +## 示例 {#examples} + +```sql +SELECT + ST_GEOMFROMGEOHASH( + '9q60y60rhs' + ) AS pipeline_geometry; + +┌──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ +│ st_geomfromgeohash('9q60y60rhs') │ +├──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤ +│ POLYGON((-120.66230535507202 35.30029535293579,-120.66230535507202 35.30030071735382,-120.66229462623596 35.30030071735382,-120.66229462623596 35.30029535293579,-120.66230535507202 35.30029535293579)) │ +└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/st-geomfromtext.md b/tidb-cloud-lake/sql/st-geomfromtext.md new file mode 100644 index 0000000000000..9b7d64254d60f --- /dev/null +++ b/tidb-cloud-lake/sql/st-geomfromtext.md @@ -0,0 +1,8 @@ +--- +title: ST_GEOMFROMTEXT +summary: ST_GEOMTRYFROMWKT 的别名。 +--- + +# ST_GEOMFROMTEXT + +[ST_GEOMTRYFROMWKT](/tidb-cloud-lake/sql/st-geometryfromwkt.md) 的别名。 \ No newline at end of file diff --git a/tidb-cloud-lake/sql/st-geomfromwkb.md b/tidb-cloud-lake/sql/st-geomfromwkb.md new file mode 100644 index 0000000000000..e36a65f1f2e0d --- /dev/null +++ b/tidb-cloud-lake/sql/st-geomfromwkb.md @@ -0,0 +1,8 @@ +--- +title: ST_GEOMFROMWKB +summary: ST_GEOMTRYFROMWKB 的别名。 +--- + +# ST_GEOMFROMWKB + +[ST_GEOMTRYFROMWKB](/tidb-cloud-lake/sql/st-geometryfromwkb.md) 的别名。 \ No newline at end of file diff --git a/tidb-cloud-lake/sql/st-geomfromwkt.md b/tidb-cloud-lake/sql/st-geomfromwkt.md new file mode 100644 index 0000000000000..9f731c1900b85 --- /dev/null +++ b/tidb-cloud-lake/sql/st-geomfromwkt.md @@ -0,0 +1,8 @@ +--- +title: ST_GEOMFROMWKT +summary: `ST_GEOMTRYFROMWKT` 的别名。 +--- + +# ST_GEOMFROMWKT + +[ST_GEOMTRYFROMWKT](/tidb-cloud-lake/sql/st-geometryfromwkt.md) 的别名。 \ No newline at end of file diff --git a/tidb-cloud-lake/sql/st-geompointfromgeohash.md b/tidb-cloud-lake/sql/st-geompointfromgeohash.md new file mode 100644 index 0000000000000..ef364a0b99dc7 --- /dev/null +++ b/tidb-cloud-lake/sql/st-geompointfromgeohash.md @@ -0,0 +1,40 @@ +--- +title: ST_GEOMPOINTFROMGEOHASH +summary: 返回一个 GEOMETRY 对象,表示 geohash 中心点对应的点。 +--- + +# ST_GEOMPOINTFROMGEOHASH + +返回一个 GEOMETRY 对象,表示 [geohash](https://en.wikipedia.org/wiki/Geohash) 中心点对应的点。 + +## 语法 {#syntax} + +```sql +ST_GEOMPOINTFROMGEOHASH() +``` + +## 参数 {#arguments} + +| 参数 | 描述 | +|-------------|---------------------------------| +| `` | 该参数必须是一个 geohash。 | + +## 返回类型 {#return-type} + +Geometry。 + +## 示例 {#examples} + +```sql +SELECT + ST_GEOMPOINTFROMGEOHASH( + 's02equ0' + ) AS pipeline_geometry; + +┌──────────────────────────────────────────────┐ +│ pipeline_geometry │ +│ Geometry │ +├──────────────────────────────────────────────┤ +│ POINT(1.0004425048828125 2.0001983642578125) │ +└──────────────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/st-hausdorffdistance.md b/tidb-cloud-lake/sql/st-hausdorffdistance.md new file mode 100644 index 0000000000000..8884159521705 --- /dev/null +++ b/tidb-cloud-lake/sql/st-hausdorffdistance.md @@ -0,0 +1,62 @@ +--- +title: ST_HAUSDORFFDISTANCE +summary: 返回两个 GEOMETRY 对象之间的离散 Hausdorff 距离。它通过查找一个对象中任意顶点到另一个对象中最近顶点的最大距离,来衡量两个几何对象相距多远。 +--- + +# ST_HAUSDORFFDISTANCE + +返回两个 GEOMETRY 对象之间的离散 Hausdorff 距离。它通过查找一个对象中任意顶点到另一个对象中最近顶点的最大距离,来衡量两个几何对象相距多远。 + +## 语法 {#syntax} + +```sql +ST_HAUSDORFFDISTANCE(, ) +``` + +## 参数 {#arguments} + +| 参数 | 描述 | +|---------------|----------------------| +| `` | 一个 GEOMETRY 表达式。 | +| `` | 一个 GEOMETRY 表达式。 | + +## 返回类型 {#return-type} + +Double。 + +## 示例 {#examples} + +```sql +SELECT ST_HAUSDORFFDISTANCE( + TO_GEOMETRY('POINT(0 0)'), + TO_GEOMETRY('POINT(0 1)') +); + +┌────────┐ +│ result │ +├────────┤ +│ 1.0 │ +└────────┘ + +SELECT ST_HAUSDORFFDISTANCE( + TO_GEOMETRY('LINESTRING(0 0, 1 0)'), + TO_GEOMETRY('LINESTRING(0 1, 1 1)') +); + +┌────────┐ +│ result │ +├────────┤ +│ 1.0 │ +└────────┘ + +SELECT ST_HAUSDORFFDISTANCE( + TO_GEOMETRY('POLYGON((0 0, 1 0, 1 1, 0 1, 0 0))'), + TO_GEOMETRY('POLYGON((2 0, 3 0, 3 1, 2 1, 2 0))') +); + +┌────────┐ +│ result │ +├────────┤ +│ 2.0 │ +└────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/st-hilbert.md b/tidb-cloud-lake/sql/st-hilbert.md new file mode 100644 index 0000000000000..224543dde3af7 --- /dev/null +++ b/tidb-cloud-lake/sql/st-hilbert.md @@ -0,0 +1,73 @@ +--- +title: ST_HILBERT +summary: 将 GEOMETRY 或 GEOGRAPHY 对象编码为 Hilbert 曲线索引。 +--- + +# ST_HILBERT + +将 GEOMETRY 或 GEOGRAPHY 对象编码为 Hilbert 曲线索引。该函数使用几何对象边界框中心点作为待编码的点。提供边界时,会先将该点归一化到指定的边界框中,再进行编码。 + +## 语法 {#syntax} + +```sql +ST_HILBERT() +ST_HILBERT(, ) +``` + +## 参数 {#arguments} + +| 参数 | 描述 | +|-----------|-------------| +| `` | 该参数必须是 GEOMETRY 或 GEOGRAPHY 类型的表达式。 | +| `` | 可选。一个数组 `[xmin, ymin, xmax, ymax]`,用于在编码前对点进行归一化。 | + +> **注意:** +> +> - Geometry:如果未提供边界框,GEOMETRY 坐标不会被归一化到特定边界框。相反,中心点的值会被映射到完整的 `float32` 域中,然后编码为 Hilbert 索引。 +> - Geography:如果未提供边界框,则默认边界为 `[-180, -90, 180, 90]`。 + +## 返回类型 {#return-type} + +UInt64。 + +## 示例 {#examples} + +### GEOMETRY 示例 {#geometry-examples} + +```sql +SELECT ST_HILBERT(TO_GEOMETRY('POINT(1 2)')) AS hilbert1, ST_HILBERT(TO_GEOMETRY('POINT(5 5)')) AS hilbert2; + +╭───────────────────────────╮ +│ hilbert1 │ hilbert2 │ +├─────────────┼─────────────┤ +│ 3355443200 │ 2155872256 │ +╰───────────────────────────╯ + +SELECT ST_HILBERT(TO_GEOMETRY('POINT(1 2)'), [0, 0, 1, 1]) AS hilbert1, ST_HILBERT(TO_GEOMETRY('POINT(5 5)'), [0, 0, 5, 5]) AS hilbert2; + +╭───────────────────────────╮ +│ hilbert1 │ hilbert2 │ +├─────────────┼─────────────┤ +│ 2863311530 │ 2863311530 │ +╰───────────────────────────╯ +``` + +### GEOGRAPHY 示例 {#geography-examples} + +```sql +SELECT ST_HILBERT(TO_GEOGRAPHY('POINT(113.15 23.06)')) AS hilbert1, ST_HILBERT(TO_GEOGRAPHY('POINT(116.25 39.54)')) AS hilbert2; + +╭───────────────────────────╮ +│ hilbert1 │ hilbert2 │ +├─────────────┼─────────────┤ +│ 3070259060 │ 3033451300 │ +╰───────────────────────────╯ + +SELECT ST_HILBERT(TO_GEOGRAPHY('POINT(113.15 23.06)'), [73, 4, 135, 53]) AS hilbert1, ST_HILBERT(TO_GEOGRAPHY('POINT(116.25 39.54)'), [73, 4, 135, 53]) AS hilbert2; + +╭───────────────────────────╮ +│ hilbert1 │ hilbert2 │ +├─────────────┼─────────────┤ +│ 3533607194 │ 2330429279 │ +╰───────────────────────────╯ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/st-intersection-agg.md b/tidb-cloud-lake/sql/st-intersection-agg.md new file mode 100644 index 0000000000000..1739bd1d05c85 --- /dev/null +++ b/tidb-cloud-lake/sql/st-intersection-agg.md @@ -0,0 +1,49 @@ +--- +title: ST_INTERSECTION_AGG +summary: 通过重复应用 ST_INTERSECTION 对多个 GEOMETRY 值进行聚合,并返回共同重叠的部分。 +--- + +# ST_INTERSECTION_AGG + +通过重复应用 `ST_INTERSECTION` 对多个 GEOMETRY 值进行聚合,并返回共同重叠的部分。 + +此函数仅支持 GEOMETRY。 + +## 语法 {#syntax} + +```sql +ST_INTERSECTION_AGG() +``` + +## 参数 {#arguments} + +| 参数 | 描述 | +|-----------|-------------| +| `` | 一个 GEOMETRY 类型的表达式。 | + +## 返回类型 {#return-type} + +GEOMETRY。 + +> **注意:** +> +> - 会忽略输入中的 NULL 行。 +> - 如果所有输入行均为 NULL,则结果为 NULL。 +> - 如果输入的 GEOMETRY 值使用了不同的 SRID,则该函数会返回错误。 + +## 示例 {#example} + +```sql +WITH data AS ( + SELECT TO_GEOMETRY('POLYGON((0 0,4 0,4 4,0 4,0 0))') AS g + UNION ALL + SELECT TO_GEOMETRY('POLYGON((1 1,3 1,3 3,1 3,1 1))') +) +SELECT ST_ASWKT(ST_INTERSECTION_AGG(g)) FROM data; + +╭──────────────────────────────────╮ +│ st_aswkt(st_intersection_agg(g)) │ +├──────────────────────────────────┤ +│ POLYGON((1 3,1 1,3 1,3 3,1 3)) │ +╰──────────────────────────────────╯ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/st-intersection.md b/tidb-cloud-lake/sql/st-intersection.md new file mode 100644 index 0000000000000..ef0045044cff1 --- /dev/null +++ b/tidb-cloud-lake/sql/st-intersection.md @@ -0,0 +1,43 @@ +--- +title: ST_INTERSECTION +summary: 返回两个 GEOMETRY 对象的共享部分。 +--- + +# ST_INTERSECTION + +返回两个 GEOMETRY 对象的共享部分。 + +此函数仅支持 GEOMETRY 值。 + +## 语法 {#syntax} + +```sql +ST_INTERSECTION(, ) +``` + +## 参数 {#arguments} + +| 参数 | 描述 | +|---------------|--------------------------------------------------------| +| `` | 该参数必须是 GEOMETRY 类型的表达式。 | +| `` | 该参数必须是 GEOMETRY 类型的表达式。 | + +> **注意:** +> +> 如果两个输入的 GEOMETRY 对象具有不同的 SRID,则该函数会报错。 + +## 返回类型 {#return-type} + +GEOMETRY。 + +## 示例 {#examples} + +```sql +SELECT ST_ASWKT(ST_INTERSECTION(TO_GEOMETRY('LINESTRING(0 0, 1 1)'), TO_GEOMETRY('LINESTRING(0 0, 1 1)'))); + +╭─────────────────────────────────────────────────────────────────────────────────────────────────────╮ +│ st_aswkt(st_intersection(to_geometry('LINESTRING(0 0, 1 1)'), to_geometry('LINESTRING(0 0, 1 1)'))) │ +├─────────────────────────────────────────────────────────────────────────────────────────────────────┤ +│ LINESTRING(0 0,1 1) │ +╰─────────────────────────────────────────────────────────────────────────────────────────────────────╯ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/st-intersects.md b/tidb-cloud-lake/sql/st-intersects.md new file mode 100644 index 0000000000000..8513396703fe9 --- /dev/null +++ b/tidb-cloud-lake/sql/st-intersects.md @@ -0,0 +1,55 @@ +--- +title: ST_INTERSECTS +summary: 如果两个 GEOMETRY 对象共享任意一部分空间,则返回 TRUE。 +--- + +# ST_INTERSECTS + +如果两个 GEOMETRY 对象共享任意一部分空间,则返回 TRUE。 + +## 语法 {#syntax} + +```sql +ST_INTERSECTS(, ) +``` + +## 参数 {#arguments} + +| 参数 | 描述 | +|---------------|-------------------------------------------------------| +| `` | 该参数必须是 GEOMETRY 类型的表达式。 | +| `` | 该参数必须是 GEOMETRY 类型的表达式。 | + +> **注意:** +> +> 如果两个输入的 GEOMETRY 对象具有不同的 SRID,则该函数会报错。 + +## 返回类型 {#return-type} + +布尔值。 + +## 示例 {#examples} + +```sql +SELECT ST_INTERSECTS( + TO_GEOMETRY('LINESTRING(0 0, 2 2)'), + TO_GEOMETRY('LINESTRING(0 2, 2 0)') +) AS intersects; + +╭────────────╮ +│ intersects │ +├────────────┤ +│ true │ +╰────────────╯ + +SELECT ST_INTERSECTS( + TO_GEOMETRY('POLYGON((0 0, 2 0, 2 2, 0 2, 0 0))'), + TO_GEOMETRY('POINT(3 3)') +) AS intersects; + +╭────────────╮ +│ intersects │ +├────────────┤ +│ false │ +╰────────────╯ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/st-isvalid.md b/tidb-cloud-lake/sql/st-isvalid.md new file mode 100644 index 0000000000000..c9598db0ccc48 --- /dev/null +++ b/tidb-cloud-lake/sql/st-isvalid.md @@ -0,0 +1,45 @@ +--- +title: ST_ISVALID +summary: 如果 GEOMETRY 对象在几何上有效(由 OGC 规范定义),则返回 TRUE。 +--- + +# ST_ISVALID + +如果 GEOMETRY 对象在几何上有效(由 OGC 规范定义),则返回 TRUE。 + +## 语法 {#syntax} + +```sql +ST_ISVALID() +``` + +## 参数 {#arguments} + +| 参数 | 描述 | +|--------------|-----------------------| +| `` | 一个 GEOMETRY 表达式。 | + +## 返回类型 {#return-type} + +布尔型。 + +## 示例 {#examples} + +```sql +SELECT ST_ISVALID(TO_GEOMETRY('POLYGON((0 0, 1 0, 1 1, 0 1, 0 0))')); + +┌──────────────────────────────────────────────────────────┐ +│ st_isvalid(to_geometry('polygon((0 0, 1 0, 1 1, 0 1, 0 0))')) │ +├──────────────────────────────────────────────────────────┤ +│ true │ +└──────────────────────────────────────────────────────────┘ + +-- Self-intersecting polygon (bowtie shape) is invalid +SELECT ST_ISVALID(TO_GEOMETRY('POLYGON((0 0, 2 2, 2 0, 0 2, 0 0))')); + +┌──────────────────────────────────────────────────────────────┐ +│ st_isvalid(to_geometry('polygon((0 0, 2 2, 2 0, 0 2, 0 0))')) │ +├──────────────────────────────────────────────────────────────┤ +│ false │ +└──────────────────────────────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/st-length.md b/tidb-cloud-lake/sql/st-length.md new file mode 100644 index 0000000000000..5ae7ab03b05f5 --- /dev/null +++ b/tidb-cloud-lake/sql/st-length.md @@ -0,0 +1,81 @@ +--- +title: ST_LENGTH +summary: 返回 GEOMETRY 或 GEOGRAPHY 对象中 LineString 的欧几里得长度。 +--- + +# ST_LENGTH + +返回 GEOMETRY 或 GEOGRAPHY 对象中 LineString 的欧几里得长度。 + +## 语法 {#syntax} + +```sql +ST_LENGTH() +``` + +## 参数 {#arguments} + +| 参数 | 描述 | +|--------------|-----------------------------------------------------------------------------| +| `` | 该参数必须是一个 GEOMETRY 或 GEOGRAPHY 类型的表达式,且其中包含 linestring。 | + +> **注意:** +> +> - 如果 `` 不是 `LineString`、`MultiLineString` 或包含 linestring 的 `GeometryCollection`,则返回 0。 +> - 如果 `` 是 `GeometryCollection`,则返回该集合中所有 linestring 长度之和。 + +## 返回类型 {#return-type} + +Double。 + +## 示例 {#examples} + +### GEOMETRY 示例 {#geometry-examples} + +```sql +SELECT + ST_LENGTH(TO_GEOMETRY('POINT(1 1)')) AS length + +┌─────────┐ +│ length │ +├─────────┤ +│ 0 │ +└─────────┘ + +SELECT + ST_LENGTH(TO_GEOMETRY('LINESTRING(0 0, 1 1)')) AS length + +┌─────────────┐ +│ length │ +├─────────────┤ +│ 1.414213562 │ +└─────────────┘ + +SELECT + ST_LENGTH( + TO_GEOMETRY('POLYGON((0 0, 0 1, 1 1, 1 0, 0 0))') + ) AS length + +┌─────────┐ +│ length │ +├─────────┤ +│ 0 │ +└─────────┘ +``` + +### GEOGRAPHY 示例 {#geography-examples} + +```sql +SELECT + ST_LENGTH( + ST_GEOGFROMWKT( + 'LINESTRING(0 0, 1 0)' + ) + ) AS length + +╭──────────────────╮ +│ length │ +├──────────────────┤ +│ 111319.490793274 │ +╰──────────────────╯ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/st-make-line.md b/tidb-cloud-lake/sql/st-make-line.md new file mode 100644 index 0000000000000..8c3b2fc7426db --- /dev/null +++ b/tidb-cloud-lake/sql/st-make-line.md @@ -0,0 +1,8 @@ +--- +title: ST_MAKE_LINE +summary: ST_MAKELINE 的别名。 +--- + +# ST_MAKE_LINE + +[ST_MAKELINE](/tidb-cloud-lake/sql/st-makeline.md) 的别名。 \ No newline at end of file diff --git a/tidb-cloud-lake/sql/st-makegeompoint.md b/tidb-cloud-lake/sql/st-makegeompoint.md new file mode 100644 index 0000000000000..3226d7e5e883a --- /dev/null +++ b/tidb-cloud-lake/sql/st-makegeompoint.md @@ -0,0 +1,55 @@ +--- +title: ST_MAKEGEOMPOINT +summary: 构造一个 GEOMETRY 对象,该对象表示具有指定经度和纬度的 Point。 +--- + +# ST_MAKEGEOMPOINT + +构造一个 GEOMETRY 对象,该对象表示具有指定经度和纬度的 Point。 + +## 语法 {#syntax} + +```sql +ST_MAKEGEOMPOINT(, ) +``` + +## 别名 {#aliases} + +- [ST_GEOM_POINT](/tidb-cloud-lake/sql/st-geom-point.md) + +## 参数 {#arguments} + +| 参数 | 描述 | +|---------------|-----------------------------------------------| +| `` | 表示经度的 Double 值。 | +| `` | 表示纬度的 Double 值。 | + +## 返回类型 {#return-type} + +Geometry。 + +## 示例 {#examples} + +```sql +SELECT + ST_MAKEGEOMPOINT( + 7.0, 8.0 + ) AS pipeline_point; + +┌────────────────┐ +│ pipeline_point │ +├────────────────┤ +│ POINT(7 8) │ +└────────────────┘ + +SELECT + ST_MAKEGEOMPOINT( + -122.3061, 37.554162 + ) AS pipeline_point; + +┌────────────────────────────┐ +│ pipeline_point │ +├────────────────────────────┤ +│ POINT(-122.3061 37.554162) │ +└────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/st-makeline.md b/tidb-cloud-lake/sql/st-makeline.md new file mode 100644 index 0000000000000..222784da3e32c --- /dev/null +++ b/tidb-cloud-lake/sql/st-makeline.md @@ -0,0 +1,71 @@ +--- +title: ST_MAKELINE +summary: 构造一个 GEOMETRY 或 GEOGRAPHY 对象,用于表示连接输入的两个 GEOMETRY 或 GEOGRAPHY 对象中各点的线。 +--- + +# ST_MAKELINE + +构造一个 GEOMETRY 或 GEOGRAPHY 对象,用于表示连接输入的两个 GEOMETRY 或 GEOGRAPHY 对象中各点的线。 + +## 语法 {#syntax} + +```sql +ST_MAKELINE(, ) +``` + +## 别名 {#aliases} + +- [ST_MAKE_LINE](/tidb-cloud-lake/sql/st-make-line.md) + +## 参数 {#arguments} + +| 参数 | 描述 | +|---------------|-------------------------------------------------------------------------------------------------------------| +| `` | 一个包含待连接点的 GEOMETRY 或 GEOGRAPHY 对象。该对象必须是 Point、MultiPoint 或 LineString。 | +| `` | 一个包含待连接点的 GEOMETRY 或 GEOGRAPHY 对象。该对象必须是 Point、MultiPoint 或 LineString。 | + +## 返回类型 {#return-type} + +Geometry。 + +## 示例 {#examples} + +### GEOMETRY 示例 {#geometry-examples} + +```sql +SELECT + ST_MAKELINE( + ST_GEOMETRYFROMWKT( + 'POINT(-122.306100 37.554162)' + ), + ST_GEOMETRYFROMWKT( + 'POINT(-104.874173 56.714538)' + ) + ) AS pipeline_line; + +┌───────────────────────────────────────────────────────┐ +│ pipeline_line │ +├───────────────────────────────────────────────────────┤ +│ LINESTRING(-122.3061 37.554162,-104.874173 56.714538) │ +└───────────────────────────────────────────────────────┘ +``` + +### GEOGRAPHY 示例 {#geography-examples} + +```sql +SELECT + ST_MAKELINE( + ST_GEOGFROMWKT( + 'POINT(-122.306100 37.554162)' + ), + ST_GEOGFROMWKT( + 'POINT(-104.874173 56.714538)' + ) + ) AS pipeline_line; + +╭───────────────────────────────────────────────────────╮ +│ pipeline_line │ +├───────────────────────────────────────────────────────┤ +│ LINESTRING(-122.3061 37.554162,-104.874173 56.714538) │ +╰───────────────────────────────────────────────────────╯ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/st-makepoint.md b/tidb-cloud-lake/sql/st-makepoint.md new file mode 100644 index 0000000000000..0f52c8c8da321 --- /dev/null +++ b/tidb-cloud-lake/sql/st-makepoint.md @@ -0,0 +1,59 @@ +--- +title: ST_MAKEPOINT +summary: 构造一个 GEOGRAPHY 对象,该对象表示具有指定经度和纬度的 Point。 +--- + +# ST_MAKEPOINT + +构造一个 GEOGRAPHY 对象,该对象表示具有指定经度和纬度的 Point。 + +## 语法 {#syntax} + +```sql +ST_MAKEPOINT(, ) +``` + +## 别名 {#aliases} + +- [ST_POINT](/tidb-cloud-lake/sql/st-point.md) + +## 参数 {#arguments} + +| 参数 | 描述 | +|---------------|-----------------------------------------------| +| `` | 表示经度的 Double 值。 | +| `` | 表示纬度的 Double 值。 | + +## 返回类型 {#return-type} + +Geography。 + +## 示例 {#examples} + +```sql +SELECT + ST_ASWKT( + ST_MAKEPOINT( + 7.0, 8.0 + ) + ) AS pipeline_point; + +┌────────────────┐ +│ pipeline_point │ +├────────────────┤ +│ POINT(7 8) │ +└────────────────┘ + +SELECT + ST_ASWKT( + ST_MAKEPOINT( + -122.3061, 37.554162 + ) + ) AS pipeline_point; + +╭────────────────────────────╮ +│ pipeline_point │ +├────────────────────────────┤ +│ POINT(-122.3061 37.554162) │ +╰────────────────────────────╯ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/st-makepolygon.md b/tidb-cloud-lake/sql/st-makepolygon.md new file mode 100644 index 0000000000000..bd19898c3449a --- /dev/null +++ b/tidb-cloud-lake/sql/st-makepolygon.md @@ -0,0 +1,64 @@ +--- +title: ST_MAKEPOLYGON +summary: 构造一个表示无孔 Polygon 的 GEOMETRY 或 GEOGRAPHY 对象。该函数使用指定的 LineString 作为外环。 +--- + +# ST_MAKEPOLYGON + +构造一个表示无孔 Polygon 的 GEOMETRY 或 GEOGRAPHY 对象。该函数使用指定的 LineString 作为外环。 + +## 语法 {#syntax} + +```sql +ST_MAKEPOLYGON() +``` + +## 别名 {#aliases} + +- [ST_POLYGON](/tidb-cloud-lake/sql/st-polygon.md) + +## 参数 {#arguments} + +| 参数 | 描述 | +|--------------|------------------------------------------------------| +| `` | 该参数必须是 GEOMETRY 或 GEOGRAPHY 类型的表达式。 | + +## 返回类型 {#return-type} + +Geometry。 + +## 示例 {#examples} + +### GEOMETRY 示例 {#geometry-examples} + +```sql +SELECT + ST_MAKEPOLYGON( + ST_GEOMETRYFROMWKT( + 'LINESTRING(0.0 0.0, 1.0 0.0, 1.0 2.0, 0.0 2.0, 0.0 0.0)' + ) + ) AS pipeline_polygon; + +┌────────────────────────────────┐ +│ pipeline_polygon │ +├────────────────────────────────┤ +│ POLYGON((0 0,1 0,1 2,0 2,0 0)) │ +└────────────────────────────────┘ +``` + +### GEOGRAPHY 示例 {#geography-examples} + +```sql +SELECT + ST_MAKEPOLYGON( + ST_GEOGFROMWKT( + 'LINESTRING(0.0 0.0, 1.0 0.0, 1.0 2.0, 0.0 2.0, 0.0 0.0)' + ) + ) AS pipeline_polygon; + +╭────────────────────────────────╮ +│ pipeline_polygon │ +├────────────────────────────────┤ +│ POLYGON((0 0,1 0,1 2,0 2,0 0)) │ +╰────────────────────────────────╯ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/st-makepolygonoriented.md b/tidb-cloud-lake/sql/st-makepolygonoriented.md new file mode 100644 index 0000000000000..f761e4b50409e --- /dev/null +++ b/tidb-cloud-lake/sql/st-makepolygonoriented.md @@ -0,0 +1,54 @@ +--- +title: ST_MAKEPOLYGONORIENTED +summary: 从 LineString 输入创建 Polygon,并保留给定的顶点顺序。与 ST_MAKEPOLYGON 不同,此函数不会重新排序顶点以强制特定的环绕方向。 +--- + +# ST_MAKEPOLYGONORIENTED + +从 LineString 输入创建 Polygon,并保留给定的顶点顺序。与 [ST_MAKEPOLYGON](/tidb-cloud-lake/sql/st-makepolygon.md) 不同,此函数不会重新排序顶点以强制特定的环绕方向。 + +## 语法 {#syntax} + +```sql +ST_MAKEPOLYGONORIENTED() +``` + +## 参数 {#arguments} + +| 参数 | 描述 | +|--------------|-----------------------------------------------------------------------------| +| `` | 类型为 LineString 的 GEOMETRY 表达式。必须至少包含 4 个点,且第一个点和最后一个点必须相同。 | + +> **注意:** +> +> - 仅接受 LineString 输入。其他类型会产生错误。 +> - LineString 必须构成有效的多边形(不能有自相交)。 + +## 返回类型 {#return-type} + +Geometry。 + +## 示例 {#examples} + +```sql +SELECT ST_ASWKT( + ST_MAKEPOLYGONORIENTED(TO_GEOMETRY('LINESTRING(0 0, 1 0, 1 2, 0 2, 0 0)')) +); + +┌──────────────────────────────────┐ +│ result │ +├──────────────────────────────────┤ +│ POLYGON((0 0,1 0,1 2,0 2,0 0)) │ +└──────────────────────────────────┘ + +-- Reversed winding order is preserved +SELECT ST_ASWKT( + ST_MAKEPOLYGONORIENTED(TO_GEOMETRY('LINESTRING(0 0, 0 2, 1 2, 1 0, 0 0)')) +); + +┌──────────────────────────────────┐ +│ result │ +├──────────────────────────────────┤ +│ POLYGON((0 0,0 2,1 2,1 0,0 0)) │ +└──────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/st-npoints.md b/tidb-cloud-lake/sql/st-npoints.md new file mode 100644 index 0000000000000..2809a6f8ddb91 --- /dev/null +++ b/tidb-cloud-lake/sql/st-npoints.md @@ -0,0 +1,86 @@ +--- +title: ST_NPOINTS +summary: 返回 GEOMETRY 或 GEOGRAPHY 对象中的点数。 +--- + +# ST_NPOINTS + +返回 GEOMETRY 或 GEOGRAPHY 对象中的点数。 + +## 语法 {#syntax} + +```sql +ST_NPOINTS() +``` + +## 别名 {#aliases} + +- [ST_NUMPOINTS](/tidb-cloud-lake/sql/st-numpoints.md) + +## 参数 {#arguments} + +| 参数 | 描述 | +|--------------|-------------------------------------------------------------| +| `` | 该参数必须是 GEOMETRY 或 GEOGRAPHY 对象类型的表达式。 | + +## 返回类型 {#return-type} + +UInt8。 + +## 示例 {#examples} + +### GEOMETRY 示例 {#geometry-examples} + +```sql +SELECT ST_NPOINTS(TO_GEOMETRY('POINT(66 12)')) AS npoints + +┌─────────┐ +│ npoints │ +├─────────┤ +│ 1 │ +└─────────┘ + +SELECT ST_NPOINTS(TO_GEOMETRY('MULTIPOINT((45 21),(12 54))')) AS npoints + +┌─────────┐ +│ npoints │ +├─────────┤ +│ 2 │ +└─────────┘ + +SELECT ST_NPOINTS(TO_GEOMETRY('LINESTRING(40 60,50 50,60 40)')) AS npoints + +┌─────────┐ +│ npoints │ +├─────────┤ +│ 3 │ +└─────────┘ + +SELECT ST_NPOINTS(TO_GEOMETRY('MULTILINESTRING((1 1,32 17),(33 12,73 49,87.1 6.1))')) AS npoints + +┌─────────┐ +│ npoints │ +├─────────┤ +│ 5 │ +└─────────┘ + +SELECT ST_NPOINTS(TO_GEOMETRY('GEOMETRYCOLLECTION(POLYGON((-10 0,0 10,10 0,-10 0)),LINESTRING(40 60,50 50,60 40),POINT(99 11))')) AS npoints + +┌─────────┐ +│ npoints │ +├─────────┤ +│ 8 │ +└─────────┘ +``` + +### GEOGRAPHY 示例 {#geography-examples} + +```sql +SELECT ST_NPOINTS(ST_GEOGFROMWKT('LINESTRING(40 60,50 50,60 40)')) AS npoints + +┌─────────┐ +│ npoints │ +├─────────┤ +│ 3 │ +└─────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/st-numpoints.md b/tidb-cloud-lake/sql/st-numpoints.md new file mode 100644 index 0000000000000..ed81ff77e83f6 --- /dev/null +++ b/tidb-cloud-lake/sql/st-numpoints.md @@ -0,0 +1,8 @@ +--- +title: ST_NUMPOINTS +summary: ST_NPOINTS 的别名。 +--- + +# ST_NUMPOINTS + +[ST_NPOINTS](/tidb-cloud-lake/sql/st-npoints.md) 的别名。 \ No newline at end of file diff --git a/tidb-cloud-lake/sql/st-perimeter.md b/tidb-cloud-lake/sql/st-perimeter.md new file mode 100644 index 0000000000000..78d131b60b824 --- /dev/null +++ b/tidb-cloud-lake/sql/st-perimeter.md @@ -0,0 +1,57 @@ +--- +title: ST_PERIMETER +summary: 返回 GEOMETRY 对象中多边形的周长,以坐标系的单位度量。 +--- + +# ST_PERIMETER + +返回 GEOMETRY 对象中多边形的周长,以坐标系的单位度量。 + +## 语法 {#syntax} + +```sql +ST_PERIMETER() +``` + +## 参数 {#arguments} + +| 参数 | 描述 | +|--------------|------------------------------------------------------| +| `` | 一个 GEOMETRY 表达式。 | + +> **注意:** +> +> 如果输入不是 Polygon 或 MultiPolygon,则返回 0。 + +## 返回类型 {#return-type} + +Double。 + +## 示例 {#examples} + +```sql +SELECT ST_PERIMETER(TO_GEOMETRY('POLYGON((0 0, 0 1, 1 1, 1 0, 0 0))')); + +┌─────────────────────────────────────────────────────────────────┐ +│ st_perimeter(to_geometry('polygon((0 0, 0 1, 1 1, 1 0, 0 0))')) │ +├─────────────────────────────────────────────────────────────────┤ +│ 4.0 │ +└─────────────────────────────────────────────────────────────────┘ + +SELECT ST_PERIMETER(TO_GEOMETRY('POLYGON((0 0, 0 3, 4 3, 4 0, 0 0))')); + +┌─────────────────────────────────────────────────────────────────┐ +│ st_perimeter(to_geometry('polygon((0 0, 0 3, 4 3, 4 0, 0 0))')) │ +├─────────────────────────────────────────────────────────────────┤ +│ 14.0 │ +└─────────────────────────────────────────────────────────────────┘ + +-- Non-polygon types return 0 +SELECT ST_PERIMETER(TO_GEOMETRY('POINT(1 1)')); + +┌──────────────────────────────────────┐ +│ st_perimeter(to_geometry('point(1 1)')) │ +├──────────────────────────────────────┤ +│ 0.0 │ +└──────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/st-point.md b/tidb-cloud-lake/sql/st-point.md new file mode 100644 index 0000000000000..f05621fb7f43e --- /dev/null +++ b/tidb-cloud-lake/sql/st-point.md @@ -0,0 +1,8 @@ +--- +title: ST_POINT +summary: ST_MAKEPOINT 的别名。 +--- + +# ST_POINT + +[ST_MAKEPOINT](/tidb-cloud-lake/sql/st-makepoint.md) 的别名。 \ No newline at end of file diff --git a/tidb-cloud-lake/sql/st-pointn.md b/tidb-cloud-lake/sql/st-pointn.md new file mode 100644 index 0000000000000..bcc6d39ee849a --- /dev/null +++ b/tidb-cloud-lake/sql/st-pointn.md @@ -0,0 +1,81 @@ +--- +title: ST_POINTN +summary: 返回 LineString 中指定索引处的 Point。 +--- + +# ST_POINTN + +返回 LineString 中指定索引处的 Point。 + +## 语法 {#syntax} + +```sql +ST_POINTN(, ) +``` + +## 参数 {#arguments} + +| 参数 | 描述 | +|--------------|-----------------------------------------------------------------------------------| +| `` | 该参数必须是一个 GEOMETRY 或 GEOGRAPHY 类型的表达式,并且表示一个 LineString。 | +| `` | 要返回的 Point 的索引。 | + +> **注意:** +> +> 索引从 1 开始计数,负索引用作从 LineString 末尾开始的偏移。如果 index 超出范围,函数会返回错误。 + +## 返回类型 {#return-type} + +Geometry。 + +## 示例 {#examples} + +### GEOMETRY 示例 {#geometry-examples} + +```sql +SELECT + ST_POINTN( + ST_GEOMETRYFROMWKT( + 'LINESTRING(1 1, 2 2, 3 3, 4 4)' + ), + 1 + ) AS pipeline_pointn; + +┌─────────────────┐ +│ pipeline_pointn │ +├─────────────────┤ +│ POINT(1 1) │ +└─────────────────┘ + +SELECT + ST_POINTN( + ST_GEOMETRYFROMWKT( + 'LINESTRING(1 1, 2 2, 3 3, 4 4)' + ), + -2 + ) AS pipeline_pointn; + +┌─────────────────┐ +│ pipeline_pointn │ +├─────────────────┤ +│ POINT(3 3) │ +└─────────────────┘ +``` + +### GEOGRAPHY 示例 {#geography-examples} + +```sql +SELECT + ST_POINTN( + ST_GEOGFROMWKT( + 'LINESTRING(1 1, 2 2, 3 3, 4 4)' + ), + 2 + ) AS pipeline_pointn; + +┌─────────────────┐ +│ pipeline_pointn │ +├─────────────────┤ +│ POINT(2 2) │ +└─────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/st-polygon.md b/tidb-cloud-lake/sql/st-polygon.md new file mode 100644 index 0000000000000..667efa63f1351 --- /dev/null +++ b/tidb-cloud-lake/sql/st-polygon.md @@ -0,0 +1,8 @@ +--- +title: ST_POLYGON +summary: ST_MAKEPOLYGON 的别名。 +--- + +# ST_POLYGON + +[ST_MAKEPOLYGON](/tidb-cloud-lake/sql/st-makepolygon.md) 的别名。 \ No newline at end of file diff --git a/tidb-cloud-lake/sql/st-setsrid.md b/tidb-cloud-lake/sql/st-setsrid.md new file mode 100644 index 0000000000000..860a04f9bccc8 --- /dev/null +++ b/tidb-cloud-lake/sql/st-setsrid.md @@ -0,0 +1,40 @@ +--- +title: ST_SETSRID +summary: 返回一个将其 SRID(空间参考系统标识符)设置为指定值的 GEOMETRY 对象。此函数只会更改 SRID,而不会影响对象的坐标。如果你还需要更改坐标以匹配新的 SRS(空间参考系统),请改用 ST_TRANSFORM。 +--- + +# ST_SETSRID + +返回一个将其 [SRID(空间参考系统标识符)](https://en.wikipedia.org/wiki/Spatial_reference_system#Identifier) 设置为指定值的 GEOMETRY 对象。此函数只会更改 SRID,而不会影响对象的坐标。如果你还需要更改坐标以匹配新的 SRS(空间参考系统),请改用 [ST_TRANSFORM](/tidb-cloud-lake/sql/st-transform.md)。 + +## 语法 {#syntax} + +```sql +ST_SETSRID(, ) +``` + +## 参数 {#arguments} + +| 参数 | 描述 | +|--------------|-----------------------------------------------------| +| `` | 该参数必须是 GEOMETRY 对象类型的表达式。 | +| `` | 在返回的 GEOMETRY 对象中要设置的 SRID 整数型值。 | + +## 返回类型 {#return-type} + +Geometry。 + +## 示例 {#examples} + +```sql +SET GEOMETRY_OUTPUT_FORMAT = 'EWKT' + +SELECT ST_SETSRID(TO_GEOMETRY('POINT(13 51)'), 4326) AS geometry + +┌────────────────────────┐ +│ geometry │ +├────────────────────────┤ +│ SRID=4326;POINT(13 51) │ +└────────────────────────┘ + +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/st-simplify.md b/tidb-cloud-lake/sql/st-simplify.md new file mode 100644 index 0000000000000..29e1f2e6610fa --- /dev/null +++ b/tidb-cloud-lake/sql/st-simplify.md @@ -0,0 +1,69 @@ +--- +title: ST_SIMPLIFY +summary: 通过移除到结果边的距离在指定容差范围内的顶点,返回 GEOMETRY 对象的简化版本。使用 Ramer-Douglas-Peucker 算法。 +--- + +# ST_SIMPLIFY + +通过移除到结果边的距离在指定容差范围内的顶点,返回 GEOMETRY 对象的简化版本。使用 Ramer-Douglas-Peucker 算法。 + +## 语法 {#syntax} + +```sql +ST_SIMPLIFY(, ) +``` + +## 参数 {#arguments} + +| 参数 | 描述 | +|---------------|-----------------------------------------------------------------------------| +| `` | 一个 GEOMETRY 表达式。适用于 LineString、MultiLineString、Polygon 和 MultiPolygon。对 Point 或 MultiPoint 无影响。 | +| `` | 用于移除顶点的最大距离容差。 | + +> **注意:** +> +> 不支持 GeometryCollection。 + +## 返回类型 {#return-type} + +Geometry。 + +## 示例 {#examples} + +```sql +SELECT ST_ASWKT( + ST_SIMPLIFY( + TO_GEOMETRY('LINESTRING(0 0, 1 0, 1 1, 2 1)'), 0.5 + ) +) AS simplified; + +┌──────────────────────┐ +│ simplified │ +├──────────────────────┤ +│ LINESTRING(0 0,2 1) │ +└──────────────────────┘ + +SELECT ST_ASWKT( + ST_SIMPLIFY( + TO_GEOMETRY('LINESTRING(1100 1100, 2500 2100, 3100 3100, 4900 1100, 3100 1900)'), 500 + ) +) AS simplified; + +┌──────────────────────────────────────────────────────┐ +│ simplified │ +├──────────────────────────────────────────────────────┤ +│ LINESTRING(1100 1100,3100 3100,4900 1100,3100 1900) │ +└──────────────────────────────────────────────────────┘ + +SELECT ST_ASWKT( + ST_SIMPLIFY( + TO_GEOMETRY('POLYGON((0 0, 1 0, 1 1, 0.5 0.5, 0 1, 0 0))'), 0.6 + ) +) AS simplified; + +┌──────────────────────────────────┐ +│ simplified │ +├──────────────────────────────────┤ +│ POLYGON((0 0,1 0,1 1,0 1,0 0)) │ +└──────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/st-srid.md b/tidb-cloud-lake/sql/st-srid.md new file mode 100644 index 0000000000000..9ea5e59a3794a --- /dev/null +++ b/tidb-cloud-lake/sql/st-srid.md @@ -0,0 +1,79 @@ +--- +title: ST_SRID +summary: 返回 GEOMETRY 或 GEOGRAPHY 对象的 SRID(空间参考系统标识符)。 +--- + +# ST_SRID + +返回 GEOMETRY 或 GEOGRAPHY 对象的 SRID(空间参考系统标识符)。 + +## 语法 {#syntax} + +```sql +ST_SRID() +``` + +## 参数 {#arguments} + +| 参数 | 描述 | +|--------------|------------------------------------------------------| +| `` | 该参数必须是 GEOMETRY 或 GEOGRAPHY 类型的表达式。 | + +## 返回类型 {#return-type} + +INT32。 + +> **注意:** +> +> - 如果 Geometry 没有 SRID,则返回默认值 `0`。 +> - 对于 Geography,SRID 始终为 `4326`。 + +## 示例 {#examples} + +### GEOMETRY 示例 {#geometry-examples} + +```sql +SELECT + ST_SRID( + TO_GEOMETRY( + 'POINT(-122.306100 37.554162)', + 1234 + ) + ) AS pipeline_srid; + +┌───────────────┐ +│ pipeline_srid │ +├───────────────┤ +│ 1234 │ +└───────────────┘ + +SELECT + ST_SRID( + ST_MAKEGEOMPOINT( + 37.5, 45.5 + ) + ) AS pipeline_srid; + +┌───────────────┐ +│ pipeline_srid │ +├───────────────┤ +│ 0 │ +└───────────────┘ +``` + +### GEOGRAPHY 示例 {#geography-examples} + +```sql +SELECT + ST_SRID( + ST_GEOGFROMWKT( + 'POINT(1 2)' + ) + ) AS pipeline_srid; + +┌───────────────┐ +│ pipeline_srid │ +├───────────────┤ +│ 4326 │ +└───────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/st-startpoint.md b/tidb-cloud-lake/sql/st-startpoint.md new file mode 100644 index 0000000000000..cc69c4e856fc9 --- /dev/null +++ b/tidb-cloud-lake/sql/st-startpoint.md @@ -0,0 +1,60 @@ +--- +title: ST_STARTPOINT +summary: 返回 LineString 中的第一个 Point。 +--- + +# ST_STARTPOINT + +返回 LineString 中的第一个 Point。 + +## 语法 {#syntax} + +```sql +ST_STARTPOINT() +``` + +## 参数 {#arguments} + +| 参数 | 描述 | +|--------------|-----------------------------------------------------------------------------------| +| `` | 该参数必须是一个 GEOMETRY 或 GEOGRAPHY 类型的表达式,并且表示一个 LineString。 | + +## 返回类型 {#return-type} + +Geometry。 + +## 示例 {#examples} + +### GEOMETRY 示例 {#geometry-examples} + +```sql +SELECT + ST_STARTPOINT( + ST_GEOMETRYFROMWKT( + 'LINESTRING(1 1, 2 2, 3 3, 4 4)' + ) + ) AS pipeline_endpoint; + +┌───────────────────┐ +│ pipeline_endpoint │ +├───────────────────┤ +│ POINT(1 1) │ +└───────────────────┘ +``` + +### GEOGRAPHY 示例 {#geography-examples} + +```sql +SELECT + ST_STARTPOINT( + ST_GEOGFROMWKT( + 'LINESTRING(1 1, 2 2, 3 3, 4 4)' + ) + ) AS pipeline_startpoint; + +┌─────────────────────┐ +│ pipeline_startpoint │ +├─────────────────────┤ +│ POINT(1 1) │ +└─────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/st-symdifference.md b/tidb-cloud-lake/sql/st-symdifference.md new file mode 100644 index 0000000000000..c1ff9ef08e87a --- /dev/null +++ b/tidb-cloud-lake/sql/st-symdifference.md @@ -0,0 +1,43 @@ +--- +title: ST_SYMDIFFERENCE +summary: 返回两个 GEOMETRY 对象中不重叠的部分。 +--- + +# ST_SYMDIFFERENCE + +返回两个 GEOMETRY 对象中不重叠的部分。 + +此函数仅支持 GEOMETRY 值。 + +## 语法 {#syntax} + +```sql +ST_SYMDIFFERENCE(, ) +``` + +## 参数 {#arguments} + +| 参数 | 描述 | +|---------------|--------------------------------------------------------| +| `` | 该参数必须是 GEOMETRY 类型的表达式。 | +| `` | 该参数必须是 GEOMETRY 类型的表达式。 | + +> **注意:** +> +> 如果两个输入的 GEOMETRY 对象具有不同的 SRID,则该函数会报错。 + +## 返回类型 {#return-type} + +GEOMETRY。 + +## 示例 {#examples} + +```sql +SELECT ST_ASWKT(ST_SYMDIFFERENCE(TO_GEOMETRY('POINT(0 0)'), TO_GEOMETRY('POINT(1 1)'))); + +╭──────────────────────────────────────────────────────────────────────────────────╮ +│ st_aswkt(st_symdifference(to_geometry('POINT(0 0)'), to_geometry('POINT(1 1)'))) │ +├──────────────────────────────────────────────────────────────────────────────────┤ +│ MULTIPOINT(0 0,1 1) │ +╰──────────────────────────────────────────────────────────────────────────────────╯ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/st-transform.md b/tidb-cloud-lake/sql/st-transform.md new file mode 100644 index 0000000000000..5930351c7a2b7 --- /dev/null +++ b/tidb-cloud-lake/sql/st-transform.md @@ -0,0 +1,49 @@ +--- +title: ST_TRANSFORM +summary: 将 GEOMETRY 对象从一个空间参考系统 (SRS) 转换到另一个空间参考系统。如果你只需要更改 SRID 而不更改坐标(例如 SRID 不正确),请改用 ST_SETSRID。 +--- + +# ST_TRANSFORM + +将 GEOMETRY 对象从一个[空间参考系统 (SRS)](https://en.wikipedia.org/wiki/Spatial_reference_system)转换到另一个。如果你只需要更改 SRID 而不更改坐标(例如 SRID 不正确),请改用 [ST_SETSRID](/tidb-cloud-lake/sql/st-setsrid.md)。 + +## 语法 {#syntax} + +```sql +ST_TRANSFORM( [, ], ) +``` + +## 参数 {#arguments} + +| 参数 | 描述 | +|---------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------| +| `` | 该参数必须是 GEOMETRY 对象类型的表达式。 | +| `` | 可选的 SRID,用于标识输入 GEOMETRY 对象当前的 SRS。如果省略此参数,则使用输入 GEOMETRY 对象中指定的 SRID。 | +| `` | 用于标识目标 SRS 的 SRID。该函数会将输入 GEOMETRY 对象转换为使用此 SRS 的新对象。 | + +## 返回类型 {#return-type} + +Geometry。 + +## 示例 {#examples} + +```sql +SET GEOMETRY_OUTPUT_FORMAT = 'EWKT' + +SELECT ST_TRANSFORM(ST_GEOMFROMWKT('POINT(389866.35 5819003.03)', 32633), 3857) AS transformed_geom + +┌───────────────────────────────────────────────┐ +│ transformed_geom │ +├───────────────────────────────────────────────┤ +│ SRID=3857;POINT(1489140.093766 6892872.19868) │ +└───────────────────────────────────────────────┘ + +SELECT ST_TRANSFORM(ST_GEOMFROMWKT('POINT(4.500212 52.161170)'), 4326, 28992) AS transformed_geom + +┌──────────────────────────────────────────────┐ +│ transformed_geom │ +├──────────────────────────────────────────────┤ +│ SRID=28992;POINT(94308.670475 464038.168827) │ +└──────────────────────────────────────────────┘ + +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/st-union-agg.md b/tidb-cloud-lake/sql/st-union-agg.md new file mode 100644 index 0000000000000..ccb350e06bd06 --- /dev/null +++ b/tidb-cloud-lake/sql/st-union-agg.md @@ -0,0 +1,49 @@ +--- +title: ST_UNION_AGG +summary: 通过重复应用 `ST_UNION` 聚合多个 GEOMETRY 值,并返回合并后的 GEOMETRY 结果。 +--- + +# ST_UNION_AGG + +通过重复应用 `ST_UNION` 聚合多个 GEOMETRY 值,并返回合并后的 GEOMETRY 结果。 + +此函数仅支持 GEOMETRY。 + +## 语法 {#syntax} + +```sql +ST_UNION_AGG() +``` + +## 参数 {#arguments} + +| 参数 | 描述 | +|-----------|-------------| +| `` | 一个 GEOMETRY 类型的表达式。 | + +## 返回类型 {#return-type} + +GEOMETRY。 + +> **注意:** +> +> - 会忽略输入中的 NULL 行。 +> - 如果所有输入行均为 NULL,结果为 NULL。 +> - 如果输入的 GEOMETRY 值使用了不同的 SRID,该函数会返回错误。 + +## 示例 {#example} + +```sql +WITH data AS ( + SELECT TO_GEOMETRY('POINT(0 0)') AS g + UNION ALL + SELECT TO_GEOMETRY('POINT(1 1)') +) +SELECT ST_ASWKT(ST_UNION_AGG(g)) FROM data; + +╭───────────────────────────╮ +│ st_aswkt(st_union_agg(g)) │ +├───────────────────────────┤ +│ MULTIPOINT(0 0,1 1) │ +╰───────────────────────────╯ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/st-union.md b/tidb-cloud-lake/sql/st-union.md new file mode 100644 index 0000000000000..0e027ab2184b4 --- /dev/null +++ b/tidb-cloud-lake/sql/st-union.md @@ -0,0 +1,43 @@ +--- +title: ST_UNION +summary: 返回由两个输入 GEOMETRY 对象组合而成的 GEOMETRY。 +--- + +# ST_UNION + +返回由两个输入 GEOMETRY 对象组合而成的 GEOMETRY。 + +该函数仅支持 GEOMETRY 值。 + +## 语法 {#syntax} + +```sql +ST_UNION(, ) +``` + +## 参数 {#arguments} + +| 参数 | 描述 | +|---------------|-------------------------------------------| +| `` | 该参数必须是 GEOMETRY 类型的表达式。 | +| `` | 该参数必须是 GEOMETRY 类型的表达式。 | + +> **注意:** +> +> 如果两个输入的 GEOMETRY 对象具有不同的 SRID,则该函数会报错。 + +## 返回类型 {#return-type} + +GEOMETRY。 + +## 示例 {#examples} + +```sql +SELECT ST_ASWKT(ST_UNION(TO_GEOMETRY('POINT(0 0)'), TO_GEOMETRY('POINT(1 1)'))); + +╭──────────────────────────────────────────────────────────────────────────╮ +│ st_aswkt(st_union(to_geometry('POINT(0 0)'), to_geometry('POINT(1 1)'))) │ +├──────────────────────────────────────────────────────────────────────────┤ +│ MULTIPOINT(0 0,1 1) │ +╰──────────────────────────────────────────────────────────────────────────╯ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/st-within.md b/tidb-cloud-lake/sql/st-within.md new file mode 100644 index 0000000000000..c8d8ac11f9ff5 --- /dev/null +++ b/tidb-cloud-lake/sql/st-within.md @@ -0,0 +1,44 @@ +--- +title: ST_WITHIN +summary: 如果第一个 GEOMETRY 对象完全位于第二个 GEOMETRY 对象之内,则返回 TRUE。 +--- + +# ST_WITHIN + +如果第一个 GEOMETRY 对象完全位于第二个 GEOMETRY 对象之内,则返回 TRUE。 + +## 语法 {#syntax} + +```sql +ST_WITHIN(, ) +``` + +## 参数 {#arguments} + +| 参数 | 描述 | +|---------------|-------------------------------------------| +| `` | 该参数必须是 GEOMETRY 类型的表达式。 | +| `` | 该参数必须是 GEOMETRY 类型的表达式。 | + +> **注意:** +> +> 如果两个输入的 GEOMETRY 对象具有不同的 SRID,则该函数会报错。 + +## 返回类型 {#return-type} + +布尔值。 + +## 示例 {#examples} + +```sql +SELECT ST_WITHIN( + TO_GEOMETRY('POINT(1 1)'), + TO_GEOMETRY('POLYGON((0 0, 2 0, 2 2, 0 2, 0 0))') +) AS within; + +╭─────────╮ +│ within │ +├─────────┤ +│ true │ +╰─────────╯ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/st-x.md b/tidb-cloud-lake/sql/st-x.md new file mode 100644 index 0000000000000..275fb0f9a2675 --- /dev/null +++ b/tidb-cloud-lake/sql/st-x.md @@ -0,0 +1,60 @@ +--- +title: ST_X +summary: 返回由 GEOMETRY 或 GEOGRAPHY 对象表示的 Point 的经度(X 坐标)。 +--- + +# ST_X + +返回由 GEOMETRY 或 GEOGRAPHY 对象表示的 Point 的经度(X 坐标)。 + +## 语法 {#syntax} + +```sql +ST_X() +``` + +## 参数 {#arguments} + +| 参数 | 描述 | +|--------------|-------------------------------------------------------------------------------| +| `` | 该参数必须是 GEOMETRY 或 GEOGRAPHY 类型的表达式,并且必须包含一个 Point。 | + +## 返回类型 {#return-type} + +Double。 + +## 示例 {#examples} + +### GEOMETRY 示例 {#geometry-examples} + +```sql +SELECT + ST_X( + ST_MAKEGEOMPOINT( + 37.5, 45.5 + ) + ) AS pipeline_x; + +┌────────────┐ +│ pipeline_x │ +├────────────┤ +│ 37.5 │ +└────────────┘ +``` + +### GEOGRAPHY 示例 {#geography-examples} + +```sql +SELECT + ST_X( + ST_GEOGFROMWKT( + 'POINT(37.5 45.5)' + ) + ) AS pipeline_x; + +┌────────────┐ +│ pipeline_x │ +├────────────┤ +│ 37.5 │ +└────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/st-xmax.md b/tidb-cloud-lake/sql/st-xmax.md new file mode 100644 index 0000000000000..1de55a9de78a4 --- /dev/null +++ b/tidb-cloud-lake/sql/st-xmax.md @@ -0,0 +1,73 @@ +--- +title: ST_XMAX +summary: 返回指定 GEOMETRY 或 GEOGRAPHY 对象中包含的所有点的最大经度(X 坐标)。 +--- + +# ST_XMAX + +返回指定 GEOMETRY 或 GEOGRAPHY 对象中包含的所有点的最大经度(X 坐标)。 + +## 语法 {#syntax} + +```sql +ST_XMAX() +``` + +## 参数 {#arguments} + +| 参数 | 描述 | +|--------------|------------------------------------------------------| +| `` | 该参数必须是 GEOMETRY 或 GEOGRAPHY 类型的表达式。 | + +## 返回类型 {#return-type} + +Double。 + +## 示例 {#examples} + +### GEOMETRY 示例 {#geometry-examples} + +```sql +SELECT + ST_XMAX( + TO_GEOMETRY( + 'GEOMETRYCOLLECTION(POINT(40 10),LINESTRING(10 10,20 20,10 40),POINT EMPTY)' + ) + ) AS pipeline_xmax; + +┌───────────────┐ +│ pipeline_xmax │ +├───────────────┤ +│ 40 │ +└───────────────┘ + +SELECT + ST_XMAX( + TO_GEOMETRY( + 'GEOMETRYCOLLECTION(POINT(40 10),LINESTRING(10 10,20 20,10 40),POLYGON((40 40,20 45,45 30,40 40)))' + ) + ) AS pipeline_xmax; + +┌───────────────┐ +│ pipeline_xmax │ +├───────────────┤ +│ 45 │ +└───────────────┘ +``` + +### GEOGRAPHY 示例 {#geography-examples} + +```sql +SELECT + ST_XMAX( + ST_GEOGFROMWKT( + 'LINESTRING(-179 0, 179 0)' + ) + ) AS pipeline_xmax; + +┌───────────────┐ +│ pipeline_xmax │ +├───────────────┤ +│ 179 │ +└───────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/st-xmin.md b/tidb-cloud-lake/sql/st-xmin.md new file mode 100644 index 0000000000000..6cbebb13925b9 --- /dev/null +++ b/tidb-cloud-lake/sql/st-xmin.md @@ -0,0 +1,73 @@ +--- +title: ST_XMIN +summary: 返回指定 GEOMETRY 或 GEOGRAPHY 对象中包含的所有点的最小经度(X 坐标)。 +--- + +# ST_XMIN + +返回指定 GEOMETRY 或 GEOGRAPHY 对象中包含的所有点的最小经度(X 坐标)。 + +## 语法 {#syntax} + +```sql +ST_XMIN() +``` + +## 参数 {#arguments} + +| 参数 | 描述 | +|--------------|------------------------------------------------------| +| `` | 该参数必须是 GEOMETRY 或 GEOGRAPHY 类型的表达式。 | + +## 返回类型 {#return-type} + +Double。 + +## 示例 {#examples} + +### GEOMETRY 示例 {#geometry-examples} + +```sql +SELECT + ST_XMIN( + TO_GEOMETRY( + 'GEOMETRYCOLLECTION(POINT(180 10),LINESTRING(20 10,30 20,40 40),POINT EMPTY)' + ) + ) AS pipeline_xmin; + +┌───────────────┐ +│ pipeline_xmin │ +├───────────────┤ +│ 20 │ +└───────────────┘ + +SELECT + ST_XMIN( + TO_GEOMETRY( + 'GEOMETRYCOLLECTION(POINT(40 10),LINESTRING(20 10,30 20,10 40),POLYGON((40 40,20 45,45 30,40 40)))' + ) + ) AS pipeline_xmin; + +┌───────────────┐ +│ pipeline_xmin │ +├───────────────┤ +│ 10 │ +└───────────────┘ +``` + +### GEOGRAPHY 示例 {#geography-examples} + +```sql +SELECT + ST_XMIN( + ST_GEOGFROMWKT( + 'LINESTRING(-179 0, 179 0)' + ) + ) AS pipeline_xmin; + +┌───────────────┐ +│ pipeline_xmin │ +├───────────────┤ +│ -179 │ +└───────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/st-y.md b/tidb-cloud-lake/sql/st-y.md new file mode 100644 index 0000000000000..6610107693c2a --- /dev/null +++ b/tidb-cloud-lake/sql/st-y.md @@ -0,0 +1,60 @@ +--- +title: ST_Y +summary: 返回由 GEOMETRY 或 GEOGRAPHY 对象表示的 Point 的纬度(Y 坐标)。 +--- + +# ST_Y + +返回由 GEOMETRY 或 GEOGRAPHY 对象表示的 Point 的纬度(Y 坐标)。 + +## 语法 {#syntax} + +```sql +ST_Y() +``` + +## 参数 {#arguments} + +| 参数 | 描述 | +|--------------|-------------------------------------------------------------------------------| +| `` | 该参数必须是 GEOMETRY 或 GEOGRAPHY 类型的表达式,并且必须包含一个 Point。 | + +## 返回类型 {#return-type} + +Double。 + +## 示例 {#examples} + +### GEOMETRY 示例 {#geometry-examples} + +```sql +SELECT + ST_Y( + ST_MAKEGEOMPOINT( + 37.5, 45.5 + ) + ) AS pipeline_y; + +┌────────────┐ +│ pipeline_y │ +├────────────┤ +│ 45.5 │ +└────────────┘ +``` + +### GEOGRAPHY 示例 {#geography-examples} + +```sql +SELECT + ST_Y( + ST_GEOGFROMWKT( + 'POINT(37.5 45.5)' + ) + ) AS pipeline_y; + +┌────────────┐ +│ pipeline_y │ +├────────────┤ +│ 45.5 │ +└────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/st-ymax.md b/tidb-cloud-lake/sql/st-ymax.md new file mode 100644 index 0000000000000..1d99ca63ef838 --- /dev/null +++ b/tidb-cloud-lake/sql/st-ymax.md @@ -0,0 +1,73 @@ +--- +title: ST_YMAX +summary: 返回指定 GEOMETRY 或 GEOGRAPHY 对象中包含的所有点的最大纬度(Y 坐标)。 +--- + +# ST_YMAX + +返回指定 GEOMETRY 或 GEOGRAPHY 对象中包含的所有点的最大纬度(Y 坐标)。 + +## 语法 {#syntax} + +```sql +ST_YMAX() +``` + +## 参数 {#arguments} + +| 参数 | 描述 | +|--------------|------------------------------------------------------| +| `` | 该参数必须是 GEOMETRY 或 GEOGRAPHY 类型的表达式。 | + +## 返回类型 {#return-type} + +Double。 + +## 示例 {#examples} + +### GEOMETRY 示例 {#geometry-examples} + +```sql +SELECT + ST_YMAX( + TO_GEOMETRY( + 'GEOMETRYCOLLECTION(POINT(180 50),LINESTRING(10 10,20 20,10 40),POINT EMPTY)' + ) + ) AS pipeline_ymax; + +┌───────────────┐ +│ pipeline_ymax │ +├───────────────┤ +│ 50 │ +└───────────────┘ + +SELECT + ST_YMAX( + TO_GEOMETRY( + 'GEOMETRYCOLLECTION(POINT(40 10),LINESTRING(10 10,20 20,10 40),POLYGON((40 40,20 45,45 30,40 40)))' + ) + ) AS pipeline_ymax; + +┌───────────────┐ +│ pipeline_ymax │ +├───────────────┤ +│ 45 │ +└───────────────┘ +``` + +### GEOGRAPHY 示例 {#geography-examples} + +```sql +SELECT + ST_YMAX( + ST_GEOGFROMWKT( + 'LINESTRING(-179 10, 179 22)' + ) + ) AS pipeline_ymax; + +┌───────────────┐ +│ pipeline_ymax │ +├───────────────┤ +│ 22 │ +└───────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/st-ymin.md b/tidb-cloud-lake/sql/st-ymin.md new file mode 100644 index 0000000000000..d5288e242097d --- /dev/null +++ b/tidb-cloud-lake/sql/st-ymin.md @@ -0,0 +1,73 @@ +--- +title: ST_YMIN +summary: 返回指定 GEOMETRY 或 GEOGRAPHY 对象中所有点的最小纬度(Y 坐标)。 +--- + +# ST_YMIN + +返回指定 GEOMETRY 或 GEOGRAPHY 对象中所有点的最小纬度(Y 坐标)。 + +## 语法 {#syntax} + +```sql +ST_YMIN() +``` + +## 参数 {#arguments} + +| 参数 | 描述 | +|--------------|------------------------------------------------------| +| `` | 该参数必须是 GEOMETRY 或 GEOGRAPHY 类型的表达式。 | + +## 返回类型 {#return-type} + +Double。 + +## 示例 {#examples} + +### GEOMETRY 示例 {#geometry-examples} + +```sql +SELECT + ST_YMIN( + TO_GEOMETRY( + 'GEOMETRYCOLLECTION(POINT(-180 -10),LINESTRING(-179 0, 179 30),POINT EMPTY)' + ) + ) AS pipeline_ymin; + +┌───────────────┐ +│ pipeline_ymin │ +├───────────────┤ +│ -10 │ +└───────────────┘ + +SELECT + ST_YMIN( + TO_GEOMETRY( + 'GEOMETRYCOLLECTION(POINT(180 0),LINESTRING(-60 -30, 60 30),POLYGON((40 40,20 45,45 30,40 40)))' + ) + ) AS pipeline_ymin; + +┌───────────────┐ +│ pipeline_ymin │ +├───────────────┤ +│ -30 │ +└───────────────┘ +``` + +### GEOGRAPHY 示例 {#geography-examples} + +```sql +SELECT + ST_YMIN( + ST_GEOGFROMWKT( + 'LINESTRING(-179 10, 179 22)' + ) + ) AS pipeline_ymin; + +┌───────────────┐ +│ pipeline_ymin │ +├───────────────┤ +│ 10 │ +└───────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/stage.md b/tidb-cloud-lake/sql/stage.md new file mode 100644 index 0000000000000..cdc9860150acd --- /dev/null +++ b/tidb-cloud-lake/sql/stage.md @@ -0,0 +1,40 @@ +--- +title: Stage +summary: 本页按功能分类,全面概述了 {{{ .lake }}} 中的 stage 操作,便于参考。 +--- + +# Stage + +本页按功能分类,全面概述了 {{{ .lake }}} 中的 stage 操作,便于参考。 + +## Stage 管理 {#stage-management} + +| Command | 描述 | +|---------|-------------| +| [CREATE STAGE](/tidb-cloud-lake/sql/create-stage.md) | 创建一个新的 stage 用于存储文件 | +| [DROP STAGE](/tidb-cloud-lake/sql/drop-stage.md) | 删除一个 stage | +| [PRESIGN](/tidb-cloud-lake/sql/presign.md) | 为 stage 访问生成预签名 URL | + +## Stage 操作 {#stage-operations} + +| Command | 描述 | +|---------|-------------| +| [LIST STAGE](/tidb-cloud-lake/sql/list-stage-files.md) | 列出 stage 中的文件 | +| [REMOVE STAGE](/tidb-cloud-lake/sql/remove-stage-files.md) | 删除 stage 中的文件 | + +## Stage 信息 {#stage-information} + +| Command | 描述 | +|---------|-------------| +| [DESC STAGE](/tidb-cloud-lake/sql/desc-stage.md) | 显示 stage 的详细信息 | +| [SHOW STAGES](/tidb-cloud-lake/sql/show-stages.md) | 列出当前或指定数据库中的所有 stage | + +## 相关主题 {#related-topics} + +- [从 Stage 加载](/tidb-cloud-lake/guides/load-from-stage.md) +- [查询与转换](/tidb-cloud-lake/guides/query-stage.md) +- [文件格式(DDL)](/tidb-cloud-lake/sql/file-format.md) + +> **注意:** +> +> {{{ .lake }}} 中的 stage 用作临时存储位置,用于保存你希望加载到表中或从表中卸载的数据文件。 \ No newline at end of file diff --git a/tidb-cloud-lake/sql/start-fifteen-minutes.md b/tidb-cloud-lake/sql/start-fifteen-minutes.md new file mode 100644 index 0000000000000..1d82c8f21a03d --- /dev/null +++ b/tidb-cloud-lake/sql/start-fifteen-minutes.md @@ -0,0 +1,37 @@ +--- +title: TO_START_OF_FIFTEEN_MINUTES +summary: 将带时间的日期(timestamp/datetime)向下舍入到十五分钟间隔的起始时间。## 语法。 +--- + +# TO_START_OF_FIFTEEN_MINUTES + +将带时间的日期(timestamp/datetime)向下舍入到十五分钟间隔的起始时间。 + +## 语法 {#syntax} + +```sql +TO_START_OF_FIFTEEN_MINUTES() +``` + +## 参数 {#arguments} + +| 参数 | 描述 | +|-----------|-------------| +| `` | 时间戳 | + +## 返回类型 {#return-type} + +`TIMESTAMP`,返回格式为 “YYYY-MM-DD hh:mm:ss.ffffff” 的日期。 + +## 示例 {#examples} + +```sql +SELECT + to_start_of_fifteen_minutes('2023-11-12 09:38:18.165575'); + +┌───────────────────────────────────────────────────────────┐ +│ to_start_of_fifteen_minutes('2023-11-12 09:38:18.165575') │ +├───────────────────────────────────────────────────────────┤ +│ 2023-11-12 09:30:00 │ +└───────────────────────────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/start-five-minutes.md b/tidb-cloud-lake/sql/start-five-minutes.md new file mode 100644 index 0000000000000..722c67cd432ed --- /dev/null +++ b/tidb-cloud-lake/sql/start-five-minutes.md @@ -0,0 +1,37 @@ +--- +title: TO_START_OF_FIVE_MINUTES +summary: 将带时间的日期(timestamp/datetime)向下舍入到五分钟时间间隔的起始时间。## 语法。 +--- + +# TO_START_OF_FIVE_MINUTES + +将带时间的日期(timestamp/datetime)向下舍入到五分钟时间间隔的起始时间。 + +## 语法 {#syntax} + +```sql +TO_START_OF_FIVE_MINUTES() +``` + +## 参数 {#arguments} + +| 参数 | 描述 | +|-----------|-------------| +| `` | 时间戳 | + +## 返回类型 {#return-type} + +`TIMESTAMP`,以 “YYYY-MM-DD hh:mm:ss.ffffff” 格式返回日期。 + +## 示例 {#examples} + +```sql +SELECT + to_start_of_five_minutes('2023-11-12 09:38:18.165575') + +┌────────────────────────────────────────────────────────┐ +│ to_start_of_five_minutes('2023-11-12 09:38:18.165575') │ +├────────────────────────────────────────────────────────┤ +│ 2023-11-12 09:35:00 │ +└────────────────────────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/start-iso-year.md b/tidb-cloud-lake/sql/start-iso-year.md new file mode 100644 index 0000000000000..faf5e8775a3af --- /dev/null +++ b/tidb-cloud-lake/sql/start-iso-year.md @@ -0,0 +1,37 @@ +--- +title: TO_START_OF_ISO_YEAR +summary: 返回某个日期或带时间的日期(timestamp/datetime)所在 ISO 年的第一天。 +--- + +# TO_START_OF_ISO_YEAR + +返回某个日期或带时间的日期(timestamp/datetime)所在 ISO 年的第一天。 + +## 语法 {#syntax} + +```sql +TO_START_OF_ISO_YEAR() +``` + +## 参数 {#arguments} + +| 参数 | 描述 | +|-----------|----------------| +| `` | 日期/时间戳 | + +## 返回类型 {#return-type} + +`DATE`,以 “YYYY-MM-DD” 格式返回日期。 + +## 示例 {#examples} + +```sql +SELECT + to_start_of_iso_year('2023-11-12 09:38:18.165575'); + +┌────────────────────────────────────────────────────┐ +│ to_start_of_iso_year('2023-11-12 09:38:18.165575') │ +├────────────────────────────────────────────────────┤ +│ 2023-01-02 │ +└────────────────────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/start-ten-minutes.md b/tidb-cloud-lake/sql/start-ten-minutes.md new file mode 100644 index 0000000000000..11bc70c7e207f --- /dev/null +++ b/tidb-cloud-lake/sql/start-ten-minutes.md @@ -0,0 +1,37 @@ +--- +title: TO_START_OF_TEN_MINUTES +summary: 将带时间的日期(timestamp/datetime)向下舍入到十分钟间隔的开始时间。 +--- + +# TO_START_OF_TEN_MINUTES + +将带时间的日期(timestamp/datetime)向下舍入到十分钟间隔的开始时间。 + +## 语法 {#syntax} + +```sql +TO_START_OF_TEN_MINUTES() +``` + +## 参数 {#arguments} + +| 参数 | 描述 | +|-----------|-------------| +| `` | 时间戳 | + +## 返回类型 {#return-type} + +`TIMESTAMP`,返回 “YYYY-MM-DD hh:mm:ss.ffffff” 格式的日期。 + +## 示例 {#examples} + +```sql +SELECT + to_start_of_ten_minutes('2023-11-12 09:38:18.165575'); + +┌───────────────────────────────────────────────────────┐ +│ to_start_of_ten_minutes('2023-11-12 09:38:18.165575') │ +├───────────────────────────────────────────────────────┤ +│ 2023-11-12 09:30:00 │ +└───────────────────────────────────────────────────────┘ +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/stddev-pop.md b/tidb-cloud-lake/sql/stddev-pop.md new file mode 100644 index 0000000000000..9735ef6c6064c --- /dev/null +++ b/tidb-cloud-lake/sql/stddev-pop.md @@ -0,0 +1,70 @@ +--- +title: STDDEV_POP +summary: 聚合函数。 +--- + +# STDDEV_POP + +聚合函数。 + +`STDDEV_POP()` 函数返回一个表达式的总体标准差(`VAR_POP()` 的平方根)。 + +> **Tip:** +> +> 也可以使用 `STD()` 或 `STDDEV()`,它们与 `STDDEV_POP()` 等价,但不是标准 SQL。 + +> **Note:** +> +> `NULL` 值不会被计入。 + +## 语法 {#syntax} + +```sql +STDDEV_POP() +STDDEV() +STD() +``` + +## 参数 {#arguments} + +| 参数 | 描述 | +|-----------|--------------------------| +| `` | 任意数值表达式 | + +## 返回类型 {#return-type} + +double + +## 示例 {#example} + +**创建表并插入示例数据** + +```sql +CREATE TABLE test_scores ( + id INT, + student_id INT, + score FLOAT +); + +INSERT INTO test_scores (id, student_id, score) +VALUES (1, 1, 80), + (2, 2, 85), + (3, 3, 90), + (4, 4, 95), + (5, 5, 100); +``` + +**查询演示:计算测试分数的总体标准差** + +```sql +SELECT STDDEV_POP(score) AS test_score_stddev_pop +FROM test_scores; +``` + +**结果** + +```sql +| test_score_stddev_pop | +|-----------------------| +| 7.07107 | +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/stddev-samp.md b/tidb-cloud-lake/sql/stddev-samp.md new file mode 100644 index 0000000000000..610bcb274d7af --- /dev/null +++ b/tidb-cloud-lake/sql/stddev-samp.md @@ -0,0 +1,61 @@ +--- +title: STDDEV_SAMP +summary: 返回表达式的样本标准差(VAR_SAMP() 的平方根)。 +--- + +# STDDEV_SAMP + +返回表达式的样本标准差(VAR_SAMP() 的平方根)。 + +- 会忽略 `NULL` 值。 +- 当只有一条输入记录时,STDDEV_SAMP() 返回 `NULL` 而不是 `0`。 + +## 语法 {#syntax} + +```sql +STDDEV_SAMP() +``` + +## 参数 {#arguments} + +| 参数 | 描述 | +| --------- | ------------------------ | +| `` | 任意数值表达式 | + +## 返回类型 {#return-type} + +Double。 + +## 示例 {#example} + +**创建表并插入示例数据** + +```sql +CREATE TABLE height_data ( + id INT, + person_id INT, + height FLOAT +); + +INSERT INTO height_data (id, person_id, height) +VALUES (1, 1, 5.8), + (2, 2, 6.1), + (3, 3, 5.9), + (4, 4, 5.7), + (5, 5, 6.3); +``` + +**查询示例:计算身高的样本标准差** + +```sql +SELECT STDDEV_SAMP(height) AS height_stddev_samp +FROM height_data; +``` + +**结果** + +```sql +| height_stddev_samp | +|--------------------| +| 0.240 | +``` \ No newline at end of file diff --git a/tidb-cloud-lake/sql/stored-procedure-scripting.md b/tidb-cloud-lake/sql/stored-procedure-scripting.md new file mode 100644 index 0000000000000..1c94d57ad6690 --- /dev/null +++ b/tidb-cloud-lake/sql/stored-procedure-scripting.md @@ -0,0 +1,639 @@ +--- +title: 存储过程与 SQL 脚本 +summary: {{{ .lake }}} 中的存储过程可让你将运行在服务器端的 SQL 逻辑封装起来,并支持控制流、变量、游标和动态语句。本文介绍如何创建存储过程,以及如何编写为其提供支持的内联脚本。 +--- + +# 存储过程与 SQL 脚本 + +{{{ .lake }}} 中的存储过程可让你将运行在服务器端的 SQL 逻辑封装起来,并支持控制流、变量、游标和动态语句。本文介绍如何创建存储过程,以及如何编写为其提供支持的内联脚本。 + +## 定义存储过程 {#defining-a-procedure} + +```sql +CREATE [OR REPLACE] PROCEDURE ( , ...) +RETURNS [NOT NULL] +LANGUAGE SQL +[COMMENT = ''] +AS $$ +BEGIN + -- Declarations and statements + RETURN ; + -- Or return a query result + -- RETURN TABLE(); +END; +$$; +``` + +| 组成部分 | 说明 | +|-----------|-------------| +| `` | 存储过程的标识符。可选是否带上 schema 限定。 | +| ` ` | 使用 {{{ .lake }}} 标量类型定义的输入参数。参数按值传递。 | +| `RETURNS [NOT NULL]` | 声明逻辑返回类型。`NOT NULL` 强制返回不可为空的响应。 | +| `LANGUAGE SQL` | {{{ .lake }}} 当前仅接受 `SQL`。 | +| `RETURN` / `RETURN TABLE` | 结束执行,并返回标量结果或表格结果。 | + +使用 [`CREATE PROCEDURE`](/tidb-cloud-lake/sql/create-procedure.md) 持久化定义,使用 [`CALL`](/tidb-cloud-lake/sql/call-procedure.md) 运行存储过程,使用 [`DROP PROCEDURE`](/tidb-cloud-lake/sql/drop-procedure.md) 删除它。 + +### 最小示例 {#minimal-example} + +```sql +CREATE OR REPLACE PROCEDURE convert_kg_to_lb(kg DOUBLE) +RETURNS DOUBLE +LANGUAGE SQL +COMMENT = 'Converts kilograms to pounds' +AS $$ +BEGIN + RETURN kg * 2.20462; +END; +$$; + +CALL PROCEDURE convert_kg_to_lb(10); +``` + +## 存储过程中的语言基础 {#language-basics-inside-procedures} + +### DECLARE 部分 {#declare-section} + +存储过程可以以可选的 `DECLARE` 块开头,在可执行部分之前初始化变量。该块中的每一项都遵循与 `LET` 相同的语法:`name [] [:= | DEFAULT ]`。如果省略初始化器,则该变量必须在读取前先被赋值;过早引用会引发错误 3129。 + +```sql +CREATE OR REPLACE PROCEDURE sp_with_declare() +RETURNS INT +LANGUAGE SQL +AS $$ +DECLARE + counter INT DEFAULT 0; +BEGIN + counter := counter + 5; + RETURN counter; +END; +$$; + +CALL PROCEDURE sp_with_declare(); +``` + +`DECLARE` 部分接受与 `LET` 相同的定义,包括可选的数据类型、`RESULTSET` 和 `CURSOR` 声明。每一项后都要使用分号。 + +### 变量与赋值 {#variables-and-assignment} + +使用 `LET` 声明变量或常量。你可以选择提供类型注解,并使用 `:=` 或 `DEFAULT` 关键字指定初始化器。如果没有初始化器,则变量必须在读取前先被赋值;否则会引发错误 3129。重新赋值时省略 `LET`。 + +```sql +CREATE OR REPLACE PROCEDURE sp_demo_variables() +RETURNS FLOAT +LANGUAGE SQL +AS $$ +BEGIN + LET total DECIMAL(10, 2) DEFAULT 100; + LET rate FLOAT := 0.07; + LET surcharge FLOAT := NULL; -- Explicitly initialize before use + LET tax FLOAT DEFAULT rate; -- DEFAULT can reference initialized variables + + total := total * rate; -- Multiply by the rate + total := total + COALESCE(surcharge, 5); -- Reassign without LET + total := total + tax; + + RETURN total; +END; +$$; + +CALL PROCEDURE sp_demo_variables(); +``` + +在存储过程中的任何位置引用未初始化的变量,都会引发错误 3129。 + +### 变量作用域 {#variable-scope} + +变量的作用域限定在其所在的外层块内。内层块可以遮蔽外层绑定,而在退出该块时,外层值会被恢复。 + +```sql +CREATE OR REPLACE PROCEDURE sp_demo_scope() +RETURNS STRING +LANGUAGE SQL +AS $$ +BEGIN + LET threshold := 10; + LET summary := 'outer=' || threshold; + + IF threshold > 0 THEN + LET threshold := 5; -- Shadows the outer value + summary := summary || ', inner=' || threshold; + END IF; + + summary := summary || ', after=' || threshold; + RETURN summary; +END; +$$; + +CALL PROCEDURE sp_demo_scope(); +``` + +### 注释 {#comments} + +存储过程支持单行注释(`-- text`)和多行注释(`/* text */`)。 + +```sql +CREATE OR REPLACE PROCEDURE sp_demo_comments() +RETURNS FLOAT +LANGUAGE SQL +AS $$ +BEGIN + -- Calculate price with tax + LET price := 15; + LET tax_rate := 0.08; + + /* + Multi-line comments are useful for documenting complex logic. + The following line returns the tax-inclusive price. + */ + RETURN price * (1 + tax_rate); +END; +$$; + +CALL PROCEDURE sp_demo_comments(); +``` + +### Lambda 表达式 {#lambda-expressions} + +Lambda 表达式用于定义内联逻辑,可以传递给数组函数,或在查询中调用。其形式为 ` -> `(当提供多个参数时,请将参数放在括号中)。该表达式可以包含类型转换、条件逻辑,甚至对过程变量的引用。 + +- 当 lambda 在 SQL 语句中运行时,使用 `:variable_name` 在 lambda 内部引用过程变量。 +- `ARRAY_TRANSFORM` 和 `ARRAY_FILTER` 等函数会对输入数组中的每个元素计算一次 lambda。 + +```sql +CREATE OR REPLACE PROCEDURE sp_demo_lambda_array() +RETURNS STRING +LANGUAGE SQL +AS $$ +BEGIN + RETURN TABLE( + SELECT ARRAY_TRANSFORM([1, 2, 3, 4], item -> (item::Int + 1)) AS incremented + ); +END; +$$; + +CALL PROCEDURE sp_demo_lambda_array(); +``` + +Lambda 也可以出现在由过程执行的查询中。 + +```sql +CREATE OR REPLACE PROCEDURE sp_demo_lambda_query() +RETURNS STRING +LANGUAGE SQL +AS $$ +BEGIN + RETURN TABLE( + SELECT + number, + ARRAY_TRANSFORM([number, number + 1], val -> (val::Int + 1)) AS next_values + FROM numbers(3) + ); +END; +$$; + +CALL PROCEDURE sp_demo_lambda_query(); +``` + +当 lambda 在 SQL 语句上下文中运行时,可通过在过程变量前加上 `:` 来在 lambda 内部捕获这些变量。 + +```sql +CREATE OR REPLACE PROCEDURE sp_lambda_filter() +RETURNS STRING +LANGUAGE SQL +AS $$ +BEGIN + LET threshold := 2; + RETURN TABLE( + SELECT ARRAY_FILTER([1, 2, 3, 4], element -> (element::Int > :threshold)) AS filtered + ); +END; +$$; + +CALL PROCEDURE sp_lambda_filter(); +``` + +你还可以在 lambda 主体中放入复杂表达式,例如 `CASE` 逻辑。 + +```sql +CREATE OR REPLACE PROCEDURE sp_lambda_case() +RETURNS STRING +LANGUAGE SQL +AS $$ +BEGIN + RETURN TABLE( + SELECT + number, + ARRAY_TRANSFORM( + [number - 1, number, number + 1], + val -> (CASE WHEN val % 2 = 0 THEN 'even' ELSE 'odd' END) + ) AS parity_window + FROM numbers(3) + ); +END; +$$; + +CALL PROCEDURE sp_lambda_case(); +``` + +## 控制流 {#control-flow} + +### IF 语句 {#if-statements} + +使用 `IF ... ELSEIF ... ELSE ... END IF;` 在过程内部进行分支处理。 + +```sql +CREATE OR REPLACE PROCEDURE sp_evaluate_score(score INT) +RETURNS STRING +LANGUAGE SQL +AS $$ +BEGIN + IF score >= 90 THEN + RETURN 'Excellent'; + ELSEIF score >= 70 THEN + RETURN 'Good'; + ELSE + RETURN 'Review'; + END IF; +END; +$$; + +CALL PROCEDURE sp_evaluate_score(82); +``` + +### CASE 表达式 {#case-expressions} + +`CASE` 表达式提供了嵌套 `IF` 语句之外的另一种选择。 + +```sql +CREATE OR REPLACE PROCEDURE sp_membership_discount(level STRING) +RETURNS FLOAT +LANGUAGE SQL +AS $$ +BEGIN + RETURN CASE + WHEN level = 'gold' THEN 0.2 + WHEN level = 'silver' THEN 0.1 + ELSE 0 + END; +END; +$$; + +CALL PROCEDURE sp_membership_discount('silver'); +``` + +### 范围 `FOR` {#range-for} + +基于范围的循环会从下界迭代到上界(包含边界值)。使用可选的 `REVERSE` 关键字可以反向遍历该范围。 + +```sql +CREATE OR REPLACE PROCEDURE sp_sum_range(start_val INT, end_val INT) +RETURNS INT +LANGUAGE SQL +AS $$ +BEGIN + LET total := 0; + FOR i IN start_val TO end_val DO + total := total + i; + END FOR; + RETURN total; +END; +$$; + +CALL PROCEDURE sp_sum_range(1, 5); +``` + +向前迭代时,范围循环要求下界小于或等于上界。 + +```sql +CREATE OR REPLACE PROCEDURE sp_reverse_count(start_val INT, end_val INT) +RETURNS STRING +LANGUAGE SQL +AS $$ +BEGIN + LET output := ''; + FOR i IN REVERSE start_val TO end_val DO + output := output || i || ' '; + END FOR; + RETURN TRIM(output); +END; +$$; + +CALL PROCEDURE sp_reverse_count(1, 5); +``` + +#### `FOR ... IN` 查询 {#for-in-queries} + +直接对查询结果进行迭代。循环变量会将各列暴露为字段。 + +```sql +CREATE OR REPLACE PROCEDURE sp_sum_query(limit_rows INT) +RETURNS BIGINT +LANGUAGE SQL +AS $$ +BEGIN + LET total := 0; + FOR rec IN SELECT number FROM numbers(:limit_rows) DO + total := total + rec.number; + END FOR; + RETURN total; +END; +$$; + +CALL PROCEDURE sp_sum_query(5); +``` + +`FOR` 也可以对先前声明的结果集变量或游标进行迭代(参见[处理查询结果](#working-with-query-results))。 + +### `WHILE` {#while} + +```sql +CREATE OR REPLACE PROCEDURE sp_factorial(n INT) +RETURNS INT +LANGUAGE SQL +AS $$ +BEGIN + LET result := 1; + WHILE n > 0 DO + result := result * n; + n := n - 1; + END WHILE; + RETURN result; +END; +$$; + +CALL PROCEDURE sp_factorial(5); +``` + +### `REPEAT` {#repeat} + +```sql +CREATE OR REPLACE PROCEDURE sp_repeat_sum(limit_val INT) +RETURNS INT +LANGUAGE SQL +AS $$ +BEGIN + LET counter := 0; + LET total := 0; + + REPEAT + counter := counter + 1; + total := total + counter; + UNTIL counter >= limit_val END REPEAT; + + RETURN total; +END; +$$; + +CALL PROCEDURE sp_repeat_sum(3); +``` + +### `LOOP` {#loop} + +```sql +CREATE OR REPLACE PROCEDURE sp_retry_counter(max_attempts INT) +RETURNS INT +LANGUAGE SQL +AS $$ +BEGIN + LET retries := 0; + LOOP + retries := retries + 1; + IF retries >= max_attempts THEN + BREAK; + END IF; + END LOOP; + + RETURN retries; +END; +$$; + +CALL PROCEDURE sp_retry_counter(5); +``` + +### Break 和 Continue {#break-and-continue} + +使用 `BREAK` 可以提前退出循环,使用 `CONTINUE` 可以跳过当前迭代并进入下一次迭代。 + +```sql +CREATE OR REPLACE PROCEDURE sp_break_example(limit_val INT) +RETURNS INT +LANGUAGE SQL +AS $$ +BEGIN + LET counter := 0; + LET total := 0; + + WHILE TRUE DO + counter := counter + 1; + IF counter > limit_val THEN + BREAK; + END IF; + IF counter % 2 = 0 THEN + CONTINUE; + END IF; + total := total + counter; + END WHILE; + + RETURN total; +END; +$$; + +CALL PROCEDURE sp_break_example(5); +``` + +使用 `BREAK