Profile Picture Storage

Store user profile pictures with thumbnail variants for efficient display at different sizes

All recipes· image-management· 10 minutesbeginner

Profile Picture Storage

Objective

Create a system for storing user profile pictures with multiple size variants. This pattern supports efficient display at different sizes without runtime resizing.

Step 1: Create Users Table with Profile Picture

Create a users table with profile picture columns.

CREATE TABLE users (
    user_id INTEGER PRIMARY KEY,
    username VARCHAR(50) NOT NULL UNIQUE,
    email VARCHAR(255) NOT NULL UNIQUE,
    display_name VARCHAR(100),
    profile_picture IMAGE(JPEG),
    profile_picture_small IMAGE(JPEG),
    profile_picture_thumb IMAGE(JPEG),
    avatar_updated_at TIMESTAMP,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

Step 2: Create Dedicated Profile Pictures Table

For more flexibility, create a separate profile pictures table.

CREATE TABLE profile_pictures (
    id INTEGER PRIMARY KEY,
    user_id INTEGER NOT NULL UNIQUE,
    original IMAGE(JPEG),
    large IMAGE(JPEG),
    medium IMAGE(JPEG),
    small IMAGE(JPEG),
    thumbnail IMAGE(JPEG),
    original_width INTEGER,
    original_height INTEGER,
    file_size BIGINT,
    uploaded_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    FOREIGN KEY (user_id) REFERENCES users(user_id)
);

Step 3: Insert Sample Users

Add sample users to the system.

INSERT INTO users (user_id, username, email, display_name) VALUES
    (1, 'alice_j', 'alice@example.com', 'Alice Johnson'),
    (2, 'bob_smith', 'bob@example.com', 'Bob Smith'),
    (3, 'carol_w', 'carol@example.com', 'Carol Williams'),
    (4, 'david_b', 'david@example.com', 'David Brown'),
    (5, 'eve_davis', 'eve@example.com', 'Eve Davis');

Step 4: Insert Profile Picture Records

Add profile picture metadata for users.

INSERT INTO profile_pictures (id, user_id, original_width, original_height, file_size, uploaded_at) VALUES
    (1, 1, 1024, 1024, 256000, CURRENT_TIMESTAMP),
    (2, 2, 800, 800, 180000, CURRENT_TIMESTAMP),
    (3, 3, 1200, 1200, 320000, CURRENT_TIMESTAMP);

Step 5: Update User Avatar Timestamps

Track when profile pictures were updated.

UPDATE users
SET avatar_updated_at = CURRENT_TIMESTAMP
WHERE user_id IN (1, 2, 3);

SELECT username, display_name, avatar_updated_at
FROM users
WHERE avatar_updated_at IS NOT NULL;

Step 6: Create Avatar Sizes Reference Table

Define standard avatar sizes.

CREATE TABLE avatar_sizes (
    size_name VARCHAR(20) PRIMARY KEY,
    width INTEGER NOT NULL,
    height INTEGER NOT NULL,
    use_case VARCHAR(100)
);

INSERT INTO avatar_sizes (size_name, width, height, use_case) VALUES
    ('original', 1024, 1024, 'Full resolution storage'),
    ('large', 512, 512, 'Profile page header'),
    ('medium', 256, 256, 'Comments and posts'),
    ('small', 128, 128, 'Navigation bar'),
    ('thumbnail', 48, 48, 'Lists and mentions');

Step 7: Query Users with Profile Pictures

Get users along with their profile picture status.

SELECT
    u.username,
    u.display_name,
    CASE
        WHEN pp.id IS NOT NULL THEN 'Has Picture'
        ELSE 'No Picture'
    END as avatar_status,
    pp.original_width,
    pp.original_height,
    pp.file_size
FROM users u
LEFT JOIN profile_pictures pp ON u.user_id = pp.user_id
ORDER BY u.username;

Step 8: Find Users Without Profile Pictures

Identify users who haven't uploaded a profile picture.

SELECT
    u.user_id,
    u.username,
    u.email,
    u.created_at
FROM users u
LEFT JOIN profile_pictures pp ON u.user_id = pp.user_id
WHERE pp.id IS NULL;

Step 9: Profile Picture Statistics

Generate statistics about profile pictures.

SELECT
    COUNT(DISTINCT u.user_id) as total_users,
    COUNT(DISTINCT pp.user_id) as users_with_pictures,
    COUNT(DISTINCT u.user_id) - COUNT(DISTINCT pp.user_id) as users_without_pictures,
    SUM(pp.file_size) as total_storage_bytes,
    AVG(pp.file_size) as avg_file_size
FROM users u
LEFT JOIN profile_pictures pp ON u.user_id = pp.user_id;

Step 10: Recent Avatar Updates

Find recently updated profile pictures.

SELECT
    u.username,
    u.display_name,
    pp.uploaded_at,
    pp.file_size
FROM users u
INNER JOIN profile_pictures pp ON u.user_id = pp.user_id
ORDER BY pp.uploaded_at DESC
LIMIT 10;

Step 11: Large Profile Pictures

Find oversized profile pictures that may need optimization.

SELECT
    u.username,
    pp.original_width,
    pp.original_height,
    pp.file_size,
    CASE
        WHEN pp.file_size > 500000 THEN 'Too Large'
        WHEN pp.file_size > 250000 THEN 'Consider Optimizing'
        ELSE 'Good Size'
    END as size_recommendation
FROM users u
INNER JOIN profile_pictures pp ON u.user_id = pp.user_id
WHERE pp.file_size > 200000
ORDER BY pp.file_size DESC;

Cleanup (Optional)

DROP TABLE IF EXISTS profile_pictures;
DROP TABLE IF EXISTS avatar_sizes;
DROP TABLE IF EXISTS users;

Expected Outcomes

  • Profile pictures stored with size variants
  • Users linked to their avatar images
  • Storage statistics calculated
  • Missing avatars identified
  • Size optimization recommendations

Avatar Size Standards

Size Dimensions Use Case
Original 1024x1024 Storage master
Large 512x512 Profile pages
Medium 256x256 Posts/comments
Small 128x128 Navigation
Thumbnail 48x48 Lists/mentions

Key Concepts Learned

  • Multiple image size variants
  • User-profile picture relationship
  • Storage optimization tracking
  • Missing data identification
  • Size recommendation queries

Tags

sqlbeginnerimagesprofilethumbnailsusers

Run this on your own machine

Install SynapCores Community Edition free, paste the SQL or Cypher above into the bundled web UI, and watch it run.

Download Free CE