<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: yang yaru</title>
    <description>The latest articles on DEV Community by yang yaru (@yaruyng).</description>
    <link>https://dev.to/yaruyng</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F2556672%2Fafe8855f-66d3-4864-8d9e-03fc071227cd.jpg</url>
      <title>DEV Community: yang yaru</title>
      <link>https://dev.to/yaruyng</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/yaruyng"/>
    <language>en</language>
    <item>
      <title>Understanding the Rerank Stage in Industrial RAG Pipelines</title>
      <dc:creator>yang yaru</dc:creator>
      <pubDate>Fri, 13 Mar 2026 09:03:30 +0000</pubDate>
      <link>https://dev.to/yaruyng/understanding-the-rerank-stage-in-industrial-rag-pipelines-582i</link>
      <guid>https://dev.to/yaruyng/understanding-the-rerank-stage-in-industrial-rag-pipelines-582i</guid>
      <description>&lt;p&gt;Retrieval-Augmented Generation (RAG) systems and modern search engines rely on multiple stages to retrieve the most relevant information for a user query. One critical component in these pipelines is &lt;strong&gt;Rerank&lt;/strong&gt;, a stage designed to improve the precision of retrieved results.&lt;/p&gt;

&lt;p&gt;In industrial systems, retrieval methods such as vector search or keyword search prioritize &lt;strong&gt;speed and recall&lt;/strong&gt;, which means they often return many candidates that are only partially relevant. The reranking stage solves this problem by &lt;strong&gt;reordering these candidates using a stronger but more computationally expensive model&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;This article explains how reranking typically works in production systems.&lt;/p&gt;




&lt;h2&gt;
  
  
  1. Query Processing
&lt;/h2&gt;

&lt;p&gt;The pipeline begins when a user submits a query. Before retrieval starts, the system may perform several preprocessing steps to better understand the user's intent.&lt;/p&gt;

&lt;p&gt;Common steps include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Query normalization&lt;/strong&gt; – removing noise, punctuation, or unnecessary tokens&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Query rewriting&lt;/strong&gt; – expanding or clarifying the query to improve recall&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Intent detection&lt;/strong&gt; – identifying the user’s goal or domain&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Example query:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"How to deploy Dify with Docker?"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;These preprocessing steps help the retrieval system generate better candidate results.&lt;/p&gt;




&lt;h2&gt;
  
  
  2. Multi-Recall (Candidate Generation)
&lt;/h2&gt;

&lt;p&gt;Next, the system retrieves a large set of candidate documents using fast retrieval strategies. This stage focuses on &lt;strong&gt;maximizing recall&lt;/strong&gt;, meaning it tries to retrieve as many potentially relevant documents as possible.&lt;/p&gt;

&lt;p&gt;Common retrieval approaches include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Vector Search&lt;/strong&gt; (embedding similarity)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Keyword Search&lt;/strong&gt; such as BM25&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Metadata filtering&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hybrid retrieval&lt;/strong&gt;, which combines multiple methods&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Vector Search → Top 50 documents&lt;/li&gt;
&lt;li&gt;Keyword Search → Top 30 documents&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;After merging, the system may have around &lt;strong&gt;80 candidate documents&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  3. Candidate Merge and Deduplication
&lt;/h2&gt;

&lt;p&gt;Because results come from multiple retrieval channels, they must be merged into a single candidate set.&lt;/p&gt;

&lt;p&gt;Typical operations include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Removing duplicate documents&lt;/li&gt;
&lt;li&gt;Normalizing scores from different retrieval methods&lt;/li&gt;
&lt;li&gt;Combining results into a unified list&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;After merging and deduplication, the candidate set may shrink to around &lt;strong&gt;60 documents&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  4. Pre-Filtering (Optional)
&lt;/h2&gt;

&lt;p&gt;To reduce computational cost before reranking, many production systems apply lightweight filtering.&lt;/p&gt;

&lt;p&gt;Examples include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Removing extremely short or low-quality documents&lt;/li&gt;
&lt;li&gt;Filtering by similarity thresholds&lt;/li&gt;
&lt;li&gt;Applying metadata constraints&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;After filtering, the system may keep around &lt;strong&gt;40 candidates&lt;/strong&gt; for reranking.&lt;/p&gt;




&lt;h2&gt;
  
  
  5. Reranking Stage (Core Step)
&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;rerank stage&lt;/strong&gt; evaluates how well each candidate document matches the query and assigns a new relevance score.&lt;/p&gt;

&lt;p&gt;Unlike embedding similarity—which compares vectors independently—rerank models typically use &lt;strong&gt;cross-encoders&lt;/strong&gt;. These models process the &lt;strong&gt;query and document together&lt;/strong&gt;, allowing them to capture deeper semantic relationships.&lt;/p&gt;

&lt;p&gt;Example scoring:&lt;/p&gt;

&lt;p&gt;Query:&lt;br&gt;
"How to deploy Dify with Docker?"&lt;/p&gt;

&lt;p&gt;Candidate scores:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Document A → 0.92&lt;/li&gt;
&lt;li&gt;Document B → 0.88&lt;/li&gt;
&lt;li&gt;Document C → 0.40&lt;/li&gt;
&lt;li&gt;Document D → 0.31&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The candidates are then reordered according to these scores.&lt;/p&gt;




&lt;h2&gt;
  
  
  6. Top-K Selection
&lt;/h2&gt;

&lt;p&gt;After reranking, the system selects the &lt;strong&gt;Top-K documents&lt;/strong&gt; with the highest relevance scores.&lt;/p&gt;

&lt;p&gt;Typically:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Top 5–10 documents&lt;/strong&gt; are selected.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These documents may be:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Sent to a &lt;strong&gt;Large Language Model (LLM)&lt;/strong&gt; as context in a RAG system&lt;/li&gt;
&lt;li&gt;Returned directly to the user in a search interface&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  7. Post-Processing (Optional)
&lt;/h2&gt;

&lt;p&gt;Some production systems apply additional processing after reranking.&lt;/p&gt;

&lt;p&gt;Examples include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Diversity control&lt;/strong&gt; to avoid returning highly similar documents&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Chunk merging&lt;/strong&gt; to combine adjacent text segments&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Context window optimization&lt;/strong&gt; to fit within LLM token limits&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These steps help improve the final response quality.&lt;/p&gt;




&lt;h2&gt;
  
  
  Typical Industrial Architecture
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User Query
    ↓
Query Rewrite / Intent Detection
    ↓
Multi-Recall
(Vector + Keyword + Metadata)
    ↓
Candidate Merge
    ↓
Pre-Filter
    ↓
Rerank (Cross-Encoder Model)
    ↓
Top-K Selection
    ↓
LLM Generation / Final Results
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Why Reranking Is Necessary
&lt;/h2&gt;

&lt;p&gt;Fast retrieval techniques such as vector search or BM25 are optimized for &lt;strong&gt;speed&lt;/strong&gt;, not deep semantic understanding. As a result, their ranking quality is limited.&lt;/p&gt;

&lt;p&gt;Reranking addresses this limitation by applying a more sophisticated model to a smaller set of candidates.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Method&lt;/th&gt;
&lt;th&gt;Speed&lt;/th&gt;
&lt;th&gt;Accuracy&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Vector Search&lt;/td&gt;
&lt;td&gt;Fast&lt;/td&gt;
&lt;td&gt;Medium&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;BM25 Keyword Search&lt;/td&gt;
&lt;td&gt;Fast&lt;/td&gt;
&lt;td&gt;Medium&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Rerank Model&lt;/td&gt;
&lt;td&gt;Slower&lt;/td&gt;
&lt;td&gt;High&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Because reranking is computationally expensive, industrial systems follow a common architecture:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fast Recall + Slow Precision&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;First, retrieve many candidates quickly. Then use a stronger model to produce a more accurate ranking.&lt;/p&gt;




&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Reranking plays a crucial role in modern search and RAG pipelines. By re-evaluating retrieved candidates with more powerful models, it significantly improves the relevance of final results while keeping system latency manageable.&lt;/p&gt;

&lt;p&gt;Understanding this stage is essential for anyone building &lt;strong&gt;production-grade AI applications&lt;/strong&gt;, especially systems that combine retrieval with large language models.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>rag</category>
      <category>llm</category>
    </item>
    <item>
      <title>Query Rewrite in RAG Systems: Why It Matters and How It Works</title>
      <dc:creator>yang yaru</dc:creator>
      <pubDate>Mon, 09 Mar 2026 08:20:48 +0000</pubDate>
      <link>https://dev.to/yaruyng/query-rewrite-in-rag-systems-why-it-matters-and-how-it-works-3mmd</link>
      <guid>https://dev.to/yaruyng/query-rewrite-in-rag-systems-why-it-matters-and-how-it-works-3mmd</guid>
      <description>&lt;p&gt;In Retrieval-Augmented Generation (RAG) systems, many developers focus heavily on &lt;strong&gt;embeddings&lt;/strong&gt; and &lt;strong&gt;vector databases&lt;/strong&gt;. However, in real-world production systems, one of the most critical components is often overlooked:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Query Rewrite.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Query rewriting significantly improves retrieval quality and can dramatically impact the overall performance of a RAG pipeline.&lt;/p&gt;

&lt;p&gt;This article explains:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What Query Rewrite is&lt;/li&gt;
&lt;li&gt;Why it is necessary&lt;/li&gt;
&lt;li&gt;How it is implemented in production systems&lt;/li&gt;
&lt;li&gt;Common engineering patterns for query optimization&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  1. What Is Query Rewrite?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Query Rewrite&lt;/strong&gt; refers to the process of transforming a user's original query into one or more optimized queries that are better suited for retrieval.&lt;/p&gt;

&lt;p&gt;Users typically ask questions in &lt;strong&gt;natural language&lt;/strong&gt;, but retrieval systems perform best when queries are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;clear&lt;/li&gt;
&lt;li&gt;explicit&lt;/li&gt;
&lt;li&gt;keyword-rich&lt;/li&gt;
&lt;li&gt;structured&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Therefore, a rewriting step is often introduced before retrieval.&lt;/p&gt;

&lt;p&gt;Basic pipeline:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User Query
     ↓
Query Rewrite
     ↓
Optimized Retrieval Query
     ↓
Vector / Keyword Search
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The rewritten queries help the retrieval system locate more relevant documents.&lt;/p&gt;




&lt;h2&gt;
  
  
  2. Why Query Rewrite Is Necessary
&lt;/h2&gt;

&lt;p&gt;User queries often suffer from several issues that reduce retrieval quality.&lt;/p&gt;

&lt;h3&gt;
  
  
  2.1 Missing Context
&lt;/h3&gt;

&lt;p&gt;Users frequently omit important context.&lt;/p&gt;

&lt;p&gt;Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User query:
What is it?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The system may need to expand it to something like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;What is the architecture of LangGraph?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Without context, retrieval becomes ineffective.&lt;/p&gt;




&lt;h3&gt;
  
  
  2.2 Conversational Language
&lt;/h3&gt;

&lt;p&gt;Users naturally ask questions in informal language.&lt;/p&gt;

&lt;p&gt;Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;How does AI connect to databases?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A retrieval-friendly query might be:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;How to connect an LLM to a database
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  2.3 Very Short Queries
&lt;/h3&gt;

&lt;p&gt;Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;LangGraph
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A better query for retrieval could be:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;LangGraph framework architecture and use cases
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  2.4 Poor Retrieval Keywords
&lt;/h3&gt;

&lt;p&gt;Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Why do AI models make things up?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A rewritten query might be:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;LLM hallucination causes
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This makes it easier to match relevant documents.&lt;/p&gt;




&lt;h2&gt;
  
  
  3. Query Rewrite in the RAG Pipeline
&lt;/h2&gt;

&lt;p&gt;A typical RAG system pipeline looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User Query
     ↓
Query Rewrite
     ↓
Intent Analysis
     ↓
Multi Retrieval
(vector / keyword / metadata)
     ↓
Hybrid Merge
     ↓
Top-K
     ↓
Score Threshold
     ↓
Rerank
     ↓
LLM
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Query rewriting is the &lt;strong&gt;first step in optimizing retrieval quality&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  4. A Practical Query Rewrite Prompt
&lt;/h2&gt;

&lt;p&gt;In many production systems, a small language model is used to generate optimized queries.&lt;/p&gt;

&lt;p&gt;Example prompt:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;You are a search query optimizer.

Rewrite the user's question to improve retrieval quality.

Rules:
1. Preserve the original meaning.
2. Remove conversational language.
3. Add missing keywords if necessary.
4. Generate 3 different search queries.

User Question:
{query}

