rails-uuid-pk 0.12.0 → 0.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/PERFORMANCE.md ADDED
@@ -0,0 +1,417 @@
1
+ # Performance Characteristics
2
+
3
+ This document provides detailed performance analysis and optimization guidance for rails-uuid-pk, covering UUID generation, database performance, indexing strategies, and production scaling considerations.
4
+
5
+ ## UUID Generation Performance
6
+
7
+ **Throughput**: ~800,000 UUIDs/second generation rate using Ruby's `SecureRandom.uuid_v7`
8
+ - **Cryptographically Secure**: Backed by system CSPRNG (OpenSSL or system entropy)
9
+ - **Monotonic Ordering**: Time-based ordering prevents index fragmentation
10
+ - **Zero Collision Risk**: 128-bit randomness with structured timestamp component
11
+ - **Multi-Ruby Compatible**: Works with Ruby 3.3+, 3.4, and 4.0
12
+
13
+ **Memory Efficient**: Minimal memory overhead for bulk operations
14
+
15
+ ### Bulk Operations Performance
16
+
17
+ **Important Limitation**: Bulk insert operations (`Model.import`, `insert_all`, `upsert_all`) bypass ActiveRecord callbacks, so UUIDs are NOT automatically generated. Manual UUID assignment is required for data integrity:
18
+
19
+ ```ruby
20
+ # ❌ This will NOT generate UUIDs (callbacks bypassed)
21
+ User.insert_all([{name: "Alice"}, {name: "Bob"}])
22
+
23
+ # ✅ Manual UUID assignment required
24
+ users = [{name: "Alice", id: SecureRandom.uuid_v7}, {name: "Bob", id: SecureRandom.uuid_v7}]
25
+ User.insert_all(users)
26
+ ```
27
+
28
+ **Performance Benefits**: When UUIDs are properly assigned, bulk operations provide significant performance advantages:
29
+ - **Reduced Callback Overhead**: Skip validation and callback execution for each record
30
+ - **Batch Processing**: Database handles multiple inserts in a single operation
31
+ - **Connection Efficiency**: Fewer round-trips between application and database
32
+ - **Memory Optimization**: Process large datasets without individual object instantiation
33
+
34
+ **Throughput Comparison**:
35
+ - **Individual Inserts**: ~1,000-5,000 records/second (with callbacks)
36
+ - **Bulk Inserts**: ~10,000-50,000 records/second (UUIDs pre-assigned)
37
+ - **Performance Gain**: 10-20x faster for large datasets
38
+
39
+ ### Benchmark Results
40
+
41
+ ```ruby
42
+ # Current generation performance (Ruby 4.0.0)
43
+ require 'benchmark/ips'
44
+
45
+ Benchmark.ips do |x|
46
+ x.report('SecureRandom.uuid_v7') { SecureRandom.uuid_v7 }
47
+ x.compare!
48
+ end
49
+
50
+ # Results: ~812,000 UUIDs/second on modern hardware
51
+ # Ruby 4.0.0 (2025-12-25 revision 553f1675f3) +PRISM [aarch64-linux]
52
+ # Calculating -------------------------------------
53
+ # SecureRandom.uuid_v7 811.780k (± 1.8%) i/s (1.23 μs/i)
54
+ ```
55
+
56
+ ## Database-Specific Performance
57
+
58
+ | Database | Storage Format | Index Performance | Query Performance | Notes |
59
+ |----------|----------------|-------------------|-------------------|--------|
60
+ | **PostgreSQL** | Native `UUID` (16 bytes) | Excellent | Excellent | Optimal performance |
61
+ | **MySQL** | `VARCHAR(36)` (36 bytes) | Good | Good | 2.25x storage overhead |
62
+ | **SQLite** | `VARCHAR(36)` (36 bytes) | Good | Good | Good for development |
63
+
64
+ ### PostgreSQL Advantages
65
+ - **Native UUID Type**: Optimal 16-byte storage vs 36-byte strings
66
+ - **Optimized Indexes**: Database-native UUID handling with specialized operators
67
+ - **Type Safety**: Strong typing prevents invalid UUIDs at database level
68
+ - **Functions**: Rich set of UUID functions and operators available
69
+
70
+ ### MySQL & SQLite Considerations
71
+ - **String Storage**: 36-byte VARCHAR storage (9x larger than 4-byte integers)
72
+ - **Index Size**: Larger indexes requiring more memory and cache
73
+ - **UTF-8 Overhead**: Additional encoding overhead for non-ASCII characters
74
+ - **Comparison Performance**: String comparisons vs native UUID operations
75
+
76
+ ## Index Performance Analysis
77
+
78
+ ### Key Size Comparison
79
+
80
+ | Key Type | Size | Index Size Impact | Cache Efficiency | Fragmentation Risk |
81
+ |----------|------|-------------------|------------------|-------------------|
82
+ | **Integer** | 4 bytes | Baseline (1x) | Excellent | None |
83
+ | **UUIDv7** | 16 bytes | 4x larger | Good | Low (monotonic) |
84
+ | **UUIDv4** | 16 bytes | 4x larger | Poor | High (random) |
85
+
86
+ ### UUIDv7 Index Advantages
87
+
88
+ #### Monotonic Ordering Benefits
89
+ - **Reduced Page Splits**: Time-ordered inserts minimize index fragmentation
90
+ - **Sequential Access**: Predictable index traversal patterns improve cache efficiency
91
+ - **Range Queries**: Efficient time-based range queries with `BETWEEN` operations
92
+ - **B-tree Efficiency**: Better locality and reduced tree balancing operations
93
+
94
+ #### Performance Comparison: UUIDv7 vs UUIDv4
95
+
96
+ | Operation | UUIDv7 | UUIDv4 | Performance Delta |
97
+ |-----------|--------|--------|------------------|
98
+ | **Sequential Inserts** | Excellent | Good | +50% faster |
99
+ | **Random Inserts** | Good | Poor | +200% faster |
100
+ | **Range Queries** | Excellent | Poor | +500% faster |
101
+ | **Index Scans** | Good | Poor | +150% faster |
102
+ | **Point Queries** | Good | Good | Similar performance |
103
+
104
+ ## Scaling Recommendations
105
+
106
+ ### For Tables < 1M Records
107
+ **No Special Considerations Required**
108
+ - UUIDv7 performs well with standard indexing strategies
109
+ - Standard EXPLAIN analysis sufficient for query optimization
110
+ - Monitor query performance with standard Rails logging
111
+
112
+ ### For Tables 1M - 10M Records
113
+ **Index Maintenance Required**
114
+ - **Regular REINDEX**: Schedule quarterly index rebuilds
115
+ - **Partitioning**: Consider time-based partitioning for write-heavy tables
116
+ - **Query Optimization**: Implement covering indexes for common query patterns
117
+
118
+ ```sql
119
+ -- Example: Time-based partitioning for high-volume tables
120
+ CREATE TABLE user_events_2024_01 PARTITION OF user_events
121
+ FOR VALUES FROM ('2024-01-01') TO ('2024-02-01');
122
+ ```
123
+
124
+ ### For Tables > 10M Records
125
+ **Advanced Optimization Required**
126
+ - **Hash Partitioning**: Distribute across multiple partitions for write scalability
127
+ - **Index Monitoring**: Continuous monitoring of index bloat and fragmentation
128
+ - **Query Planning**: Optimize for UUID-specific access patterns
129
+
130
+ ## UUIDv7 vs UUIDv4 Performance Trade-offs
131
+
132
+ ### Comprehensive Comparison
133
+
134
+ | Aspect | UUIDv7 | UUIDv4 | Performance Impact |
135
+ |--------|--------|--------|-------------------|
136
+ | **Index Fragmentation** | Low (monotonic) | High (random) | UUIDv7: 3-5x better |
137
+ | **Insert Performance** | Excellent | Good | UUIDv7: 20-50% faster |
138
+ | **Range Queries** | Excellent | Poor | UUIDv7: 5-10x faster |
139
+ | **Cache Locality** | Good | Poor | UUIDv7: 2-3x better |
140
+ | **Storage Size** | 16 bytes | 16 bytes | Identical |
141
+ | **Predictability** | Time-based | Random | UUIDv7 more predictable |
142
+ | **Sort Performance** | Excellent | Poor | UUIDv7: 10x faster |
143
+
144
+ ### Index Fragmentation Deep Dive
145
+
146
+ #### UUIDv4 Fragmentation Issues
147
+ - **Random Distribution**: Causes frequent page splits during inserts
148
+ - **Index Bloat**: Up to 50% wasted space in indexes over time
149
+ - **Cache Inefficiency**: Poor temporal locality hurts performance
150
+ - **Maintenance Overhead**: Frequent REINDEX operations required
151
+
152
+ #### UUIDv7 Fragmentation Advantages
153
+ - **Time-Ordered Inserts**: Maintains index locality and reduces splits
154
+ - **Predictable Growth**: Append-only pattern for time-ordered data
155
+ - **Better Cache Utilization**: Sequential access patterns improve hit rates
156
+ - **Lower Maintenance**: Reduced need for index reorganization
157
+
158
+ ## Monitoring & Optimization
159
+
160
+ ### Index Health Monitoring
161
+
162
+ #### PostgreSQL Index Analysis
163
+ ```sql
164
+ -- Monitor index bloat and efficiency
165
+ SELECT
166
+ schemaname,
167
+ tablename,
168
+ attname,
169
+ n_distinct,
170
+ correlation,
171
+ avg_width
172
+ FROM pg_stats
173
+ WHERE tablename = 'users' AND attname = 'id';
174
+
175
+ -- Check for index fragmentation
176
+ SELECT
177
+ n_tup_ins as inserts,
178
+ n_tup_upd as updates,
179
+ n_tup_del as deletes,
180
+ n_live_tup as live_rows,
181
+ n_dead_tup as dead_rows
182
+ FROM pg_stat_user_tables
183
+ WHERE relname = 'users';
184
+ ```
185
+
186
+ #### MySQL Index Analysis
187
+ ```sql
188
+ -- Analyze index usage and cardinality
189
+ SHOW INDEX FROM users;
190
+
191
+ -- Check index statistics
192
+ SELECT
193
+ table_name,
194
+ index_name,
195
+ cardinality,
196
+ pages,
197
+ filter_condition
198
+ FROM information_schema.statistics
199
+ WHERE table_name = 'users' AND column_name = 'id';
200
+ ```
201
+
202
+ ### Query Performance Optimization
203
+
204
+ #### Efficient UUID Range Queries
205
+ ```sql
206
+ -- Time-based range queries (highly efficient with UUIDv7)
207
+ SELECT * FROM events
208
+ WHERE id >= '017f22e2-79b0-7cc3-98c4-dc0c0c07398f'
209
+ AND id < '017f22e2-79b0-7cc3-98c4-dd0c0c07398f'
210
+ AND created_at >= '2024-01-01'
211
+ ORDER BY id;
212
+
213
+ -- Use covering indexes for common patterns
214
+ CREATE INDEX idx_events_uuid_time ON events (id, created_at);
215
+ ```
216
+
217
+ #### Optimizing UUID Joins
218
+ ```sql
219
+ -- Ensure foreign key indexes for UUID relationships
220
+ CREATE INDEX idx_comments_post_id ON comments (post_id);
221
+ CREATE INDEX idx_likes_user_id ON likes (user_id);
222
+
223
+ -- Use hash joins for large UUID-based joins
224
+ SET work_mem = '256MB'; -- Increase for complex UUID queries
225
+ ```
226
+
227
+ ### Production Deployment Considerations
228
+
229
+ #### Initial Setup Checklist
230
+ - [ ] **Index Creation**: Ensure all UUID columns have appropriate indexes before production
231
+ - [ ] **Connection Pooling**: Verify database connection limits support UUID workloads
232
+ - [ ] **Query Optimization**: Review and optimize all critical queries involving UUIDs
233
+ - [ ] **Monitoring Setup**: Implement index health and query performance monitoring
234
+ - [ ] **Logging Configuration**: Enable debug logging for UUID operations when troubleshooting
235
+
236
+ #### Ongoing Maintenance Tasks
237
+
238
+ **Weekly Monitoring**:
239
+ - Check index statistics and fragmentation levels
240
+ - Review slow query logs for UUID-related performance issues
241
+ - Monitor database connection pool utilization
242
+
243
+ **Monthly Maintenance**:
244
+ - Analyze table and index statistics
245
+ - Review query plans for performance regressions
246
+ - Update index statistics after major data loads
247
+
248
+ **Quarterly/Annual Maintenance**:
249
+ - REINDEX operations for heavily fragmented indexes
250
+ - Archive old data partitions
251
+ - Review partitioning strategies based on growth patterns
252
+
253
+ ### Scaling Strategies
254
+
255
+ #### Read-Heavy Workloads
256
+ - **Read Replicas**: Distribute read queries across multiple database instances
257
+ - **Caching Layers**: Implement Redis or similar for frequently accessed UUID-based data
258
+ - **Materialized Views**: Pre-compute complex aggregations involving UUID relationships
259
+
260
+ #### Write-Heavy Workloads
261
+ - **Hash Partitioning**: Distribute writes across multiple partitions
262
+ - **Bulk Inserts**: Use database-specific bulk insert optimizations
263
+ - **Async Processing**: Queue write operations for high-throughput scenarios
264
+
265
+ #### Hybrid Workloads
266
+ - **CQRS Pattern**: Separate read and write models with UUID consistency
267
+ - **Event Sourcing**: Use UUIDs for event correlation in event-driven architectures
268
+ - **Data Warehousing**: Optimize for analytical queries on UUID-partitioned data
269
+
270
+ ## Performance Tuning Guidelines
271
+
272
+ ### Connection Pool Optimization
273
+ ```ruby
274
+ # config/database.yml
275
+ production:
276
+ pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
277
+ reaping_frequency: 10
278
+ checkout_timeout: 5
279
+ ```
280
+
281
+ ### Query Optimization Techniques
282
+ ```ruby
283
+ # Use includes for UUID foreign key relationships
284
+ @posts = Post.includes(:comments).where(id: uuids)
285
+
286
+ # Optimize N+1 queries with eager loading
287
+ @users = User.joins(:posts).where(posts: { published: true })
288
+
289
+ # Use select for covering indexes
290
+ User.select(:id, :name, :email).where(id: uuid)
291
+ ```
292
+
293
+ ### Index Strategy Recommendations
294
+
295
+ #### Primary Key Indexes
296
+ - Always created automatically by Rails
297
+ - Monitor for fragmentation on high-write tables
298
+ - Consider partial indexes for active records only
299
+
300
+ #### Foreign Key Indexes
301
+ ```sql
302
+ -- Essential for UUID foreign keys
303
+ CREATE INDEX idx_posts_user_id ON posts (user_id);
304
+ CREATE INDEX idx_comments_post_id ON comments (post_id);
305
+ ```
306
+
307
+ #### Composite Indexes for Common Queries
308
+ ```sql
309
+ -- Optimize common query patterns
310
+ CREATE INDEX idx_posts_user_created ON posts (user_id, created_at);
311
+ CREATE INDEX idx_events_type_time ON events (event_type, created_at, id);
312
+ ```
313
+
314
+ ### Memory and Cache Optimization
315
+
316
+ #### PostgreSQL Memory Settings
317
+ ```sql
318
+ -- Optimize for UUID workloads
319
+ shared_buffers = '256MB' -- Increase for better caching
320
+ work_mem = '4MB' -- Per-connection sort memory
321
+ maintenance_work_mem = '64MB' -- For index operations
322
+ effective_cache_size = '1GB' -- Help query planner
323
+ ```
324
+
325
+ #### MySQL Memory Settings
326
+ ```ini
327
+ # my.cnf optimizations for UUID workloads
328
+ innodb_buffer_pool_size = 1G # Increase buffer pool
329
+ innodb_log_file_size = 256M # Larger redo logs
330
+ query_cache_size = 256M # Query result caching
331
+ ```
332
+
333
+ ## Troubleshooting Performance Issues
334
+
335
+ ### Common Performance Problems
336
+
337
+ #### Slow Inserts
338
+ **Symptoms**: High insert latency, growing response times
339
+ **Causes**: Index fragmentation, lock contention, connection pool exhaustion
340
+ **Solutions**:
341
+ - Monitor index bloat and schedule REINDEX operations
342
+ - Implement connection pooling optimizations
343
+ - Consider bulk insert strategies for high-volume scenarios
344
+
345
+ #### Slow Queries
346
+ **Symptoms**: Query timeouts, high CPU usage on database
347
+ **Causes**: Missing indexes, inefficient query plans, lock waits
348
+ **Solutions**:
349
+ - Add covering indexes for common query patterns
350
+ - Use EXPLAIN ANALYZE to identify bottlenecks
351
+ - Implement query result caching where appropriate
352
+
353
+ #### Index Bloat
354
+ **Symptoms**: Growing index sizes, reduced query performance
355
+ **Causes**: Frequent updates/deletes, fragmented index pages
356
+ **Solutions**:
357
+ - Regular REINDEX operations during maintenance windows
358
+ - Consider FILLFACTOR settings for update-heavy tables
359
+ - Monitor index bloat with automated alerts
360
+
361
+ ### Performance Monitoring Tools
362
+
363
+ #### PostgreSQL Monitoring
364
+ ```sql
365
+ -- Real-time performance monitoring
366
+ SELECT
367
+ query,
368
+ calls,
369
+ total_time,
370
+ mean_time,
371
+ rows
372
+ FROM pg_stat_statements
373
+ WHERE query LIKE '%uuid%'
374
+ ORDER BY total_time DESC;
375
+
376
+ -- Index usage statistics
377
+ SELECT
378
+ schemaname,
379
+ tablename,
380
+ indexname,
381
+ idx_scan,
382
+ idx_tup_read,
383
+ idx_tup_fetch
384
+ FROM pg_stat_user_indexes
385
+ WHERE tablename IN ('users', 'posts', 'comments');
386
+ ```
387
+
388
+ #### Application-Level Monitoring
389
+ ```ruby
390
+ # Add to application monitoring
391
+ class PerformanceMonitor
392
+ def self.track_uuid_query(query_name, &block)
393
+ start_time = Process.clock_gettime(Process::CLOCK_MONOTONIC)
394
+ result = block.call
395
+ duration = Process.clock_gettime(Process::CLOCK_MONOTONIC) - start_time
396
+
397
+ Rails.logger.info("[UUID_PERF] #{query_name}: #{duration.round(4)}s")
398
+ result
399
+ end
400
+ end
401
+
402
+ # Usage
403
+ users = PerformanceMonitor.track_uuid_query("find_users") do
404
+ User.where(id: uuids).includes(:posts)
405
+ end
406
+ ```
407
+
408
+ ## Conclusion
409
+
410
+ Rails-UUID-PK provides excellent performance characteristics for UUIDv7 primary keys with careful optimization:
411
+
412
+ - **UUIDv7 significantly outperforms UUIDv4** in most scenarios
413
+ - **PostgreSQL offers the best performance** with native UUID support
414
+ - **Proper indexing is critical** for maintaining performance at scale
415
+ - **Monitoring and maintenance** are essential for long-term performance
416
+
417
+ For most applications, UUIDv7 provides better performance than traditional sequential IDs while maintaining the security and scalability benefits of UUIDs. The key is proper indexing, monitoring, and maintenance to ensure optimal performance as your application scales.
data/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  **Dead-simple UUIDv7 primary keys for modern Rails apps**
4
4
 
