Ten thousand files, three hundred kilobytes
The canteen billing app was changed to write one CSV file per order into HDFS. It looked tidy: o_1.csv, o_2.csv, … After one busy morning there are 10,000 files with only 339 KB of data between them. Uploading them took almost five minutes, reading them back took 15 seconds, and the cluster admin calls Riya: the NameNode just gained 20,000 new objects to keep in memory. The same data as one file uploads in 2 seconds and costs the NameNode 2 objects.
This is the famous small files problem. HDFS was designed for a few million large files. Every file, folder and block is an object in the NameNode's memory, and every file needs its own calls to the NameNode and its own pipeline to DataNodes. A 33-byte file costs the NameNode about as much as a 128 MB one.
Then the data size doesn't matter at all?
For the NameNode, hardly. For jobs, small files also mean one map task per file, so 10,000 tiny tasks that spend more time starting than working. Today we measure all of it, and then fix it: pack the files into a Hadoop Archive, and see why the real fix is to never write them in the first place.
The small files problem
The small files problem refers to the degradation of HDFS and processing performance when data is stored as a large number of files significantly smaller than the HDFS block size. Because the NameNode keeps every file, directory and block as an object in memory (commonly estimated at roughly 150 bytes each), the number of files rather than the volume of data determines NameNode heap use, RPC load and the time for listings, block reports and restarts. Each small file also requires separate metadata operations and a separate block write and read, and frameworks typically create at least one input split (and task) per file, so job overhead grows with file count. Mitigations include writing larger files at the source, periodic compaction, container formats (SequenceFile, Avro, Parquet), Hadoop Archives (HAR), and input formats that combine files (CombineFileInputFormat).
HDFS keeps a catalogue card for every file and block. Millions of tiny files mean millions of cards, endless trips to the catalogue, and thousands of tiny jobs, even if all the files together are small. Store fewer, bigger files.
Words you'll meet in this lesson
har://.From our lab (Hadoop 3.5.0, same 338,894 bytes)
| NameNode objects | FilesTotal 41 → 10,043 and BlocksTotal 31 → 10,031 after the small files; fsck: 10,000 blocks, average 33 B |
|---|---|
| Upload | 10,000 files: 281,026 ms (one -put command) · 1 file: 2,133 ms |
| Read everything | 10,000 files: 15,168 ms · 1 file: 1,892 ms |
| Local disk | du -sh of the 10,000 local files: 40 M for 339 KB of data (4 KB blocks) |
| After HAR + delete | 4 files in orders.har; NameNode back to FilesTotal 49, BlocksTotal 35 |
Small files at three levels
Beginner A library that registers every page
- Imagine a library that makes a catalogue card for every book. Fine. Now someone donates 10,000 single-page leaflets: 10,000 cards, 10,000 shelf slots.
- The librarian's card box (NameNode memory) fills up, and finding anything takes longer, even though the leaflets together are thinner than one book.
- Binding the leaflets into one volume (compaction or an archive) needs one card.
Intermediate Where the cost comes from
- NameNode memory: each file + block ≈ 2 objects. Our 10,000 files added 20,000 objects; the big file added 2.
- RPCs: each file needs create, addBlock, complete, plus a DataNode pipeline. That is why the upload took 281 s instead of 2 s, even in one JVM.
- Reading: one
getBlockLocationsand one DataNode connection per file: 15.2 s vs 1.9 s. - Jobs: MapReduce and Spark create about one split per file. 10,000 files → about 10,000 tasks, each lasting milliseconds after seconds of start-up.
Advanced How teams fix it
- At the source: buffer and write larger files (e.g. a file per hour per partition, not per event); streaming sinks with sensible flush intervals.
- Compaction jobs: Spark
coalesce/repartition, Hive merge settings, or table-format commands (DeltaOPTIMIZE, Iceberg rewrite_data_files) on a schedule. - Containers: SequenceFile or Avro with filename as key; Parquet tables instead of per-record files.
- HAR: for archives that must keep file names but are rarely read. HAR files are immutable and add an index lookup on read.
- Guardrails: name quotas (Lesson 7.4) on landing folders, monitoring of average file size per folder, and federation for unavoidable churn (Lesson 7.2).
Exam tip: For “What is the small files problem in Hadoop and how do you solve it?”, give the two costs (NameNode memory, roughly 150 bytes per object; one map task per file), one number (e.g. 10,000 files vs 1 file), and three solutions: HAR, SequenceFile/combining, CombineFileInputFormat, plus “write bigger files at source”.
Solutions compared
| Solution | Reduces NameNode objects | Keeps file names | Readable by jobs | Notes |
|---|---|---|---|---|
| Write bigger files at source | Yes, best | n/a | Yes | The real fix; needs app change |
| Compaction (Spark, Hive, table formats) | Yes | No (records merged) | Yes | Schedule regularly |
| HAR (hadoop archive) | Yes | Yes (har://) | Yes, via har:// | Immutable; extra index lookups |
| SequenceFile / Avro container | Yes | As keys | Yes | Needs a pack job and readers that understand it |
| CombineFileInputFormat | No | Yes | Fewer tasks | Fixes job overhead only |
Where small files come from
Per-event writers
Apps writing one file per order, click or sensor reading.
designStreaming micro-batches
A file every few seconds per partition (Lesson 2.2 of Big Data Fundamentals).
streamingOver-partitioning
Partitioning by date AND hour AND city AND item gives tiny folders with tiny files.
tablesToo many reducers
A job with 2,000 reducers writing 2,000 files of 50 KB each.
jobsA quick health metric: average file size = CONTENT_SIZE / FILE_COUNT from hdfs dfs -count. Our /small folder averaged 34 bytes. Anything far below the block size in a big folder deserves a compaction plan.
Measuring and fixing small files
Run on the Module 5 lab cluster with small_files_lab.sh (in “Run it on your PC”).
Create the same data two ways
Even the local disk wastes space: 339 KB of data occupy 40 MB because each tiny file takes a 4 KB block (Big Data Fundamentals, Lesson 2.3).seq 1 10000 | while read i; do printf 'order_id,item,amount\n%d,chai,20\n' $i > o_$i.csv; done cat /tmp/small/*.csv > /tmp/big.csv10000 40M /tmp/small 338894 bytes in big.csvUpload both and watch the NameNode
4 minutes 41 seconds vs 2 seconds for the same bytes. The NameNode gained 10,002 files (10,000 + two folders) and 10,000 blocks. (Its JMX counters refresh with a delay, so they didn't show the single big file's +1 within our 6 s wait; fsck below confirms it.)hdfs dfs -put /tmp/small/*.csv /small/ hdfs dfs -put /tmp/big.csv /big/ curl -s 'http://localhost:9870/jmx?qry=Hadoop:service=NameNode,name=FSNamesystem' # FilesTotal, BlocksTotalNameNode before : FilesTotal 41 BlocksTotal 31 put 10000 files: 281026 ms NameNode after small files: FilesTotal 10043 BlocksTotal 10031 put 1 file: 2133 msSame bytes, very different object counts
Identical bytes on DataNode disks (HDFS blocks are only as big as their data, so no disk is wasted there). The difference is entirely in the NameNode: 10,000 blocks averaging 33 bytes.hdfs dfs -count -v /small /big hdfs dfs -du -s /small /big hdfs fsck /small ; hdfs fsck /bigDIR_COUNT FILE_COUNT CONTENT_SIZE PATHNAME 1 10000 338894 /small 1 1 338894 /big 338894 1016682 /small 338894 1016682 /big Total blocks (validated): 10000 (avg. block size 33 B) Total blocks (validated): 1 (avg. block size 338894 B)Read everything back
Same 20,000 lines. The small files needed 10,000 location lookups and 10,000 DataNode connections: 8 times slower, and that's with one client and no job framework.hdfs dfs -cat '/small/*.csv' | wc -l hdfs dfs -cat /big/big.csv | wc -l20000 read 10000 files: 15168 ms 20000 read 1 file: 1892 msFix: pack them into a Hadoop Archive
The archive job (a MapReduce job, here in local mode) packed all data into onehadoop archive -archiveName orders.har -p /small /archives hdfs dfs -ls /archives/orders.har hdfs dfs -count -v har:///archives/orders.har ; hdfs dfs -cat har:///archives/orders.har/o_42.csvarchive job took 24 s -rw-r--r-- 3 hadoop supergroup 0 2026-10-21 16:39 /archives/orders.har/_SUCCESS -rw-r--r-- 3 hadoop supergroup 834555 2026-10-21 16:39 /archives/orders.har/_index -rw-r--r-- 3 hadoop supergroup 388 2026-10-21 16:39 /archives/orders.har/_masterindex -rw-r--r-- 3 hadoop supergroup 338894 2026-10-21 16:39 /archives/orders.har/part-0 1 10000 338894 har:///archives/orders.har order_id,item,amount 42,chai,20part-0file plus an index. Throughhar://the 10,000 names still exist and can be read individually.Delete the originals and check the NameNode
From over 10,000 files and blocks back to 49 and 35: the archive costs the NameNode 4 files. The trade-off: archives are immutable, and each read first consults the index.hdfs dfs -rm -r -skipTrash /smallremoved /small NameNode after HAR, without /small: FilesTotal 49 BlocksTotal 35
A compaction or archive job must finish and be verified before deleting the originals, and readers must be switched to the new location. Delete first and a failed job means lost data.
What the NameNode does for each tiny file
Six steps comparing one small-file upload with one big-file upload, then the archive fix.
- 10,000 tiny files start uploading in one command.
- It takes 281 s, and the NameNode now tracks about 10,000 more files and blocks.
- The same bytes as one file: 2.1 s, one file, one block.
- Reading all small files takes 15.2 s; the big file 1.9 s.
- A Hadoop Archive packs the small files into a few files, still readable by name.
- With the originals removed, the NameNode is back to a few dozen objects.
- Every small file needs create, addBlock and complete calls to the NameNode and its own write pipeline.
- Repeated 10,000 times: about 30,000 NameNode calls and 20,000 objects in its memory.
- One big file: the same three calls and two objects, then one efficient stream of bytes.
- Reading costs one location lookup and one DataNode connection per file.
- A HAR stores the file names in its own index file, so the NameNode only sees a few files.
- Removing the originals returns the NameNode to a small object count. (Squares are symbolic.)
Small files at work
1. Nightly compaction of streaming data
Streaming jobs write small files all day for freshness; a nightly Spark or table-format job rewrites yesterday's partitions into files of a few hundred MB.
2. Monitoring average file size
Platform teams scan the namespace (from fsimage with the Offline Image Viewer, Lesson 5.4) to rank folders by file count and average size, and ask the owners of the worst offenders to fix their writers.
3. Archiving old logs and documents
Years of small log or document files that must stay individually retrievable are packed into HAR archives (or containers) so they stop costing NameNode memory.
4. IoT and per-event uploads redesigned
Systems that once wrote one file per sensor reading switch to a message queue (Kafka) and write hourly files per device group, cutting file counts by orders of magnitude.
Simplified; organisations differ in tools and policies.
Count the NameNode's work for small and big files
This model counts NameNode objects (files + blocks), NameNode calls and map tasks for the same data stored as many small files or a few big ones. The cost per object comes from the common rule of thumb of about 150 bytes of heap.
import math
BLOCK = 128 * 1024 * 1024
HEAP_PER_OBJECT = 150 # bytes, rule of thumb
def cost(total_bytes, n_files):
size = total_bytes / n_files
blocks_per_file = max(1, math.ceil(size / BLOCK))
objects = n_files * (1 + blocks_per_file)
calls = n_files * (2 + blocks_per_file) # create + complete + addBlock per block
tasks = n_files * blocks_per_file # about one split per block (one per small file)
return objects, calls, tasks, objects * HEAP_PER_OBJECT
data = 338_894
for n in [10_000, 1]:
o, c, t, heap = cost(data, n)
print(f"{n:>6} files: {o:>6} objects, {c:>6} NameNode calls, {t:>6} map tasks, ~{heap / 1024:.0f} KB heap")objects = n_files * (1 + blocks_per_file)Each file is at least two objects: the file and its block. Our lab: +10,000 files and +10,000 blocks.calls = n_files * (2 + blocks_per_file) # create + complete + addBlock per blockEach file needs its own create, addBlock and complete calls, the reason 10,000 uploads took 281 s.tasks = n_files * blocks_per_file # about one split per block (one per small file)Frameworks create about one split per file: 10,000 tiny tasks, mostly start-up overhead.
Run it on your PC: 10,000 files vs 1, then archive them
Run this against the Module 5 lab cluster. It creates 10,000 tiny CSV files and one file with the same bytes inside the namenode container, uploads both, reads NameNode counters from /jmx, compares reads, then packs the small files into a Hadoop Archive. It takes about 6 minutes, most of it the small-file upload.
Small files lab
#!/usr/bin/env bash
# small_files_lab.sh: the same 10 MB of orders as 10,000 tiny files vs 1 file, and what the NameNode pays.
NN="docker exec lab5-namenode-1"
jmx() { sleep 6; $NN bash -c "curl -s 'http://localhost:9870/jmx?qry=Hadoop:service=NameNode,name=FSNamesystem'" | python3 -c "import sys,json; b=json.load(sys.stdin)['beans'][0]; print('FilesTotal', b['FilesTotal'], ' BlocksTotal', b['BlocksTotal'])"; }
run() { echo "\$ $1"; $NN bash -c "$1" 2>&1 | grep -v -E "^\s*$|WARN|INFO"; echo; }
run "hdfs dfs -rm -r -f -skipTrash /small /big /archives > /dev/null; rm -rf /tmp/small && mkdir -p /tmp/small && cd /tmp/small && seq 1 10000 | while read i; do printf 'order_id,item,amount\n%d,chai,20\n' \$i > o_\$i.csv; done; ls | wc -l; du -sh /tmp/small; cat /tmp/small/*.csv > /tmp/big.csv; ls -l /tmp/big.csv | awk '{print \$5, \"bytes in big.csv\"}'"
echo "NameNode before : $(jmx)"; echo
run "hdfs dfs -mkdir -p /small /big; s=\$(date +%s%N); hdfs dfs -put /tmp/small/*.csv /small/; echo put 10000 files: \$(( (\$(date +%s%N)-s)/1000000 )) ms"
echo "NameNode after small files: $(jmx)"; echo
run "s=\$(date +%s%N); hdfs dfs -put /tmp/big.csv /big/; echo put 1 file: \$(( (\$(date +%s%N)-s)/1000000 )) ms"
echo "NameNode after big file : $(jmx)"; echo
run "hdfs dfs -count -v /small /big"
run "hdfs dfs -du -s /small /big"
run "s=\$(date +%s%N); hdfs dfs -cat '/small/*.csv' | wc -l; echo read 10000 files: \$(( (\$(date +%s%N)-s)/1000000 )) ms"
run "s=\$(date +%s%N); hdfs dfs -cat /big/big.csv | wc -l; echo read 1 file: \$(( (\$(date +%s%N)-s)/1000000 )) ms"
run "hdfs fsck /small | grep -E 'Total files|Total blocks|Average block size'; hdfs fsck /big | grep -E 'Total files|Total blocks|Average block size'"
echo "=== FIX 1: pack the small files into a Hadoop Archive (HAR)"
run "s=\$(date +%s); hadoop archive -archiveName orders.har -p /small /archives > /dev/null 2>&1; echo archive job took \$(( \$(date +%s)-s )) s; hdfs dfs -ls /archives/orders.har"
run "hdfs dfs -count -v har:///archives/orders.har; hdfs dfs -cat har:///archives/orders.har/o_42.csv"
run "hdfs dfs -rm -r -skipTrash /small > /dev/null && echo removed /small"
echo "NameNode after HAR, without /small: $(jmx)"
# Run: bash small_files_lab.shReal output. Timings vary; the ratio stays dramatic. The JMX counters refresh with a delay, which is why the line after the big file still shows the earlier values; fsck shows its 1 file and 1 block.
Packing small files into one container
A container (like a SequenceFile or a HAR) stores many small files inside one big file and keeps an index of where each one starts. Follow three files being packed and one being read back.
Worked examples: real problems, solved and traced in memory
Three small-files calculations: NameNode heap, job overhead, and the payoff of compaction.
How much NameNode memory do small files cost?
Problem statement
A team writes 20 lakh files a day, each 30 KB (one block each), and keeps them for 180 days. Using about 150 bytes per object, how much NameNode heap do they occupy?
20,00,000/day · 180 days · 2 objects/file
360,000,000 files -> 101 GB of NameNode heap
Approach
- Files kept = per day × days.
- Objects = files × 2 (file + block).
- Heap = objects × 150 B.
Solution: run it live
What happens in memory, step by step
Recorded from a real Python run: press Next to execute one line at a time. Watch variables change in each frame, and lists and dictionaries (numbered #1, #2 …) fill up as objects.
How long do 10,000 tiny tasks take?
Problem statement
A job reads 10,000 small files, one map task each. Each task spends 1.5 s starting and 0.05 s working. With 200 task slots, how long does the map phase take, compared with 2 tasks reading 2 big files (1.5 s + 40 s work each)?
10,000 × (1.5 + 0.05) s / 200 slots vs 2 × 41.5 s
small files: 77.5 s (4.2 task-hours of pure start-up) big files : 41.5 s
Approach
- Waves = tasks / slots.
- Time = waves × task time.
- Compare.
Solution: run it live
What happens in memory, step by step
Recorded from a real Python run: press Next to execute one line at a time. Watch variables change in each frame, and lists and dictionaries (numbered #1, #2 …) fill up as objects.
Is a nightly compaction job worth it?
Problem statement
A streaming job creates 2,880 files per partition per day across 50 partitions. Compaction rewrites each day into 2 files per partition, costing 20 minutes of a 40-node cluster (₹600 per node-hour). Each NameNode object costs ₹0.0002 per day in extra heap and GC (illustrative). Compare the yearly cost with and without compaction.
2,880 × 50 files/day · compaction 20 min × 40 nodes
heap/GC cost avoided: Rs 3,844,720 compaction cost: Rs 2,920,000
Approach
- Objects avoided per day.
- Objects accumulate: day d keeps d days of files.
- Compare with compaction cost.
Solution: run it live
What happens in memory, step by step
Recorded from a real Python run: press Next to execute one line at a time. Watch variables change in each frame, and lists and dictionaries (numbered #1, #2 …) fill up as objects.
Check yourself
Quick revision
Lesson 7.5 in one screen
- Small files cost the NameNode (≈150 B per file/folder/block, rule of thumb), RPCs and tasks, not DataNode disk.
- Lab (338,894 bytes): 10,000 files upload 281 s vs 2.1 s; read 15.2 s vs 1.9 s; +10,000 files and blocks; fsck avg block 33 B.
- DataNode raw bytes were identical (1,016,682): blocks are only as big as their data.
- Fixes: write bigger files at source; scheduled compaction (Spark, Hive, Delta OPTIMIZE, Iceberg rewrite); containers (SequenceFile, Avro, Parquet).
- HAR:
hadoop archive -archiveName x.har -p /src /dest; read viahar://; immutable. - CombineFileInputFormat reduces tasks, not NameNode objects.
- Watch average file size (
-count), use name quotas on landing zones.
Interview and viva questions
What is the small files problem in Hadoop?
When data is stored as many files much smaller than the block size, the NameNode must keep an object in memory for each file and block, handle separate RPCs for each, and jobs create a task per file. Memory, NameNode load and job overhead grow with the number of files, not the amount of data, which limits scalability and performance.
How do you solve the small files problem?
Prevent it by writing larger files (batching, sensible streaming intervals, fewer reducers). Clean up existing data with compaction jobs that rewrite small files into large ones, Hadoop Archives (HAR) for rarely accessed data, or container formats like SequenceFile/Avro/Parquet. Use CombineFileInputFormat to reduce task counts when reading.
What is a Hadoop Archive (HAR)?
An archive created by the hadoop archive command (a MapReduce job) that packs many files into a few large part files plus index files. The original paths remain readable through the har:// file system, while the NameNode stores only the archive's few files. HAR files are immutable.
Do small files waste DataNode disk space in HDFS?
Not in the way local file systems do: an HDFS block replica only occupies the bytes it contains. In our lab, 10,000 small files and one big file used the same raw bytes. The waste is in NameNode memory, RPC load and job overhead.
What file size should data in HDFS have?
As a guideline, hundreds of MB to a few GB per file: at least around the block size (128 MB) and big enough that jobs have reasonably sized splits, while not so big that a single file limits parallelism (for non-splittable formats).
Practice problems
Small-files exercises using the real counts and timings from the lab.
Objects added
FilesTotal went 41 → 10,043 and BlocksTotal 31 → 10,031. How many objects did the NameNode gain?
two counters
20002 objects
Show solution and explanation
print((10043 - 41) + (10031 - 31), "objects")How it works: 20,002: 10,000 files, 2 folders and 10,000 blocks.
Slowdown factors
Compute how many times slower upload and read were for the small files.
281,026 vs 2,133 ms · 15,168 vs 1,892 ms
upload 132x slower, read 8.0x slower
Show solution and explanation
print(f"upload {281026 / 2133:.0f}x slower, read {15168 / 1892:.1f}x slower")How it works: About 132× slower to upload and 8× slower to read, for identical bytes.
Average file size
What is the average size of the 10,000 files?
338,894 bytes / 10,000
33.8894 bytes
Show solution and explanation
print(338894 / 10000, "bytes")How it works: About 34 bytes; fsck reports 33 B (rounded down).
Heap after a year
An app creates 5,000 small files per hour, each one block, kept forever. How many objects after one year, and roughly how much heap at 150 B each?
5,000/hour × 8,760 hours
87,600,000 objects -> 12.2 GB
Show solution and explanation
files = 5000 * 8760
print(f"{files * 2:,} objects -> {files * 2 * 150 / 1024**3:.1f} GB")How it works: 8.76 crore objects, about 12 GB of heap from a single application.
Parse the HAR index idea
Given an index of name → (offset, length) and the big file, read o_3.csv.
index + bytes
b'3,dosa,40\n'
Show solution and explanation
part0 = b"1,chai,20\n2,poha,30\n3,dosa,40\n"
index = {"o_1.csv": (0, 10), "o_2.csv": (10, 10), "o_3.csv": (20, 10)}
o, l = index["o_3.csv"]
print(part0[o:o + l])How it works: b"3,dosa,40\n": one index lookup and one read from part-0, like har:// does.
Tasks with combining
10,000 small files of 34 bytes; CombineFileInputFormat packs files into splits of up to 128 MB. How many tasks?
10,000 × 34 B
1 task(s)
Show solution and explanation
import math
print(max(1, math.ceil(10000 * 34 / (128 * 1024**2))), "task(s)")How it works: 1 task instead of 10,000, but the NameNode still holds 20,000 objects.
Fix the writer or buy RAM?
Option A: a bigger NameNode server with 512 GB RAM for ₹35 lakh. Option B: 3 developer-weeks (₹1.5 lakh each) to batch writes, which removes 90% of new small files. Which is cheaper, and which keeps working next year?
₹35 lakh vs 3 × ₹1.5 lakh
A: Rs 35 lakh, B: Rs 4.5 lakh
Show solution and explanation
a, b = 35, 3 * 1.5
print(f"A: Rs {a} lakh, B: Rs {b} lakh")How it works: B costs ₹4.5 lakh vs ₹35 lakh (illustrative) and stops the growth; A only postpones the problem.
Compaction planner
Given partition sizes (MB) and file counts, plan how many output files each partition needs at a 256 MB target, and how many objects are saved.
3 partitions
dt=2026-10-19: 2880 -> 22 files dt=2026-10-20: 2880 -> 24 files dt=2026-10-21: 1500 -> 2 files objects saved: 14424
Show solution and explanation
import math
parts = {"dt=2026-10-19": (5400, 2880), "dt=2026-10-20": (6100, 2880), "dt=2026-10-21": (300, 1500)}
saved = 0
for p, (mb, files) in parts.items():
out = max(1, math.ceil(mb / 256))
saved += (files - out) * 2
print(f"{p}: {files} -> {out} files")
print("objects saved:", saved)How it works: 22 + 24 + 2 output files; about 14,424 objects saved. Real compaction jobs also respect sort order and table formats.
Real-world scenario questions (asked in company interviews)
The small files problem is one of the most asked Hadoop interview topics, from freshers to architects.
“Why is HDFS bad at small files?”
Almost guaranteed in a Hadoop interview.
The interviewer is checking: NameNode memory and task overhead.
Show a strong answer
- Every file and block is an object in NameNode RAM (~150 bytes each); millions of tiny files exhaust the heap.
- Each file means separate NameNode calls and DataNode connections, and one map task per file.
- Fixes: bigger files at source, compaction, HAR or SequenceFiles, CombineFileInputFormat.
A Spark Streaming job writes 50,000 files an hour
Analysts' queries on the output table get slower each week; the NameNode heap keeps growing.
The interviewer is checking: write-side and cleanup-side fixes.
Show a strong answer
- Reduce output partitions per micro-batch (coalesce) and increase the trigger interval if freshness allows.
- Use a table format (Delta/Iceberg/Hudi) and schedule compaction (OPTIMIZE / rewrite) for closed partitions.
- Monitor average file size per partition and alert when it drops.
Find the folders causing the most NameNode load
The cluster has 40 crore objects; you must find who owns them without hammering the NameNode.
The interviewer is checking: offline analysis.
Show a strong answer
- Fetch the latest fsimage (
hdfs dfsadmin -fetchImage) and convert it with the Offline Image Viewer to a delimited file. - Aggregate by folder: file count, total size, average size; rank by file count with small average size.
- Work with owners: compaction or HAR for old data, writer fixes for new data, name quotas on landing folders.
“HAR or SequenceFile?”
A follow-up after you list solutions.
The interviewer is checking: when each fits.
Show a strong answer
- HAR keeps the original paths readable through har:// with no code change for readers; good for archives. It is immutable and reading has index overhead.
- SequenceFile packs files as key-value records (name → bytes); efficient and splittable for MapReduce, but readers must use the container.
- For tabular data, compaction into Parquet is usually better than both.