Return JSON format:
{
 "intent": "...",
 "queries": ["...", "...", "..."]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This prompt produces &lt;strong&gt;structured retrieval queries&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  5. Example
&lt;/h2&gt;

&lt;p&gt;User input:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;What is the difference between LangGraph and AutoGPT?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Rewritten output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="nl"&gt;"intent"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"compare two AI agent frameworks"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="nl"&gt;"queries"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="s2"&gt;"LangGraph vs AutoGPT architecture comparison"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="s2"&gt;"differences between LangGraph and AutoGPT agent framework"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="s2"&gt;"LangGraph workflow design vs AutoGPT autonomous agent"&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each generated query can then be sent to the retrieval system independently.&lt;/p&gt;




&lt;h2&gt;
  
  
  6. Common Query Rewrite Patterns
&lt;/h2&gt;

&lt;p&gt;Production systems typically implement query rewriting in several ways.&lt;/p&gt;

&lt;h3&gt;
  
  
  6.1 Multi-Query Retrieval
&lt;/h3&gt;

&lt;p&gt;The system generates multiple queries from a single user question.&lt;/p&gt;

&lt;p&gt;Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Query 1 → vector search
Query 2 → vector search
Query 3 → vector search
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The results are then merged and ranked.&lt;/p&gt;

&lt;p&gt;Frameworks such as &lt;strong&gt;LangChain&lt;/strong&gt; implement this strategy with components like &lt;em&gt;MultiQueryRetriever&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Advantages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Higher recall&lt;/li&gt;
&lt;li&gt;Better document coverage&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Disadvantages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Increased retrieval cost&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  6.2 Query Decomposition
&lt;/h3&gt;

&lt;p&gt;Complex questions are split into smaller sub-questions.&lt;/p&gt;

&lt;p&gt;Example:&lt;/p&gt;

&lt;p&gt;User query:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Why is LangGraph more stable than AutoGPT?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Decomposed queries:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;LangGraph architecture
AutoGPT architecture
AutoGPT stability issues
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each query retrieves documents independently.&lt;/p&gt;

&lt;p&gt;This method is particularly effective for &lt;strong&gt;complex reasoning tasks&lt;/strong&gt;.&lt;/p&gt;




&lt;h3&gt;
  
  
  6.3 Query Routing
&lt;/h3&gt;

&lt;p&gt;Some systems determine the &lt;strong&gt;intent&lt;/strong&gt; of the query and route it to different retrieval mechanisms.&lt;/p&gt;

&lt;p&gt;Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Query
 ↓
Intent Detection
 ↓
Router
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Example routing table:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Intent&lt;/th&gt;
&lt;th&gt;Retrieval Method&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Technical explanation&lt;/td&gt;
&lt;td&gt;Vector search&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;API documentation&lt;/td&gt;
&lt;td&gt;Keyword search&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Database query&lt;/td&gt;
&lt;td&gt;SQL&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  7. The Full Query Optimization Pipeline
&lt;/h2&gt;

&lt;p&gt;In advanced RAG systems, query processing often includes multiple steps:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User Query
   ↓
Query Rewrite
   ↓
Intent Detection
   ↓
Query Expansion
   ↓
Multi Retrieval
(vector + keyword)
   ↓
Hybrid Merge
   ↓
Top-K
   ↓
Rerank
   ↓
LLM
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In practice, most RAG optimizations focus on three core areas:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Query Quality
Retrieval Strategy
Reranking
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  8. A Less Known Optimization Trick
&lt;/h2&gt;

&lt;p&gt;Some systems do not stop at generating multiple queries.&lt;/p&gt;

&lt;p&gt;Instead, they perform an additional step:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Rewrite
↓
Generate 5 queries
↓
Select the best 3 queries
↓
Run retrieval
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This approach is sometimes called &lt;strong&gt;self-query optimization&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;It improves retrieval quality while controlling cost.&lt;/p&gt;




&lt;h2&gt;
  
  
  9. Why Query Rewrite Matters More for Large Knowledge Bases
&lt;/h2&gt;

&lt;p&gt;When a knowledge base is small:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;~1000 documents
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A simple query may still retrieve relevant information.&lt;/p&gt;

&lt;p&gt;But in large systems:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;~1,000,000 documents
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Query quality becomes critical.&lt;/p&gt;

&lt;p&gt;Poor queries lead to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Low recall
↓
Missing documents
↓
Incorrect or incomplete LLM responses
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  10. Frameworks Supporting Query Rewrite
&lt;/h2&gt;

&lt;p&gt;Several RAG frameworks provide built-in query transformation tools:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;LangChain&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;LlamaIndex&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Haystack&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These frameworks include features such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Query transformation&lt;/li&gt;
&lt;li&gt;Multi-query retrieval&lt;/li&gt;
&lt;li&gt;Sub-question decomposition&lt;/li&gt;
&lt;li&gt;Query routing&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All of these techniques fall under the broader concept of &lt;strong&gt;query optimization&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;While embeddings and vector databases are essential components of RAG systems, &lt;strong&gt;query quality often determines retrieval performance&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;A well-designed Query Rewrite layer can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;improve recall&lt;/li&gt;
&lt;li&gt;increase retrieval relevance&lt;/li&gt;
&lt;li&gt;reduce hallucinations&lt;/li&gt;
&lt;li&gt;enhance overall system reliability&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In many production RAG pipelines, optimizing the &lt;strong&gt;query itself&lt;/strong&gt; is one of the most effective ways to improve results.&lt;/p&gt;

</description>
      <category>llm</category>
      <category>rag</category>
    </item>
    <item>
      <title>Retrieval Strategy Design: Vector, Keyword, and Hybrid Search</title>
      <dc:creator>yang yaru</dc:creator>
      <pubDate>Sat, 28 Feb 2026 06:08:56 +0000</pubDate>
      <link>https://dev.to/yaruyng/retrieval-strategy-design-vector-keyword-and-hybrid-search-53j3</link>
      <guid>https://dev.to/yaruyng/retrieval-strategy-design-vector-keyword-and-hybrid-search-53j3</guid>
      <description>&lt;p&gt;This article explains how to design a &lt;strong&gt;modern retrieval strategy&lt;/strong&gt; for AI systems, especially Retrieval-Augmented Generation (RAG). The focus is not only on definitions, but on &lt;strong&gt;engineering trade-offs, system architecture, and practical defaults&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The target audience is backend engineers who can already &lt;em&gt;use&lt;/em&gt; embeddings, but want to &lt;strong&gt;design reliable and controllable search systems&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  1. Where Retrieval Strategy Fits in the System
&lt;/h2&gt;

&lt;p&gt;A typical modern retrieval pipeline looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User Query
  ↓
Query Rewrite / Intent Analysis
  ↓
Multi-Channel Retrieval
  (Vector / Keyword / Metadata)
  ↓
Hybrid Merge
  ↓
Top-K Limiting
  ↓
Score Threshold Filtering
  ↓
(Optional) Reranking
  ↓
LLM Generation
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Concepts like &lt;strong&gt;vector search&lt;/strong&gt;, &lt;strong&gt;hybrid search&lt;/strong&gt;, &lt;strong&gt;Top-K&lt;/strong&gt;, and &lt;strong&gt;threshold filtering&lt;/strong&gt; are not isolated features. They work together inside the &lt;em&gt;recall and filtering&lt;/em&gt; stages of this pipeline.&lt;/p&gt;




&lt;h2&gt;
  
  
  2. Vector Search: The Semantic Recall Layer
&lt;/h2&gt;

&lt;h3&gt;
  
  
  2.1 What Vector Search Solves
&lt;/h3&gt;

&lt;p&gt;Vector search addresses the problem of &lt;strong&gt;semantic mismatch&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The user and the document use different words&lt;/li&gt;
&lt;li&gt;The meaning is similar, but lexical overlap is low&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Query: How to reduce dopamine addiction
Document: Attention control and dopamine regulation
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Keyword search fails here, but embeddings succeed.&lt;/p&gt;




&lt;h3&gt;
  
  
  2.2 Core Parameters Engineers Must Understand
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Similarity Metric
&lt;/h4&gt;

&lt;p&gt;The most common similarity metrics are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Cosine Similarity (industry default)&lt;/li&gt;
&lt;li&gt;Dot Product&lt;/li&gt;
&lt;li&gt;L2 Distance&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Most embedding models are trained assuming &lt;strong&gt;cosine similarity&lt;/strong&gt;, so databases typically follow that convention.&lt;/p&gt;




&lt;h4&gt;
  
  
  Index Type (Performance-Critical)
&lt;/h4&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Index Type&lt;/th&gt;
&lt;th&gt;Use Case&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Flat&lt;/td&gt;
&lt;td&gt;Small datasets, maximum accuracy&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;HNSW&lt;/td&gt;
&lt;td&gt;General-purpose, production default&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;IVF&lt;/td&gt;
&lt;td&gt;Very large-scale datasets&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;For most knowledge-base and RAG systems, &lt;strong&gt;HNSW&lt;/strong&gt; is the best trade-off.&lt;/p&gt;




&lt;h3&gt;
  
  
  2.3 The Fundamental Weakness of Vector Search
&lt;/h3&gt;

&lt;p&gt;Vector search is strong at recall, but weak at precision:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It retrieves &lt;em&gt;related&lt;/em&gt; content&lt;/li&gt;
&lt;li&gt;It may retrieve &lt;em&gt;irrelevant but semantically nearby&lt;/em&gt; content&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is why vector search &lt;strong&gt;must be combined&lt;/strong&gt; with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Top-K limits&lt;/li&gt;
&lt;li&gt;Score thresholds&lt;/li&gt;
&lt;li&gt;Reranking&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  3. Keyword Search (BM25): The Precision Layer
&lt;/h2&gt;

&lt;p&gt;Keyword search is not obsolete. Its role is &lt;strong&gt;deterministic precision&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;It excels at:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Code and stack traces&lt;/li&gt;
&lt;li&gt;API names&lt;/li&gt;
&lt;li&gt;Error messages&lt;/li&gt;
&lt;li&gt;Proper nouns&lt;/li&gt;
&lt;li&gt;Numbers and IDs&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In many technical queries, keyword search outperforms embeddings.&lt;/p&gt;

&lt;p&gt;Another key benefit is &lt;strong&gt;controllability&lt;/strong&gt;: keyword matching acts as a deterministic filter that reduces hallucinations.&lt;/p&gt;




&lt;h2&gt;
  
  
  4. Hybrid Search: The Industry Standard
&lt;/h2&gt;

&lt;p&gt;Hybrid search combines the strengths of both approaches:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Vector search for semantic recall&lt;/li&gt;
&lt;li&gt;Keyword search for lexical precision&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is no longer optional in production systems.&lt;/p&gt;




&lt;h3&gt;
  
  
  4.1 Parallel Hybrid (Most Common)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Vector Search Top-K = 20
Keyword Search Top-K = 20
↓
Merge Results
↓
Rerank
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Advantages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Simple to implement&lt;/li&gt;
&lt;li&gt;Stable behavior&lt;/li&gt;
&lt;li&gt;Widely used in production&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  4.2 Score Fusion Hybrid
&lt;/h3&gt;

&lt;p&gt;A weighted scoring approach:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Final Score = α × Vector Score + β × BM25 Score
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This method is suitable for search-engine-like systems that require strong global ranking.&lt;/p&gt;




&lt;h2&gt;
  
  
  5. Top-K: A Recall Boundary, Not a Quality Guarantee
&lt;/h2&gt;

&lt;p&gt;A common misconception is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Higher Top-K means better results&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In reality:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Top-K defines the &lt;em&gt;maximum recall scope&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;Large Top-K increases noise&lt;/li&gt;
&lt;li&gt;Token usage and latency increase rapidly&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Practical Defaults
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Scenario&lt;/th&gt;
&lt;th&gt;Recommended Top-K&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;FAQ&lt;/td&gt;
&lt;td&gt;3–5&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Technical Docs&lt;/td&gt;
&lt;td&gt;5–10&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Code Search&lt;/td&gt;
&lt;td&gt;10–20&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;For most RAG systems:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Vector Top-K: 8–10&lt;/li&gt;
&lt;li&gt;Keyword Top-K: 8–10&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  6. Score Threshold Filtering: The Missing Safeguard
&lt;/h2&gt;

&lt;p&gt;Top-K always returns results — even when nothing is relevant.&lt;/p&gt;

&lt;p&gt;Threshold filtering solves this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Only keep results where score &amp;gt; threshold
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Without thresholds, systems produce classic failures:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Query: Apple phone
Result: Apple fruit
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Threshold Guidelines (Cosine Similarity)
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Similarity&lt;/th&gt;
&lt;th&gt;Interpretation&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&amp;gt; 0.85&lt;/td&gt;
&lt;td&gt;Strongly relevant&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;0.75–0.85&lt;/td&gt;
&lt;td&gt;Acceptable&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&amp;lt; 0.70&lt;/td&gt;
&lt;td&gt;Noise&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Many production systems use:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;threshold ≈ 0.78
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  7. A Practical, Production-Ready Retrieval Strategy
&lt;/h2&gt;

&lt;p&gt;A robust default pipeline:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1. Optional Query Rewrite
2. Vector Search (Top-K = 10)
3. Keyword Search (Top-K = 10)
4. Merge Results
5. Filter: score &amp;gt; 0.78
6. Rerank Top 5
7. Send Top 3 to LLM
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This structure balances recall, precision, cost, and stability.&lt;/p&gt;




&lt;h2&gt;
  
  
  8. What Engineers Should Actually Focus On
&lt;/h2&gt;

&lt;h3&gt;
  
  
  8.1 Recall vs Precision Trade-off
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Vector Search → Recall
Keyword Search → Precision
Reranker → Final Quality
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Understanding this triangle is more important than tuning any single parameter.&lt;/p&gt;




&lt;h3&gt;
  
  
  8.2 Chunk Design Matters More Than Algorithms
&lt;/h3&gt;

&lt;p&gt;Poor chunking breaks all retrieval strategies:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Chunks too long → embedding dilution&lt;/li&gt;
&lt;li&gt;Chunks too short → context fragmentation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Good retrieval starts with good chunk boundaries.&lt;/p&gt;




&lt;h3&gt;
  
  
  8.3 Top-K Is Not the Final Output Size
&lt;/h3&gt;

&lt;p&gt;Typical production flow:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Retrieve 20
Filter to 12
Rerank to 5
LLM consumes 3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Modern retrieval systems are not built on vector search alone.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Hybrid retrieval + threshold filtering + reranking&lt;/strong&gt; is the real foundation of stable, production-grade RAG systems.&lt;/p&gt;

&lt;p&gt;If you design retrieval with a system mindset instead of a single-algorithm mindset, quality improves dramatically.&lt;/p&gt;

</description>
      <category>rag</category>
    </item>
    <item>
      <title>Designing a Scalable Knowledge Base for Large Language Models</title>
      <dc:creator>yang yaru</dc:creator>
      <pubDate>Wed, 11 Feb 2026 06:47:41 +0000</pubDate>
      <link>https://dev.to/yaruyng/designing-a-scalable-knowledge-base-for-large-language-models-45jd</link>
      <guid>https://dev.to/yaruyng/designing-a-scalable-knowledge-base-for-large-language-models-45jd</guid>
      <description>&lt;p&gt;&lt;em&gt;A Practical Engineering Guide to Cleaning, Semantic Chunking, Metadata, and Batch Embeddings&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Large Language Model (LLM) knowledge bases are often misunderstood as simply “vectorizing documents.” In reality, a production-grade knowledge system is a &lt;strong&gt;retrieval infrastructure&lt;/strong&gt; that must be traceable, incremental, and measurable.&lt;/p&gt;

&lt;p&gt;This article walks through a practical engineering pipeline covering:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Data cleaning and normalization&lt;/li&gt;
&lt;li&gt;Semantic chunking strategies&lt;/li&gt;
&lt;li&gt;Metadata schema design&lt;/li&gt;
&lt;li&gt;Batch embedding architecture&lt;/li&gt;
&lt;li&gt;Retrieval and evaluation considerations&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The focus is not theory, but implementation decisions that work in real systems.&lt;/p&gt;




&lt;h2&gt;
  
  
  1. System Architecture Overview
&lt;/h2&gt;

&lt;p&gt;Before implementation, define the boundaries of your pipeline. A robust LLM knowledge base usually consists of the following stages:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Ingest → Normalize → Chunk → Enrich → Embed → Index → Retrieve → Monitor
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Core Responsibilities
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Ingest&lt;/strong&gt;: PDFs, web pages, Markdown, databases, or internal docs&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Normalize&lt;/strong&gt;: Convert raw content into structured blocks&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Chunk&lt;/strong&gt;: Create retrieval-ready units&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Enrich&lt;/strong&gt;: Attach metadata and context&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Embed&lt;/strong&gt;: Generate vectors with version control&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Index&lt;/strong&gt;: Build hybrid search indexes&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Serve&lt;/strong&gt;: Retrieval + reranking + citation&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Monitor&lt;/strong&gt;: Evaluate retrieval quality continuously&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A knowledge base is closer to a search engine than a simple storage system.&lt;/p&gt;




&lt;h2&gt;
  
  
  2. Data Cleaning and Normalization
&lt;/h2&gt;

&lt;p&gt;The goal is not to “clean aggressively,” but to preserve structural signals.&lt;/p&gt;

&lt;h3&gt;
  
  
  Required Processing
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Convert all content to UTF-8&lt;/li&gt;
&lt;li&gt;Normalize whitespace and line breaks&lt;/li&gt;
&lt;li&gt;Remove duplicated navigation/footer content&lt;/li&gt;
&lt;li&gt;Detect headings (H1/H2/H3 or numeric sections)&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Preserve structural blocks:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Paragraphs&lt;/li&gt;
&lt;li&gt;Lists&lt;/li&gt;
&lt;li&gt;Tables&lt;/li&gt;
&lt;li&gt;Code blocks&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;Avoid flattening everything into plain text. Structure improves both retrieval accuracy and traceability.&lt;/p&gt;

&lt;h3&gt;
  
  
  Common Noise Sources
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Web navigation bars and cookie banners&lt;/li&gt;
&lt;li&gt;PDF headers and repeated page numbers&lt;/li&gt;
&lt;li&gt;Hyphenated line breaks in scanned PDFs&lt;/li&gt;
&lt;li&gt;Template content repeated across pages&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Tables should ideally be converted into Markdown or &lt;code&gt;key: value&lt;/code&gt; rows so that LLMs can interpret them correctly.&lt;/p&gt;




&lt;h2&gt;
  
  
  3. Semantic Chunking Strategy
&lt;/h2&gt;

&lt;p&gt;Chunking is the most important factor affecting retrieval performance.&lt;/p&gt;

&lt;h3&gt;
  
  
  Chunking Goals
&lt;/h3&gt;

&lt;p&gt;A good chunk should be:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Self-contained&lt;/strong&gt;: understandable without large context&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Traceable&lt;/strong&gt;: linked back to its original location&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Searchable&lt;/strong&gt;: not too long or too fragmented&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Recommended Hierarchical Approach
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Structure-aware splitting (Preferred)&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;Split by document headings first&lt;/li&gt;
&lt;li&gt;Merge paragraphs inside each section&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Recursive splitting&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;Paragraph → Line → Sentence → Token boundary&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Semantic boundary detection (Advanced)&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;Use topic shifts or embeddings to find natural breaks&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Chunk Size and Overlap
&lt;/h3&gt;

&lt;p&gt;Typical engineering defaults:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;FAQ or policies: 200–450 tokens, overlap 30–80&lt;/li&gt;
&lt;li&gt;Technical docs: 300–700 tokens, overlap 50–120&lt;/li&gt;
&lt;li&gt;Long reports or research: 400–900 tokens, overlap 80–150&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Overlap prevents losing context when answers span boundaries.&lt;/p&gt;

&lt;h3&gt;
  
  
  Parent–Child Chunk Design
&lt;/h3&gt;

&lt;p&gt;A highly effective production pattern:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Child chunks&lt;/strong&gt;: smaller pieces used for vector retrieval&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Parent chunks&lt;/strong&gt;: larger contextual sections passed to the LLM&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Workflow:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Retrieve child chunks&lt;/li&gt;
&lt;li&gt;Expand to parent chunks&lt;/li&gt;
&lt;li&gt;Send parents to the model for generation&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This significantly improves answer coherence.&lt;/p&gt;




&lt;h2&gt;
  
  
  4. Metadata Schema Design
&lt;/h2&gt;

&lt;p&gt;Metadata is not optional. It enables filtering, access control, versioning, and debugging.&lt;/p&gt;

&lt;h3&gt;
  
  
  Minimum Viable Metadata
&lt;/h3&gt;

&lt;p&gt;Each chunk should include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;doc_id&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chunk_id&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;title&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;section_path&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;source_uri&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;page_start / page_end&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;created_at / updated_at&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;language&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;hash&lt;/code&gt; (content checksum)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;tenant/project&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;acl&lt;/code&gt; (access control)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Enhanced Metadata (Recommended)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;doc_version&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;effective_date&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;tags&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;entities&lt;/code&gt; (product names, systems, people)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;content_type&lt;/code&gt; (faq, guide, spec, code)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;parent_id&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;quality_flags&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These fields enable advanced filtering and evaluation later.&lt;/p&gt;

&lt;h3&gt;
  
  
  Stable Chunk ID Strategy
&lt;/h3&gt;

&lt;p&gt;Chunk IDs must remain stable across re-processing.&lt;/p&gt;

&lt;p&gt;Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;chunk_id = sha1(doc_id + doc_version + section_path + chunk_index + text_hash_prefix)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Only changed content should produce new IDs.&lt;/p&gt;




&lt;h2&gt;
  
  
  5. Batch Embedding Architecture
&lt;/h2&gt;

&lt;p&gt;Embedding pipelines must be &lt;strong&gt;idempotent&lt;/strong&gt;, &lt;strong&gt;incremental&lt;/strong&gt;, and &lt;strong&gt;observable&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Suggested Data Model
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;documents&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;doc_id, version, uri, title, checksum&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;chunks&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;chunk_id, doc_id, text, metadata_json, hash&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;embeddings&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;chunk_id, model_name, dim, vector, text_hash&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;embedding_jobs&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;job_id, status, created_at&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;embedding_job_items&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;job_id, chunk_id, retry_count, error&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Key Engineering Practices
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Only embed chunks whose hash changed&lt;/li&gt;
&lt;li&gt;Process in batches (32–256 chunks or token-limited)&lt;/li&gt;
&lt;li&gt;Control concurrency to avoid rate limits&lt;/li&gt;
&lt;li&gt;Implement exponential retry&lt;/li&gt;
&lt;li&gt;Monitor throughput and failure rates&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Supporting Multiple Models
&lt;/h3&gt;

&lt;p&gt;Embedding records must include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;model_name&lt;/li&gt;
&lt;li&gt;model_version&lt;/li&gt;
&lt;li&gt;vector_dimension&lt;/li&gt;
&lt;li&gt;normalized_flag&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Allow multiple embeddings per chunk for gradual migration between models.&lt;/p&gt;




&lt;h2&gt;
  
  
  6. Retrieval Design: Hybrid Search and Reranking
&lt;/h2&gt;

&lt;p&gt;Vector search alone is rarely sufficient.&lt;/p&gt;

&lt;h3&gt;
  
  
  Recommended Retrieval Pipeline
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Hybrid retrieval:&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;Vector similarity&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;BM25 keyword search&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Metadata filtering:&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;tenant/project&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;ACL&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;document type&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Reranking:&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Lightweight reranker or LLM scoring&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Source citation:&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Return &lt;code&gt;source_uri + section_path + page&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Hybrid search dramatically improves precision for exact terms and technical names.&lt;/p&gt;




&lt;h2&gt;
  
  
  7. Chunk Quality Monitoring
&lt;/h2&gt;

&lt;p&gt;Many production issues are caused by poor chunks rather than model failures.&lt;/p&gt;

&lt;p&gt;Common anti-patterns:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Chunks shorter than 50 tokens&lt;/li&gt;
&lt;li&gt;Chunks longer than 1200 tokens&lt;/li&gt;
&lt;li&gt;Repeated template content&lt;/li&gt;
&lt;li&gt;Missing title context&lt;/li&gt;
&lt;li&gt;Duplicate sections occupying top results&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Add a simple rule engine that tags chunks with &lt;code&gt;quality_flags&lt;/code&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  8. End-to-End Processing Pipeline
&lt;/h2&gt;

&lt;p&gt;A practical implementation roadmap:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Ingest documents and generate &lt;code&gt;doc_id&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Extract structured blocks&lt;/li&gt;
&lt;li&gt;Remove noise and duplicates&lt;/li&gt;
&lt;li&gt;Build parent chunks from sections&lt;/li&gt;
&lt;li&gt;Generate child chunks with overlap&lt;/li&gt;
&lt;li&gt;Attach metadata and hashes&lt;/li&gt;
&lt;li&gt;Upsert into &lt;code&gt;chunks&lt;/code&gt; table&lt;/li&gt;
&lt;li&gt;Create embedding jobs for new/changed chunks&lt;/li&gt;
&lt;li&gt;Batch embedding with workers&lt;/li&gt;
&lt;li&gt;Build vector and keyword indexes&lt;/li&gt;
&lt;li&gt;Run evaluation queries (golden dataset)&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;Designing an LLM knowledge base is less about models and more about &lt;strong&gt;information architecture&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The biggest improvements usually come from:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Better chunk structure&lt;/li&gt;
&lt;li&gt;Strong metadata design&lt;/li&gt;
&lt;li&gt;Incremental embedding pipelines&lt;/li&gt;
&lt;li&gt;Hybrid retrieval strategies&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you treat your knowledge base like a search system rather than a document dump, both retrieval accuracy and generation quality improve significantly.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>llm</category>
    </item>
    <item>
      <title>How to Choose the Right Model for Your AI Application(A Practical Engineering Guide)</title>
      <dc:creator>yang yaru</dc:creator>
      <pubDate>Fri, 30 Jan 2026 07:10:13 +0000</pubDate>
      <link>https://dev.to/yaruyng/how-to-choose-the-right-model-for-your-ai-applicationa-practical-engineering-guide-28al</link>
      <guid>https://dev.to/yaruyng/how-to-choose-the-right-model-for-your-ai-applicationa-practical-engineering-guide-28al</guid>
      <description>&lt;p&gt;Choosing an AI model is not about finding &lt;em&gt;the strongest&lt;/em&gt; model.&lt;/p&gt;

&lt;p&gt;It is about finding &lt;strong&gt;the most suitable model for your specific scenario&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Many developers waste money, suffer from slow responses, or over-engineer their systems simply because they start with the wrong assumption:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Bigger model = better product.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In reality:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;There is no best model.&lt;br&gt;&lt;br&gt;
Only the best model &lt;em&gt;for your use case&lt;/em&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This article provides a &lt;strong&gt;practical, engineering-oriented framework&lt;/strong&gt; for selecting models in real AI applications.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. The Four Core Dimensions of Model Selection
&lt;/h2&gt;

&lt;p&gt;Every model choice is a trade-off between:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Capability (reasoning, language quality)&lt;/li&gt;
&lt;li&gt;Latency (response speed)&lt;/li&gt;
&lt;li&gt;Cost (per-token price)&lt;/li&gt;
&lt;li&gt;Controllability (structured output reliability)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You cannot maximize all four simultaneously.&lt;/p&gt;

&lt;p&gt;Good model selection means choosing the right balance.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. First: Classify Your Application
&lt;/h2&gt;

&lt;p&gt;Before choosing a model, identify which category your feature belongs to.&lt;/p&gt;

&lt;h3&gt;
  
  
  A. Generative Tasks
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Article writing
&lt;/li&gt;
&lt;li&gt;Copywriting
&lt;/li&gt;
&lt;li&gt;Story generation
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  B. Q&amp;amp;A Tasks
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Customer support
&lt;/li&gt;
&lt;li&gt;Knowledge base Q&amp;amp;A
&lt;/li&gt;
&lt;li&gt;FAQ bots
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  C. Structured Output Tasks
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;JSON generation
&lt;/li&gt;
&lt;li&gt;Tables
&lt;/li&gt;
&lt;li&gt;Fixed schemas
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  D. Strong Reasoning Tasks
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Multi-step logical reasoning
&lt;/li&gt;
&lt;li&gt;Complex code analysis
&lt;/li&gt;
&lt;li&gt;Data reasoning
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  E. Embedding Tasks
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Vectorization
&lt;/li&gt;
&lt;li&gt;Semantic search
&lt;/li&gt;
&lt;li&gt;Similarity matching
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  3. Capability Requirements by Category
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Task Type&lt;/th&gt;
&lt;th&gt;Needs Top-Tier Model?&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Text generation&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Customer service&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Structured JSON&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Strong reasoning&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Code generation&lt;/td&gt;
&lt;td&gt;Medium–High&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Embedding&lt;/td&gt;
&lt;td&gt;No (use embedding model)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Most applications do not need frontier models.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Industry-Proven Three-Tier Model Strategy
&lt;/h2&gt;

&lt;p&gt;Mature systems rarely use a single model.&lt;/p&gt;

&lt;p&gt;Instead:&lt;/p&gt;

&lt;h3&gt;
  
  
  Tier 1 — Cheap Model
&lt;/h3&gt;

&lt;p&gt;Handles ~70% of traffic&lt;/p&gt;

&lt;h3&gt;
  
  
  Tier 2 — Mid-Level Model
&lt;/h3&gt;

&lt;p&gt;Handles moderately complex requests&lt;/p&gt;

&lt;h3&gt;
  
  
  Tier 3 — Strong Model
&lt;/h3&gt;

&lt;p&gt;Used only for hard cases&lt;/p&gt;

&lt;p&gt;Architecture:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User Request
    |
Rule / Router
    |
Simple → Cheap Model
Medium → Mid Model
Complex → Strong Model
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This drastically reduces cost while maintaining quality.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Embeddings Are a Separate Track
&lt;/h2&gt;

&lt;p&gt;Never use chat models to create vectors.&lt;/p&gt;

&lt;p&gt;Use a &lt;strong&gt;dedicated embedding model&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Pipeline:&lt;/p&gt;

&lt;p&gt;Text → Embedding Model → Vector → Vector DB&lt;/p&gt;

&lt;p&gt;Advantages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Much cheaper&lt;/li&gt;
&lt;li&gt;Better semantic consistency&lt;/li&gt;
&lt;li&gt;Faster&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  6. Practical Model Selection Workflow
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Step 1 — Define I/O Contract
&lt;/h3&gt;

&lt;p&gt;Example:&lt;/p&gt;

&lt;p&gt;Input: ...&lt;br&gt;
Output: ...&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2 — Start with Mid-Level Model
&lt;/h3&gt;

&lt;p&gt;Get the system working first.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3 — Measure
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Output quality&lt;/li&gt;
&lt;li&gt;Latency&lt;/li&gt;
&lt;li&gt;Cost per request&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Step 4 — Upgrade Only If Needed
&lt;/h3&gt;

&lt;p&gt;Only upgrade when:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Frequent hallucinations&lt;/li&gt;
&lt;li&gt;Logical breakdown&lt;/li&gt;
&lt;li&gt;Prompt already optimized&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  7. A Useful Rule of Thumb
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;If prompt engineering can fix it,&lt;br&gt;&lt;br&gt;
do NOT switch models.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Most failures are caused by:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Weak prompts&lt;/li&gt;
&lt;li&gt;Missing constraints&lt;/li&gt;
&lt;li&gt;Unclear output formats&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Not weak models.&lt;/p&gt;

&lt;h2&gt;
  
  
  8. Temperature Guidelines
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Scenario&lt;/th&gt;
&lt;th&gt;Temperature&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Article writing&lt;/td&gt;
&lt;td&gt;0.7&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Stable output&lt;/td&gt;
&lt;td&gt;0.2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;JSON generation&lt;/td&gt;
&lt;td&gt;0.1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Creative writing&lt;/td&gt;
&lt;td&gt;0.8&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;For article generation:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;0.6 – 0.7&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  9. Three Common Beginner Mistakes
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Mistake 1
&lt;/h3&gt;

&lt;p&gt;Using the most expensive model by default&lt;/p&gt;

&lt;h3&gt;
  
  
  Mistake 2
&lt;/h3&gt;

&lt;p&gt;No caching&lt;/p&gt;

&lt;p&gt;Same prompt → regenerate → waste money&lt;/p&gt;

&lt;h3&gt;
  
  
  Mistake 3
&lt;/h3&gt;

&lt;p&gt;No retry mechanism&lt;/p&gt;

&lt;p&gt;Should have:&lt;/p&gt;

&lt;p&gt;Fail → Retry once → Log&lt;/p&gt;

&lt;h2&gt;
  
  
  10. Backend-Oriented Architecture
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Controller
|
Service
|
Prompt Builder
|
Model Router
 |       |
Cheap  Strong
|
AI Provider
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  11. When Should You Upgrade to Stronger Models?
&lt;/h2&gt;

&lt;p&gt;Only when:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;content frequently go off-topic&lt;/li&gt;
&lt;li&gt;Logical structure collapses&lt;/li&gt;
&lt;li&gt;Prompts already well designed&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  12. Final Takeaway
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Start with mid-level models
&lt;/li&gt;
&lt;li&gt;Use embedding models for vectors
&lt;/li&gt;
&lt;li&gt;Let prompts and parameters do most of the work
&lt;/li&gt;
&lt;li&gt;Add model tiers later
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Good architecture beats expensive models.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;*If you found this useful, feel free to adapt it into your own system design or produce&lt;/p&gt;

</description>
      <category>ai</category>
      <category>llm</category>
    </item>
    <item>
      <title>How to Write a Developer-Level Prompt: A Practical Guide</title>
      <dc:creator>yang yaru</dc:creator>
      <pubDate>Fri, 30 Jan 2026 06:46:38 +0000</pubDate>
      <link>https://dev.to/yaruyng/how-to-write-a-developer-level-prompt-a-practical-guide-4240</link>
      <guid>https://dev.to/yaruyng/how-to-write-a-developer-level-prompt-a-practical-guide-4240</guid>
      <description>&lt;p&gt;Large Language Models (LLMs) do not work well with vague instructions.&lt;br&gt;&lt;br&gt;
If you want consistent, controllable, and production-grade behavior, you must move beyond simple “user prompts” and start designing &lt;strong&gt;Developer-level prompts&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;This article explains:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What a Developer Prompt is
&lt;/li&gt;
&lt;li&gt;How it differs from other prompt types
&lt;/li&gt;
&lt;li&gt;A practical structure you can reuse
&lt;/li&gt;
&lt;li&gt;Real-world examples
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  1. Prompt Layers: System, Developer, and User
&lt;/h2&gt;

&lt;p&gt;Modern LLM applications usually operate with three layers of instructions:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Layer&lt;/th&gt;
&lt;th&gt;Purpose&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;System Prompt&lt;/td&gt;
&lt;td&gt;Defines global behavior of the model&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Developer Prompt&lt;/td&gt;
&lt;td&gt;Defines product-level rules&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;User Prompt&lt;/td&gt;
&lt;td&gt;Defines per-request task&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Think of it like this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;System Prompt&lt;/strong&gt; → Constitution
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Developer Prompt&lt;/strong&gt; → Job description
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;User Prompt&lt;/strong&gt; → Daily task
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Your focus as a builder is primarily the &lt;strong&gt;Developer Prompt&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. What Is a Developer Prompt?
&lt;/h2&gt;

&lt;p&gt;A Developer Prompt is a persistent instruction set that defines:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Who the model is
&lt;/li&gt;
&lt;li&gt;What its main responsibility is
&lt;/li&gt;
&lt;li&gt;What rules it must follow
&lt;/li&gt;
&lt;li&gt;What it is allowed and not allowed to do
&lt;/li&gt;
&lt;li&gt;How it must format output
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It is not about &lt;em&gt;what the user asks&lt;/em&gt;.&lt;br&gt;&lt;br&gt;
It is about &lt;em&gt;how the system behaves&lt;/em&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A Developer Prompt turns a general AI into a specialized product component.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  3. Why Developer Prompts Matter
&lt;/h2&gt;

&lt;p&gt;Without a Developer Prompt:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The model improvises
&lt;/li&gt;
&lt;li&gt;Output style changes
&lt;/li&gt;
&lt;li&gt;Hallucinations increase
&lt;/li&gt;
&lt;li&gt;Formatting becomes inconsistent
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With a Developer Prompt:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Behavior becomes stable
&lt;/li&gt;
&lt;li&gt;Boundaries are enforced
&lt;/li&gt;
&lt;li&gt;Outputs are predictable
&lt;/li&gt;
&lt;li&gt;Product quality improves
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is the difference between experimentation and engineering.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Standard Structure of a Developer Prompt
&lt;/h2&gt;

&lt;p&gt;A strong Developer Prompt usually contains five sections:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Role
&lt;/li&gt;
&lt;li&gt;Goal
&lt;/li&gt;
&lt;li&gt;Knowledge Scope
&lt;/li&gt;
&lt;li&gt;Behavior Rules
&lt;/li&gt;
&lt;li&gt;Output Format
&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Generic Template
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
text
You are a {role}.

Your primary goal is to {goal}.

You must follow these rules:
1. ...
2. ...
3. ...

You can only use the following knowledge sources:
- ...

If information is missing, respond with:
"I don't know based on the provided information."

Output format:
- ...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

</description>
      <category>ai</category>
      <category>promptengineering</category>
    </item>
    <item>
      <title>Retrieval Technique Series-6.A Discourse on Design in High-Performance Retrieval Systems</title>
      <dc:creator>yang yaru</dc:creator>
      <pubDate>Mon, 28 Jul 2025 03:59:07 +0000</pubDate>
      <link>https://dev.to/yaruyng/retrieval-technique-series-5a-discourse-on-design-in-high-performance-retrieval-systems-455</link>
      <guid>https://dev.to/yaruyng/retrieval-technique-series-5a-discourse-on-design-in-high-performance-retrieval-systems-455</guid>
      <description>&lt;p&gt;In an era defined by data, the ability to retrieve information quickly and accurately is no longer a luxury—it's a fundamental requirement. From the search engines that power our curiosity to the e-commerce platforms that recommend our next purchase, high-performance retrieval systems are the invisible engines of our digital world. But what does it take to build a system that can sift through petabytes of data in milliseconds?&lt;/p&gt;

&lt;p&gt;The answer lies in a set of core architectural philosophies. These are not just technical tricks but foundational principles that ensure scalability, speed, and stability. Let's explore four of the most critical design ideas that underpin modern, high-performance retrieval systems.&lt;/p&gt;

&lt;h2&gt;
  
  
  Principle 1: Decoupling the Index from the Data
&lt;/h2&gt;

&lt;p&gt;At its core, a retrieval system works much like a library. To find a book, you don't scan every shelf; you first consult the card catalog—the index. This analogy highlights our first principle: the separation of the index from the actual data.&lt;/p&gt;

&lt;p&gt;The Index: This is a lightweight, highly optimized data structure that maps search terms to the locations of the documents that contain them. Its primary job is to enable fast lookups.&lt;br&gt;
The Data: This is the full, original content of the documents themselves (e.g., web pages, product descriptions, user profiles).&lt;br&gt;
By decoupling these two, we gain immense benefits. The index, being much smaller than the raw data, can often be stored in faster media like SSDs or even loaded entirely into RAM. This allows the system to perform the initial "where is it?" query at lightning speed. Once the relevant document locations are identified, the system can then fetch the full data from slower, more cost-effective storage like HDDs or cloud object storage. This separation also allows for independent scaling—we can add more resources to our indexing service without altering our primary data storage, and vice-versa.&lt;/p&gt;

&lt;h2&gt;
  
  
  Principle 2: Minimizing Disk I/O
&lt;/h2&gt;

&lt;p&gt;The single greatest bottleneck in most data-intensive systems is disk input/output (I/O). Accessing data from a spinning disk or even an SSD is orders of magnitude slower than accessing it from memory (RAM). Therefore, a relentless focus on minimizing disk I/O is paramount for performance.&lt;/p&gt;

&lt;p&gt;Several techniques are employed to achieve this:&lt;/p&gt;

&lt;p&gt;Aggressive Caching: Frequently accessed index blocks and popular documents are kept in memory caches. The system checks the cache first, avoiding a trip to the disk entirely if the data is present.&lt;br&gt;
Data Compression: Compressing data reduces its size on disk, meaning fewer bytes need to be read for any given query. This trades a small amount of CPU time (for decompression) for a significant reduction in I/O latency.&lt;br&gt;
Sequential Access Patterns: Random disk access is notoriously slow. Modern systems often use data structures like Log-Structured Merge-Trees (LSM-Trees) that convert random writes into sequential appends, which are much faster. Similarly, structuring data to be read sequentially can dramatically improve throughput.&lt;/p&gt;

&lt;h2&gt;
  
  
  Principle 3: Implementing Read-Write Separation
&lt;/h2&gt;

&lt;p&gt;The workload of a retrieval system is typically asymmetrical. There are often far more read operations (users searching) than write operations (new data being indexed). The requirements for these two operations are also different: reads must be ultra-fast, while writes need to be durable and consistent.&lt;/p&gt;

&lt;p&gt;This leads to the principle of Read-Write Separation, also known as Command Query Responsibility Segregation (CQRS). In this model:&lt;/p&gt;

&lt;p&gt;The Write Path handles data ingestion, updates, and indexing. It can be optimized for throughput and data integrity.&lt;br&gt;
The Read Path handles user queries. It operates on a separate, read-optimized copy of the data.&lt;br&gt;
This separation allows us to scale each path independently. If search traffic spikes, we can simply spin up more read replicas without impacting the indexing process. This architecture also improves system resilience; a failure or slowdown in the write system won't bring down the search functionality for users.&lt;/p&gt;

&lt;h2&gt;
  
  
  Principle 4: Adopting a Layered or Tiered Architecture
&lt;/h2&gt;

&lt;p&gt;It's not feasible to apply complex, computationally expensive logic to every single document in a massive dataset for every query. To solve this, high-performance systems adopt a multi-stage, layered processing approach, creating a "funnel" that progressively refines the results.&lt;/p&gt;

&lt;p&gt;A typical search funnel might look like this:&lt;/p&gt;

&lt;p&gt;Recall Layer (or Matching): This first layer quickly scans the index to retrieve a large set of potentially relevant candidates—perhaps thousands or tens of thousands of documents. The goal here is high recall (don't miss anything important) and speed. The scoring logic is simple and fast.&lt;br&gt;
Ranking Layer (or Scoring): The candidate set from the first layer is passed to a second, more sophisticated layer. Here, more complex ranking models, often powered by machine learning, are used to score and order the documents more accurately. Since this is only applied to a smaller subset of documents, the computational cost is manageable.&lt;br&gt;
Re-ranking Layer (or Blending): A final layer may take the top-ranked results and apply further business logic, personalization, or diversity rules to produce the final list presented to the user.&lt;br&gt;
This tiered approach ensures that the most expensive computations are reserved for only the most promising candidates, striking a perfect balance between accuracy and performance.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Building a high-performance retrieval system is a masterclass in managing trade-offs. By embracing these four fundamental design philosophies—separating index and data, minimizing disk I/O, segregating reads and writes, and processing in layers—engineers can construct systems that are not only incredibly fast but also scalable, resilient, and efficient. These principles, working in concert, form the bedrock of the seamless information access we rely on every day.&lt;/p&gt;

</description>
      <category>rag</category>
    </item>
    <item>
      <title>Retrieval Technique Series-5.How Large-Scale Search Systems Accelerate Retrieval with Distributed Technology</title>
      <dc:creator>yang yaru</dc:creator>
      <pubDate>Wed, 11 Jun 2025 06:14:37 +0000</pubDate>
      <link>https://dev.to/yaruyng/retrieval-technique-series-5how-large-scale-search-systems-accelerate-retrieval-with-distributed-4418</link>
      <guid>https://dev.to/yaruyng/retrieval-technique-series-5how-large-scale-search-systems-accelerate-retrieval-with-distributed-4418</guid>
      <description>&lt;p&gt;In the era of big data, search systems must handle massive volumes of information and user queries efficiently. Traditional single-server architectures quickly become bottlenecks as data and traffic grow. To address this, large-scale search systems leverage distributed technology and index sharding to accelerate retrieval and ensure scalability. In this post, we’ll explore how these techniques work, their advantages, and the challenges they bring.&lt;/p&gt;

&lt;h2&gt;
  
  
  What are the advantages of distributed technology?
&lt;/h2&gt;

&lt;p&gt;Distributed technology is the decomposition of large tasks into multiple subtasks, using multiple servers to jointly undertake tasks, which greatly improves the overall system's service capabilities compared to single machine systems.&lt;/p&gt;

&lt;h2&gt;
  
  
  What does a simple distributed structure look like?
&lt;/h2&gt;

&lt;p&gt;A complete distributed system will have complex service management mechanisms, including service registration, service discovery, load balancing, traffic control, remote calling, and redundant backup. Here, let's first set aside the implementation details of distributed systems and return to their essence, which is to start with "letting multiple servers share the task" and see how a simple distributed retrieval system works. Firstly, we need a server that receives requests, but it does not perform specific query tasks. It is only responsible for task distribution, which we call a distribution server. Multiple index servers are the ones that actually perform the retrieval task, each of which stores a complete inverted index and is capable of completing the retrieval task. When the distribution server receives a request, it will send the current query request to a relatively idle index server for querying based on the load balancing mechanism. The specific retrieval work is independently completed by the indexing server and the results are returned.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;                +----------------------+
                |   Dispatcher Server  |        The dispatcher server receives the request and forwards it to a specific index server, 
                +----------------------+          according to the load balancing mechanism.
                        |
             -------------------------------------------------------
             |                      |                              |
+---------------------+  +---------------------+   ...   +---------------------+
|  Full Index Data    |  |  Full Index Data    |         |  Full Index Data    |
|  Index Server 1     |  |  Index Server 2     |         |  Index Server n     |
+---------------------+  +---------------------+         +---------------------+

The index server processes the request and returns the search result.

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  What is Index Sharding?
&lt;/h2&gt;

&lt;p&gt;Index sharding is the process of splitting a large search index into smaller, manageable pieces (shards) that can be distributed across multiple servers. Each shard contains a subset of the data, allowing the system to process queries in parallel and balance the load.&lt;/p&gt;

&lt;h2&gt;
  
  
  How Index Sharding Works
&lt;/h2&gt;

&lt;p&gt;There are two main strategies for sharding:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Document-Based Sharding
&lt;/h3&gt;

&lt;p&gt;Each shard contains a subset of documents.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;+---------------------------------------------------------------+
|                        All Documents                          |
|  +-------------------+      ...      +-------------------+    |
|  | Document Set 1    |               | Document Set n    |    |
|  +-------------------+               +-------------------+    |
+---------------------------------------------------------------+
           |                                      |
           v                                      v
   Generate Index Shard 1                 Generate Index Shard n
           |                                      |
           v                                      v
+--------------------------------+   +--------------------------------+
| word 1 -&amp;gt;doc 1-&amp;gt;doc 2...doc 19 |   |word 1 -&amp;gt;doc 23-&amp;gt;doc 25...doc 41|
| word 2 -&amp;gt;doc 3-&amp;gt;doc 4...doc 14 |   |word 2 -&amp;gt;doc 12-&amp;gt;doc 16...doc 30|
|   ...                          |   |    ...                         |
| word n -&amp;gt;doc 1-&amp;gt;doc 3...doc 15 |   |word n -&amp;gt;doc 21-&amp;gt;doc 24...doc 35|
+--------------------------------+   +--------------------------------+

Note: The posting list in a single shard is incomplete.

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When a query arrives:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;                        +----------------------+
                        |  Dispatcher Server   |
                        +----------------------+
                                 |
        -------------------------------------------------
        |                       |                      |
+-------------------+  +-------------------+   ...   +-------------------+
|  Index Shard 1    |  |  Index Shard 2    |         |  Index Shard 3    |
|  Index Server 1   |  |  Index Server 2   |         |  Index Server n   |
+-------------------+  +-------------------+         +-------------------+

1. The dispatcher server receives the query request and sends the request to all index servers with different index shards.

2. Each index server searches its own loaded index shard and returns the search results to the dispatcher server.

3. The dispatcher server merges all returned results and returns the final result.

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Advantages:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Accelerates search efficiency.&lt;/li&gt;
&lt;li&gt;Evenly distributes queries and balances server load.&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Makes it easier to update the index by adding or modifying documents.&lt;br&gt;
&lt;strong&gt;Management Challenges:&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Requires careful balancing of query loads across shards.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. Keyword-Based Sharding
&lt;/h3&gt;

&lt;p&gt;Each shard is responsible for a subset of keywords.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;+-------------------+
|   All Documents   |
+-------------------+
          |
          v
   Generate Complete Inverted Index
          |
          v

 Incomplete |
 dictionary | Complete posting list in shard
 in shard   |                 
+--------------------------------------------+
| word 1  -----&amp;gt; doc 1 -&amp;gt; doc 2 ... doc 41   |
| word 2  -----&amp;gt; doc 3 -&amp;gt; doc 4 ... doc 30   |
|   ...                                      |
| word 20 -----&amp;gt; doc 1 -&amp;gt; doc 3 ... doc 35   |
+--------------------------------------------+
+--------------------------------------------+
| word 41 -----&amp;gt; doc 1 -&amp;gt; doc 5 ... doc 41   |
| word 42 -----&amp;gt; doc 2 -&amp;gt; doc 6 ... doc 30   |
|   ...                                      |
| word n  -----&amp;gt; doc 3 -&amp;gt; doc 4 ... doc 35   |
+--------------------------------------------+

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When a query arrives:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Query: key1 + key2

                        +----------------------+
                        |  Dispatcher Server   |
                        +----------------------+
                          /               \
                         /                 \
        +---------------------+   +---------------------+   ...   +---------------------+
        |  Full Index Data    |   |  Full Index Data    |         |  Full Index Data    |
        |  Index Server 1     |   |  Index Server 2     |         |  Index Server n     |
        +---------------------+   +---------------------+         +---------------------+

 (Return posting list for key1)   (Return posting list for key2)

1. The dispatcher server receives the request and, based on the query, dispatches it to one or more index servers.
2. Index servers process the request and return the complete search results.
3. The dispatcher server merges the results and returns the final result.

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Advantages:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Reduces duplicate computation.&lt;br&gt;
&lt;strong&gt;Management Challenges:&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If queries contain many keywords not evenly distributed, performance may drop.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;High-frequency keywords can overload specific shards.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Index sharding and distributed technology are essential for building scalable, high-performance search systems. By splitting the index and distributing the workload, these systems can handle massive data volumes and high query rates efficiently. However, careful planning and management are required to avoid bottlenecks and ensure balanced performance.&lt;/p&gt;

</description>
      <category>database</category>
      <category>rag</category>
    </item>
    <item>
      <title>Retrieval Technique Series-4.How Search Engines Generate Indexes for Trillions of Websites?</title>
      <dc:creator>yang yaru</dc:creator>
      <pubDate>Fri, 06 Jun 2025 03:21:41 +0000</pubDate>
      <link>https://dev.to/yaruyng/retrieval-technique-series-4how-search-engines-generate-indexes-for-trillions-of-websites-2bn5</link>
      <guid>https://dev.to/yaruyng/retrieval-technique-series-4how-search-engines-generate-indexes-for-trillions-of-websites-2bn5</guid>
      <description>&lt;h1&gt;
  
  
  How to Generate Inverted Indexes Larger Than Memory Capacity
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Review of In-Memory Inverted Index Generation
&lt;/h2&gt;

&lt;p&gt;For small document collections that fit in memory, we generate hash-based inverted indexes as follows:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Assign unique, sequential IDs to each document&lt;/li&gt;
&lt;li&gt;Scan each document sequentially, generating  tuples&lt;/li&gt;
&lt;li&gt;Store these tuples in an inverted table with the keyword as the key (position information can be omitted if unnecessary)&lt;/li&gt;
&lt;li&gt;Repeat until all documents are processed&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This creates an in-memory inverted index.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[Document Analysis Process]

+------------+                +---------------------------------------------+
| word 1     |                | Keywords | DocID  | Position | Posting List |
| word 2     |    Analyze     +----------+--------+----------+--------------+
| word 1     | ------------&amp;gt;  | Word 1   | Doc 2  | [1,3]    |              |
| doc 2      |                | Word 2   | Doc 2  | [2]      |              |
+------------+                +---------------------------------------------+
                                    |
                                    |
                                    v
If key exists in posting list, directly insert node:
word 1 -------&amp;gt; doc 1 -------&amp;gt; doc 2

If key doesn't exist in index, insert key and create posting list:
word 2 -------&amp;gt; doc 2

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Handling Large-Scale Document Collections
&lt;/h2&gt;

&lt;p&gt;For large-scale document collections, we need a different approach. Can we split them into smaller collections to build inverted indexes in memory? How do we combine these smaller indexes into a complete large-scale inverted index stored on disk?&lt;/p&gt;

&lt;p&gt;Industrial-grade inverted indexes are more complex than what we've studied. For example, if a document contains "Geek Time" , not only might these four characters be added to the dictionary as keywords, but "Geek" , "Time" , and "Geek Time"  might also be added. This results in a very large dictionary, potentially containing millions or tens of millions of terms.&lt;/p&gt;

&lt;p&gt;Since words have different lengths and storage requirements, we assign a number to each word in the dictionary and store the corresponding string. In the posting list, we record not just document IDs but also position information, frequency, and other details. Each node in the posting list is a complex structure identified by document ID.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Dictionary                          Posting List
+--------------+      +-----------------------------------------------+
| word ID 1    | ---&amp;gt; | [doc 1, pos, tf,...] -&amp;gt; [doc 2, pos, tf,...]   -&amp;gt; ... -&amp;gt; [doc 19, pos, tf,...] |
| string       |      +-----------------------------------------------+
+--------------+
| word ID 2    |      +-----------------------------------------------+
| string       | ---&amp;gt; | [doc 19, pos, tf,...] -&amp;gt; [doc 21, pos, tf,...]  -&amp;gt; ... -&amp;gt; [doc 38, pos, tf,...] |
+--------------+      +-----------------------------------------------+
       :
       :
| word ID n    |      +-----------------------------------------------+
| string       | ---&amp;gt; | [doc 7, pos, tf,...] -&amp;gt; [doc 11, pos, tf,...]  -&amp;gt; ... -&amp;gt; [doc 43, pos, tf,...] |
+--------------+      +-----------------------------------------------+

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Generating Industrial-Grade Inverted Indexes
&lt;/h2&gt;

&lt;p&gt;Here's how we generate a large-scale inverted index:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Divide large document collections into multiple smaller sets&lt;/li&gt;
&lt;li&gt;Generate in-memory inverted indexes for each small document set&lt;/li&gt;
&lt;li&gt;Store these in-memory indexes on disk as temporary inverted files:

&lt;ul&gt;
&lt;li&gt;Sort the document lists by keyword string size&lt;/li&gt;
&lt;li&gt;Write each keyword and its corresponding document list as a record to the temporary file&lt;/li&gt;
&lt;li&gt;Records in the temporary file are ordered, and we don't need to store keyword IDs (as they're only locally unique)
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Index Table (In Memory)                                                                                  Temporary Files (Disk)

+----------------+                                                                                    +---------------------------+
| word ID 1      |                                                                                    | string 1 | posting list 1 |
| string         |---&amp;gt; doc 1 --&amp;gt; doc 2 --&amp;gt; ... --&amp;gt; doc 19                                             +---------------------------+
+----------------+                                                                                    | string 2 | posting list 2 |
                                                                                                      +---------------------------+
+----------------+                                                                                    | string 3 | posting list 3 |
| word ID 2      |                                                  Write to temporary files          +---------------------------+
| string         |---&amp;gt; doc 19 --&amp;gt; doc 20 --&amp;gt; ... --&amp;gt; doc 34         by key value order                |            ...            |
+----------------+                                                -----------------&amp;gt;                  +---------------------------+
                                                                                                      | string n | posting list n |
        ...                                                                                           +---------------------------+                                            
+----------------+                                             
| word ID n      |                                             
| string         |---&amp;gt; doc 1 --&amp;gt; doc 20 --&amp;gt; ... --&amp;gt; doc 53     
+----------------+

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Process each batch of small document collections to generate corresponding temporary files&lt;/li&gt;
&lt;li&gt;Merge multiple temporary files using multi-way merge:

&lt;ul&gt;
&lt;li&gt;Extract the current record's keyword from each temporary file&lt;/li&gt;
&lt;li&gt;For identical keywords, read out and merge the corresponding posting lists&lt;/li&gt;
&lt;li&gt;If the posting list fits in memory, merge it there and write the result to the final inverted file&lt;/li&gt;
&lt;li&gt;If the posting list is too large, process it in segments&lt;/li&gt;
&lt;li&gt;Assign a globally unique ID to each keyword after merging
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Temporary File 1               Temporary File 2           Temporary File 3
+-----------------------+  +-----------------------+  +-----------------------+
| string 1|posting list |  | string 1|posting list |  | string 3|posting list |
+-----------------------+  +-----------------------+  +-----------------------+
| string 2|posting list |  | string 3|posting list |  | string 4|posting list |
+-----------------------+  +-----------------------+  +-----------------------+
| string 3|posting list |  | string 4|posting list |  | string 5|posting list |
+-----------------------+  +-----------------------+  +-----------------------+
|          ...          |  |           ...         |  |           ...         |
+-----------------------+  +-----------------------+  +-----------------------+
| string n|posting list |  | string i|posting list |  | string j|posting list |
+-----------------------+  +-----------------------+  +-----------------------+
        |                         |                         |
        +-------------------------+-------------------------+
                                  |
                                  v
                     +-------------------------------------+
                     | word ID 1 | string 1 | posting list |
                     +-------------------------------------+
                     | word ID 2 | string 2 | posting list |
                     +-------------------------------------+
                     | word ID 3 | string 3 | posting list |
                     +-------------------------------------+
                     |                  ...                |
                     +-------------------------------------+
                     | word ID n | string n | posting list |
                     +-------------------------------------+
                            Complete Sorted File

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This approach is similar to the Map-Reduce distributed computing paradigm, making it easy to implement on multiple machines to significantly improve efficiency.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using Disk-Based Inverted Files for Retrieval
&lt;/h2&gt;

&lt;p&gt;When using large-scale inverted files for retrieval, the core principle is to load as much data as possible into memory since memory retrieval is much faster than disk access.&lt;/p&gt;

&lt;p&gt;An inverted index consists of two parts: the dictionary (key collection) and the document lists. In many applications, the dictionary is small enough to load into memory using a hash table.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Hash Table (In Memory)                 |        Inverted Index File (Disk)
                                       |
+----------------+                     |        +----------------------------+
| word ID 1      |                     |        | word ID 1 | posting list 1 |
| string         |---&amp;gt; pos ------------|------&amp;gt; +----------------------------+
+----------------+                     |        | word ID 2 | posting list 2 |
                                       |        +----------------------------+
+----------------+                     |        | word ID 3 | posting list 3 |
| word ID 2      |                     |        +----------------------------+
| string         |---&amp;gt; pos ------------|------&amp;gt; |              ...           |
+----------------+                     |        +----------------------------+
        :                              |        | word ID n | posting list n |
        :                              |        +----------------------------+
+----------------+                     |
| word ID n      |                     |
| string         |---&amp;gt; pos ------------|-------&amp;gt;
+----------------+                     |
                                       |

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When a query occurs:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Search the in-memory hash table to find the corresponding key&lt;/li&gt;
&lt;li&gt;Read the posting list associated with that key from disk into memory for processing&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If the dictionary is too large for memory, we can use a B+ tree to search it, treating it as an ordered sequence of keys.&lt;/p&gt;

&lt;p&gt;The retrieval process can be summarized in two steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Use a B+ tree or similar technology to query the keyword in the dictionary&lt;/li&gt;
&lt;li&gt;Read out the posting list for that keyword and process it in memory
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;B-tree/B+ tree (In Memory)      Dictionary File (Disk)           Inverted Index File (Disk)

       •                    +----------------------------+     +----------------------------+
      / \                   | word ID 1 | string 1 | pos |----&amp;gt;| word ID 1 | posting list 1 |
     •   •---------------&amp;gt;  +----------------------------+     +----------------------------+
    /                       | word ID 2 | string 2 | pos |----&amp;gt;| word ID 2 | posting list 2 |
   •                        +----------------------------+     +----------------------------+
  / \                       | word ID 3 | string 3 | pos |----&amp;gt;| word ID 3 | posting list 3 |
 •   •-------------------&amp;gt;  +----------------------------+     +----------------------------+
                            |              ...           |     |             ...            |
                            +----------------------------+     +----------------------------+
                            | word ID n | string n | pos |----&amp;gt;| word ID n | posting list n |
                            +----------------------------+     +----------------------------+

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Handling Very Large Posting Lists
&lt;/h2&gt;

&lt;p&gt;For extremely popular keywords that might appear in hundreds of millions of pages, the posting lists may be too large to load into memory. In such cases:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create B+ tree-like indexes for oversized posting lists&lt;/li&gt;
&lt;li&gt;Load only useful data blocks into memory to reduce disk access&lt;/li&gt;
&lt;li&gt;For shorter posting lists, load them directly into memory&lt;/li&gt;
&lt;li&gt;Use caching techniques like LRU to keep frequently used posting lists in memory&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Key Takeaways
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;We can generate trillion-level inverted indexes using multi-file merging and implement retrieval through dictionary and document list queries.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Two fundamental design principles:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Load as much data as possible into memory (index compression is crucial here)&lt;/li&gt;
&lt;li&gt;Break large data collections into smaller sets (the core idea of distributed systems)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>database</category>
      <category>rag</category>
    </item>
    <item>
      <title>Retrieval Technique Series-3.Why Do Logging Systems Primarily Use LSM Trees Instead of B+ Trees?</title>
      <dc:creator>yang yaru</dc:creator>
      <pubDate>Wed, 04 Jun 2025 03:24:07 +0000</pubDate>
      <link>https://dev.to/yaruyng/retrieval-technique-series-3why-do-logging-systems-primarily-use-lsm-trees-instead-of-b-trees-5b8e</link>
      <guid>https://dev.to/yaruyng/retrieval-technique-series-3why-do-logging-systems-primarily-use-lsm-trees-instead-of-b-trees-5b8e</guid>
      <description>&lt;p&gt;In the world of NoSQL databases, the choice of data structure can significantly impact performance and efficiency. Logging systems, in particular, have found a reliable ally in Log-Structured Merge (LSM) trees, which offer distinct advantages over traditional B+ trees. This blog explores why LSM trees are favored in logging systems, focusing on their design philosophy and performance characteristics.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Limitations of B+ Trees
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Performance Bottlenecks
&lt;/h3&gt;

&lt;p&gt;B+ trees are widely used in relational databases due to their efficient range queries and balanced structures. However, they encounter performance bottlenecks in write-heavy applications, such as logging systems. Each insert operation in a B+ tree may require multiple disk writes to maintain its structure, leading to increased latency.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;┌───────────────────────────┐
│        B+ Tree Write      │
│  ┌──────┐   ┌──────┐      │
│  │Insert│   │Update│      │
│  └──────┘   └──────┘      │
│      │         │          │
│      ▼         ▼          │
│  Multiple Disk Writes     │
└───────────────────────────┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Inherent Write Amplification
&lt;/h3&gt;

&lt;p&gt;B+ trees suffer from write amplification, where a single logical write can result in multiple physical writes due to the need to maintain balance and order in the tree. This can cause significant overhead in high-throughput environments, making them less ideal for logging applications.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;┌───────────────────────────┐
│      Write Amplification  │
│  ┌─────────────┐          │
│  │Logical Write│          │
│  └─────────────┘          │
│           │               │
│           ▼               │
│  Multiple Physical Writes │
└───────────────────────────┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Advantages of LSM Trees
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Write Optimization
&lt;/h3&gt;

&lt;p&gt;LSM trees are designed specifically for write-heavy workloads. They accumulate writes in memory (in a structure called a MemTable) before merging them into disk-based structures in batches. This approach significantly reduces the number of disk writes, leading to better performance in logging systems.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;┌───────────────────────────┐
│        LSM Tree Write     │
│  ┌──────┐                 │
│  │Insert│                 │
│  └──────┘                 │
│      │                    │
│  Accumulate in Memory     │
│      │                    │
│      ▼                    │
│   Batch Disk Write        │
└───────────────────────────┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Efficient Data Merging
&lt;/h3&gt;

&lt;p&gt;LSM trees periodically merge the data stored in the MemTable with data on disk, ensuring that the structure remains efficient and compact. This merging process is designed to minimize the impact on read performance, allowing for fast retrieval even as new data is continuously written.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;┌────────────────────────────┐
│     Efficient Data Merge   │
│  ┌────────┐   ┌────────┐   │
│  │MemTable│   │ Disk   │   │
│  └────────┘   └────────┘   │
│        │                   │
│        ▼                   │
│     Merge Process          │
└────────────────────────────┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  LSM Tree Design Philosophy
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Batch Writes and Reduced I/O
&lt;/h3&gt;

&lt;p&gt;The core design philosophy of LSM trees revolves around reducing the frequency of I/O operations. By accumulating multiple writes in memory and performing batch writes, LSM trees ensure that the underlying storage system is not overwhelmed by frequent updates.&lt;/p&gt;

&lt;h3&gt;
  
  
  Handling High Write Frequencies
&lt;/h3&gt;

&lt;p&gt;Logging systems often generate large volumes of data in a short period. LSM trees are well-suited to handle high write frequencies without compromising performance. This capability allows logging systems to scale efficiently.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;┌────────────────────────────┐
│   Handling High Write      │
│           Frequencies      │
│  ┌────────┐   ┌────────┐   │
│  │Log Data│   │LSM Tree│   │
│  └────────┘   └────────┘   │
│        │                   │
│        ▼                   │
│    Efficient Processing    │
└────────────────────────────┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Search Operations and Recent Data
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Optimized Searching
&lt;/h3&gt;

&lt;p&gt;LSM trees also optimize search operations. When searching for data, they check the MemTable first, providing quick access to the most recently written data. If not found, the search continues in the disk-based structures. This approach minimizes the time spent on searches, especially for recent data.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;┌───────────────────────────┐
│       Optimized Search    │
│  ┌───────────────┐        │
│  │ Check MemTable│        │
│  └───────────────┘        │
│        │                  │
│        ▼                  │
│     Found?                │
│      │                    │
│      ├────────────┐       │
│      ▼            ▼       │
│   Yes          No         │
│  Return       Search Disk │
└───────────────────────────┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;LSM trees offer a compelling solution for logging systems that require efficient write performance and optimized search capabilities. Their ability to handle large volumes of write operations with reduced write amplification makes them a preferred choice over B+ trees in NoSQL implementations.&lt;/p&gt;

&lt;p&gt;As logging systems continue to evolve and generate vast amounts of data, understanding the advantages of LSM trees will be crucial for designing robust, high-performance applications that can efficiently handle today's data challenges.&lt;/p&gt;

</description>
      <category>datastructures</category>
      <category>database</category>
      <category>rag</category>
    </item>
    <item>
      <title>Retrieval Technique Series-2.How to Index Massive Disk Data Using B+ Trees</title>
      <dc:creator>yang yaru</dc:creator>
      <pubDate>Wed, 21 May 2025 02:52:22 +0000</pubDate>
      <link>https://dev.to/yaruyng/retrieval-technique-series-2how-to-index-massive-disk-data-using-b-trees-4hn0</link>
      <guid>https://dev.to/yaruyng/retrieval-technique-series-2how-to-index-massive-disk-data-using-b-trees-4hn0</guid>
      <description>&lt;p&gt;In today's data-driven world, the ability to efficiently store and retrieve massive amounts of information is crucial for any database system. When dealing with data that exceeds the capacity of main memory, specialized data structures become essential. Among these structures, the B+ tree stands out as one of the most powerful and widely implemented indexing mechanisms in modern database systems. This blog explores how B+ trees enable efficient retrieval of massive disk-based data.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Features of B+ Trees
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Suitable for Range Queries
&lt;/h3&gt;

&lt;p&gt;One of the most significant advantages of B+ trees is their exceptional performance for range queries. Unlike hash indexes that excel at point queries but struggle with ranges, B+ trees maintain data in sorted order, making them ideal for operations like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SELECT * FROM customers WHERE age BETWEEN 25 AND 40;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The structure allows for efficient traversal through consecutive keys, as illustrated below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;┌─────────────────────────────────────────────────────┐
│                  Range Query Process                │
│                                                     │
│  1. Find the leaf containing the lower bound (25)   │
│  2. Scan sequentially through leaf nodes            │
│  3. Continue until reaching upper bound (40)        │
│                                                     │
└─────────────────────────────────────────────────────┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Structure of B+ Trees
&lt;/h2&gt;

&lt;p&gt;A key design of the B+ tree is to make the size of a node equal to the size of a block. The data stored within a node is not an element, but an ordered array that can hold m elements.&lt;/p&gt;

&lt;h3&gt;
  
  
  Internal Nodes
&lt;/h3&gt;

&lt;p&gt;Internal nodes in a B+ tree serve as navigational aids, containing keys that guide the search process but don't store actual data records. Each internal node contains:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Sorted keys that define the ranges&lt;/li&gt;
&lt;li&gt;Pointers to child nodes&lt;/li&gt;
&lt;li&gt;A minimum fill factor (typically 50%) to ensure efficient space utilization
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;┌───────── Internal Node ────────┐
│                                │
│  ┌─────┐┌─────┐┌─────┐         │                   
│  │ K₁  ││ K₂  ││ K₃  │         │
│  └─────┘└─────┘└─────┘         │
│  │ P₁  ││ P₂  ││ P₃  │  ...    │
│  └─────┘└─────┘└─────┘         │
│     │                          │
│     ▼                          │
│  Pointer to                    │
│  child node                    │
│                                │
└────────────────────────────────┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Leaf Nodes
&lt;/h3&gt;

&lt;p&gt;Leaf nodes are where the actual data (or pointers to data) resides. When a B+ tree is used for database indexing, the leaf nodes typically store the key value (Key) and the location of the corresponding data record on disk (pointer). The key characteristics of leaf nodes include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;They contain the indexed keys and associated data records (or pointers to records)&lt;/li&gt;
&lt;li&gt;All leaf nodes are at the same level, ensuring balanced tree height&lt;/li&gt;
&lt;li&gt;Leaf nodes are linked together in a doubly-linked list, facilitating efficient range queries
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;                       ┌──────── Leaf Node ────────┐                      ┌──────── Leaf Node ────────┐     
                       │                           │                      │                           │      
                       │  ┌─────┐┌─────┐┌─────┐    │                      │  ┌─────┐┌─────┐┌─────┐    │     
                       │  │ K₁  ││ K₂  ││ K₃  │    │                      │  │ K₁  ││ K₂  ││ K₃  │    │     
                       │  └─────┘└─────┘└─────┘    │                      │  └─────┘└─────┘└─────┘    │    
  ... ◄──────────────► │  │ P₁  ││ P₂  ││ P₃  │... │  ◄───────────────►   │  │ P₁  ││ P₂  ││ P₃  │... │      
        Previous Leaf  │  └─────┘└─────┘└─────┘    │     Next Leaf        │  └─────┘└─────┘└─────┘    │                  
                       │     │                     │                      │     │                     │ 
                       │     ▼                     │                      │     ▼                     │   
                       │  pointers to data         │                      │  pointers to data         │       
                       └───────────────────────────┘                      └───────────────────────────┘           

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Search Process in B+ Trees
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Starting from the Root Node
&lt;/h3&gt;

&lt;p&gt;Every search operation in a B+ tree begins at the root node. The process follows these steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Compare the search key with the keys in the root node&lt;/li&gt;
&lt;li&gt;Determine which child pointer to follow&lt;/li&gt;
&lt;li&gt;Traverse down the tree until reaching a leaf node
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;┌────────────────────────────────────────┐
│               Root Node                │
│           ┌─────┐   ┌─────┐            │
│           │ 30  │   │ 70  │            │
│           └─────┘   └─────┘            │
│              │         │               │
└──────────────┼─────────┼───────────────┘
               ▼         ▼
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│   &amp;lt; 30 Node     │ │  30-70 Node     │ │   &amp;gt; 70 Node     │
│ ┌────┐ ┌────┐   │ │ ┌────┐ ┌────┐   │ │ ┌────┐ ┌────┐   │
│ │ 10 │ │ 20 │   │ │ │ 40 │ │ 60 │   │ │ │ 80 │ │ 90 │   │
│ └────┘ └────┘   │ │ └────┘ └────┘   │ │ └────┘ └────┘   │
└─────────────────┘ └─────────────────┘ └─────────────────┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Traversing Internal Nodes Layer by Layer
&lt;/h3&gt;

&lt;p&gt;As the search progresses through the tree:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;At each internal node, the algorithm compares the search key with the node's keys&lt;/li&gt;
&lt;li&gt;It follows the appropriate pointer based on the comparison&lt;/li&gt;
&lt;li&gt;This process continues until reaching a leaf node&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Implementing Range Queries via Doubly-Linked Lists
&lt;/h3&gt;

&lt;p&gt;The doubly-linked list connecting all leaf nodes is what makes B+ trees particularly efficient for range queries:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;First, locate the leaf node containing the lower bound of the range&lt;/li&gt;
&lt;li&gt;Scan sequentially through the linked list of leaf nodes&lt;/li&gt;
&lt;li&gt;Continue until reaching the upper bound of the range
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;┌──────────┐   ┌──────────┐   ┌──────────┐   ┌──────────┐
│ Leaf 1   │◄─►│ Leaf 2   │◄─►│ Leaf 3   │◄─►│ Leaf 4   │
│ Keys:    │   │ Keys:    │   │ Keys:    │   │ Keys:    │
│ 10,15,20 │   │ 25,30,35 │   │ 40,45,50 │   │ 55,60,65 │
└──────────┘   └──────────┘   └──────────┘   └──────────┘
                    ▲               ▲
                    │               │
                    └───────────────┘
                    Range query from
                      30 to 45
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Dynamic Adjustments in B+ Trees(A node has 4 elements)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Inserting Data
&lt;/h3&gt;

&lt;p&gt;When inserting new data into a B+ tree:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Locate the appropriate leaf node&lt;/li&gt;
&lt;li&gt;Insert the key in sorted order&lt;/li&gt;
&lt;li&gt;If the node overflows (exceeds maximum capacity):

&lt;ul&gt;
&lt;li&gt;Split the node into two&lt;/li&gt;
&lt;li&gt;Promote the middle key to the parent&lt;/li&gt;
&lt;li&gt;Adjust pointers accordingly
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Before insertion of 45:
┌───────────────┐
│    Node A     │
│ 30, 40, 50, 60│
└───────────────┘

After insertion and split:
        ┌─────┐
        │ 45  │  ← Promoted to parent
        └─────┘
         /   \
        /     \
┌───────────┐ ┌───────────┐
│  Node A   │ │  Node B   │
│ 30, 40    │ │ 45, 50, 60│
└───────────┘ └───────────┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Deleting Data
&lt;/h3&gt;

&lt;p&gt;The deletion process involves:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Finding the key to be deleted&lt;/li&gt;
&lt;li&gt;Removing it from the leaf node&lt;/li&gt;
&lt;li&gt;If the node becomes underfilled:

&lt;ul&gt;
&lt;li&gt;Borrow keys from siblings if possible&lt;/li&gt;
&lt;li&gt;Merge with siblings if necessary&lt;/li&gt;
&lt;li&gt;Adjust parent nodes accordingly
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Before deletion of 40:
┌───────────┐ ┌───────────┐
│  Node A   │ │  Node B   │
│ 30, 40    │ │ 45, 50, 60│
└───────────┘ └───────────┘
      Parent key: 45

After deletion and potential merge:
┌─────────────────┐
│     Node AB     │
│ 30, 45, 50, 60  │
└─────────────────┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Advantages of B+ Trees
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Suitable for Large-Scale Data
&lt;/h3&gt;

&lt;p&gt;B+ trees are specifically designed to handle data that doesn't fit in memory:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The tree structure minimizes disk I/O operations&lt;/li&gt;
&lt;li&gt;The height of the tree grows logarithmically with the number of records&lt;/li&gt;
&lt;li&gt;Even with millions or billions of records, a B+ tree typically has a height of 3-4 levels
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;┌────────────────────────────────────────────────┐
│        B+ Tree Performance Characteristics     │
├────────────────────────┬───────────────────────┤
│ Number of Records      │ Typical Tree Height   │
├────────────────────────┼───────────────────────┤
│ 1,000                  │ 2                     │
│ 1,000,000              │ 3                     │
│ 1,000,000,000          │ 4                     │
└────────────────────────┴───────────────────────┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Index Data Stored on Disk
&lt;/h3&gt;

&lt;p&gt;B+ trees are optimized for disk-based storage:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Node size is aligned with disk block size (typically 4KB to 16KB)&lt;/li&gt;
&lt;li&gt;This alignment minimizes the number of disk I/O operations&lt;/li&gt;
&lt;li&gt;Internal nodes are often cached in memory for faster access
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;┌───────────────────────────────────────────────────┐
│              Disk-Based B+ Tree                   │
│                                                   │
│  ┌─────────┐                                      │
│  │ Memory  │  Root and frequently accessed nodes  │
│  │ Cache   │  kept in memory                      │
│  └─────────┘                                      │
│        │                                          │
│        ▼                                          │
│  ┌─────────┐                                      │
│  │  Disk   │  Most nodes stored on disk,          │
│  │ Storage │  loaded as needed                    │
│  └─────────┘                                      │
│                                                   │
└───────────────────────────────────────────────────┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Design Philosophy
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Separation of Index and Data
&lt;/h3&gt;

&lt;p&gt;A key design principle of B+ trees is the separation of indexing structure from the actual data:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Leaf nodes contain either the full data records or pointers to them&lt;/li&gt;
&lt;li&gt;This separation allows for more efficient use of cache memory&lt;/li&gt;
&lt;li&gt;It also enables different organizations of the data itself
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;┌───────────────────────────────────────────────────┐
│           Index and Data Separation               │
│                                                   │
│  ┌─────────────────┐                              │
│  │   B+ Tree Index │                              │
│  │   Structure     │                              │
│  └────────┬────────┘                              │
│           │                                       │
│           │ References                            │
│           ▼                                       │
│  ┌─────────────────┐                              │
│  │   Actual Data   │                              │
│  │   Records       │                              │
│  └─────────────────┘                              │
│                                                   │
└───────────────────────────────────────────────────┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Practical Implementation
&lt;/h2&gt;

&lt;p&gt;To better understand how B+ trees work in practice, let's consider simplified implementations in Java and Go:&lt;/p&gt;

&lt;h3&gt;
  
  
  Java Implementation
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.util.ArrayList&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.util.List&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.util.AbstractMap.SimpleEntry&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;BPlusTree&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;K&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Comparable&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;K&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;,&lt;/span&gt; &lt;span class="no"&gt;V&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;Node&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;K&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="no"&gt;V&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;maxKeys&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;BPlusTree&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;maxKeys&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;root&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;LeafNode&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;gt;(&lt;/span&gt;&lt;span class="n"&gt;maxKeys&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;maxKeys&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;maxKeys&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="no"&gt;V&lt;/span&gt; &lt;span class="nf"&gt;search&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="no"&gt;K&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;search&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;SimpleEntry&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;K&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="no"&gt;V&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;rangeQuery&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="no"&gt;K&lt;/span&gt; &lt;span class="n"&gt;startKey&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="no"&gt;K&lt;/span&gt; &lt;span class="n"&gt;endKey&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;SimpleEntry&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;K&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="no"&gt;V&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ArrayList&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;gt;();&lt;/span&gt;

        &lt;span class="c1"&gt;// Find leaf node containing the start key&lt;/span&gt;
        &lt;span class="nc"&gt;LeafNode&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;K&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="no"&gt;V&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;findLeafNode&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;startKey&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

        &lt;span class="c1"&gt;// Collect all keys in range by following leaf pointers&lt;/span&gt;
        &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;node&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;keys&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;size&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                &lt;span class="no"&gt;K&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;keys&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
                &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;compareTo&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;startKey&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;compareTo&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;endKey&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                    &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;add&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;SimpleEntry&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;values&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;)));&lt;/span&gt;
                &lt;span class="o"&gt;}&lt;/span&gt;
                &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;compareTo&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;endKey&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
                &lt;span class="o"&gt;}&lt;/span&gt;
            &lt;span class="o"&gt;}&lt;/span&gt;
            &lt;span class="n"&gt;node&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;next&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;LeafNode&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;K&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="no"&gt;V&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;findLeafNode&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Node&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;K&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="no"&gt;V&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="no"&gt;K&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;node&lt;/span&gt; &lt;span class="k"&gt;instanceof&lt;/span&gt; &lt;span class="nc"&gt;LeafNode&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;LeafNode&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;K&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="no"&gt;V&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;)&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;

        &lt;span class="nc"&gt;InternalNode&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;K&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="no"&gt;V&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;internalNode&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;InternalNode&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;K&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="no"&gt;V&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;)&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;internalNode&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;keys&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;size&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;compareTo&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;internalNode&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;keys&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++;&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;findLeafNode&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;internalNode&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;children&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;abstract&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Node&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;K&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Comparable&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;K&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;,&lt;/span&gt; &lt;span class="no"&gt;V&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;K&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;keys&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;maxKeys&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

        &lt;span class="nc"&gt;Node&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;maxKeys&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;keys&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ArrayList&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;gt;();&lt;/span&gt;
            &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;maxKeys&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;maxKeys&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;

        &lt;span class="kd"&gt;abstract&lt;/span&gt; &lt;span class="no"&gt;V&lt;/span&gt; &lt;span class="nf"&gt;search&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="no"&gt;K&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;InternalNode&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;K&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Comparable&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;K&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;,&lt;/span&gt; &lt;span class="no"&gt;V&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Node&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;K&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="no"&gt;V&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Node&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;K&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="no"&gt;V&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;children&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

        &lt;span class="nc"&gt;InternalNode&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;maxKeys&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="kd"&gt;super&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;maxKeys&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
            &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;children&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ArrayList&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;gt;();&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;

        &lt;span class="nd"&gt;@Override&lt;/span&gt;
        &lt;span class="no"&gt;V&lt;/span&gt; &lt;span class="nf"&gt;search&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="no"&gt;K&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
            &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;keys&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;size&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;compareTo&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;keys&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++;&lt;/span&gt;
            &lt;span class="o"&gt;}&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;children&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;search&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;LeafNode&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;K&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Comparable&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;K&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;,&lt;/span&gt; &lt;span class="no"&gt;V&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Node&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;K&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="no"&gt;V&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;V&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;values&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="nc"&gt;LeafNode&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;K&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="no"&gt;V&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;next&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="nc"&gt;LeafNode&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;K&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="no"&gt;V&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;prev&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

        &lt;span class="nc"&gt;LeafNode&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;maxKeys&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="kd"&gt;super&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;maxKeys&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
            &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;values&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ArrayList&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;gt;();&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;

        &lt;span class="nd"&gt;@Override&lt;/span&gt;
        &lt;span class="no"&gt;V&lt;/span&gt; &lt;span class="nf"&gt;search&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="no"&gt;K&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;keys&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;size&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;keys&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;equals&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;values&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
                &lt;span class="o"&gt;}&lt;/span&gt;
            &lt;span class="o"&gt;}&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Go Implementation
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;bplustree&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"fmt"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;KeyValuePair&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Key&lt;/span&gt;   &lt;span class="k"&gt;interface&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;
    &lt;span class="n"&gt;Value&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;BPlusTreeNode&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;IsLeaf&lt;/span&gt;   &lt;span class="kt"&gt;bool&lt;/span&gt;
    &lt;span class="n"&gt;Keys&lt;/span&gt;     &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="k"&gt;interface&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;
    &lt;span class="n"&gt;Children&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;BPlusTreeNode&lt;/span&gt;
    &lt;span class="n"&gt;Next&lt;/span&gt;     &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;BPlusTreeNode&lt;/span&gt;
    &lt;span class="n"&gt;Prev&lt;/span&gt;     &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;BPlusTreeNode&lt;/span&gt;
    &lt;span class="n"&gt;Values&lt;/span&gt;   &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="k"&gt;interface&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;
    &lt;span class="n"&gt;MaxKeys&lt;/span&gt;  &lt;span class="kt"&gt;int&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;BPlusTree&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Root&lt;/span&gt;    &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;BPlusTreeNode&lt;/span&gt;
    &lt;span class="n"&gt;MaxKeys&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;NewBPlusTree&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;maxKeys&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;BPlusTree&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;BPlusTree&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;Root&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;BPlusTreeNode&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;IsLeaf&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;  &lt;span class="no"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;Keys&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;    &lt;span class="nb"&gt;make&lt;/span&gt;&lt;span class="p"&gt;([]&lt;/span&gt;&lt;span class="k"&gt;interface&lt;/span&gt;&lt;span class="p"&gt;{},&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="n"&gt;Values&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;  &lt;span class="nb"&gt;make&lt;/span&gt;&lt;span class="p"&gt;([]&lt;/span&gt;&lt;span class="k"&gt;interface&lt;/span&gt;&lt;span class="p"&gt;{},&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="n"&gt;MaxKeys&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;maxKeys&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="n"&gt;MaxKeys&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;maxKeys&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;BPlusTree&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;Search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt;&lt;span class="p"&gt;{})&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Root&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;BPlusTree&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;node&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;BPlusTreeNode&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt;&lt;span class="p"&gt;{})&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IsLeaf&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;range&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Keys&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;compare&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Values&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c"&gt;// If not leaf, find the appropriate child&lt;/span&gt;
    &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Keys&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;compare&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Keys&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Children&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;BPlusTree&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;RangeQuery&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;startKey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;endKey&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt;&lt;span class="p"&gt;{})&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="n"&gt;KeyValuePair&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// Find leaf node containing the start key&lt;/span&gt;
    &lt;span class="n"&gt;node&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Root&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IsLeaf&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Keys&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;compare&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;startKey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Keys&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="n"&gt;node&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Children&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c"&gt;// Collect all keys in range by following leaf pointers&lt;/span&gt;
    &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nb"&gt;make&lt;/span&gt;&lt;span class="p"&gt;([]&lt;/span&gt;&lt;span class="n"&gt;KeyValuePair&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;range&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Keys&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;compare&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;startKey&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;compare&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;endKey&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;KeyValuePair&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;Key&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Value&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Values&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]})&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;compare&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;endKey&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="n"&gt;node&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Next&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;// Helper function to compare keys&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;compare&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt;&lt;span class="p"&gt;{})&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;switch&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;type&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;
    &lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
        &lt;span class="nb"&gt;panic&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Unsupported type for comparison"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;B+ trees have become the backbone of indexing in disk-based database systems for good reasons. Their balanced structure ensures consistent performance regardless of data size, while their leaf-level linked list enables efficient range queries. The design specifically addresses the challenges of disk-based storage by minimizing I/O operations and maximizing cache utilization.&lt;/p&gt;

