10. Perl Storable – Complete Beginner Tutorial

1. What Problem Are We Solving?

In Perl, hashes and arrays live in memory (RAM). When your script finishes, they disappear. But sometimes you want your data to survive:

  • Save configuration
  • Store user data
  • Create a small database
  • Cache results
The Storable module solves this.Storable allows you to freeze a Perl data structure into a file and later thaw it back into memory exactly as it was.

2. Basic Example - Store One Structure

We begin with a simple nested hash: our custom structure from Section 9.
use strict;
use warnings;
use Storable;

my %CS = (
    'Name' => {
        'first_name' => 'Reinier',
        'last_name' => 'Maliepaard',
    },
    'Website' => 'www.reiniermaliepaard.nl',
    'Programming' => {
        'language' => ['Perl', 'newLisp', 'Windows Commandline'],
    },
);

store \%CS, 'data.db';
print "Data stored in data.db\n";

my $ref = retrieve('data.db');
print "Data retrieved from data.db\n";

print "Name: $ref->{Name}->{first_name} $ref->{Name}->{last_name}\n";
print "Website: $ref->{Website}\n\n";

print "Programming languages:\n";
print " - $_\n" for @{ $ref->{Programming}->{language} };
Notice the arrows: $ref->{Name}->{first_name}. Each arrow moves one level deeper into the structure.

3. Expanding to Multiple Users

use strict;
use warnings;
use Storable;

my %CS = (
    'Reinier Maliepaard' => {
        'Name' => { first_name => 'Reinier', last_name => 'Maliepaard' },
        'Website' => 'www.reiniermaliepaard.example',
        'Programming' => { language => ['Perl','newLisp','Windows Commandline'] },
    },

    'Jeppe Van Dijk' => {
        'Name' => { first_name => 'Jeppe', last_name => 'Van Dijk' },
        'Website' => 'www.jeppevandijk.example',
        'Programming' => { language => ['Python','Bash'] },
    },

    'Cato Mayer' => {
        'Name' => { first_name => 'Cato', last_name => 'Mayer' },
        'Website' => 'www.catomayer.example',
        'Programming' => { language => ['Java','C++'] },
    },
);

store \%CS, 'data.db';
print "Mini database stored in data.db";

This is a hash of hashes. The top-level keys are full names. Each name points to a complete user record.

4. Interactive Mini Database Tool

Now we retrieve the database and allow user interaction.
use strict;
use warnings;
use Storable;

my $ref = retrieve('data.db');

print "Mini User Database\n";
print "-----------------\n";
print "1. Retrieve user by name\n";
print "2. Search users by programming language\n";
print "3. List all users\n";
print "Choose option (1, 2, or 3): ";
chomp(my $option = <STDIN>);

if ($option eq '1') {
    # Retrieve by name (case-insensitive)
    print "Enter full user name: ";
    chomp(my $user_input = <STDIN>);

    # Find the actual key ignoring case
    my ($user_name) = grep { lc($_) eq lc($user_input) } keys %$ref;

    if ($user_name) {
        my $info = $ref->{$user_name};
        print "\nUser: $user_name\n";
        print "  Website: $info->{Website}\n";
        print "  First Name: $info->{Name}->{first_name}\n";
        print "  Last Name:  $info->{Name}->{last_name}\n";
        print "  Programming languages:\n";
        print " - $_\n" for @{ $info->{Programming}->{language} };
    } else {
        print "User '$user_input' not found.\n";
    }
} elsif ($option eq '2') {
    # Search by programming language
    print "Enter programming language to search: ";
    chomp(my $search_lang = <STDIN>);
    
    my $found = 0;
    print "\nUsers who know '$search_lang':\n\n";

    for my $user (sort keys %$ref) {
        my $languages = $ref->{$user}->{Programming}->{language};
        if (grep { lc($_) eq lc($search_lang) } @$languages) {
            $found = 1;
            print "User: $user\n";
            print "  Website: $ref->{$user}->{Website}\n";
            print "  Languages: " . join(", ", @$languages) . "\n\n";
        }
    }
    print "No users found with '$search_lang'.\n" unless $found;

} elsif ($option eq '3') {
    # List all users
    print "\nAll Users in the Database:\n\n";
    for my $user (sort keys %$ref) {
        my $info = $ref->{$user};
        print "User: $user\n";
        print "  Website: $info->{Website}\n";
        print "  Programming Languages: " . join(", ", @{ $info->{Programming}->{language} }) . "\n";
        print "\n";
    }
}
else {
    print "\nInvalid option. Please choose 1, 2, or 3.\n";
}

5. Understanding What You Just Built

The file data.db is not text. It is binary.

Storable converts your hash into a serialized binary format. When you call retrieve(), Perl reconstructs the exact same structure in memory.

  • Memory: hash
  • store(): binary file
  • retrieve(): hash again
You are storing the Perl data structure itself, not a text representation of it.

6. Performance – Is It Fast?

For small and medium datasets, Storable is very fast.

Benchmark (Loading ~1 MB dataset)

Machine Type Storage Storable SQLite Text Parsing
Modern Desktop (16 GB RAM) SSD 0.003 – 0.008 sec 0.005 – 0.012 sec 0.020 – 0.050 sec
Older Machine (4 GB RAM) SSD 0.01 – 0.03 sec 0.02 – 0.05 sec 0.08 – 0.15 sec
Older Machine (4 GB RAM) HDD 0.03 – 0.10 sec 0.05 – 0.15 sec 0.15 – 0.40 sec

What this means:

  • Storable is extremely fast for loading full structures.
  • SSD makes a noticeable difference.
  • Text formats require parsing, which takes longer.

7. When Should You Use Storable?

Use Storable when you want to save a Perl array or hash to a file and load it back later. It's a good choice for small programs that don’t need a full database — for example, saving program settings or simple stored data. However, it’s not suitable for very large amounts of data, programs used by many people at the same time, or situations where the data must be shared with other programming languages.

Final Summary

You built:

  • A persistent Perl structure
  • A mini file-based database
  • A searchable user system

All using one module: Storable.