Mastering Postgres
Introduction
Introduction to the course
Overview of course structure
Postgres vs. everyone
The psql CLI
Data Types
Introduction to schema
Integers
Numeric
Floating point
Storing money
NaNs and infinity
Casting types
Characters types
Check constraints
Domain types
Charsets and collations
Binary data
UUIDs
Boolean
Enums
Timestamps
Timezones
Dates and times
Advanced Data Types
Intervals
Serial type
Sequences
Identity
Network and mac addresses
JSON
Arrays
Generated columns
Text search types
Bit string
Ranges
Composite types
Nulls
Unique constraints
Exclusion constraints
Foreign key constraints
Indexing
Introduction to indexes
Heaps and CTIDs
B-Tree overview
Primary keys vs. secondary indexes
Primary key types
Where to add indexes
Index selectivity
Composite indexes
Composite range
Combining multiple indexes
Covering indexes
Partial indexes
Index ordering
Ordering nulls in indexes
Advanced Indexing
Functional indexes
Duplicate indexes
Hash indexes
Naming indexes
Understanding Query Plans
Introduction to explain
Explain structure
Scan nodes
Costs and rows
Explain analyze
Generating Results
Introduction to queries
Cross joins
Inner joins
Outer joins
Subqueries
Lateral joins
ROWS FROM
Filling gaps in sequences
Subquery elimination
Combining queries
Set generating functions
Indexing joins
Advanced SQL
Introduction to advanced SQL
Grouping
Grouping sets, rollups, cubes
Window functions
CTEs
CTEs with window functions
Recursive CTE
Hierarchical recursive CTE
Handling nulls
Row value syntax
Views
Materialized views
Removing duplicate rows
Upsert
Returning keyword
COALESCE + generated column
Full Text Search
Introduction to full text search
Searching with LIKE
Vectors, queries, and ranks
Websearch
Ranking
Indexing full text search
Highlighting
Advanced JSON
Intro to JSON
JSON vs JSONB
Validating JSON
Creating JSON objects + arrays
JSON extraction
JSON containment
JSON existence
JSON recordset
Updating JSON
Indexing JSON parts
GIN index
Vectors (pgvector)
Intro to pgvector
Vector embedding columns
Find related articles
Upsert vector embedding
Semantic search
Other operators
Vector indexes
Outro
Thank you
Bonus interviews
Heroku's glory days & Postgres vs the world (with Craig Kerstiens)
Creating a Postgres platform with Monica & Tudor from Xata.io
Bootstrapping an email service provider (with Jesse Hanley)
Locked video

Please purchase the course to watch this video.

Video thumbnail
Advanced Data Types
Network and mac addresses

Full Course

$
349
$399
USD, one-time fee
Mastering Postgres is single-handedly the most thorough and informative database course I’ve seen. I’ve gone from someone who barely knew the basics of Postgres and how it works to being comfortable with the advanced topics of Postgres.
Ryan Hendrickson
Ryan Hendrickson

PostgreSQL database platform

Shorten dev cycles with branching and zero-downtime schema migrations.

Test Data

I've made my test data available for you to use and follow along.

Download
or
Use on Xata

Summary

Learn how storing network addresses and MAC addresses in a database using specialized data types like `INET`, `CIDR`, and `MAC` can improve efficiency and save storage space compared to using plain text. These data types simplify operations and speed up queries, such as searching for IP ranges or understanding address components. The video also touches on how MAC addresses can be stored in more compact forms, recommending these types when they suit your needs.

Video Transcript

Storing network addresses and Mac addresses in the database is not terribly common, but honestly, it's not that uncommon. If you ever need to store stuff like this, this is going to be much more efficient the way that we're about to look at. It's gonna be much more efficient than just using a text representation, not only in storage space, but also inefficiency when querying. We can actually just search for ranges or we can pull off parts of some of these addresses without having to parse the text.

So we're gonna look at CIDR, we're gonna look at INET and we're gonna look at MAC addresses. Let's take a look.

We're gonna start with the INET examples. We're just gonna say that IP address is an INET, and I'm gonna copy all of this 'cause you certainly don't wanna watch me type all of this in. We have several different styles of address that we can put in there. Some are just the host address, some have the subnet mask, some are IPv6. We can run that. If we were to just read back, select * from inet_examples; and take a look at that, totally works just fine.

One thing I do wanna show you is, if we take a look at this as text and we were to say, let's call this pg_column_size, and we take a look at that, it is 40 bytes as text. However, if we were to cast this back to an INET, you'll see it is much smaller at 22 bytes. There is an actual underlying data structure here that is not text and it is much more compact and we can do operations on it, not only on IPv6, but IPv4, IPv4 subnet.

We can do operations on all of these things, which is part of the reason if you think all the way back to the beginning to pick the data type that most accurately represents the reality. In reality, this is not a string. This is not a string, this is an IP address and there is a data structure that can represent that accurately. Let's look at some of the functions that we can run on these things. Now my networking skills are a little bit rusty, so we're not gonna go into great depth about all of these functions. But if we look, we have host, mask length, network, and abbreviation, and we see that that works just perfectly. We have the host only, which has dropped the mask, and then we have the mask length, we have the network only and where possible and abbreviated IP. This is pretty cool. This also allows us to do quicker lookups when we talk about figuring out if an IP is in a certain range.

When it comes to ranges, we're probably gonna want to use the CIDR type, C-I-D-R. We're probably gonna want to use that type. Let's take a look at that now. The type is just CIDR, and we'll go ahead and create this table. And then I'm just gonna drop these in here. You have a network IPv4, a larger IPv4, and an IPv6 network. When we get down to the querying section of this course, we'll look at a few things that we can do with network addresses, but right now, I just wanna show you, they are all retained. If we do cidr_examples, we've got all of our data in there. And again, these are stored in a non-text representation, which makes them more compact and easier to operate on.

Finally, let's look at Mac addresses. This is probably only useful to like four of you, so we're just gonna kinda breeze through it, but it is kinda cool. With Mac addresses, you have two options. If we have that, you can cast it to a Mac address, which is the 6-byte version, or you can cast it to the 8-byte version. If we did pg_column_size here and took a look at that, that is the 8-byte version. That is the 6-byte version.

Some Mac addresses require the 8-byte version, but you can cast the 6 to an 8, and it should be just fine. The 8 can store the 6, or the 8 if you have an 8-byte version, you need to use the 8. Now let's see what this looks like. Text, much, much larger, much larger as text 21 versus, in this case, six or eight. So again, that's gonna be way more compact. These are kinda fun types to talk about. They're incredibly useful if you actually need to use them. But regardless is kind of fun.

I love this esoteric stuff. If you have a use case for this, please reach for these types. Otherwise, I hope you enjoyed that.