What you will be able to do
- Choose a file format TYPE for structured and semi-structured files, and know which types are load-only
- Pick compression and parsing settings, and size files so loads run in parallel
- Use INFER_SCHEMA to derive column definitions, and know its format-specific limitations
- Query and load METADATA$ columns from staged files
1.File format objects and the supported types
A named file format tells Snowflake how to read a set of staged files. You create it with CREATE FILE FORMAT, and it can be reused by stages, queries and COPY statements. If you declare it TEMPORARY, it is dropped when the session ends. CREATE OR ALTER FILE FORMAT can change a format's type-specific options and its comment, but not its TYPE.
If you don't specify TYPE, it defaults to CSV. Structured data usually comes as CSV, which means any delimited plain-text file: despite the name, any valid character can be the field separator. Semi-structured data comes as JSON, AVRO, ORC, Parquet or XML. On load, JSON can be newline-delimited (NDJSON) or comma-separated, but unloads are always written as NDJSON. Not every type works in both directions, as the table below shows.
Semi-structured values usually end up in a VARIANT column, which can hold objects up to 128 MB without a declared length. VARCHAR columns default to 16 MB, so you have to declare a larger size explicitly if you need one.
| TYPE | What it is | Load | Unload |
|---|---|---|---|
| CSV | Flat, delimited plain text (default type) | Yes | Yes |
| JSON | Plain text with one or more JSON documents (semi-structured) | Yes | Yes (NDJSON only) |
| AVRO | Binary AVRO file | Yes | No |
| ORC | Binary ORC file | Yes | No |
| PARQUET | Binary Parquet file | Yes | Yes |
| XML | Plain text containing XML elements | Yes | No |
Checkpoint 1 of 6· Check yourself
A pipeline has to unload table data back to cloud storage in a semi-structured format. Which TYPE can it NOT use?
XML, AVRO and ORC are load-only. JSON and Parquet support both loading and unloading, and JSON unloads are written as NDJSON.
“XML (for loading only;”Source: docs.snowflake.com
2.Compression, file sizing and parsing options
Each TYPE has its own COMPRESSION values. AUTO is listed for every type that has the option. The binary columnar formats have their own codecs, and the reference lists no COMPRESSION option at all for ORC.
| TYPE | COMPRESSION values listed |
|---|---|
| CSV, JSON, XML | AUTO, GZIP, BZ2, BROTLI, ZSTD, DEFLATE, RAW_DEFLATE, NONE |
| AVRO | AUTO, GZIP, BROTLI, ZSTD, DEFLATE, RAW_DEFLATE, NONE |
| PARQUET | AUTO, LZO, SNAPPY, NONE |
| ORC | Not listed |
Compression also changes how the work is split up. A load can't run more operations in parallel than there are files, so Snowflake recommends compressed files of roughly 100–250 MB or more and advises against very large files of 100 GB or more. Combine small files, split large ones, and split by line so that no record spans two chunks. There is one exception for large uncompressed CSV files (over 128 MB) that follow RFC4180. Snowflake can scan these in parallel, but only if MULTI_LINE = FALSE, COMPRESSION = NONE and ON_ERROR is ABORT_STATEMENT or CONTINUE.
Parsing options handle the rest. The default character set is UTF-8, and ENCODING declares any other. Fields that contain the delimiter, or the Windows carriage return, should be enclosed in quotes, and quotes inside the data must be escaped. Every row should have the same number of columns. The CSV options reflect this: FIELD_OPTIONALLY_ENCLOSED_BY, ESCAPE, SKIP_HEADER, PARSE_HEADER, NULL_IF and ERROR_ON_COLUMN_COUNT_MISMATCH. JSON has STRIP_OUTER_ARRAY, and XML has STRIP_OUTER_ELEMENT.
Checkpoint 2 of 6· Check yourself
A 4 GB RFC4180-compliant CSV file is loaded with COMPRESSION = GZIP and MULTI_LINE = FALSE. Why doesn't Snowflake scan it in parallel?
Parallel scanning of a single large CSV only happens when the file is uncompressed, MULTI_LINE is FALSE, and ON_ERROR is ABORT_STATEMENT or CONTINUE.
“when MULTI_LINE is set to FALSE, COMPRESSION is set to NONE, and ON_ERROR is set to ABORT_STATEMENT or CONTINUE”Source: docs.snowflake.com
Sources2
3.INFER_SCHEMA: deriving table design from staged files
You can design the target table without opening the files yourself. The INFER_SCHEMA table function reads staged Parquet, Avro, ORC, JSON or CSV files and returns one row per detected column. Each row has COLUMN_NAME, TYPE, NULLABLE, EXPRESSION (in the form $1:COLUMN_NAME::TYPE, mainly for external tables), FILENAMES and ORDER_ID. It needs a LOCATION (a named stage or the user stage, with an optional path) and a FILE_FORMAT object.
-- Create a file format that sets the file type as Parquet.
CREATE FILE FORMAT my_parquet_format
TYPE = parquet;
-- Query the INFER_SCHEMA function.
SELECT *
FROM TABLE(
INFER_SCHEMA(
LOCATION=>'@mystage'
, FILE_FORMAT=>'my_parquet_format'
)
);You can pass the output to CREATE TABLE, CREATE EXTERNAL TABLE or CREATE ICEBERG TABLE ... USING TEMPLATE, and GENERATE_COLUMN_DESCRIPTION turns the output into column text for a CREATE statement. A few arguments control the cost and accuracy of the scan:
- FILES names up to 1000 specific files. MAX_FILE_COUNT caps how many files are scanned but doesn't let you choose which ones.
- MAX_RECORDS_PER_FILE applies only to CSV and JSON, and it can reduce accuracy.
- With IGNORE_CASE => TRUE, column names come back in uppercase and the expression uses GET_IGNORE_CASE.
- Use KIND => 'ICEBERG' when inferring Parquet for Iceberg tables. Otherwise the column definitions may be wrong.
The limitations are what the exam tests. Table stages aren't supported. For CSV, column names come from the header row only when the format sets PARSE_HEADER = TRUE, and that option can't be combined with SKIP_HEADER. With the default, columns are named c1, c2 and so on. For CSV and JSON, every column is reported as NULLABLE, and DATE_FORMAT, TIME_FORMAT and TIMESTAMP_FORMAT are ignored. Every timestamp variant comes back as TIMESTAMP_NTZ, and only the first level of nesting is inferred.
Checkpoint 3 of 6· Fill the gap
Which argument tells INFER_SCHEMA how to parse the single staged file?
SELECT *
FROM TABLE(
INFER_SCHEMA(
LOCATION=>'@mystage/geography/cities.parquet'
, ? =>'my_parquet_format'
)
);FILE_FORMAT names the file format object that describes the staged files. FILES lists file names, and KIND selects Snowflake or Iceberg types.
Source: docs.snowflake.comCheckpoint 4 of 6· Exam question
An application team uploads JSON export files where every file is a single top-level array containing thousands of individual order objects, such as `[{...},{...},{...}]`. The team wants each order object loaded as its own row in a VARIANT column, rather than the whole array landing in one row. Which JSON file format option achieves this?
Correct answer: A — Enable `STRIP_OUTER_ARRAY = TRUE` on the JSON file format so the enclosing brackets are removed and each element of the array is inserted as a separate row.
- A. `STRIP_OUTER_ARRAY` removes the outermost square brackets of a JSON document during load, so each object that was an element of that array is inserted as its own separate row instead of the whole array being stored in a single row.
- B. `ALLOW_DUPLICATE` controls whether repeated object keys within the same JSON object are tolerated during parsing; it does not change how many rows an array of objects produces on load.
- C. `STRIP_NULL_VALUES` removes object fields whose value is `NULL` from the parsed VARIANT, which reduces stored data volume but does not split an outer array into multiple rows.
- D. `IGNORE_UTF8_ERRORS` replaces invalid UTF-8 characters during parsing instead of failing the load, and has no bearing on whether an outer array is split into one row per element.
Sources3
4.Extracting metadata from staged files
For every file in an internal or external stage, Snowflake generates virtual metadata columns. You can select them alongside the data columns ($1, $2, ...) when you query the stage, or load them with COPY INTO <table>. This is how a target table records lineage, meaning which file and which row each record came from. The file format still matters here. In the source's CSV example, leaving out the |-delimited format means the delimiter is ignored, so each whole line ends up in $1.
| Column | What it returns |
|---|---|
| METADATA$FILENAME | Name of the staged file the row belongs to, including the full path |
| METADATA$FILE_ROW_NUMBER | Row number of each record in the staged file |
| METADATA$FILE_CONTENT_KEY | Checksum of the staged file the row belongs to |
| METADATA$FILE_LAST_MODIFIED | Listed as a queryable metadata column |
| METADATA$START_SCAN_TIME | Start timestamp of the operation for each record, as TIMESTAMP_LTZ |
To persist metadata, use the transformation form of COPY: a SELECT list in the FROM (...) clause that pulls the METADATA$ columns and the data columns into named target columns. Metadata can only be captured as rows are loaded. You can't insert it into rows that already exist, so add the lineage columns before the first load rather than backfilling them afterwards.
Checkpoint 5 of 6· Exam question
A data engineer needs to make a laptop-generated batch of Parquet files available to Snowflake without provisioning any cloud storage bucket, and the files should be private to that individual engineer's session rather than shared with the rest of the account. Which stage should the engineer use?
Correct answer: A — The engineer's own user stage, referenced as `@~`, uploaded to with the `PUT` command and then loaded with `COPY INTO` from that same user stage reference.
- A. A user stage (`@~`) is automatically allocated to each individual user for storing files that only that user needs to load, is populated with `PUT` from a local machine, and cannot be granted to other users, matching the requirement for a private, no-bucket-provisioning location.
- B. A table stage is tied to a specific table rather than a specific user, and any user with load privileges on that table can stage and load files there, so it does not give one engineer's files privacy from the rest of the account.
- C. A named internal stage is a shareable schema-level object; access is controlled through grants, so multiple roles can be given USAGE and write to it, which does not match a requirement for a single engineer's private location.
- D. An external stage requires provisioning and configuring a cloud storage bucket (or a storage integration) ahead of time, which is exactly the extra infrastructure step the engineer wants to avoid for a quick local upload.
Checkpoint 6 of 6· Check yourself
An engineer wants every loaded row to record its source file name. Which approach works?
Metadata is captured through COPY's transformation syntax as rows are loaded. You can't insert it into existing rows, and SELECT * doesn't return it.
“Use the data transformation syntax (i.e. a SELECT list) in your COPY statement.”Source: docs.snowflake.com
Sources4
Exam traps
Each one states something that sounds right. Open it to see what is actually true.
1.INFER_SCHEMA can read files from any stage, including a table stage.Why is that wrong?
INFER_SCHEMA supports named stages (internal or external) and the user stage, but not table stages.
Covered in INFER_SCHEMA: deriving table design from staged files
2.Setting PARSE_HEADER = TRUE together with SKIP_HEADER = 1 lets INFER_SCHEMA read column names from the header and then skip it.Why is that wrong?
SKIP_HEADER can't be used with PARSE_HEADER = TRUE. PARSE_HEADER on its own treats the first row as the source of column names.
Covered in INFER_SCHEMA: deriving table design from staged files
3.Lineage columns can be added later by updating existing rows with METADATA$FILENAME.Why is that wrong?
Metadata can only be queried at read time or loaded as rows are copied. It can't be inserted into rows that already exist.
Covered in Extracting metadata from staged files
Sources
Every claim above is drawn from one of these pages, quoted as it was written on the date shown.
- 1.
“JSON is a semi-structured file format.”
↩︎ File format objects and the supported types“When you unload table data to files, Snowflake outputs only to NDJSON format.”
↩︎ File format objects and the supported types“Supported alterations include changes to the formatTypeOptions and COMMENT properties.”
↩︎ File format objects and the supported types“XML (for loading only;”
↩︎ Checkpoint - 2.
“The default size for VARCHAR columns is 16 MB (8 MB for binary).”
↩︎ File format objects and the supported types“we recommend aiming to produce data files roughly 100-250 MB (or larger) in size compressed.”
↩︎ Compression, file sizing and parsing options“We recommend splitting large files by line to avoid records that span chunks.”
↩︎ Compression, file sizing and parsing options“Use the ENCODING file format option to specify the character set for the data files.”
↩︎ Compression, file sizing and parsing options“Fields that contain delimiter characters should be enclosed in quotes (single or double).”
↩︎ Compression, file sizing and parsing options“when MULTI_LINE is set to FALSE, COMPRESSION is set to NONE, and ON_ERROR is set to ABORT_STATEMENT or CONTINUE”
↩︎ Checkpoint - 3.
“This function supports Apache Parquet, Apache Avro, ORC, JSON, and CSV files.”
↩︎ INFER_SCHEMA: deriving table design from staged files“You can execute the CREATE TABLE, CREATE EXTERNAL TABLE, or CREATE ICEBERG TABLE command with the USING TEMPLATE clause”
↩︎ INFER_SCHEMA: deriving table design from staged files“we strongly recommend that you set KIND => 'ICEBERG'. Otherwise, the column definitions returned by the function might be incorrect.”
↩︎ INFER_SCHEMA: deriving table design from staged files“All the variations of timestamp data types are retrieved as TIMESTAMP_NTZ without any time zone information.”
↩︎ INFER_SCHEMA: deriving table design from staged files“The default value FALSE will return column names as c*, where * is the position of the column.”
↩︎ INFER_SCHEMA: deriving table design from staged files“This SQL function supports named stages (internal or external) and user stages only. It does not support table stages.”
↩︎ Exam trap 1“The SKIP_HEADER option is not supported with PARSE_HEADER = TRUE.”
↩︎ Exam trap 2 - 4.
“Snowflake automatically generates metadata for files in internal (i.e. Snowflake) stages or external (Amazon S3, Google Cloud Storage, or Microsoft Azure) stages.”
↩︎ Extracting metadata from staged files“The COPY INTO <table> command supports copying metadata from staged data files into a target table.”
↩︎ Extracting metadata from staged files“In the second query, the file format is omitted, causing the | field delimiter to be ignored”
↩︎ Extracting metadata from staged files“Metadata cannot be inserted into existing table rows.”
↩︎ Exam trap 3“Metadata columns can only be queried by name; as such, they are not included in the output of any of the following statements:”
↩︎ Prediction“Use the data transformation syntax (i.e. a SELECT list) in your COPY statement.”
↩︎ Checkpoint