Skip to content

Instantly share code, notes, and snippets.

View benoittgt's full-sized avatar
🏳️‍🌈

Benoit Tigeot benoittgt

🏳️‍🌈
View GitHub Profile
@benoittgt
benoittgt / excited_dev.md
Created September 23, 2024 08:23
As Rails developers, why we are excited about PostgreSQL 17

At the time of writing this article, PostgreSQL 17 is nearly out. On September 5th, the first release candidate was published. The final release is expected on September 26th, but we can already explain why we’ve been eagerly awaiting this release since 1 year.

At Lifen, we’ve loved Rails from the beginning. We have several Rails applications, each with different scopes and teams, all using PostgreSQL as the main database. Some of these applications handle a significant amount of traffic, and their databases need to be properly monitored. This is done by the infrastructure team and the developers themselves using PgAnalyze, Grafana and sometimes AWS console with "Performance Insight".

More than a year ago, we started monitoring the 95th and 99th percentile response times (p95, p99) on an endpoint that was experiencing timeouts. These p99 times were important because they involved a client with significantly mo

# frozen_string_literal: true
require "bundler/inline"
gemfile(true) do
source "https://rubygems.org"
gem "rails"
gem "pg"
end
require "active_record"
require "minitest/autorun"
require "logger"
@benoittgt
benoittgt / server.rb
Created July 11, 2024 11:40 — forked from leandronsp/server.rb
HTTP server using Ractors (Ruby 3)
require 'socket'
@queue = Ractor.new do
loop do
Ractor.yield(Ractor.receive, move: true)
end
end
listener = Ractor.new(@queue) do |queue|
socket = TCPServer.new(PORT)
@benoittgt
benoittgt / postgresql_upgrade.sh
Created April 11, 2024 13:05
Small basic script to run after upgrade commands on Postgresql
#!/bin/bash
set -e
# Use this script with
# Add space before the command to not save it into you shell history
# ./update_postgresql.sh -h pg-xxx.region.rds.amazonaws.com -p password
# Define default host and password
host="localhost"
user="admin"
class ThreadPool
def initialize(size)
@size = size
@jobs = Queue.new
@pool = Array.new(@size) do |i|
Thread.new do
Thread.current[:id] = i
catch(:exit) do
loop do
job, args = @jobs.pop
@benoittgt
benoittgt / max_uuid.sql
Created November 29, 2023 16:08
max uuid
-- Create a table with a UUID column
CREATE TABLE your_table (
id serial PRIMARY KEY,
uuid_column uuid
);
-- Insert 400 rows with UUIDs
INSERT INTO your_table (uuid_column)
SELECT gen_random_uuid() FROM generate_series(1, 400);
@benoittgt
benoittgt / index_diff_cast_timestampz_date.sql
Created November 7, 2023 08:40
Diff size index casting
DROP TABLE IF EXISTS notifications;
CREATE TABLE notifications (
id SERIAL PRIMARY KEY,
created_at TIMESTAMPTZ DEFAULT now() NOT NULL
);
INSERT INTO
notifications (created_at)
SELECT
(LOCALTIMESTAMP - interval '1 month' * random())::timestamptz
@benoittgt
benoittgt / benchmark_define.rb
Last active November 3, 2023 10:45
Struct.new VS Data.define
require 'benchmark/ips'
DataS = Struct.new(:encoder, :values) do # :nodoc:
def hash
[encoder, values].hash
end
end
DataD = Data.define(:encoder, :values) do # :nodoc:
def hash
@benoittgt
benoittgt / pg_stat_statements.sql
Created October 4, 2023 17:33
Quickly look at pg_stat_statements
-- based on https://www.crunchydata.com/blog/understanding-postgres-iops
SELECT
interval '1 millisecond' * total_exec_time AS "Total Exec. Time",
to_char (
(total_exec_time / sum(total_exec_time) OVER ()) * 100,
'FM90D0'
) || '%' AS "Proportional Exec. Time",
to_char (calls, 'FM999G999G999G990') AS "Calls",
interval '1 millisecond' * (blk_read_time + blk_write_time) AS "Time Spent on IO",
@benoittgt
benoittgt / unaccent_bind.rb
Created September 8, 2023 10:23
Force bind parameter and prepared statement with unaccent query with ActiveRecord and Arel
bind_param = Arel::Nodes::BindParam.new(ActiveRecord::Relation::QueryAttribute.new('search_text', "%Nate%", ActiveRecord::Type::String.new))
Customer.where(Customer.arel_table["search_text"].matches(
Arel::Nodes::NamedFunction.new('unaccent', [Arel::Nodes::build_quoted(bind_param)]),
nil,
true # case insensitive
))