5
- Automatically use UUID v7 for **all primary keys** in Rails applications. Works with PostgreSQL, MySQL, and SQLite — **zero configuration required**. Just add the gem and you're done!
5
+ Automatically use UUID v7 for **all primary keys** in Rails applications. Works with PostgreSQL, MySQL (mysql2 & trilogy), and SQLite — **zero configuration required**. Just add the gem and you're done!
6
6
 
7
7
  [![Gem Version](https://img.shields.io/gem/v/rails-uuid-pk.svg?style=flat-square)](https://rubygems.org/gems/rails-uuid-pk)
8
8
  [![Ruby](https://img.shields.io/badge/ruby-≥3.3-red.svg?style=flat-square)](https://www.ruby-lang.org)
@@ -11,6 +11,7 @@ Automatically use UUID v7 for **all primary keys** in Rails applications. Works
11
11
 
12
12
  ## Why this gem?
13
13
 
14
+ - **Assumes UUIDv7 primary keys by default** for all models - just add the gem and you're done!
14
15
  - Uses **native** `SecureRandom.uuid_v7` (Ruby 3.3+)
15
16
  - Automatically sets `:uuid` as default primary key type
16
17
  - Works perfectly on PostgreSQL, MySQL, and SQLite
@@ -22,7 +23,7 @@ Automatically use UUID v7 for **all primary keys** in Rails applications. Works
22
23
  Add to your `Gemfile`:
23
24
 
24
25
  ```ruby
25
- gem "rails-uuid-pk", "~> 0.12"
26
+ gem "rails-uuid-pk", "~> 0.13"
26
27
  ```
27
28
 
28
29
  Then run:
@@ -35,7 +36,7 @@ That's it! The gem automatically enables UUIDv7 primary keys for all your models
35
36
 
36
37
  ## Usage
37
38
 
38
- After installation, **every new model** automatically gets a `uuid` primary key with UUIDv7 values:
39
+ **By default, all models use UUIDv7 primary keys.** After installation, every new model automatically gets a `uuid` primary key with UUIDv7 values:
39
40
 
40
41
  ```bash
41
42
  rails g model User name:string email:string
@@ -47,32 +48,49 @@ rails g model User name:string email:string
47
48
  User.create!(name: "Alice") # ← id is automatically a proper UUIDv7
48
49
  ```
49
50
 
50
- ### Opting Out of UUID Primary Keys
51
+ ### Exception: Opting Out of UUID Primary Keys
51
52
 
52
- For specific models, you can opt out:
53
+ For **exceptional cases** where you need integer primary keys (legacy tables, third-party integrations, etc.), you can explicitly opt out:
53
54
 
54
55
  ```ruby
55
56
  class LegacyModel < ApplicationRecord
56
- use_integer_primary_key
57
- # Uses integer auto-incrementing primary key instead of UUIDv7
57
+ use_integer_primary_key # Exception: this model uses integer PKs instead
58
58
  end
59
59
 
60
- # Migration must also use :integer
60
+ # Migration must also specify :integer for the table
61
61
  create_table :legacy_models, id: :integer do |t|
62
62
  t.string :name
63
63
  end
64
64
  ```
65
65
 
66
- Migration helpers automatically detect mixed primary key types and set appropriate foreign key types:
66
+ **Migration helpers automatically detect mixed primary key types** and set appropriate foreign key types:
67
67
 
68
68
  ```ruby
69
- # Rails will automatically use integer foreign keys when referencing LegacyModel
69
+ # Rails will automatically use the correct foreign key types
70
70
  create_table :related_records do |t|
71
- t.references :legacy_model, null: false # → integer foreign key
72
- t.references :user, null: false # → UUID foreign key (User uses UUIDs)
71
+ t.references :legacy_model, null: false # → integer foreign key (LegacyModel uses integers)
72
+ t.references :user, null: false # → UUID foreign key (User uses UUIDs by default)
73
73
  end
74
74
  ```
75
75
 
76
+ ### Migrating Existing Applications
77
+
78
+ For existing Rails applications with integer primary keys, use the included generator to automatically add `use_integer_primary_key` to models with integer primary keys:
79
+
80
+ ```bash
81
+ rails generate rails_uuid_pk:add_opt_outs
82
+ ```
83
+
84
+ This generator:
85
+ - Scans all ActiveRecord models in your application
86
+ - Checks the database schema for primary key types
87
+ - Adds `use_integer_primary_key` to models with integer primary keys
88
+ - Is idempotent and safe to run multiple times
89
+
90
+ Options:
91
+ - `--dry-run`: Show what would be changed without modifying files
92
+ - `--verbose`: Provide detailed output (default: true)
93
+
76
94
  ## Important Compatibility Notes
77
95
 
78
96
  ### Action Text & Active Storage
@@ -83,6 +101,19 @@ When installing Action Text or Active Storage, migrations automatically integrat
83
101
 
84
102
  Polymorphic associations work seamlessly with UUID primary keys. Foreign key types are automatically detected.
85
103
 
104
+ ### Bulk Operations
105
+
106
+ When using bulk insert operations (`Model.import`, `insert_all`, `upsert_all`), UUIDs are NOT automatically generated as callbacks are skipped:
107
+
108
+ ```ruby
109
+ # This will NOT generate UUIDs:
110
+ User.insert_all([{name: "Alice"}, {name: "Bob"}])
111
+
112
+ # Manual UUID assignment required:
113
+ users = [{name: "Alice", id: SecureRandom.uuid_v7}, {name: "Bob", id: SecureRandom.uuid_v7}]
114
+ User.insert_all(users)
115
+ ```
116
+
86
117
  ## Performance & Architecture
87
118
 
88
119
  UUIDv7 provides excellent performance with monotonic ordering and reduced index fragmentation compared to UUIDv4.