Hive architecture and HiveQL
This lecture puts a SQL layer over Hadoop with Hive. It covers architecture, data types, file formats, and HiveQL for defining, loading, and querying tables. After this page you can trace a query through the Driver and Metastore. You can also write DDL, DML, GROUP BY and JOIN queries, and compute sample query outputs by hand.
Why Hive existsSearch on YouTube
Hadoop and HDFS could store huge datasets. The catch: the way to ask a question of that data was a hand-written MapReduce job in Java. A task as small as "count rows by category" needed a full Mapper class, a Reducer class, a Driver, and job config code.
That put analysis out of reach for analysts who knew SQL but not distributed Java. Companies like Facebook needed a bridge. Hive is that bridge: SQL-literate people query petabyte-scale data in HDFS without writing MapReduce first.
The same question, two ways ("total sales by region"):
SELECT region, SUM(amount) AS total
FROM sales.orders
GROUP BY region;Three lines of HiveQL replace 100+ lines of Java. Anyone who knows SQL can read and change it at once.
Where Hive came fromSearch on YouTube
Facebook built Hive out of need. Its data grew fast. It rose from tens of gigabytes a day in 2006 to about 1 terabyte a day in 2007. Within a few more years it hit roughly 15 terabytes a day. The data sat in Hadoop. The analysts knew SQL, not Java.
| Year | Event |
|---|---|
| 2007 | Development begins inside Facebook, led by Joydeep Sen Sarma and Ashish Thusoo |
| 2008 | Facebook releases Hive to open source |
| 2010 | Hive becomes a top-level Apache project ("Apache Hive") |
| Today | Standard SQL layer for Hadoop warehouses; releases are on the 4.x line |
Hive architectureSearch on YouTube
A query passes through fixed layers. Each layer has one job.
Hive Client (top layer). This is how a user or program connects:
- Thrift Server. Hive is built on Apache Thrift, a cross-language RPC framework. Clients in Python, PHP, or C++ connect, not only Java clients.
- JDBC Driver. Java applications connect through the standard
java.sqlinterface, like any relational database. - ODBC Driver. BI and reporting tools (Tableau, Power BI) connect through the ODBC standard.
Hive Services. These entry points receive the query:
- Hive Web UI. A browser interface for queries without a terminal.
- CLI. The command-line shell. It is the Hive equivalent of the Pig Grunt shell.
- HiveServer2. Listens for remote JDBC, ODBC, and Thrift connections. It serves many users at once. This makes Hive a shared warehouse, not a single-user tool.
Hive Driver. Every query ends up here, whatever client sent it. The Driver manages the full query lifecycle. It receives the HiveQL statement. It parses, compiles, and optimizes it into an execution plan. It talks to the Metastore first, because it must know table schemas, column types, and partition locations before it compiles.
Metastore. The catalog, not the data. It stores table names, column names and types, partition info, and the HDFS paths of each table's files.
Execution engine and HDFS. The compiled plan runs here. In the classic design this box is MapReduce; in a modern deployment it is often Tez or Spark. The role stays the same: the engine that crunches the data. HDFS holds the real files. The engine reads from HDFS and writes back to it.
The slide lists the run as numbered steps:
- Send the query from the CLI, Web UI, or a remote client to the driver.
- Get the plan: the driver opens a session handle and passes the query to the compiler.
- Get metadata: the compiler asks the Metastore for table and column details.
- Send metadata: the Metastore answers the compiler.
- Send plan: the compiler returns the execution plan to the driver.
- Execute plan: the driver sends the plan to the execution engine, which runs the job and touches HDFS files.
- Fetch results: the driver fetches results from the execution engine.
- Send results: the driver sends results to the user interface.
MetastoreSearch on YouTube
The Metastore is a central repository. It stores structure info for every table and Hive partition in the warehouse. That means column names and types used to read and write data, plus the HDFS files where the data lives. It never stores the data itself.
One shared catalog serves many tools. Other engines can read the same table definitions.
Key characteristicsSearch on YouTube
| # | Trait | Meaning |
|---|---|---|
| 1 | SQL-like interface | HiveQL looks like SQL, so SQL users start fast |
| 2 | Built on Hadoop / HDFS | Inherits distributed storage and fault tolerance |
| 3 | Schema-on-read | Structure applies at query time, not load time, so ingestion stays flexible |
| 4 | Extensible with UDFs | Java, Python, and other languages cover what SQL lacks |
| 5 | Pluggable engines | Compiles to MapReduce, Tez, or Spark; Tez is recommended in Hive 4.x |
| 6 | Centralized Metastore | One shared catalog of tables, columns, and partitions |
| 7 | Batch analytics at scale | Built for large scans and aggregations, not row-level OLTP |
| 8 | Open source Apache project | Free, widely adopted, large ecosystem |
Schema-on-read has one sharp edge: LOAD DATA never validates column types. Bad rows surface at query time.
Primitive data typesSearch on YouTube
| Group | Type | Size | Example |
|---|---|---|---|
| Numeric | TINYINT | 1-byte signed integer | 5 |
| Numeric | SMALLINT | 2-byte signed integer | 320 |
| Numeric | INT | 4-byte signed integer | 100000 |
| Numeric | BIGINT | 8-byte signed integer | 100000000000 |
| Numeric | FLOAT / DOUBLE | single / double float | 3.14 |
| Numeric | DECIMAL(p,s) | fixed precision and scale | 1234.56 |
| Date/Time | DATE | calendar date | '2026-08-18' |
| Date/Time | TIMESTAMP | date plus time | '2026-08-18 14:30:00' |
| Date/Time | INTERVAL | time span | INTERVAL '3' DAY |
| String/Misc | STRING | unbounded text | 'hive' |
| String/Misc | VARCHAR(n) | variable length | VARCHAR(20) |
| String/Misc | CHAR(n) | fixed length | CHAR(10) |
| String/Misc | BOOLEAN | true / false | TRUE |
| String/Misc | BINARY | raw bytes | 0x48 69 |
Complex data typesSearch on YouTube
One column can hold nested data. This fits JSON and log sources that are not flat.
| Type | Idea | Example |
|---|---|---|
ARRAY<STRING> | Ordered values of one type, indexed from zero | ['red','blue'] |
MAP<STRING,INT> | Unordered key-value pairs; keys are primitive | {'a':1,'b':2} |
STRUCT<name:STRING,age:INT> | Named fields, each with its own type, like a row in a cell | {'name':'Anu','age':21} |
UNIONTYPE<INT,STRING> | One of several types at a time; rarely used | {0:42} or {1:'x'} |
Access syntax mirrors Pig: tags[0] for an ARRAY, attributes['color'] for a MAP, dimensions.length for a STRUCT with dot notation.
Worked example. One row holds every type. The slide creates this table and inserts one full row.
CREATE TABLE sales.product_catalog (
product_id INT, sku SMALLINT, total_sold BIGINT,
unit_price FLOAT, revenue DOUBLE, margin_pct DECIMAL(5,2),
launch_date DATE, last_updated TIMESTAMP,
product_name STRING, category_code VARCHAR(10),
warehouse_zone CHAR(3), is_active BOOLEAN,
tags ARRAY<STRING>,
attributes MAP<STRING,STRING>,
dimensions STRUCT<length:FLOAT,width:FLOAT,height:FLOAT>)
ROW FORMAT DELIMITED FIELDS TERMINATED BY ','
COLLECTION ITEMS TERMINATED BY '|'
MAP KEYS TERMINATED BY ':'
STORED AS TEXTFILE;INSERT INTO sales.product_catalog VALUES (
501, 12, 3400, 799.99, 2719966.00, 18.50,
'2025-01-15', '2026-08-20 10:15:00',
'Wireless Mouse', 'ELEC', 'A12', true,
array('electronics','accessory'),
map('color','black','brand','TechCo'),
named_struct('length',10.5,'width',6.2,'height',3.1));Query into the nested fields.
SELECT product_name,
tags[0] AS first_tag,
attributes['color'] AS color,
dimensions.length AS length_cm
FROM sales.product_catalog;Output (one row):
Wireless Mouse electronics black 10.5tags[0] picks the first array item (zero-indexed). attributes['color'] looks up the map key. dimensions.length reaches into the struct.
File formatsSearch on YouTube
STORED AS in CREATE TABLE controls the physical layout. The choice changes speed, size, and features such as ACID.
| Format | Layout | Note |
|---|---|---|
TEXTFILE | Plain delimited text, one record per line | Default; readable, no compression, slowest scans |
SEQUENCEFILE | Row-based | Hadoop native binary key-value; splittable, compressible, not columnar |
RCFILE | Columnar (legacy) | Early Hive columnar format, superseded by ORC |
ORC | Columnar, recommended | Hive native; per-column stats, strong compression, base for ACID tables |
PARQUET | Columnar, interoperable | Shared with Spark, Trino, Presto, Iceberg; best cross-engine pick |
AVRO | Row-based, schema evolution | JSON schema travels with the data; evolves cleanly |
Hive-only analytics with repeated filtering: STORED AS ORC. Tables needing UPDATE / DELETE: ORC plus ('transactional'='true'), required for ACID. Tables also read by Spark, Trino, or Presto: STORED AS PARQUET. Schemas that change over time, or streaming ingestion: STORED AS AVRO. Raw landing or one-time staging data: TEXTFILE is fine, then convert to ORC or Parquet before serious querying.
CREATE TABLE orders (order_id INT, customer_id INT, amount DOUBLE)
STORED AS ORC
TBLPROPERTIES ('transactional'='true');Databases in HiveSearch on YouTube
DATABASE and SCHEMA are interchangeable. CREATE SCHEMA and CREATE DATABASE do the same thing.
CREATE DATABASE IF NOT EXISTS sales
COMMENT 'Sales warehouse'
WITH DBPROPERTIES ('owner'='analytics-team');
SHOW DATABASES;
USE sales;
DESCRIBE DATABASE EXTENDED sales;
ALTER DATABASE sales SET DBPROPERTIES
('reviewed'='2026-08');
DROP DATABASE IF EXISTS sales CASCADE;Three rules from the slides:
DROP DATABASEfails on a non-empty database unlessCASCADEis added.CASCADEdrops every table inside too.- A database
LOCATIONchange affects new tables created after the change. It never moves existing data. - Every table belongs to exactly one database.
defaultis a database nameddefault.
Worked example. Build the sales database the way a project starts.
CREATE DATABASE IF NOT EXISTS sales
COMMENT 'Sales analytics warehouse'
WITH DBPROPERTIES ('owner'='cse412-batch2026');SHOW DATABASES;default
salesUSE sales;
DESCRIBE DATABASE EXTENDED sales;sales hdfs://localhost:9000/user/hive/warehouse/sales.db
cse412-student USER {owner=cse412-batch2026}The path is the warehouse directory for the database. The properties map holds the owner label.
ALTER DATABASE sales SET DBPROPERTIES ('reviewed'='2026-08-24');Run DESCRIBE DATABASE EXTENDED sales; again. The map now holds both owner and reviewed.
HiveQL categoriesSearch on YouTube
HiveQL looks like SQL. Hive is a warehouse over files, not a transactional database. That shapes each category:
| Category | Statements | Example |
|---|---|---|
| DDL (definition) | CREATE, ALTER, DROP, TRUNCATE | CREATE TABLE orders (...); |
| DML (manipulation) | LOAD, INSERT, UPDATE, DELETE | INSERT INTO TABLE orders ...; |
| DQL (queries) | SELECT, JOIN, GROUP BY, sorting | SELECT * FROM orders; |
| Views | plain and materialized views | CREATE VIEW big_orders AS ...; |
| What replaced indexes | statistics and design tools | ANALYZE TABLE ... COMPUTE STATISTICS; |
| Design | partitioning, bucketing, format choice | PARTITIONED BY (order_date STRING); |
Creating and changing tablesSearch on YouTube
CREATE TABLE IF NOT EXISTS sales.orders (
order_id INT, customer_id INT, amount DOUBLE, order_date DATE
)
ROW FORMAT DELIMITED FIELDS TERMINATED BY ','
STORED AS ORC;
ALTER TABLE sales.orders ADD COLUMNS (region STRING);
ALTER TABLE sales.orders RENAME TO sales.customer_orders;
TRUNCATE TABLE sales.customer_orders;Managed (also called internal) table. Hive owns the data lifecycle. DROP TABLE deletes both the schema and the files.
External table. Created with EXTERNAL and a LOCATION. DROP TABLE removes the metadata. The data stays on disk.
TRUNCATE TABLE. Removes all rows, keeps the definition. Works on managed tables.
Worked example. Load the sample orders into a managed table. Then show the external-table difference.
Sample files used through the rest of this page:
customers.csv (customer_id, name, since):
1,Rajiv,2021
2,Omer,2022
3,Rajesh,2020
4,Divya,2023orders.csv (order_id, customer_id, amount, order_date):
101,1,450.00,2026-08-10
102,2,0.00,2026-08-10
103,1,220.50,2026-08-11
104,3,180.00,2026-08-11
105,4,999.99,2026-08-12Order 102 is cancelled (amount = 0). It stays in the file so query examples have something to filter.
CREATE TABLE IF NOT EXISTS sales.orders (
order_id INT, customer_id INT, amount DOUBLE, order_date STRING)
ROW FORMAT DELIMITED FIELDS TERMINATED BY ','
STORED AS TEXTFILE;
LOAD DATA LOCAL INPATH '/home/student/orders.csv'
INTO TABLE sales.orders;Loading data to table sales.orders
Table sales.orders stats: [numFiles=1, numRows=0, totalSize=157]SELECT * FROM sales.orders;101 1 450.0 2026-08-10
102 2 0.0 2026-08-10
103 1 220.5 2026-08-11
104 3 180.0 2026-08-11
105 4 999.99 2026-08-12Add a column the file lacks. Existing rows return NULL for it.
ALTER TABLE sales.orders ADD COLUMNS (region STRING);
SELECT order_id, region FROM sales.orders LIMIT 2;101 NULL
102 NULLExternal table over a file Hive must not own.
CREATE EXTERNAL TABLE sales.orders_ext (
order_id INT, customer_id INT, amount DOUBLE, order_date STRING)
ROW FORMAT DELIMITED FIELDS TERMINATED BY ','
LOCATION '/user/student/external/orders';
DROP TABLE sales.orders_ext;The metadata is gone. The file at /user/student/external/orders still sits on HDFS untouched. Had sales.orders (managed) been dropped instead, both its definition and its loaded file would vanish.
Partitioning and bucketingSearch on YouTube
PARTITIONED BY splits a table into separate directories by column value. Queries that filter on the Hive partition column skip whole directories. Use columns with low-to-moderate cardinality that queries filter on often (date, region, country). Too many tiny partitions strain the Metastore.
CLUSTERED BY hashes rows into a fixed number of files by column value, within a Hive partition or across the table. Use it for high-cardinality join or sampling keys. It enables bucket map joins and TABLESAMPLE.
This lecture gives the short form. Partitioning, bucketing and joins gives the full treatment with the bucket-number rule and the join types.
Worked example. Partition the orders by day, then read one day.
CREATE TABLE sales.orders_partitioned (
order_id INT, customer_id INT, amount DOUBLE)
PARTITIONED BY (order_date STRING)
STORED AS ORC;
INSERT OVERWRITE TABLE sales.orders_partitioned
PARTITION (order_date='2026-08-10')
SELECT order_id, customer_id, amount FROM sales.orders
WHERE order_date='2026-08-10';Repeat for '2026-08-11' and '2026-08-12' the same way.
SHOW PARTITIONS sales.orders_partitioned;order_date=2026-08-10
order_date=2026-08-11
order_date=2026-08-12SELECT * FROM sales.orders_partitioned
WHERE order_date = '2026-08-11';103 1 220.5 2026-08-11
104 3 180.0 2026-08-11This query reads the order_date=2026-08-11 directory. The 2026-08-10 and 2026-08-12 directories are never touched. That skipping is partition pruning.
Bucket the same data by customer_id into 4 files.
CREATE TABLE sales.orders_bucketed (
order_id INT, customer_id INT, amount DOUBLE, order_date STRING)
CLUSTERED BY (customer_id) INTO 4 BUCKETS
STORED AS ORC;
INSERT OVERWRITE TABLE sales.orders_bucketed
SELECT order_id, customer_id, amount, order_date FROM sales.orders;For INT keys the hash is the value itself, so bucket :
Rows with the same customer_id always land in the same file. That shared placement is what makes bucket joins fast.
Loading and inserting dataSearch on YouTube
LOAD DATA moves or copies files as-is. No MapReduce or Tez job runs. INSERT ... SELECT always runs a query, so it can filter, join, or transform on the way in.
LOAD DATA LOCAL INPATH '/home/user/orders.csv'
INTO TABLE sales.orders;
INSERT INTO TABLE sales.orders
SELECT * FROM sales.orders_staging WHERE amount > 0;
INSERT OVERWRITE TABLE sales.orders PARTITION (order_date='2026-08-18')
SELECT order_id, customer_id, amount FROM sales.orders_staging;
EXPORT TABLE sales.orders TO 'hdfs:///backup/orders';
IMPORT TABLE sales.orders FROM 'hdfs:///backup/orders';INSERT INTO appends rows. INSERT OVERWRITE replaces a table (or Hive partition) fully. EXPORT / IMPORT move a table, schema plus data, between clusters.
LOCAL means the path is on the client machine (/home/user/orders.csv). Without LOCAL, the path is already on HDFS. LOAD DATA without OVERWRITE appends; with OVERWRITE it replaces.
ACID tables with UPDATE and DELETESearch on YouTube
UPDATE and DELETE work on ACID (transactional) tables. An ordinary table does not support them; the statement fails. The ACID recipe: STORED AS ORC plus TBLPROPERTIES ('transactional'='true'), with CLUSTERED BY into buckets on older Hive versions.
CREATE TABLE sales.accounts (id INT, balance DOUBLE)
CLUSTERED BY (id) INTO 8 BUCKETS
STORED AS ORC
TBLPROPERTIES ('transactional'='true');
UPDATE sales.accounts SET balance = balance - 100 WHERE id = 42;
DELETE FROM sales.accounts WHERE balance <= 0;Worked example. Insert an order, then move money on an ACID table.
INSERT INTO TABLE sales.orders (order_id, customer_id, amount, order_date)
VALUES (106, 2, 375.25, '2026-08-13');
SELECT * FROM sales.orders WHERE order_id = 106;106 2 375.25 2026-08-13 NULLThe trailing NULL is the region column added earlier. Watch out: the slide omits the column list. The list is required here because the table now has five columns and the insert supplies four.
CREATE TABLE sales.accounts (
customer_id INT, balance DOUBLE)
CLUSTERED BY (customer_id) INTO 4 BUCKETS
STORED AS ORC
TBLPROPERTIES ('transactional'='true');
INSERT INTO sales.accounts VALUES
(1,1000.00), (2,500.00), (3,750.00), (4,220.00);
UPDATE sales.accounts SET balance = balance - 100
WHERE customer_id = 1;
SELECT * FROM sales.accounts WHERE customer_id = 1;1 900.0Balance math: .
UPDATE on an ordinary table fails.
UPDATE sales.orders SET amount = 0 WHERE order_id = 106;FAILED: SemanticException [Error 10294]: Attempt to do update or delete
using transaction manager that does not support these operations.sales.orders was never created with transactional=true. The failure is the rule, shown as a real error.
QueriesSearch on YouTube
Standard shape: WHERE filters rows, GROUP BY aggregates, HAVING filters the aggregates, ORDER BY sorts, LIMIT caps output.
SELECT customer_id, SUM(amount) AS total
FROM sales.orders
WHERE order_date >= '2026-01-01'
GROUP BY customer_id
HAVING SUM(amount) > 1000
ORDER BY total DESC
LIMIT 10;Four ways to order rows:
| Clause | Scope | Example |
|---|---|---|
ORDER BY | One global order; slow on huge results | ORDER BY total DESC; |
SORT BY | Sorted within each reduce task, not global | SORT BY amount; |
DISTRIBUTE BY | Sends matching rows to the same reduce task, unsorted | DISTRIBUTE BY customer_id; |
CLUSTER BY | Shorthand for DISTRIBUTE BY x SORT BY x | CLUSTER BY customer_id; |
Join types: INNER, LEFT / RIGHT / FULL OUTER, LEFT SEMI (an EXISTS-style join), and CROSS.
O-S-D-C: One Sorts, Distribute Collects
ORDER BY gives one global order. SORT BY sorts within each reduce task. DISTRIBUTE BY collects matching rows onto one reduce task. CLUSTER BY combines both: distribute plus sort.
Worked example. Total spend per customer, biggest first (orders 101-106 on file).
SELECT customer_id, SUM(amount) AS total_spent
FROM sales.orders
WHERE amount > 0
GROUP BY customer_id
ORDER BY total_spent DESC;Step 1, filter (WHERE amount > 0): order 102 drops out (cancelled, amount 0). Five rows stay: 101, 103, 104, 105, 106.
Step 2, group and sum:
Step 3, sort descending:
4 999.99
1 670.5
2 375.25
3 180.0Worked example. Bring in names with a JOIN, then filter with HAVING.
SELECT o.order_id, c.name, o.amount
FROM sales.orders o
JOIN sales.customers c ON o.customer_id = c.customer_id
WHERE o.amount > 0
ORDER BY o.order_id;Match each order to its customer row; drop order 102 (amount = 0):
101 Rajiv 450.0
103 Rajiv 220.5
104 Rajesh 180.0
105 Divya 999.99
106 Omer 375.25HAVING on six rows. Orders 101-106 are on file. Per-customer totals become:
SELECT customer_id, SUM(amount) AS total
FROM sales.orders
GROUP BY customer_id
HAVING SUM(amount) > 500
ORDER BY total DESC
LIMIT 2;4 999.99
1 670.5WHERE would fail here: it cannot see SUM(amount). HAVING filters after aggregation. LIMIT 2 keeps the top two.
Cross-join size. With 4 customers and the first 5 orders, CROSS JOIN (every pair) returns rows.
Views and materialized viewsSearch on YouTube
A plain view is a saved query, not a copy of data. Each query re-runs the SELECT on current data. Plain views are read-only. They simplify complex queries and hide columns from some users.
CREATE VIEW sales.big_orders AS
SELECT order_id, customer_id, amount
FROM sales.orders
WHERE amount > 1000;
DROP VIEW IF EXISTS sales.big_orders;A materialized view stores its result physically (Hive 3.0 and later). The optimizer can rewrite a matching base-table query to use it: same answer, far less work. Stale data is the cost: inserts into the base table stay invisible until REBUILD.
CREATE MATERIALIZED VIEW sales.daily_totals AS
SELECT order_date, SUM(amount) AS total
FROM sales.orders GROUP BY order_date;
ALTER MATERIALIZED VIEW sales.daily_totals
REBUILD;Worked example. Save the big-orders filter, then watch a materialized view go stale.
CREATE VIEW sales.big_orders AS
SELECT order_id, customer_id, amount
FROM sales.orders
WHERE amount > 400;
SELECT * FROM sales.big_orders;Orders on file are 101-106. Filter amount > 400:
101 1 450.0
105 4 999.99Materialized daily totals.
CREATE MATERIALIZED VIEW sales.daily_totals AS
SELECT order_date, SUM(amount) AS total
FROM sales.orders
GROUP BY order_date;
SELECT * FROM sales.daily_totals;Day sums over orders 101-106:
2026-08-10 450.0
2026-08-11 400.5
2026-08-12 999.99
2026-08-13 375.25Insert a row, then read again before and after REBUILD.
INSERT INTO TABLE sales.orders (order_id, customer_id, amount, order_date)
VALUES (107, 3, 60.00, '2026-08-13');
SELECT * FROM sales.daily_totals WHERE order_date = '2026-08-13';2026-08-13 375.25Still the old total. The new 60.00 order is invisible.
ALTER MATERIALIZED VIEW sales.daily_totals REBUILD;
SELECT * FROM sales.daily_totals WHERE order_date = '2026-08-13';2026-08-13 435.25Rebuild math: . The plain view sales.big_orders needs no rebuild: it would show order 107 at once if 107 passed its filter (it does not: ).
What replaced indexesSearch on YouTube
Hive had CREATE INDEX before 3.0. It was removed in Hive 3.0 (tracked as HIVE-18448) for limited benefit versus maintenance cost. Current Hive has no CREATE INDEX at all. Four tools do the job now:
| Replacement | How it helps | Example |
|---|---|---|
| Materialized views | Pre-compute expensive results, with automatic rewrite | CREATE MATERIALIZED VIEW v AS SELECT ...; |
| Columnar formats | Per-column min/max stats skip blocks that cannot match | STORED AS ORC; |
| Partitioning and bucketing | Prune directories or files before reading | PARTITIONED BY (order_date STRING); |
| Statistics | ANALYZE TABLE feeds the optimizer row counts and value ranges | ANALYZE TABLE orders COMPUTE STATISTICS; |
ANALYZE TABLE orders COMPUTE STATISTICS;Schema design principlesSearch on YouTube
- Schema-on-read, not schema-on-write. Hive applies structure at query time.
LOAD DATAnever validates column types. - Pick Hive partition columns with care. Low-to-moderate cardinality, filtered often.
PARTITIONED BY (order_date STRING), notcustomer_id. - Use bucketing for high-cardinality keys. Enables bucket map joins that partitioning cannot.
CLUSTERED BY (customer_id) INTO 16 BUCKETS. - Default to ORC or Parquet. Keep
TEXTFILEfor raw landing data. Convert withSTORED AS ORC;before serious querying. - Avoid the small-files problem. Many tiny files slow the NameNode and planning.
INSERT OVERWRITEcompacts after streaming ingestion. - Keep statistics current. Feeds the optimizer real numbers, not guesses.
ANALYZE TABLE orders COMPUTE STATISTICS FOR COLUMNS;
Do not partition by a high-cardinality column such as customer_id. Each value becomes a directory, and thousands of tiny partitions strain the Metastore. Partition by date or region; bucket by the high-cardinality key instead.
Quick self-testSearch on YouTube
1. Why did Facebook build Hive, and what does its main query show?
Hadoop needed hand-written MapReduce in Java for every question. Most analysts knew SQL, not Java. Hive lets them query HDFS data with SQL-like statements. The slide demo replaces 100+ lines of Java with a three-line GROUP BY query.
2. Name the four layers a query passes through, in order. What sits underneath them?
Four layers: Client (Thrift / JDBC / ODBC), Services (Web UI, CLI, HiveServer2), Driver, Metastore. The execution engine (MapReduce, Tez, or Spark) and HDFS sit underneath. The Driver checks the Metastore before compiling the plan.
3. What does the Metastore store, and what does it never store?
It stores metadata: table names, column names and types, Hive partition info, and HDFS file locations. It never stores the data itself. The data lives in HDFS files.
4. Query the sample orders: total spend per customer with amount greater than 0, biggest first. Give all four rows.
Filter drops order 102. Sums: customer ; customer ; customer ; customer . Descending: 4 999.99, 1 670.5, 2 375.25, 3 180.0.
5. A table is CLUSTERED BY (customer_id) INTO 4 BUCKETS. Which bucket holds customer_id 3 and 4? (INT hash equals the value.)
Bucket value . Customer : . Customer : . Rows with id 1 always land in bucket 1 together.
6. Differentiate a managed table from an external table on DROP.
DROP TABLE on a managed (internal) table deletes the schema and the files. On an external table it deletes the metadata; the files at LOCATION stay on disk.
7. Daily totals show 2026-08-13 as 375.25. Then order 107 (60.00, same day) is inserted. What does the materialized view show before and after REBUILD?
Before: still 375.25 (stale). After REBUILD: . A plain view would show the new row at once, with no rebuild step.
8. Differentiate ORDER BY, SORT BY, DISTRIBUTE BY, and CLUSTER BY.
ORDER BY gives one global order. SORT BY sorts within each reduce task. DISTRIBUTE BY sends matching rows to one reduce task without sorting. CLUSTER BY is both: distribute plus sort on the same key.
9. Why does UPDATE fail on sales.orders but work on sales.accounts?
UPDATE needs an ACID table: STORED AS ORC with transactional=true. sales.accounts has both, so the update runs. sales.orders lacks them, so Hive raises error 10294.
10. Name two replacements for Hive indexes (removed in 3.0) and the JIRA id.
Any two: materialized views, ORC/Parquet column stats, partitioning and bucketing, ANALYZE TABLE ... COMPUTE STATISTICS. Removal tracked as HIVE-18448.
- Hive gives SQL-literate users access to HDFS data without hand-written MapReduce. Facebook built it (2007), open-sourced it (2008); Apache top-level since 2010, now 4.x.
- Query path: Client (Thrift/JDBC/ODBC) to Services (Web UI, CLI, HiveServer2) to Driver; Driver checks the Metastore, compiles a plan; the engine (MapReduce/Tez/Spark) reads HDFS.
- Metastore holds metadata (schemas, partitions, file paths), never data.
- Traits: SQL-like, Hadoop-based, schema-on-read, UDF-extensible, pluggable engines (Tez recommended in 4.x), batch analytics, not OLTP.
- Primitive types:
TINYINTtoBIGINT,FLOAT/DOUBLE,DECIMAL(p,s),DATE,TIMESTAMP,INTERVAL,STRING,VARCHAR(n),CHAR(n),BOOLEAN,BINARY. - Complex types:
ARRAY(tags[0]),MAP(attributes['color']),STRUCT(dimensions.length), rarely usedUNIONTYPE. - Formats: ORC for Hive-only and ACID tables, Parquet for cross-engine reads, Avro for evolving schemas,
TEXTFILEfor raw landing data. DATABASE=SCHEMA;DROP DATABASEneedsCASCADEwhen non-empty;LOCATIONchanges affect new tables.- Managed (internal) tables:
DROPdeletes schema and files. External tables:DROPdeletes metadata; files stay.TRUNCATEkeeps schema, clears rows, managed tables. - Hive partition columns: low cardinality, often filtered. Bucket keys: high cardinality, for joins and sampling.
LOAD DATAcopies files with no job.INSERT ... SELECTruns a query.INSERT OVERWRITEreplaces.EXPORT/IMPORTmove schema plus data.UPDATE/DELETEneed ACID tables:STORED AS ORCwithtransactional=true; ordinary tables raise error 10294.- Query shape:
WHERE,GROUP BY,HAVING,ORDER BY,LIMIT. Four orderings:ORDER BYglobal,SORT BYper reduce task,DISTRIBUTE BYcollects,CLUSTER BYis both. Joins: inner, outer, left semi, cross. - Plain views rerun each time and stay fresh. Materialized views store results, read fast, go stale until
REBUILD; the optimizer can auto-rewrite queries to use them. - Indexes were removed in Hive 3.0 (HIVE-18448). Replacements: materialized views, columnar stats, partitioning/bucketing,
ANALYZE TABLE ... COMPUTE STATISTICS. - Design rules: schema-on-read, date/region partitions, bucket high-cardinality keys, ORC/Parquet default, compact small files, current statistics.
Hadoop Tutorial for Beginners
Architecture of Hive, Components of Hive: Hive shell, HiveQL
What is Hive and HiveQL?