&lt;p&gt;When designing database systems that must handle large volumes of data, understanding B+ trees is essential. They represent one of the most elegant solutions to the problem of efficiently retrieving data from disk-based storage systems, balancing the trade-offs between memory usage, disk access patterns, and query performance.&lt;/p&gt;

&lt;p&gt;Whether you're developing a database system in Java, Go, or any other language, the B+ tree is a fundamental concept that demonstrates how clever algorithm design can overcome the physical limitations of storage hardware. The implementations provided above, while simplified, illustrate the core concepts that make B+ trees so valuable in database systems.&lt;/p&gt;

</description>
      <category>database</category>
      <category>datastructures</category>
      <category>rag</category>
    </item>
    <item>
      <title>Retrieval Technique Series-1.Linear Structure Retrieval</title>
      <dc:creator>yang yaru</dc:creator>
      <pubDate>Mon, 14 Apr 2025 06:02:31 +0000</pubDate>
      <link>https://dev.to/yaruyng/retrieval-technique-series-1linear-structure-retrieval-8k3</link>
      <guid>https://dev.to/yaruyng/retrieval-technique-series-1linear-structure-retrieval-8k3</guid>
      <description>&lt;p&gt;Understanding the Essence of Retrieval Through Arrays and Linked Lists&lt;/p&gt;

