AI 资讯
SQL Formatting Best Practices: A Practical Guide for Engineers
SQL is arguably the most widely used language in software engineering, yet it is often the least carefully written. Most teams enforce strict linting on their application code but leave SQL queries as a free-for-all. This guide covers the formatting rules that separate maintainable, team-friendly SQL from query spaghetti that haunts on-call rotations. Why Poorly Written SQL Is a Real Engineering Problem Unformatted SQL is not just an aesthetic issue - it is a correctness risk. Dense, run-on queries make it nearly impossible to spot accidental Cartesian products, missing GROUP BY clauses, or WHERE conditions that silently bypass indexes. By the time a performance problem surfaces in production, tracing it back to the root cause becomes a painful exercise in reading someone else's stream of consciousness. Rule 1: Keyword Capitalization SQL engines treat select and SELECT identically, but human readers do not. Always uppercase reserved keywords such as SELECT, FROM, WHERE, JOIN, GROUP BY, and ORDER BY. Keep table names, column names, and aliases lowercase. This single habit immediately creates a visual boundary between the logic structure of the query and the underlying data it operates on. Rule 2: Indentation and Clause Alignment Think of SQL clauses as layers in a data pipeline. Each major clause - SELECT, FROM, WHERE, GROUP BY, ORDER BY - should start at the left margin. Columns and filter conditions beneath them should be indented by 4 spaces (or 1 tab, as long as your team is consistent). This structure lets any reviewer skim the query top-to-bottom and understand the data flow at a glance. Rule 3: Trailing vs. Leading Commas This is a genuinely debated topic on data teams. Leading commas (placing the comma at the start of each new line) make version control diffs significantly cleaner when columns are added or removed. Trailing commas look more natural for developers coming from JavaScript or Python. Neither approach is wrong - what is wrong is mixing both styles
AI 资讯
Why Your Vector Database Is Overpriced: Lucene's 32x Compression and Serverless Economics
Why Your Vector Database Is Overpriced: Lucene's 32x Compression and Serverless Economics In 2026, the boundary between "search engine" and "AI infrastructure" has dissolved. What started as text indexing has become the backbone of retrieval-augmented generation, vector databases, and serverless AI pipelines. This is the story of how the oldest search technology in the Java ecosystem became the most important infrastructure you've never noticed. The Convergence No One Saw Coming Five years ago, if you said Apache Lucene would power the next generation of AI infrastructure, you'd have been laughed out of the room. Lucene was the boring Java library that powered Elasticsearch — reliable, yes, but hardly exciting. The action was in vector databases: Pinecone, Weaviate, Qdrant. The cool kids had moved on. That narrative died in 2025. What happened was a structural inversion. While vector-native databases optimized for one thing (fast similarity search), the real production pain points were everywhere else: hybrid search, metadata filtering, provenance tracking, multi-tenant security, and — most critically — the ability to query both your documents and your vectors in a single, unified system. Lucene didn't just survive this transition. It engineered it. Through a series of aggressive, hardware-native optimizations between versions 10.0 and 10.4, Lucene transformed from a text indexer into a vector search kernel capable of outperforming specialized databases while maintaining the operational maturity that enterprises actually need. And Elasticsearch, riding on Lucene's coattails, didn't just integrate vectors — it re-architected itself into a stateless, serverless platform that happens to do search. This post examines three layers of that transformation: the engine (Lucene), the platform (Elasticsearch), and the architecture (AI-native search infrastructure). Each layer tells a different story, but they share a common thread: the future of AI infrastructure is being buil
AI 资讯
What Happens When a Database Operation Fails Midway? NestJS Transactions to the Rescue
Imagine a simple money transfer scenario. John sends money to his friend Sarah. The system successfully deducts money from John's account, but before it can credit Sarah's account, the application crashes. Without proper safeguards, John's money would disappear from the system, creating inconsistent and unreliable financial records. To prevent this type of problem, database transactions are used. Transactions ensure that a group of related database operations either complete successfully together or fail together. If any part of the process encounters an error, all changes are reverted, ensuring that the database remains consistent. Transactions make database operations atomic. Atomicity means that all operations inside a transaction are treated as a single unit of work. Either every operation succeeds and is committed to the database, or all operations fail and are rolled back. Partial updates are never permanently stored. A database transaction is a group of one or more database operations executed as a single unit. Either all operations succeed together or all operations fail together. This guarantees database consistency even if an application crashes, a network failure occurs, or an unexpected error is encountered during execution. It is important to understand that a transaction is not simply a single database query. While individual queries such as save, update, or delete interact with the database, a transaction wraps multiple queries inside a controlled all-or-nothing boundary. This prevents partial updates and ensures data integrity throughout the process. Prerequisites Before starting, make sure you have the following: Basic knowledge of NestJS Basic understanding of TypeORM Basic knowledge of PostgreSQL Understanding of basic database operations (save, update, delete) in TypeORM Project Setup In this article, we will create a simple NestJS application to demonstrate the importance of transactional queries when multiple database write or update operations
AI 资讯
QN : Ingest and transform data in a lakehouse
lakehouse has two storage areas ; Files and Tables Files Store structured, queryable data by sql Supports schema definitions and ACID transactions Tables Stores Raw or semi-structured data(CSV, parquet, JSON) No schema support Flexible for data explorations Schema allows for logical ordering of data on business functions or domain (sales,marketing etc) A dbo schema is enabled by default once a lakehouse is created Schema-enabled lakehouses also support schema-level permissions and cross-workspace queries using the four-part namespace Lakehouse mode : Lakehouse Explorer and SQL analytics endpoint Lakehouse Explorer: Allows managing, Update, create, upload of data.You can switch between tables in the lakehouse SQL anlytics endpoit : Does not allow modifying of the underlying data. You can query using TSQL at read only mode. Loading data into lakehouse: Upload data into files/ folders on the explorer Load into delta tables (no code) Transform using power query in dataflow gen2 INgest into notebooks using apache spark (programmatically) Use Copy data to move data into differnt sources using data factory pipelines -Shortcuts allow you to reference external data reducing copies. Access is managed by One Lake. Schema shortcuts map an entire schema to a folder of Delta tables in another lakehouse. SQL analytics endpoint provides read-only access to lakehouse tables using T-SQL queries. SQL USE CASES : adhoc queries, BI connections to power bi or azure data studio, Data validation You can use SQL views to store reusable query logic. Views are useful when you need to apply business rules, simplify complex joins, or provide curated data for downstream consumers. You can use Spark SQL for SQL-like queries or PySpark for programmatic data manipulation in Notebooks. Spark SQL works well for familiar SQL patterns. PySpark provides greater flexibility for complex transformations and integration with Python libraries. Power BI is the business intelligence and reporting layer in Fabr
AI 资讯
DuckLake Spec, pg_background 2.0, and pgsql_tweaks 1.0.3 Enhance Database Ecosystem
DuckLake Spec, pg_background 2.0, and pgsql_tweaks 1.0.3 Enhance Database Ecosystem Today's Highlights This week's highlights include DuckDB's new DuckLake specification for simplified dataframe integration with data lakes, alongside key updates from the PostgreSQL community. We cover pg_background 2.0 for safer asynchronous SQL execution and the release of pgsql_tweaks 1.0.3 for enhanced monitoring and performance tuning. The DuckLake Spec Is so Simple, Even a Clanker Can Build One for Dataframes (DuckDB Blog) Source: https://duckdb.org/2026/05/04/ducklake-dataframe.html The DuckDB team has unveiled the DuckLake v1.0 specification, a significant step towards simplifying data lake interactions with dataframes. This specification aims to provide a robust yet straightforward framework for reading and writing dataframes directly from and to data lake storage, emphasizing ease of implementation. The announcement highlights the specification's simplicity, so much so that even AI can be leveraged to generate compatible dataframe reader/writer tools. This initiative promises to democratize data lake access, allowing developers and data engineers to integrate DuckDB's powerful analytical capabilities with their data lake architectures more seamlessly. By defining a clear standard, DuckLake facilitates the creation of a vibrant ecosystem of tools and connectors, enabling efficient data processing directly within the data lake context without complex ETL pipelines. This development positions DuckDB as an even more versatile tool for analytical workloads, bridging the gap between local data processing and large-scale data lake environments. The ability to easily build data lake connectors, potentially even with AI assistance, marks a notable shift towards more accessible and integrated data workflows. This could streamline operations for data scientists and analysts who frequently work with large datasets stored in various data lake formats, allowing them to leverage DuckDB's
AI 资讯
Self-Host Postgres or Use Supabase? Here's How to Decide
Short answer first: use Supabase if you want Postgres plus auth, realtime, storage, and a dashboard as one managed bundle. Self-host Postgres – or use a managed Postgres – if you mostly need a database and your app already handles its own auth and logic. The choice is not really "Postgres vs Supabase". It's whether you need the extra layers Supabase puts on top of Postgres. Supabase is not a database Supabase runs on PostgreSQL, but it's a stack of services around it: Postgres – the actual database Auth – user signup, login, JWT tokens Realtime – live updates over websockets Storage – an S3-style file store Edge Functions – serverless functions Studio – dashboard + auto-generated REST/GraphQL API So "self-host Postgres or use Supabase" compares a plain database to a full backend. The honest question: do you need those extra layers, or just the database underneath them? A quick test: You use Supabase Auth, Storage, and Realtime → Supabase earns its place. You use one of them → it's replaceable. You use none and treat it as "Postgres with a nice dashboard" → you want plain Postgres. Side-by-side comparison Factor Supabase (managed) Self-hosted Supabase Plain Postgres (managed or self-hosted) Database engine PostgreSQL PostgreSQL PostgreSQL Built-in auth Yes Yes No (bring your own) Realtime / websockets Yes Yes No File storage Yes Yes No Dashboard + auto API Yes Yes No (use any SQL client) Backups Managed (limits by plan) You manage Managed or you manage Cost shape Metered, grows with usage Server cost + your time Database only Self-host effort None High (many containers) Low–medium Lock-in Medium–high Medium Very low The lock-in point decides it for many teams. Your data is standard Postgres in every option ( pg_dump portable). The lock-in is everything else: Auth tokens, Storage paths, Supabase-specific RLS policies, Edge Function code. The more Supabase-specific features you adopt, the harder the exit. When each option wins Pick managed Supabase when: You're startin
AI 资讯
100 Days of ClickHouse® – Day 6: Importing CSV Files into ClickHouse®
CSV files are one of the most common formats for storing and exchanging data. Whether you’re working with logs, analytics data, application exports, or reports, there will likely come a time when you need to load CSV data into ClickHouse®. The good news is that ClickHouse® makes CSV ingestion straightforward and efficient. In this guide, you’ll learn how to create a table, prepare a CSV file, load CSV data into ClickHouse®, and verify that the data has been imported successfully. Why Use CSV Files with ClickHouse®? CSV (Comma-Separated Values) files are simple, portable, and supported by virtually every data platform. Common use cases include: Importing exported application data Loading historical datasets Migrating data from other databases Testing analytics workloads Sharing data between systems Because ClickHouse® is designed for high-performance analytics, it can efficiently process and query large CSV datasets once they are loaded into a table. Sample CSV File Let’s assume we have a file named employees.csv with the following contents: id,name,department,salary 1,Alice,Engineering,75000 2,Bob,Marketing,60000 3,Charlie,Finance,70000 This simple dataset will help demonstrate how to load CSV data into ClickHouse®. Step 1: Create a Table in ClickHouse® Before importing data, create a table that matches the structure of the CSV file. CREATE TABLE employees ( id UInt32, name String, department String, salary UInt32 ) ENGINE = MergeTree() ORDER BY id; This table contains four columns that correspond directly to the columns in our CSV file. Step 2: Load CSV Data into ClickHouse® There are several ways to import CSV data, but one of the most common methods is using the ClickHouse® client. Run the following command: clickhouse-client --query=" INSERT INTO employees FORMAT CSVWithNames" < employees.csv The CSVWithNames format tells ClickHouse® that the first row contains column headers. After executing the command, ClickHouse® will read the CSV file and insert the records
开发者
From Individual Sandbox to Multiplayer: Group Rooms, Linked Servers, and Gamification in T-SQL Online
We just deployed a major update to our SQL Server web sandbox, moving from an individual tool to a collaborative environment: ✅ Group Rooms (Beta): Create private rooms using security tokens to chat and write code together in real time. ✅ Simulated Linked Servers (Beta): Connect with your friends' sandboxes to run cross-queries strictly in read-only mode to preserve performance. ✅ Gamification & XP: Earn experience points and unlock technical badges as you run queries or build database schemas. ✅ Social Layer: Manage your friends list and customize your public developer profile to showcase your achievements. Currently, all features are completely free to use during this phase of the platform. Try it out with your colleagues at tsqlsandbox.online and leave your feedback below!
AI 资讯
PostgreSQL 2200D Error: Causes and Solutions Complete Guide
PostgreSQL Error 2200D: invalid escape octet The 2200D: invalid escape octet error occurs in PostgreSQL when a bytea value contains an invalid escape sequence. This typically happens with the legacy escape format for binary data, where octet values must be represented as three-digit octal numbers in the range \000 to \377 . If the escape sequence falls outside this range or uses non-octal digits, PostgreSQL raises this error immediately. Top 3 Causes 1. Out-of-range octal values in bytea escape literals The bytea escape format only accepts octal values from \000 to \377 (decimal 0–255). Using values like \400 or non-octal digits like \9 will trigger this error. -- BAD: \400 exceeds valid octal range (max is \377) SELECT E ' \\ 400' :: bytea ; -- ERROR: invalid escape octet -- BAD: \9 is not a valid octal digit SELECT E ' \\ 9AB' :: bytea ; -- ERROR: invalid escape octet -- GOOD: valid octal escape sequences SELECT E ' \\ 377' :: bytea ; -- decimal 255 SELECT E ' \\ 101' :: bytea ; -- 'A' character SELECT E ' \\ 000' :: bytea ; -- null byte 2. Using escape format strings with hex output format Since PostgreSQL 9.0, the default bytea_output is hex . Applications that mix hex -format output back into escape -format input processing can generate malformed escape sequences. -- Check current bytea output format SHOW bytea_output ; -- GOOD: Use hex format (recommended for all new projects) SELECT ' \x DEADBEEF' :: bytea ; SELECT ' \x 48656C6C6F' :: bytea ; -- 'Hello' -- GOOD: Use encode/decode for safe conversions SELECT encode ( ' \x DEADBEEF' :: bytea , 'hex' ); -- output as hex string SELECT encode ( ' \x DEADBEEF' :: bytea , 'base64' ); -- output as base64 SELECT decode ( 'deadbeef' , 'hex' ); -- hex string → bytea SELECT decode ( 'SGVsbG8=' , 'base64' ); -- base64 → bytea 3. Incorrect escaping during data migration or manual SQL When migrating binary data from other databases (Oracle, MySQL) or writing raw INSERT statements manually, developers often confuse octal and
AI 资讯
Extended RUM in DocumentDB extension for PostgreSQL: Efficient ESR (Equality, Sort, Range) Queries
Last year, I examined RUM indexes within this series on multi-key indexing, demonstrating that they cannot substitute MongoDB's compound indexes for sorted queries. A year later, Microsoft has fixed this in the DocumentDB extension for PostgreSQL with an Extended RUM index that preserves the ordering of the keys, allowing an ordered scan rather than a bitmap scan. Let's revisit our pagination query to see how it performs now. I start a container with the latest DocumentDB (version v0.112-0 from May 26, 2026): docker run -d --name documentdb-local -p 10260:10260 -p 9712:9712 ghcr.io/documentdb/documentdb/documentdb-local:latest --username franck --password franck --start-pg I can connect to PostgreSQL on port 9712, where many extensions are installed, including the extended RUM index: docker exec -it documentdb-local psql -p 9712 postgres psql ( 17.10 ( Debian 17.10-1.pgdg13+1 )) Type "help" for help. postgres = # \dx List of installed extensions Name | Version | Schema | Description ------------------------- +---------+------------+------------------------------------------------------------ documentdb | 0.112-0 | public | API surface for DocumentDB for PostgreSQL documentdb_core | 0.112-0 | public | Core API surface for DocumentDB on PostgreSQL documentdb_extended_rum | 0.112-0 | public | DocumentDB Extended RUM index access method pg_cron | 1.6 | pg_catalog | Job scheduler for PostgreSQL plpgsql | 1.0 | pg_catalog | PL/pgSQL procedural language postgis | 3.6.3 | public | PostGIS geometry and geography spatial types and functions tsm_system_rows | 1.0 | public | TABLESAMPLE method which accepts number of rows as a limit vector | 0.8.2 | public | vector data type and ivfflat and hnsw access methods ( 8 rows ) postgres = # I can also connect to the MongoDB-compatible API: docker exec -it documentdb-local mongosh -u franck -p franck 'mongodb://localhost:10260/?tls=true&tlsAllowInvalidCertificates=true' Current Mongosh Log ID: 6a0b3b537d2a1c3471d1a7ba Connecting to: mo
AI 资讯
We Replaced Redis with MySQL SKIP LOCKED for Inventory Reservation — Oversells Went to Zero
For two years, our Sponsored Placements service booked limited ad inventory through Redis: a counter in Redis, a Redlock around the decrement, and a TTL key per hold. It oversold. Not catastrophically — consistently. 40–60 double-booked placements a month , each one a manual refund and an apology email to an advertiser. The root cause was never one bug. It was the architecture: two sources of truth that could not be made atomic with each other. The count lived in Redis; the ownership lived in SQL. No transaction spans both. The Redlock only ever protected the Redis half. The one mental shift SKIP LOCKED turns a contended table into a concurrent work queue. Instead of every request fighting over one counter, each request grabs different rows and ignores the ones someone else is holding. FOR UPDATE alone serializes — that's the experience that scares people off SQL locking. FOR UPDATE SKIP LOCKED is the opposite: a transaction that would have blocked instead skips the locked row and takes the next free one. One row per reservable unit, then: START TRANSACTION ; SELECT id FROM inventory_unit WHERE placement_id = 42 AND ( status = 'available' OR ( status = 'held' AND hold_expires_at < NOW ( 3 ))) -- self-healing expiry ORDER BY id LIMIT 2 FOR UPDATE SKIP LOCKED ; -- the whole trick UPDATE inventory_unit SET status = 'held' , reservation_id = 'uuid' , hold_expires_at = NOW ( 3 ) + INTERVAL 10 MINUTE WHERE id IN ( 1107 , 1108 ); INSERT INTO reservation (...) VALUES (...); COMMIT ; Two concurrent requests for the same pool lock different rows. Neither waits. The claim, the hold, and the reservation are one transaction — there is nothing to reconcile because there is nothing else. The numbers (8 weeks before vs 8 weeks after) Metric Redis + Redlock MySQL SKIP LOCKED Oversells / month 40–60 0 Reservation p95 210 ms 34 ms Reservation p99 540 ms 61 ms Throughput / instance ~600 RPS 1,400 RPS Lock-wait timeouts / day ~900 <5 Nightly reconciliation 9–14 min deleted Redis cluster
AI 资讯
The Future of Query Optimization: AI-Driven Insights in Big Data
Query optimization has never been a solved problem. The moment you think your database is running efficiently, data volumes triple, access patterns shift, and suddenly your carefully tuned indexes are doing more harm than good. For decades, database engineers have relied on rule-based query planners — systems that follow deterministic logic to pick execution plans. That model is cracking under the weight of modern big data workloads. AI-driven query optimization is emerging as the answer, and it's already changing how high-scale systems handle billions of records in real time. This isn't about replacing the database administrator. It's about giving them — and the database itself — a fundamentally smarter toolset. Why Traditional Query Planners Hit a Wall Every relational database ships with a query planner: a component that reads your SQL, examines table statistics, and decides how to execute the query. PostgreSQL's planner, for instance, uses cost-based estimation to choose between sequential scans, index scans, hash joins, and nested loops. The system is elegant, and it works — until it doesn't. The problem is that cost-based planners operate on inherently stale statistics. They estimate cardinality (the number of rows a filter will return) based on histograms and samples collected at the last ANALYZE run. When data distributions drift — as they constantly do in real-world systems — those estimates go wrong, sometimes catastrophically. A planner that believes a filter will return 100 rows but actually gets 10 million will choose a completely wrong join strategy, turning a 200ms query into a 45-second disaster. Scale compounds this fragility. In big data environments running on distributed systems like Apache Spark, Trino, or BigQuery, a bad plan doesn't just waste one machine's resources — it cascades across hundreds of nodes, blowing through memory budgets and creating shuffle bottlenecks that ripple across the cluster. How AI Changes the Optimization Equation AI
AI 资讯
A practical SQL query tuning playbook: execution plans, joins, indexes, and the traps
SQL tuning is the process of making a database query run faster and cheaper — cutting response time while minimizing the system resources it burns. Here's the playbook I actually use, from "this query is slow" to "this query is fixed," with the traps that bite people in the middle. The loop Tuning is iterative. The shape is always the same: Identify the problem. Find the slow query (logs, profiler, or user feedback) and measure a baseline — execution time and resource usage. You can't claim an improvement you didn't measure. Analyze & rewrite. Review the SQL for redundant joins, unnecessary work, and complex subqueries. Tighten the WHERE , select only the columns you need, convert subqueries to joins where it helps. Read the execution plan. Understand how the engine actually runs the query; find inefficient join orders and needless full scans. Revisit indexes. Evaluate whether existing indexes help; add or restructure as needed. Consider schema changes. If a column is updated so often that indexing it hurts, split it out. Sometimes the model is the bottleneck. Tune settings/hardware if it comes to that. Re-test and repeat. Apply changes, re-check the plan, confirm the gain, monitor. Reading an execution plan The execution plan shows how the DB will run your query — table scans, index access, join methods. Read it well and you can pinpoint where the time goes. Most engines expose it: EXPLAIN (MySQL/PostgreSQL), EXPLAIN PLAN FOR (Oracle), SET SHOWPLAN_ALL ON (SQL Server). Operators to know: Full Table Scan — reads every row. Happens when there's no suitable index, or the query can't use one. Index Scan — scans via an index; usually cheaper than a table scan. Index Seek — jumps to specific key values; very efficient, reads only the rows it needs. Nested Loops / Hash Join / Merge Join — the three ways to join two tables (more below). Sort — orders data; excessive sorting is a common performance drag. Three numbers that matter: Cost — estimated resources a step will cons
AI 资讯
ExtendDB: Open Source Amazon DynamoDB Compatible Adapter with Pluggable Storage Backends
AWS recently announced ExtendDB, a DynamoDB-compatible adapter that lets developers use the DynamoDB API with different storage backends, starting with PostgreSQL. The project supports existing SDKs and tools without modification, giving teams greater flexibility to run DynamoDB-style workloads outside of native DynamoDB while maintaining compatibility with current applications and workflows. By Renato Losio
AI 资讯
DuckDB 1.5.3 & Quack Protocol Release; PostgreSQL File Descriptor Tuning
DuckDB 1.5.3 & Quack Protocol Release; PostgreSQL File Descriptor Tuning Today's Highlights This week's database news highlights significant advancements for DuckDB, including a feature-packed 1.5.3 release and the innovative Quack client-server protocol. We also delve into a critical PostgreSQL performance tuning guide on managing file descriptors. DuckDB 1.5.3: Not an Ordinary Patch Release (DuckDB Blog) Source: https://duckdb.org/2026/05/20/announcing-duckdb-153.html DuckDB has announced the release of version v1.5.3, a "patch release" that, despite its designation, delivers a substantial upgrade to the ecosystem. While the core DuckDB engine sees limited bugfixes, the true power of this release lies in the significantly upgraded extensions that ship alongside it. These extensions introduce a wealth of new features that enhance DuckDB's capabilities across various data processing tasks, making it much more than a routine update. Key among the new features is the integration of the Quack client-server protocol, which is highlighted as a major advancement. This allows DuckDB instances to communicate and operate in more distributed, concurrent environments, expanding its utility beyond purely embedded scenarios. Developers are encouraged to explore the updated extensions for improved functionality, ranging from new data formats to enhanced analytical operations. This release underscores DuckDB's commitment to continuous innovation through its modular extension system, providing users with powerful new tools without requiring major core engine overhauls for every new feature. Comment: This release is a great example of how DuckDB's extension model brings rapid innovation. Developers should check the extension changelogs, as that's where the real new features are. Quack: The DuckDB Client-Server Protocol (DuckDB Blog) Source: https://duckdb.org/2026/05/12/quack-remote-protocol.html The DuckDB team has introduced Quack, a new client-server protocol designed to enable s
AI 资讯
Building a SQL Lexer in Rust: Why I Replaced `Vec ` with `&str` and `Ident(String)` with Spans
I've been building a database engine from scratch in Rust, and I recently finished the lexer. The lexer itself wasn't the most interesting part. What I found more valuable was how my design evolved as I learned more about Rust and how compilers and database systems are typically implemented. My First Approach When I started, I stored the input as a Vec<char> . It felt straightforward because I could access characters directly without worrying about UTF-8 boundaries. I also represented identifiers like this: Ident ( String ) At first glance, this seems perfectly reasonable. Every identifier token carries its own text, making it easy for the parser to consume. The Problem As the lexer grew, I started asking myself a simple question: The identifier already exists in the original SQL query. Why am I allocating another string and copying the same data into every token? For a query like: SELECT username , email FROM users ; the source text already contains: username email users Creating separate String allocations for each identifier means duplicating data that already exists. I also learned an important detail about Rust enums. The size of an enum is influenced by its largest variant. Once variants start carrying additional data, every token instance becomes larger than it otherwise needs to be. Moving to a Span-Based Design Instead of storing identifier text directly inside tokens, I switched to storing only the token kind: Ident along with source location information: Span { start , end , line , column , } Now the token only answers two questions: What is this token? Where did it come from? If the parser needs the actual identifier text, it can recover it directly from the original SQL source using the stored byte range. Replacing Vec<char> with &str The second design change was moving away from: Vec < char > and operating directly on: & str using lifetimes. Instead of creating another collection containing the entire input, the lexer now walks over borrowed source tex
开发者
Cloudflare Identifies Query Planning Bottleneck in ClickHouse
Cloudflare recently described how a slowdown in its billing pipeline was traced to contention inside the query planning stage of ClickHouse. The team profiled the bottleneck and patched ClickHouse to replace an exclusive lock with a shared lock, drop the per-query copy of the parts list, and improve part filtering. By Renato Losio
AI 资讯
I built a free SQL practice game where you work at a fictional Singapore bank
I've been frustrated with SQL learning resources for a while. Most are either: Dry reference docs Toy exercises with no context ("SELECT * FROM employees") Paid platforms with paywalls after level 3 So I built SQLwak — a free, browser-based SQL game where you're hired as a Graduate Analyst at Lion City Bank , a fictional Singapore bank. How it works Instead of abstract exercises, every challenge is a real business request from a colleague: "The Operations team needs all Central region branches for an upcoming audit." "Risk wants customers with credit scores below 600 who have active loans." "Finance needs vessels ranked by cargo revenue — use window functions." You write actual SQL against a realistic 9-table banking database and get immediate feedback. 57 levels across 4 tiers Tier Skills 🟢 Foundational SELECT, WHERE, ORDER BY, LIMIT 🟡 Intermediate JOINs, GROUP BY, HAVING, subqueries 🔴 Advanced CTEs, multi-table aggregations ⚫ Expert Window functions (RANK/DENSE_RANK OVER PARTITION BY), UNION ALL, compound CTEs The database schema Lion City Bank has two divisions: Retail Banking: customers, accounts, transactions, loans, branches, products Maritime Trade Finance (Advanced/Expert levels): vessels, cargo_shipments, trade_finance_facilities — covering voyages between Singapore, Port Klang, Bangkok, Jakarta, and Ho Chi Minh City. The maritime division exists because Singapore is a major trade hub. It makes the Expert levels genuinely interesting — you're ranking vessels by cargo revenue and analyzing trade finance utilisation rates, not just counting rows. Technical details Next.js 15 + TypeScript + Tailwind CSS SQLite via WebAssembly — all query execution is client-side, no backend needed Deployed on Vercel Fully open source: github.com/martinl5/sqlwak No signup. No download. Just SQL. Open the link and start writing queries: sqlwak.vercel.app Would love feedback on difficulty progression, new level ideas, or schema additions. What SQL concepts do you wish you'd pract
AI 资讯
DuckDB Integrates Lance Lakehouse; SQLite CVE Fix; Postgres 19 Beta on K8s
DuckDB Integrates Lance Lakehouse; SQLite CVE Fix; Postgres 19 Beta on K8s Today's Highlights This week, DuckDB introduces integrated vector and hybrid search with the Lance lakehouse format, enabling advanced AI workloads directly from SQL. Meanwhile, SQLite addresses a significant security vulnerability with a recent fix, and a new guide helps users test PostgreSQL 19 beta efficiently in Kubernetes clusters. Test-Driving the Lance Lakehouse Format in DuckDB (DuckDB Blog) Source: https://duckdb.org/2026/05/21/test-driving-lance.html DuckDB has announced a new integration allowing users to test-drive the Lance lakehouse format, a design specifically geared towards AI workloads. This collaboration between LanceDB and DuckLabs brings fast vector and hybrid search capabilities directly into DuckDB SQL, significantly streamlining data analysis for machine learning applications. The integration means users can perform complex queries involving vector embeddings and traditional tabular data without needing to move data between different systems or tools. This is a crucial development for data scientists and engineers who rely on efficient data access and processing for large-scale AI projects. The ability to perform sophisticated searches within the familiar DuckDB environment enhances productivity and reduces the operational overhead typically associated with managing specialized vector databases. This new feature democratizes access to advanced data structures for AI, making it simpler to build and prototype machine learning models on massive datasets. By supporting an open lakehouse format, DuckDB continues to position itself as a versatile analytical database, bridging the gap between traditional data warehousing and emerging AI data needs. Users are encouraged to try out this integration, which promises to unlock new possibilities for data exploration and feature engineering using a unified SQL interface. It's an excellent example of how embedded analytical databases
AI 资讯
Learn SQL Once, Use It for 30 Years: Why the Skill Doesn't Expire
A post titled "Learn SQL Once, Use It for 30 Years" hit the front page of r/programming this week (307 points, 48 comments). The claim sounds like the kind of thing a database vendor would put on a billboard, so I went looking for the part that holds up. It turns out the longevity is not marketing. It is a property of how the language was designed, and it is the reason SQL is one of the few skills on a developer's resume that does not quietly expire. I run a site that compares developer tools, which means I spend a lot of time watching technologies rise, peak, and get replaced. Most of what you learn in this field has a half-life measured in single-digit years. The framework you mastered in 2019 is legacy by 2024. SQL is the strange exception, and the reasons are worth understanding before you decide where to spend your next month of learning. Where the staying power comes from SQL did not start as a language. It started as a math paper. In 1970, Edgar Codd published "A Relational Model of Data for Large Shared Data Banks," which proposed organizing data into tables of rows and columns with formal rules for combining them. IBM built a query language on top of that model in the mid-1970s, called it SEQUEL, and later renamed it SQL after a trademark conflict. The important detail is the order: the model came first, the language second. SQL is a surface over a mathematical foundation that has not needed to change. That foundation is why the skill compounds instead of decaying. When you learn SQL, you are not memorizing one vendor's API. You are learning the relational model, and the model is the same whether the data sits in Postgres, MySQL, SQLite, Oracle, or SQL Server. A join is a join everywhere. Move from one database to another and the syntax shifts at the edges, but the way you think about the problem carries over intact. Compare that to a frontend framework, where moving stacks means relearning how to think, not just how to type. Declarative is the whole trick