fix: replace uuid columns with rowid aliases

This commit is contained in:
sjdonado
2025-03-20 07:34:33 +01:00
parent e14fc266bb
commit 38f9cfd48e
3 changed files with 184 additions and 1 deletions
+3 -1
View File
@@ -42,7 +42,9 @@ module App::Controllers
slug = @env.params.url["slug"]
link_data = nil
Database.raw_query("SELECT id, url FROM links WHERE slug = (?) LIMIT 1", slug) do |result|
# LIMIT 1 degrades performance on unique field searches
# slug autoindex has better perormance than the covering index
Database.raw_query("SELECT id, url FROM links WHERE slug = (?)", slug) do |result|
if result.move_next
link_data = {result.read(String), result.read(String)}
end
@@ -0,0 +1,102 @@
-- +micrate Up
-- SQL in section 'Up' is executed when this migration is applied
-- 1. Create new users table with INTEGER PK
CREATE TABLE users_new (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name VARCHAR(100) NOT NULL,
api_key VARCHAR(64) UNIQUE NOT NULL,
created_at INTEGER DEFAULT CURRENT_TIMESTAMP NOT NULL,
updated_at INTEGER DEFAULT CURRENT_TIMESTAMP NOT NULL
);
-- Create a mapping table to track old and new user IDs
CREATE TEMPORARY TABLE user_id_map (
old_id TEXT,
new_id INTEGER
);
-- Insert users data and capture the mappings
INSERT INTO users_new (name, api_key, created_at, updated_at)
SELECT name, api_key, created_at, updated_at FROM users;
INSERT INTO user_id_map
SELECT u.id, u_new.id
FROM users u
JOIN users_new u_new ON u_new.api_key = u.api_key;
-- 2. Create new links table with INTEGER PK
CREATE TABLE links_new (
id INTEGER PRIMARY KEY AUTOINCREMENT,
user_id INTEGER NOT NULL,
slug VARCHAR(8) UNIQUE NOT NULL,
url TEXT NOT NULL,
created_at INTEGER DEFAULT CURRENT_TIMESTAMP NOT NULL,
updated_at INTEGER DEFAULT CURRENT_TIMESTAMP NOT NULL,
FOREIGN KEY (user_id) REFERENCES users_new(id) ON DELETE CASCADE
);
-- Create a mapping table for links
CREATE TEMPORARY TABLE link_id_map (
old_id TEXT,
new_id INTEGER
);
-- Insert links data with new user_id foreign keys
INSERT INTO links_new (user_id, slug, url, created_at, updated_at)
SELECT
(SELECT new_id FROM user_id_map WHERE old_id = l.user_id),
l.slug,
l.url,
l.created_at,
l.updated_at
FROM links l;
-- Create the mapping for links
INSERT INTO link_id_map
SELECT l.id, l_new.id
FROM links l
JOIN links_new l_new ON l_new.slug = l.slug AND l_new.url = l.url;
-- 3. Create new clicks table with INTEGER PK
CREATE TABLE clicks_new (
id INTEGER PRIMARY KEY AUTOINCREMENT,
link_id INTEGER NOT NULL,
user_agent TEXT,
browser TEXT,
os TEXT,
referer TEXT,
country TEXT,
created_at INTEGER DEFAULT CURRENT_TIMESTAMP NOT NULL,
updated_at INTEGER DEFAULT CURRENT_TIMESTAMP NOT NULL,
FOREIGN KEY (link_id) REFERENCES links_new(id) ON DELETE CASCADE
);
-- Insert clicks data with new link_id foreign keys
INSERT INTO clicks_new (link_id, user_agent, browser, os, referer, country, created_at, updated_at)
SELECT
(SELECT new_id FROM link_id_map WHERE old_id = c.link_id),
c.user_agent,
c.browser,
c.os,
c.referer,
c.country,
c.created_at,
c.updated_at
FROM clicks c;
-- 4. Drop old tables and rename new tables
DROP TABLE clicks;
DROP TABLE links;
DROP TABLE users;
ALTER TABLE clicks_new RENAME TO clicks;
ALTER TABLE links_new RENAME TO links;
ALTER TABLE users_new RENAME TO users;
-- 5. Drop unused indexes
DROP INDEX IF EXISTS index_users_api_key;
DROP INDEX IF EXISTS idx_links_slug;
DROP INDEX IF EXISTS idx_links_slug_optimized;
-- +micrate Down
-- SQL section 'Down' is executed when this migration is rolled back
+79
View File
@@ -0,0 +1,79 @@
-- Create 10 users
INSERT INTO users (name, api_key)
VALUES
('User 1', 'secure_api_key_1'),
('User 2', 'secure_api_key_2'),
('User 3', 'secure_api_key_3'),
('User 4', 'secure_api_key_4'),
('User 5', 'secure_api_key_5'),
('User 6', 'secure_api_key_6'),
('User 7', 'secure_api_key_7'),
('User 8', 'secure_api_key_8'),
('User 9', 'secure_api_key_9'),
('User 10', 'secure_api_key_10');
-- Create 1,000 links (100 per user)
WITH RECURSIVE link_numbers(n) AS (
SELECT 1
UNION ALL
SELECT n+1 FROM link_numbers
LIMIT 1000
)
INSERT INTO links (user_id, slug, url)
SELECT
((n-1) % 10) + 1, -- User ID (1-10)
'slug' || n, -- Unique slug
'https://sjdonado.com/page/' || n
FROM link_numbers;
-- Create 1,000,000 clicks (1,000 per link)
WITH RECURSIVE link_numbers(link_id) AS (
SELECT id FROM links
),
click_batch(link_id, n) AS (
SELECT link_id, 1 FROM link_numbers
UNION ALL
SELECT link_id, n+1 FROM click_batch WHERE n < 1000
)
INSERT INTO clicks (link_id, user_agent, browser, os, referer, country)
SELECT
link_id,
CASE (n % 5)
WHEN 0 THEN 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)'
WHEN 1 THEN 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15)'
WHEN 2 THEN 'Mozilla/5.0 (iPhone; CPU iPhone OS 14_0)'
WHEN 3 THEN 'Mozilla/5.0 (X11; Linux x86_64)'
ELSE 'Mozilla/5.0 (Android 11; Mobile)'
END,
CASE (n % 3)
WHEN 0 THEN 'Chrome'
WHEN 1 THEN 'Firefox'
ELSE 'Safari'
END,
CASE (n % 4)
WHEN 0 THEN 'Windows'
WHEN 1 THEN 'macOS'
WHEN 2 THEN 'iOS'
ELSE 'Android'
END,
CASE (n % 6)
WHEN 0 THEN 'https://sjdonado.com'
WHEN 1 THEN 'https://donado.co'
WHEN 2 THEN 'https://idonthavespotify.donado.co'
WHEN 3 THEN 'https://spookyplanning.com'
WHEN 4 THEN 'https://github.com/sjdonado'
ELSE NULL
END,
CASE (n % 10)
WHEN 0 THEN 'US'
WHEN 1 THEN 'UK'
WHEN 2 THEN 'Canada'
WHEN 3 THEN 'Germany'
WHEN 4 THEN 'France'
WHEN 5 THEN 'Japan'
WHEN 6 THEN 'Australia'
WHEN 7 THEN 'Brazil'
WHEN 8 THEN 'India'
ELSE 'China'
END
FROM click_batch;