&lt;p&gt;In today's information explosion era, retrieval technology has become an indispensable part of our daily lives and work.Whether searching for information through search engines or retrieving records from databases, the efficiency and accuracy of retrieving records directly impact our user experience.To deeply understand complex retrieval systems, we must start with the most fundamental data structures-arrays and linked lists, the two basic linear structures.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Essence of Retrieval
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Definition of Retrieval
&lt;/h3&gt;

&lt;p&gt;Retrieval is essentially the process of finding specific elements within a series of data.This seemingly simple operation is actually one of the most fundamental and important operations in computer science.From simple array traversal to complex web indexing, all implements the core functionality of "retrieval".&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;┌─────────────────────────────────┐
│                                 │
│         RETRIEVAL PROCESS       │
│                                 │
│  ┌─────┐     ┌─────────┐        │
│  │Input│────▶│Searching│        │
│  └─────┘     │Algorithm│        │
│              └────┬────┘        │
│                   │             │
│                   ▼             │
│              ┌─────────┐        │
│              │ Output  │        │
│              └─────────┘        │
│                                 │
└─────────────────────────────────┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Relationship Between Retrieval Efficiency and Data Storage Methods
&lt;/h3&gt;

&lt;p&gt;The way data is stored directly determines retrieval efficiency.Different data structures have different storage characteristics and therefor different retrieval performance.In linear structure,arrays and linked lists are the two most basic storage methods with fundamentally different retrival characteristics.&lt;/p&gt;

