AI 资讯
From MySQL to MongoDB in Spring Boot — Everything That Changed in My Code
In my last post I wrote about an error that cost me a full evening: my pom.xml had the MongoDB starter, but my code was still full of JPA annotations. The compiler kept saying cannot find symbol: class Entity . That post was about the error. This post is about the fix — every single line I had to change to move my Task Manager project from MySQL to MongoDB. If you are planning the same switch, this is the checklist I wish I had. 1. The dependency Before (MySQL + JPA): <dependency> <groupId> org.springframework.boot </groupId> <artifactId> spring-boot-starter-data-jpa </artifactId> </dependency> <dependency> <groupId> com.mysql </groupId> <artifactId> mysql-connector-j </artifactId> <scope> runtime </scope> </dependency> After (MongoDB): <dependency> <groupId> org.springframework.boot </groupId> <artifactId> spring-boot-starter-data-mongodb </artifactId> </dependency> One starter replaces two dependencies. And this is exactly where my problem started — I added the new one but never removed the old one, so half my code still compiled and half did not. Remove the JPA starter completely. If you leave it in, the jakarta.persistence annotations still resolve, and you will not notice you are mixing two worlds until something breaks at runtime. 2. application.properties Before: spring.datasource.url = jdbc:mysql://localhost:3306/taskmanager spring.datasource.username = root spring.datasource.password = yourpassword spring.jpa.hibernate.ddl-auto = update spring.jpa.show-sql = true After: spring.data.mongodb.uri = mongodb://localhost:27017/taskmanager Five lines became one. No ddl-auto because MongoDB has no schema to create. No dialect because there is no SQL being generated. The database and the collection are created automatically the first time you insert a document. 3. The model class This is where most of the work was. Here is my actual Task class after the migration: package com.taskmanager.task_manager ; import com.fasterxml.jackson.annotation.JsonIgnore ; import org.
AI 资讯
Prisma Studio is not an admin panel
If you build with Prisma, you already know Prisma Studio. Run one command and you get a clean, visual way to browse and edit rows in your database. It's genuinely useful, and I reach for it every day while developing. But somewhere between "I need to look at my data" and "I need to let a support agent safely edit a customer's record in production," Prisma Studio quietly stops being the right tool. It was never trying to be that tool. It's a database viewer. An admin panel is something else, and the gap between the two is exactly the part that matters once real people and real permissions are involved. I ended up building a small package to fill that gap for my own Express + Prisma apps. Writing it forced me to be precise about what an admin panel actually adds on top of a database browser. Here's the distinction as I now understand it. A database browser shows rows. An admin panel governs them. Prisma Studio connects to your database and shows you everything. That's the point of it, and it's also why you'd never hand it to a non-engineer or expose it in production. It has no concept of who is looking, what they're allowed to do, or which rows they're allowed to touch. An admin panel's whole job is those three questions. The package I built mounts a React UI at /admin and a guarded JSON API under /admin/api/* on your existing Express app. Every single request through that API runs the same pipeline, in the same order: authentication → permission check → tenant scope → validation → Prisma mutation/query → optional audit event That ordering is the entire difference. A database browser skips straight to the mutation. An admin panel refuses to run the mutation until it knows the request is authenticated, permitted, scoped to the right tenant, and valid. Permissions and scope are two different questions This was the design decision I care most about, because collapsing these two into one is how data leaks happen. Permissions decide which actions a role may take. Can an ed
AI 资讯
RDS High Availability and credential rotation without downtime
I got an AWS question and implemented it to make sure that the option is correct. A critical financial application runs on RDS for PostgreSQL. The requirements are tight: 1-second RPO, 60-second RTO, and database credentials rotated every 30 days without taking the application offline. Two independent problems. Two independent solutions. Prerequisites Check these before running terraform apply : RDS Proxy availability RDS Proxy is not available on all instance types. It requires instances with at least 2 vCPUs. db.t3.micro is not supported. db.t3.medium and above work. Terraform executor permissions The IAM principal running Terraform needs, at minimum: rds:CreateDBInstance rds:CreateDBProxy rds:CreateDBProxyTargetGroup rds:RegisterDBProxyTargets rds:ModifyDBInstance iam:CreateRole iam:AttachRolePolicy iam:PutRolePolicy iam:PassRole secretsmanager:CreateSecret secretsmanager:PutSecretValue secretsmanager:RotateSecret lambda:CreateFunction lambda:AddPermission ec2:CreateSecurityGroup ec2:AuthorizeSecurityGroupIngress ec2:CreateDBSubnetGroup AdministratorAccess on the account covers all of these. Lock it down after the initial setup. VPC requirements RDS Proxy runs inside your VPC. You need at least two private subnets in different Availability Zones. The rotation Lambda also runs inside the VPC so it can reach the RDS instance directly during the credential update step. The problem Database failure recovery RPO of 1 second means almost no data loss is acceptable. RTO of 60 seconds means the application must resume within a minute of a failure. A standard single-instance RDS setup fails both requirements: there is no automatic failover, and restoring from a backup takes far longer than 60 seconds. Credential rotation Rotating credentials on a schedule sounds simple until you factor in application downtime. If you update a password and the application still holds connections authenticated with the old one, those connections fail. The rotation mechanism needs to handle
AI 资讯
Distributed Locking in Practice: Guarantees, Failure Scenarios and Better Alternatives (2/4)
In this article, we'll explore the mechanisms to solve the coordination problem. 8. Introducing Leases To address the problem of permanent ownership, distributed systems typically replace it with temporary ownership. This concept is known as a lease . Instead of granting indefinite control over a resource, the coordination service assigns ownership for a limited period of time. Rather than stating, “You own this resource until you explicitly release it,” the system instead says, “You own this resource for the next 30 seconds.” This changes the interaction model significantly. Acquire Lease | v Execute Work | v Renew Lease | v Continue Processing As long as the application remains healthy, it periodically renews the lease to maintain ownership. If the application crashes or becomes unresponsive, it can no longer renew the lease. Once the lease duration expires, ownership is automatically revoked. At that point, another application becomes eligible to acquire the lease and continue the work. Leases solve a critical problem in distributed systems: they prevent abandoned locks from blocking progress indefinitely . The system can recover automatically without manual intervention. However, while leases improve availability, they also introduce a new class of subtle and more complex problems. Leases Depend on Time To understand the next challenge, assume the lease duration is thirty seconds. Application A successfully acquires the lease. Lease Granted Duration = 30 seconds After twenty seconds, the JVM begins a long Full Garbage Collection cycle. This pause lasts forty seconds, significantly longer than the lease duration. The timeline now becomes problematic. Lease Granted | | Processing | | GC Pause (40 sec) | | Lease Expires While Application A is paused, the lease expires. During this time, another application requests access to the same resource. The coordination service observes that the previous lease has expired and therefore grants ownership to Application B. Appl
AI 资讯
Your Database Is Making 4 Promises. Here's What ACID Means.
Introduction Your program keeps opening transactions. A signup writes a new user row. A checkout debits one account and credits another. A form submission updates three related tables at once. You wrap it all in BEGIN and COMMIT and move on, trusting that the database will handle whatever happens in between. Most of the time it does. But what is it actually promising you when it handles that? And what does it have to do behind the scenes to keep that promise? Say a user transfers ₹1,000 from Account A to Account B. The application runs two updates: subtract 1,000 from A, add 1,000 to B. Now say the server crashes right after the first update runs but before the second one does. Account A: -₹1,000 Account B: +₹0 That money didn't move. It vanished. No error message fixes that, and no user accepts "the server restarted" as an explanation for their missing balance. This is the exact problem a set of guarantees called ACID was built to solve. Most developers can recite the acronym, Atomicity, Consistency, Isolation, Durability, without being able to explain what any of the four words actually promise, or what the database has to do internally to keep those promises. This article tries to fix that. -- 1. What Is a Transaction? Before ACID makes sense, you need to understand what a transaction actually is. A transaction is a group of one or more database operations treated as a single logical unit of work. Either the whole group succeeds, or none of it does. The bank transfer above is a textbook transaction: two updates that only make sense together. In SQL, a transaction usually looks like this: BEGIN ; UPDATE accounts SET balance = balance - 1000 WHERE id = 1 ; UPDATE accounts SET balance = balance + 1000 WHERE id = 2 ; COMMIT ; BEGIN tells the database "everything from here on is one unit." COMMIT tells it "we're done, make it permanent." If something goes wrong in between, a constraint violation, a crash, the application deciding to cancel, the database can issue a RO
AI 资讯
Rebuilding the Cerebras Knowledge Base: Results Appendix (P1–P4)
This is the data appendix for Posts 1–4 . The narrative and takeaways live in the main posts. This page is pure measurement. Eval set: 22 questions (P1) → expanded to 31 questions (P2 onward) Corpus evolution: P1/P2: ~3,700 docs (raw threads + code chunks) P3/P4: 16,315 docs (distilled threads + bursts + code) Quick comparison (same 31-question set) Metric Vector P2 Hybrid P2 Vector P3 Hybrid P3 Hybrid + Rerank (P4) recall@1 0.68 0.61 0.52 0.39 0.87 recall@3 0.84 0.65 0.71 0.65 0.94 recall@10 0.90 0.90 0.81 0.94 0.94 MRR 0.77 0.67 0.63 0.57 0.90 Takeaway: Hybrid alone never beat pure vector on this corpus. Hybrid + LLM rerank is the first clear win. P1 — Naive vector baseline Corpus: 3,000 raw issue threads + 687 code chunks Embeddings: BGE-M3 (1024d), max_seq_length=1024, HNSW cosine Numbers (22 questions) Metric Score recall@10 1.00 (22/22) recall@3 0.95 recall@1 0.77 (17/22) Main k=1 misses Exact error pastes ( TypeError: Object of type int64... , AttributeError: 'Depends'... ) — ranked 4–5 instead of 1 jsonable_encoder code chunk outranked by issues about the function API key header implementation (code vs similar issues) Paraphrase questions (dependency injection outside routes, custom 404) Pattern: Dense search is strong on recall@10 but weak when the query has a sharp lexical signal. Ops notes Ingest wall time ~40 min (GitHub API is the bottleneck) BGE-M3 OOM on Apple Silicon fixed by capping max_seq_length=1024 Python 3.13 + uv editable install issue fixed by pinning 3.12 P2 — Hybrid (vector + FTS + RRF) Corpus: Same size as P1, with better comment pagination and symbol-based code IDs Eval set: Expanded to 31 questions (added exact error pastes + rare identifiers) Numbers Metric Vector FTS Hybrid recall@1 0.68 0.42 0.61 recall@3 0.84 0.48 0.65 recall@10 0.90 0.65 0.90 MRR 0.77 0.47 0.67 Headline: Hybrid is not a strict win over vector-only. Where hybrid helped Exact error pastes (e.g. TypeError: int64 is not JSON serializable ) → moved from rank 5 → 1 Near-d
AI 资讯
SQLite forensics: why deleting rows doesn't erase secrets (FTS, free pages, VACUUM)
You deleted the row. The secret is gone from the app, the queries return nothing, and the dashboard is clean. In SQLite — the database behind most session stores, browser profiles, and agent state files — that delete is a fiction. The bytes are still in the file. Three ways deleted data survives 1. Free pages. SQLite doesn't zero out the space a deleted row occupied. The page is marked free and added to the freelist; the old bytes stay until they're overwritten by a future write. A file that's been deleted-from is a forensics goldmine: recover the freelist pages and the "deleted" rows come back. 2. FTS virtual tables. If the database uses SQLite's full-text search (FTS5), the FTS index keeps its own copies of the indexed text, maintained separately from the source tables. Delete the row from the source table and the FTS index still contains the tokens — searchable. This is the one that catches people: their app shows the secret is gone, and the FTS index still has it. 3. WAL and journal files. In WAL mode, recent writes live in the -wal file; transactions in the -journal file. Both can retain pre-delete content until checkpointed or cleaned. "Deleted" in SQLite means "no longer referenced", not "no longer present". What erasure actually requires Making a secret physically disappear from a SQLite database takes three operations, in order: Replace the value everywhere it lives. Known secret values get replaced across all tables; pattern matches (API key formats) get masked. Two layers, because you can't enumerate every secret that leaked. Rebuild the FTS indexes. INSERT INTO t(t) VALUES('rebuild') style rebuilds, or drop/recreate the virtual tables — so the index no longer contains the old tokens. Run VACUUM. VACUUM rewrites the entire database file, copying only live data into a fresh file — free pages with old bytes are discarded in the process. After VACUUM, the file's raw bytes no longer contain the secret. (Note: VACUUM doesn't shrink WAL files; those need a chec
AI 资讯
How PGSimCity Turns PostgreSQL Complexity Into a Virtual City 3D Simulation
Nikolay Samokhvalov has developed PGSimCity, an open-source educational tool that visualises PostgreSQL mechanics as a 3D spatial simulation in the browser. It assists backend developers and site reliability engineers in understanding SQL and the dynamics of kernel execution. The project is available on GitHub and aims to enhance understanding of database architecture through interactive elements. By Olimpiu Pop
产品设计
Why 'WHERE x = NULL' Never Works in SQL (And What to Use Instead)
Adapted from the SQL Essentials Companion Guide . You write a query to find every customer with no phone number on file. WHERE phone = NULL looks obviously correct — and it returns zero rows, even though you can see NULL sitting right there in the column. Nothing crashes. No error. The query just quietly lies to you about what's in the table. This isn't SQL being broken. It's SQL being consistent about something most languages don't force you to think about: NULL doesn't mean "nothing," it means "unknown." And you can't compare something to unknown with = and expect a real answer. What's actually happening Take this table: -- customers | id | name | phone | | ----|-------------|------------| | 1 | Jordan Lee | 555 - 0142 | | 2 | Sam Rivera | NULL | | 3 | Alex Chen | 555 - 0198 | SELECT name FROM customers WHERE phone = NULL ; -- returns 0 rows SQL doesn't evaluate conditions as just true or false — it has a third result: unknown . phone = NULL asks "does this unknown value equal this other unknown value?" There's no way to answer that, so SQL returns UNKNOWN for every single row, including Sam Rivera's. And WHERE only keeps rows where the condition is TRUE . UNKNOWN doesn't qualify, so the row gets filtered out — the exact same as if it had evaluated to FALSE . This is true even for the row that "should" match. NULL = NULL isn't TRUE — it's also UNKNOWN . NULL never equals anything, not even another NULL . That's the whole rule, and it applies uniformly, which is why = can't be patched into working here — it's not almost right, it's answering a different question than the one you're asking. The fix, step by step Recognize the symptom : a query that runs cleanly but returns fewer rows than it should — especially zero rows when you can see matching data — with a NULL column somewhere in the WHERE clause. Swap = for IS NULL (or != for IS NOT NULL ). These are dedicated operators built specifically to test for absence, not comparison operators being asked to do somethin
AI 资讯
I Reverse-Engineered a Restaurant ERP With No Documentation. Here's What It Taught Me About Being a Self-Taught Developer.
There is no manual for TronSoft. No API reference, no schema diagram, no forum thread explaining why a comanda refuses to close. If you want to understand it, you open the database and start pulling threads until something makes sense. That's exactly what I did — for months, on top of my actual job. The problem nobody wrote down I'm the Operations Manager at a restaurant in Itaúna, a mid-sized town in Minas Gerais, Brazil. I'm also the only person there who writes software. Not because I was hired to — because the restaurant runs on a Brazilian ERP called TronSoft, built on a Firebird database, and Firebird doesn't come with the kind of ecosystem you get around Postgres or MySQL. No Stack Overflow flood of answers. No official docs beyond a thin operator manual. Vendor support exists, but it's slow, and it doesn't scale to "I want to automate this specific internal workflow at 11pm on a Tuesday." So when I needed to automate payment reconciliation, close out comandas without touching the vendor's fragile UI, and trigger fiscal document emission (NFC-e) reliably, I didn't have a spec to follow. I had a live production database and a lot of curiosity. Learning a system by watching it think I started the way you'd expect: opening tables, guessing at relationships, breaking things in a test environment until I understood why they broke. Over time that turned into something more systematic — I ended up documenting 390 tables and 514 foreign keys across roughly 40 functional modules, entirely from observation. No vendor documentation, no source code access. Just structure, inference, and a lot of trial and error. Some of what I learned only reveals itself under pressure: Firebird's SQL dialect has its own quirks — FIRST 1 instead of LIMIT , for one. Small thing, but it breaks every query you copy-paste from a Postgres tutorial. Primary keys aren't auto-incrementing in the way you'd assume. They're driven by generators ( GEN_ID ), and if you write a record without syncing
AI 资讯
AWS News - S1E2
Last week we kicked off a series covering the (data/storage/network) announcements that, in my view, had the most impact. This week I'm bringing 5 more recent launches to run through the fine-tooth comb. Description, the pain point it solved, and my critical take on each one. 1. Aurora DSQL lands in five more regions What it is: Aurora DSQL, AWS's distributed, serverless SQL database, is now available in Asia Pacific (Hong Kong), Asia Pacific (Mumbai), Asia Pacific (Singapore), Europe (Stockholm), and South America (São Paulo). With this launch, it now covers 19 regions total. Official link: https://aws.amazon.com/about-aws/whats-new/2026/05/amazon-aurora-dsql-five-additional-aws-regions/ How it used to be (the pain point): Until now, if you wanted to run Aurora DSQL with decent latency for users in Brazil, there was no regional option here. You either accepted the latency of hitting us-east-1 (an ugly phrase for a transactional application to hear) or gave up on DSQL entirely and went with a traditional Aurora PostgreSQL, purely for geographic proximity. My take: region expansion is the kind of announcement that isn't sexy, but it's what decides whether a service actually goes into production or stays a showcase item. With São Paulo on the list, the main adoption blocker for DSQL around here (latency) drops significantly. That said, it's worth remembering DSQL is still a relatively young product, with compatibility limitations against full PostgreSQL (extensions, certain data types, certain transactional features). Regional presence solves latency, it doesn't solve feature-set maturity. Those are two separate conversations. 2. Aurora DSQL gets a native PHP connector What it is: launch of the Aurora DSQL connector for PHP (PDO_PGSQL), which handles IAM authentication natively: generates a token per connection, guarantees the valid token gets used, and keeps full compatibility with the PDO_PGSQL that the PHP ecosystem already knows. It also brings retry with exponent
AI 资讯
What a Small-Business CRM Needs Beyond Contact Storage
A contact table is easy to build. A usable CRM is an operations system. The difficult part is not storing a name and email address. It is preserving context as work moves between people, organizations, deals, tasks, notes, imports, reports, and follow-up. That requires deliberate data modeling and product decisions. Model relationships, not isolated records A customer may belong to an organization. An organization may have several contacts. A deal can involve multiple people, tasks, notes, and status changes. If those relationships are flattened into one spreadsheet-like table, duplicate data and contradictory updates appear quickly. Define stable identifiers and explicit relationships early. Treat activity history as a product feature Users need to know what changed, when it changed, and who changed it. Audit history supports troubleshooting and accountability. It also makes bulk operations safer: after an import or mass edit, an administrator should be able to understand the result rather than guessing which rows moved. Decide which actions deserve history, how long it is retained, and who can see it. Avoid collecting sensitive data simply because the schema allows it. Design imports for failure CSV import is where clean demos meet messy reality. A useful import flow should provide: column mapping; required-field validation; duplicate-handling rules; a preview before committing; clear row-level errors; an exportable error report; idempotent or recoverable behavior where practical. Never assume the first row contains perfect headers or that dates, phone numbers, and booleans use one format. Make views part of the workflow Saved filters and views let different roles focus on their work without changing the underlying data. A sales view may emphasize open deals and next actions. An operations view may emphasize overdue tasks. An administrator may need import history and permission context. This is more than UI convenience: it is a way to keep one shared system useful
AI 资讯
Durable Memory: Why Vector Databases Aren't Enough
Part 3 of the Building the AI Memory Stack series After finishing Part 2, I noticed something. The...
AI 资讯
Reclaiming Terabytes: How to Cut a Managed Database Bill Without Downtime
Managed databases are the cloud cost line people quietly stop looking at. Compute gets rightsized, storage on the instances gets cleaned, but the RDS, Aurora, or Azure SQL bill just grows, because a database feels too load-bearing to touch. It is not. Here is how I have cut managed database spend without a maintenance window, in the order of least risk to most. The theme throughout: databases give you more no-downtime levers than people assume, and the biggest wins are usually storage and rightsizing, not some exotic re-architecture. Start with the free win: reclaim dead storage Storage is where the surprise terabytes hide, and most of it comes off with zero downtime. Drop what nobody reads. Old audit tables, soft-deleted rows that were never purged, expired sessions, staging data that got promoted to prod years ago. A DELETE in batches plus a purge job is the boring, safe first move. Reclaim space after deletes. On Postgres, deleted rows leave bloat until vacuumed. Run VACUUM (and check pg_stat_user_tables for dead tuples). On SQL Server / Azure SQL, rebuild or reorganize fragmented indexes to reclaim pages. This is where the "reclaimed terabytes" headlines actually come from. Kill redundant indexes. Unused and duplicate indexes cost storage and slow writes. Postgres pg_stat_user_indexes (look for idx_scan = 0 ) and SQL Server's missing/unused index DMVs tell you which ones earn their keep. Dropping an unused index is online. Right-size your storage type. On AWS, moving from gp2 to gp3 lets you provision IOPS and throughput independently and usually costs less for the same performance. The modify is applied without downtime. None of the above requires a window. It is pure hygiene, and on a neglected database it is often the single biggest line-item drop. Rightsize the instance (yes, without downtime) The reflex fear is that resizing a database means an outage. With a Multi-AZ deployment it usually does not. Check if you are oversized first. Pull 30 days of CPU, fre
AI 资讯
I Built HackForPinas to Make Philippine Hackathons Easier to Discover
In my previous article, I talked about Train Track, the transit app I built around Metro Manila's railway systems. This project started with a completely different problem. I kept thinking about how difficult it can be to discover hackathons and coding competitions. Not because they don't exist. They do. The problem is that they're scattered everywhere. A university might announce one. A government agency might host another. A private company might run one. A developer community might post another. And suddenly you're checking multiple websites just to figure out: What can I actually join? So I built HackForPinas. What is HackForPinas? HackForPinas is a free, public, and open-source directory for Philippine: Hackathons Coding challenges Technology competitions The idea is pretty straightforward: Make opportunities easier to discover. Events can be filtered by: Region Format Organizer type Status Organizers are categorized as: Government University Private Instead of browsing through unrelated websites, users can explore opportunities in one place. But the more I worked on it, the more I realized that the directory itself wasn't the hardest part. The data was. The Data Problem Imagine trying to collect hackathons from different websites. One might have an RSS feed. Another might use WordPress. Another might expose an API. Another might have an ordinary HTML page. And another might not have anything structured at all. So HackForPinas uses multiple scraping strategies: WordPress REST API RSS GDG Community Eventbrite HTML + Cheerio The scraper runs through a background endpoint and collects events from different Philippine technology sources. The interesting part wasn't: "Can I scrape a website?" It was: Can I turn information from completely different sources into one consistent dataset? That became a much more interesting engineering problem. I Didn't Want Anyone to Publish Directly There's another problem with a public directory. If anyone can submit an event, what s
AI 资讯
Your AI agent writes migrations that look safe. Here's what they actually do to Postgres.
You've seen the headlines by now. An agent in Cursor wiped a company's production database, backups and all, in about nine seconds. Replit's agent nuked another company's prod. Same shape every time: the agent was sure of itself, the SQL was valid, and nobody was in the loop to say wait. Those are the loud failures. The fix for them is boring and you already know it. Don't hand an agent write access to prod. Read-only by default, propose instead of apply, keep a human on the button. But there's a quieter version that a permissions policy won't catch, and that's the one I want to talk about. Your agent is probably doing it right now. It looks completely fine in the diff. The migration that passes review and still takes the site down Ask an agent to make an email column unique. It writes: ALTER TABLE users ADD CONSTRAINT users_email_unique UNIQUE ( email ); Correct SQL. Does exactly what you asked. It sails through review because there's nothing to see. Then on a users table with any real size, it grabs an ACCESS EXCLUSIVE lock and scans every row to build the unique index, and for the whole length of that scan nothing else can read or write the table. The API starts timing out. The connection pool fills. Now you're in an incident over a one-line migration that everybody approved. The agent didn't do anything a decent junior engineer wouldn't have done. That's the trap. The danger isn't the SQL, it's the lock the SQL takes, and you can't see a lock by reading a statement. You'd have to know Postgres locking cold: which DDL grabs which lock, and for how long, and what it shuts out while it holds. And you'll still miss one at 2am. I got tired of missing them. So I measured one. What the lock actually costs I ran the same schema change two ways against a real Postgres 18. Fifty million rows, twenty connections doing ordinary traffic. The unsafe version was a plain SET NOT NULL , which also scans under ACCESS EXCLUSIVE . The safe version was the NOT VALID then VALIDATE da
开发者
Netflix Adopts Cloud-Native Job Queueing System Kueue to Replace an In-House Solution
Netflix migrated most of its batch workloads onto Kueue, an open-source cloud-native batch job execution system that has outgrown its homegrown solution over the years. The company mapped the capabilities previously created in-house to Kueue’s functionality and also benefited from new features that would have been costly to incorporate into its homegrown solution. By Rafał Gancarz
AI 资讯
SQL Window Functions: How to Get the Top Row Per Group
By the end of this page you can answer the question that stops most people the first week they write SQL: which row is the best one in each category. You will know OVER and PARTITION BY , the three ranking functions and how each treats a tie, a running total, and LAG for comparing a row to the one before it. It is about twenty-five minutes. Here is what to actually do with it. The next time you write GROUP BY genre and get back a best rating without the name attached to it, stop rewriting the GROUP BY . Add ROW_NUMBER() OVER (PARTITION BY genre ORDER BY rating DESC) to the plain query instead, then keep the rows numbered 1. That is the whole move, and it replaces a query most people never get working. The short version: a window function adds a calculated column to each row while leaving every row in place. Grouping collapses rows. A window looks at them. One idea decides everything else on this page, so it gets the picture. Both halves do the same arithmetic over the same four rows, and only one of them still has four rows at the end. The original carries a diagram here. In words: Two panels side by side, each starting from the same stack of four identical row shapes. The left panel is labelled GROUP BY. Its four rows funnel down through a single arrow into one row at the bottom, and the four original rows are shown faded to indicate they are gone from the result. Only one row remains. The right panel is labelled OVER. Its four rows stay exactly where they are, at full strength, and each one gains a small badge on its right hand side holding a number: one, two, three, four. Nothing funnels and nothing is faded. The contrast is the whole idea: the left panel ends with a single summary row and no way to say which original row it came from, while the right panel ends with all four rows still present, each carrying its own calculated value. The worked example is real. Every number on this page comes from a published portfolio project: finding the genuinely overlooked g
AI 资讯
GROUP BY and HAVING: How to Summarize Rows Without Getting a Fake Answer
By the end of this page you can write a summary query and know its answer is real. You will know exactly what GROUP BY does to your rows, which columns you are allowed to select afterwards and why, where WHERE goes, where HAVING goes, and why swapping them is the difference between a finding and a number that means nothing. It is about twenty-five minutes. Here is what to actually do with it. On the next summary query you write, add one line setting a minimum group size before you read the ranking. One line, and it removes the most common way a summary query produces a confident wrong answer. The short version: WHERE filters rows before grouping. HAVING filters groups after. Without a HAVING floor, tiny groups float to the top of every ranking. One idea decides everything else here, so it gets the picture. Grouping happens in the middle of the query, and the two filters sit on opposite sides of it. The original carries a diagram here. In words: A left-to-right pipeline in four stages. Stage one is a column of eight individual row boxes. Stage two is a gate labelled WHERE, through which six rows pass and two are crossed out and stopped. Stage three shows the surviving six rows collapsing into three group boxes, one holding three rows, one holding two rows, and one holding a single row. Stage four is a second gate labelled HAVING, through which the group of three and the group of two pass, while the group holding only one row is crossed out and stopped. The result at the far right is two groups. The picture shows that WHERE acts on individual rows before any grouping exists, and HAVING acts on whole groups after they have been formed, which is why the two filters cannot be swapped. The worked example is real. Every number on this page comes from a published portfolio project: 82,956 games from the Steam catalogue, with review counts, ratings and genres. The queries run against the full dataset at Steam Hidden Gems on GitHub . If SELECT and WHERE are also new, start wi
AI 资讯
SQL Foundations, Start to Finish
By the end of this page you can say, out loud and in your own words, what every core piece of SQL does. What a table and a row really are. The six clauses, and the order they actually run in, which is not the order you type them. NULL , and why it breaks comparisons. Filtering, aggregation, GROUP BY and HAVING . Joins. CASE . Subqueries, CTEs and window functions. Keys and indexes. That list is most of what an analyst job, an interview, and a first real dataset will ask of you. Here is what to actually do with it. Go through once end to end without stopping, just for the shape. Then come back to the retrieval sheet near the bottom, cover the right-hand column, and try to say each answer before you read it. That second pass is where the learning happens, and there is measured evidence for it further down. The short version: SQL is one sentence with six parts, and every part answers a different question about your rows. Learn what each part does and where it runs, and the rest is vocabulary. One idea decides more of your SQL experience than any other, so it gets the picture. You write a query in one order. The database runs it in a different order. Almost every confusing SQL error is that gap. The original carries a diagram here. In words: Two columns of stacked boxes face each other. The left column, headed "you write", lists the clauses in typing order from top to bottom: SELECT, FROM, WHERE, GROUP BY, HAVING, ORDER BY, LIMIT. The right column, headed "it runs", lists the same clauses in execution order: FROM, WHERE, GROUP BY, HAVING, SELECT, ORDER BY, LIMIT. Curved lines connect each clause on the left to the same clause on the right. Six of the seven lines run roughly straight across. One line, the one belonging to SELECT, is drawn in a strong accent color and sweeps steeply downward from the very top of the left column to the fifth position on the right, showing that SELECT is written first but runs almost last, after grouping has already happened. What this page