&lt;h2&gt;
  
  
  Storage Characteristics of Arrays and Linked Lists
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Arrary Characteristics
&lt;/h3&gt;

&lt;p&gt;Arrays are data structures with contiguous storage, where elements are adjacent in memory.This storage method has the following characteristics:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Strong random access capability: can directly access elements at any position through indexing, with O(1) time complexity&lt;/li&gt;
&lt;li&gt;High memory utilization: no additional pointer overhead&lt;/li&gt;
&lt;li&gt;Cache-friendly: contiguous memory layout benefits CPU cache utilization&lt;/li&gt;
&lt;li&gt;However, arrays are usually fixed in size, and dynamic size adjustment requires memory reallocation
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;┌───────────────────────────────────────┐
│               ARRAY                   │
├───┬───┬───┬───┬───┬───┬───┬───┬───┬───┤
│ 0 │ 1 │ 2 │ 3 │ 4 │ 5 │ 6 │ 7 │ 8 │ 9 │
└───┴───┴───┴───┴───┴───┴───┴───┴───┴───┘
  ▲                   ▲               ▲
  │                   │               │
Direct access      Direct access   Direct access
   O(1)               O(1)           O(1)

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Linked List Characteristics
&lt;/h3&gt;

&lt;p&gt;Linked lists are non-contiguous storage data structures that connect nodes through pointers. The characteristics of linked lists include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Dynamic memory allocation: nodes can be added or removed dynamically as needed&lt;/li&gt;
&lt;li&gt;Efficient insertion and deletion operations: no need to move other elements, just adjust pointers&lt;/li&gt;
&lt;li&gt;However, linked lists do not support random access; accessing a specific position requires traversal from the head
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;┌────────┐     ┌────────┐     ┌────────┐     ┌────────┐
│  Data  │     │  Data  │     │  Data  │     │  Data  │
│ ┌────┐ │     │ ┌────┐ │     │ ┌────┐ │     │ ┌────┐ │
│ │ 10 │ │     │ │ 20 │ │     │ │ 30 │ │     │ │ 40 │ │
│ └────┘ │     │ └────┘ │     │ └────┘ │     │ └────┘ │
│  Next  │     │  Next  │     │  Next  │     │  Next  │
│ ┌────┐ │     │ ┌────┐ │     │ ┌────┐ │     │ ┌────┐ │
│ │ ──────────▶│ ──────────▶│ ──────────▶│  NULL │ │
│ └────┘ │     │ └────┘ │     │ └────┘ │     │ └────┘ │
└────────┘     └────────┘     └────────┘     └────────┘
    Head                                         Tail

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Representatives of Linear Structures
&lt;/h3&gt;

&lt;p&gt;Besides arrays and linked lists, linear structures also include stacks, queues, and other data structures that store data in a linear order, each with its own characteristics and applicable scenarios.&lt;/p&gt;

&lt;h2&gt;
  
  
  Improving Array Retrieval Efficiency
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Binary Search Algorithm
&lt;/h3&gt;

&lt;p&gt;For sorted arrays, binary search is an efficient retrieval algorithm. Its basic idea is:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Divide the search interval in half&lt;/li&gt;
&lt;li&gt;Determine which half contains the target value&lt;/li&gt;
&lt;li&gt;Continue searching in the corresponding half-interval&lt;/li&gt;
&lt;li&gt;Repeat the above steps until the target value is found or determined not to exist&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Binary search has a time complexity of O(log n), far superior to linear search's O(n).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┐
│ 1 │ 3 │ 5 │ 7 │ 9 │ 11│ 13│ 15│ 17│ 19│  Search for 11
└───┴───┴───┴───┴───┴───┴───┴───┴───┴───┘
                  ▲
                  │
               mid = 9
              9 &amp;lt; 11, go right

┌───┬───┬───┬───┬───┐
│ 11│ 13│ 15│ 17│ 19│  Search for 11
└───┴───┴───┴───┴───┘
  ▲
  │
mid = 11
11 = 11, found!

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Implementation Steps
&lt;/h3&gt;

&lt;p&gt;The implementation of binary search needs to pay attention to the following points:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The array must be sorted&lt;/li&gt;
&lt;li&gt;Boundary conditions must be handled correctly&lt;/li&gt;
&lt;li&gt;Prevent integer overflow&lt;/li&gt;
&lt;li&gt;Handle cases with duplicate elements&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Binary Search Efficiency
&lt;/h3&gt;

&lt;p&gt;The efficiency of binary search is mainly reflected in:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Time complexity: O(log n)&lt;/li&gt;
&lt;li&gt;Space complexity: O(1) (iterative implementation) or O(log n) (recursive implementation)&lt;/li&gt;
&lt;li&gt;For large datasets, the efficiency improvement is particularly significant&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Advantages and Disadvantages of Linked Lists
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Linked List Retrieval Efficiency
&lt;/h3&gt;

&lt;p&gt;The retrieval efficiency of linked lists is relatively low, mainly because:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;They do not support random access; traversal must start from the head node&lt;/li&gt;
&lt;li&gt;Time complexity is O(n)&lt;/li&gt;
&lt;li&gt;Not cache-friendly, as nodes are scattered throughout memory
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;┌────────┐     ┌────────┐     ┌────────┐     ┌────────┐
│  Head  │     │        │     │        │     │  Tail  │
│  Node  │────▶│  Node  │────▶│  Node  │────▶│  Node  │
└────────┘     └────────┘     └────────┘     └────────┘
    ▲
    │
  Start here and traverse sequentially
  to find any element: O(n)

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Dynamic Adjustment Capability of Linked Lists
&lt;/h3&gt;

&lt;p&gt;Despite low retrieval efficiency, linked lists have significant advantages in dynamic adjustment:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Time complexity for insertion and deletion operations is O(1) (assuming the position is known)&lt;/li&gt;
&lt;li&gt;No need to pre-allocate fixed-size memory&lt;/li&gt;
&lt;li&gt;Efficiently handle dynamically changing datasets&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Flexible Modification of Linked Lists
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Flexible Adjustment of Non-Contiguous Storage Space
&lt;/h3&gt;

&lt;p&gt;The non-contiguous storage characteristic of linked lists allows them to flexibly adapt to various memory constraints:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Can utilize fragmented memory space&lt;/li&gt;
&lt;li&gt;Not limited by physical memory contiguity&lt;/li&gt;
&lt;li&gt;Suitable for use in memory-constrained environments&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Examples of Modified Linked Lists
&lt;/h3&gt;

&lt;p&gt;To improve the retrieval efficiency of linked lists, various modifications can be made:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Skip List: Add multiple levels of indexes to achieve average O(log n) search time&lt;/li&gt;
&lt;li&gt;Doubly Linked List: Support bidirectional traversal, improving retrieval efficiency in specific scenarios&lt;/li&gt;
&lt;li&gt;Circular Linked List: Suitable for scenarios requiring circular access&lt;/li&gt;
&lt;li&gt;Hash Linked List: Combining the advantages of hash tables and linked lists
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Skip List Structure:
┌───┐                                  ┌───┐
│ H │──────────────────────────────────▶ T │  Level 3
└─┬─┘                                  └───┘
  │
┌─▼─┐          ┌───┐                   ┌───┐
│ H │──────────▶ 30│───────────────────▶ T │  Level 2
└─┬─┘          └───┘                   └───┘
  │
┌─▼─┐  ┌───┐   ┌───┐   ┌───┐          ┌───┐
│ H │──▶ 10│───▶ 30│───▶ 50│──────────▶ T │  Level 1
└─┬─┘  └───┘   └───┘   └───┘          └───┘
  │
┌─▼─┐  ┌───┐   ┌───┐   ┌───┐   ┌───┐  ┌───┐
│ H │──▶ 10│───▶ 20│───▶ 30│───▶ 50│──▶ T │  Level 0
└───┘  └───┘   └───┘   └───┘   └───┘  └───┘

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Key Review
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Retrieval Technology and Efficiency Analysis of Linear Structures
&lt;/h3&gt;

&lt;p&gt;The retrieval efficiency of linear structures mainly depends on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Data storage method (contiguous vs. non-contiguous)&lt;/li&gt;
&lt;li&gt;Whether the data is sorted&lt;/li&gt;
&lt;li&gt;Choice of retrieval algorithm&lt;/li&gt;
&lt;li&gt;Data scale&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Core Ideas of Retrieval
&lt;/h3&gt;

&lt;p&gt;The core ideas of retrieval technology include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Reducing the number of comparisons&lt;/li&gt;
&lt;li&gt;Utilizing data characteristics (such as order)&lt;/li&gt;
&lt;li&gt;Balancing space and time&lt;/li&gt;
&lt;li&gt;Choosing appropriate data structures for specific application scenarios&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By deeply understanding the two basic linear data structures—arrays and linked lists—we can better grasp the essence of retrieval technology and lay a solid foundation for learning more complex retrieval algorithms and data structures. In practical applications, we need to choose appropriate data structures and retrieval algorithms based on specific scenarios and requirements to achieve optimal performance and user experience.&lt;/p&gt;

&lt;p&gt;Whether traditional information retrieval systems or modern search engines, all are built on these basic principles through continuous optimization and innovation to construct more efficient and accurate retrieval systems. Therefore, mastering the retrieval principles of linear structures is our first step in understanding and applying modern retrieval technology.&lt;/p&gt;

</description>
      <category>datastructures</category>
      <category>rag</category>
    </item>
  </channel>
</rss>
