{"id":7435,"date":"2026-08-17T04:22:09","date_gmt":"2026-08-17T11:22:09","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/azure-sql\/?p=7435"},"modified":"2026-08-27T21:33:31","modified_gmt":"2026-08-28T04:33:31","slug":"beyond-vector-indexes-azure-sql-brings-optimizer-intelligence-to-vector-search","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/azure-sql\/beyond-vector-indexes-azure-sql-brings-optimizer-intelligence-to-vector-search\/","title":{"rendered":"Beyond Vector Indexes: Azure SQL Brings Optimizer Intelligence to Vector Search"},"content":{"rendered":"<p><em><span class=\"TextRun SCXW165600249 BCX8\" lang=\"EN-US\" xml:lang=\"EN-US\" data-contrast=\"none\"><span class=\"NormalTextRun SCXW165600249 BCX8\">Why p<\/span><span class=\"NormalTextRun SCXW165600249 BCX8\">roduction AI retrieval depends on <strong>more<\/strong> than vector index <\/span><span class=\"NormalTextRun SCXW165600249 BCX8\">performance.<\/span><\/span><span class=\"EOP Selected SCXW165600249 BCX8\" data-ccp-props=\"{&quot;201341983&quot;:0,&quot;335559739&quot;:140,&quot;335559740&quot;:269}\">\u00a0<\/span><\/em><\/p>\n<p>It&#8217;s easy to think of AI retrieval as a vector search problem. For many developers, the first conversation starts with vector index benchmarks: How many queries per second can it handle? What&#8217;s the latency? What&#8217;s the recall? How well does it scale?<\/p>\n<p>Those metrics are critical, but production AI retrieval rarely consists of vector similarity alone. Equally important is what happens when vector search becomes part of a real application workload, one that includes filters, joins, security policies, ranking logic, and live operational data.<\/p>\n<p>Generating similar candidates at scale is only the first part of the problem. The harder challenge is helping the database find the right results after the rest of the SQL query is considered<\/p>\n<h3><b><span data-contrast=\"none\">The reality of production AI retrieval<\/span><\/b><span data-ccp-props=\"{&quot;134245418&quot;:true,&quot;134245529&quot;:true,&quot;201341983&quot;:0,&quot;335559738&quot;:280,&quot;335559739&quot;:160,&quot;335559740&quot;:269}\">\u00a0<\/span><\/h3>\n<p><span data-contrast=\"none\">Consider an enterprise support application where a support engineer investigates VPN failures after a password reset. The engineer searches for &#8220;VPN connection fails after password reset&#8221; to find similar incidents and known resolutions.<\/span><span data-ccp-props=\"{&quot;201341983&quot;:0,&quot;335559685&quot;:360,&quot;335559739&quot;:140,&quot;335559740&quot;:269,&quot;335559991&quot;:360}\">\u00a0<\/span><\/p>\n<p><span data-contrast=\"none\">Finding semantically similar tickets is only part of the task. The engineer also needs results that are still open, belong to the relevant product area, include customer information from related tables, and are visible under existing security policies. Some of these conditions depend on values known only when the query executes, such as the selected product area, tenant, or current user context.<\/span><span data-ccp-props=\"{&quot;201341983&quot;:0,&quot;335559739&quot;:140,&quot;335559740&quot;:269}\">\u00a0<\/span><\/p>\n<p><span class=\"TextRun SCXW184925135 BCX8\" lang=\"EN-US\" xml:lang=\"EN-US\" data-contrast=\"none\"><span class=\"NormalTextRun SCXW184925135 BCX8\">Conceptually, the query might look like this:<\/span><\/span><\/p>\n<pre class=\"prettyprint language-sql\"><code class=\"language-sql\">DECLARE @ProductArea NVARCHAR(50) = 'Networking'; \r\nDECLARE @TenantId UNIQUEIDENTIFIER = @CurrentTenantId; \r\n \r\nSELECT TOP (10) WITH APPROXIMATE \r\n    t.TicketId, \r\n    t.Title, \r\n    t.PriorityLevel, \r\n    t.TicketStatus, \r\n    c.CustomerName, \r\n    p.ProductName, \r\n    s.distance \r\nFROM VECTOR_SEARCH( \r\n    TABLE = dbo.SupportTicketEmbeddings, \r\n    COLUMN = IssueEmbedding, \r\n    SIMILAR_TO = @query_vector, \r\n    METRIC = 'cosine' \r\n) AS s \r\nJOIN dbo.SupportTickets t \r\n    ON s.TicketId = t.TicketId \r\nJOIN dbo.Customers c \r\n    ON t.CustomerId = c.CustomerId \r\nJOIN dbo.Products p \r\n    ON t.ProductId = p.ProductId \r\nWHERE t.TicketStatus = 'Open' \r\n  AND p.ProductName = @ProductArea \r\n  AND c.TenantId = @TenantId \r\nORDER BY s.distance; <\/code><\/pre>\n<p>The application expresses a straightforward requirement. The database faces a more complex optimization problem: find semantically relevant records, apply relational predicates, and return the requested qualifying results while minimizing unnecessary vector exploration and distance calculations.<\/p>\n<h3><span class=\"TextRun SCXW211600263 BCX8\" lang=\"EN-US\" xml:lang=\"EN-US\" data-contrast=\"none\"><span class=\"NormalTextRun SCXW211600263 BCX8\" data-ccp-parastyle=\"heading 1\">When vector retrieval lives outside the <\/span><span class=\"NormalTextRun SCXW211600263 BCX8\" data-ccp-parastyle=\"heading 1\">database<\/span><\/span><span class=\"EOP Selected SCXW211600263 BCX8\" data-ccp-props=\"{&quot;134245418&quot;:true,&quot;134245529&quot;:true,&quot;201341983&quot;:0,&quot;335559738&quot;:280,&quot;335559739&quot;:160,&quot;335559740&quot;:269}\">\u00a0<\/span><\/h3>\n<p>The challenge becomes more apparent, when vector retrieval happens in a separate vector database, applications commonly split the workflow into multiple steps.<\/p>\n<ol>\n<li>Send the query embedding to the external vector database.<\/li>\n<li>Retrieve a fixed set of candidate IDs, for example, the top 100 nearest matches.<\/li>\n<li>Send those candidate IDs to the relational database.<\/li>\n<li>Apply filters, joins, permissions, and business rules in SQL.<\/li>\n<li>Request more vector candidates and repeat the relational query if too few rows qualify.<\/li>\n<\/ol>\n<p><figure id=\"attachment_7437\" aria-labelledby=\"figcaption_attachment_7437\" class=\"wp-caption aligncenter\" ><a href=\"https:\/\/devblogs.microsoft.com\/azure-sql\/wp-content\/uploads\/sites\/56\/2026\/08\/vectorexternaldb-e1786965331105.webp\"><img decoding=\"async\" class=\"wp-image-7437 size-full\" src=\"https:\/\/devblogs.microsoft.com\/azure-sql\/wp-content\/uploads\/sites\/56\/2026\/08\/vectorexternaldb-e1786965331105.webp\" alt=\"Diagram of vector retrieval across separate systems. The application sends a query embedding to an external vector database, receives the top 100 candidate IDs, passes them to a relational SQL query that applies ticket status and priority filters, and requests more candidates when only six qualify.\" width=\"647\" height=\"434\" srcset=\"https:\/\/devblogs.microsoft.com\/azure-sql\/wp-content\/uploads\/sites\/56\/2026\/08\/vectorexternaldb-e1786965331105.webp 647w, https:\/\/devblogs.microsoft.com\/azure-sql\/wp-content\/uploads\/sites\/56\/2026\/08\/vectorexternaldb-e1786965331105-300x201.webp 300w\" sizes=\"(max-width: 647px) 100vw, 647px\" \/><\/a><figcaption id=\"figcaption_attachment_7437\" class=\"wp-caption-text\">Diagram of vector retrieval across separate systems.<\/figcaption><\/figure><\/p>\n<p>The vector database knows which embeddings are similar, but it may not have visibility into all the relational predicates, joins, security rules, and live business data evaluated by SQL. The relational database understands those constraints, but it receives only the candidate set selected by the external vector system.\nThe two systems optimize different parts of the request independently. This increases application complexity and data movement, while placing the burden of choosing candidate counts, coordinating retries, and reconciling data and security boundaries on the developer.<\/p>\n<h3>Vector Retrieval as a Part of SQL Query Processing<\/h3>\n<p>The challenge is not simply where vectors are stored. The challenge is how vector retrieval participates in the execution of the complete query.<\/p>\n<p><strong>In Azure SQL, vectors are not stored as opaque blobs or managed through an external service bolted onto the database.<\/strong><\/p>\n<p>SQL query optimizers have benefited from decades of investment in cardinality estimation and cost-based plan selection.<\/p>\n<p>Because vector search is fully composable with relational operators such as filters, joins, aggregates, and security predicates, the optimizer can cost it in the context of the complete query. It can then compare alternative execution strategies and choose an efficient plan for a query containing vector search, rather than optimizing vector retrieval as an isolated step. DiskANN provides efficient candidate generation over large vector collections, while the SQL optimizer integrates that retrieval with the rest of the query.<\/p>\n<p><figure id=\"attachment_7436\" aria-labelledby=\"figcaption_attachment_7436\" class=\"wp-caption aligncenter\" ><a href=\"https:\/\/devblogs.microsoft.com\/azure-sql\/wp-content\/uploads\/sites\/56\/2026\/08\/queryoptvector.webp\"><img decoding=\"async\" class=\"wp-image-7436 size-full\" src=\"https:\/\/devblogs.microsoft.com\/azure-sql\/wp-content\/uploads\/sites\/56\/2026\/08\/queryoptvector.webp\" alt=\"Vector search becomes part of the same optimization framework as relational processing\" width=\"798\" height=\"135\" srcset=\"https:\/\/devblogs.microsoft.com\/azure-sql\/wp-content\/uploads\/sites\/56\/2026\/08\/queryoptvector.webp 798w, https:\/\/devblogs.microsoft.com\/azure-sql\/wp-content\/uploads\/sites\/56\/2026\/08\/queryoptvector-300x51.webp 300w, https:\/\/devblogs.microsoft.com\/azure-sql\/wp-content\/uploads\/sites\/56\/2026\/08\/queryoptvector-768x130.webp 768w\" sizes=\"(max-width: 798px) 100vw, 798px\" \/><\/a><figcaption id=\"figcaption_attachment_7436\" class=\"wp-caption-text\">Vector search becomes part of the same optimization framework as relational processing<\/figcaption><\/figure><\/p>\n<h3><\/h3>\n<h3><span lang=\"EN-US\">How Azure SQL evolved beyond post-filtering<\/span><\/h3>\n<p>Earlier DiskANN-based vector retrieval in Azure SQL followed a post-filtering model. The vector index first returned a candidate set, and relational predicates were applied afterward.<\/p>\n<p>This works well when predicates are broad and most candidates qualify. As filters become more selective, however, many candidates may be discarded.<\/p>\n<p>Azure SQL has moved beyond this model. The latest <a href=\"https:\/\/devblogs.microsoft.com\/azure-sql\/diskann-vector-index-improvements\/\">DiskANN Vector Index improvements<\/a> introduced iterative filtering, where predicates are applied during vector search rather than only after a fixed candidate set is generated. T<\/p>\n<p>Here\u2019s a quick side-by-side comparison:<\/p>\n<table>\n<thead>\n<tr>\n<td><strong>Before (Post-Filtering)<\/strong><\/td>\n<td><strong>New Version (Iterative Filtering)<\/strong><\/td>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td><strong>The Problem:<\/strong>\u00a0Filtering happened\u00a0<em>after<\/em>\u00a0retrieving vectors<\/td>\n<td><strong>The Solution:<\/strong>\u00a0Filtering happens\u00a0<em>during<\/em>\u00a0the search<\/td>\n<\/tr>\n<tr>\n<td>You had to over-fetch and hope enough matched<\/td>\n<td>The search can continue until the requested number of qualifying results is found, when enough matching rows exist.<\/td>\n<\/tr>\n<tr>\n<td>&nbsp;<\/p>\n<p>SELECT TOP (20) t.id, t.title, s.distance<\/p>\n<p>FROM VECTOR_SEARCH(<\/p>\n<p>TABLE = wikipedia_articles,<\/p>\n<p>COLUMN = title_vector,<\/p>\n<p>SIMILAR_TO = @query_vector,<\/p>\n<p>METRIC = &#8216;cosine&#8217;,<\/p>\n<p>TOP_N = 20\u00a0 \/* Over-fetch *\/<\/p>\n<p>) AS s<\/p>\n<p>WHERE category = &#8216;Technology&#8217;<\/p>\n<p>ORDER BY s.distance;<\/td>\n<td>&nbsp;<\/p>\n<p>SELECT TOP (10) WITH APPROXIMATE<\/p>\n<p>t.id, t.title, s.distance<\/p>\n<p>FROM VECTOR_SEARCH(<\/p>\n<p>TABLE = wikipedia_articles AS t,<\/p>\n<p>COLUMN = title_vector,<\/p>\n<p>SIMILAR_TO = @query_vector,<\/p>\n<p>METRIC = &#8216;cosine&#8217;<\/p>\n<p>) AS s<\/p>\n<p>WHERE t.category = &#8216;Technology&#8217;<\/p>\n<p>ORDER BY s.distance;<\/td>\n<\/tr>\n<tr>\n<td><strong>Result:<\/strong>\u00a0Maybe 10 results, maybe 3, maybe 0<\/td>\n<td><strong>Result:<\/strong> Up to 10 qualifying Technology articles, when enough matching rows exist.<\/td>\n<\/tr>\n<tr>\n<td>Had to guess how many to fetch (TOP_N = 20? 100?)<\/td>\n<td>No longer need to select a fixed over-fetch value<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>Candidate exploration and relational qualification now work together. The engine no longer has to commit to a single fixed candidate count before it knows how the rest of the query will behave.<\/p>\n<p>&nbsp;<\/p>\n<h2>One query, more intelligent choices<\/h2>\n<p><strong>WITH APPROXIMATE <\/strong>tells Azure SQL that approximate nearest-neighbor results are acceptable while leaving the execution strategy to the engine.<\/p>\n<p>At <strong>compile<\/strong> time, the optimizer evaluates available approaches using the complete query context and estimated execution cost. Approximate nearest-neighbour(ANN) search may work well for large vector collections when predicates are not highly selective. Queries containing highly selective filters may benefit from exact nearest-neighbor search instead of additional approximate nearest-neighbor (ANN) exploration. The exact choice is workload-dependent and may consider factors such as predicate selectivity, data distribution, available relational and vector indexes, and the requested result count. These examples are illustrative and not a guaranteed decision matrix.<\/p>\n<p>At <strong>runtime<\/strong>, the execution engine can adapt to available resources and query conditions. When additional qualifying rows are needed to satisfy a filtered Top-K request, Azure SQL can switch between approximate nearest-neighbor (ANN) search and exact nearest-neighbor(KNN) search as appropriate. This helps return qualifying results without requiring the application to guess an over-fetch value.<\/p>\n<p>The same T-SQL surface can therefore support different execution strategies based on the query and available resources. Developers do not need to choose between\u00a0 ANN search and exact nearest-neighbor search. They express the retrieval intent, and Azure SQL determines how best to execute the query.<\/p>\n<h2>Bringing the power of SQL to AI retrieval<\/h2>\n<p>Every database can add a vector index. The larger challenge is integrating vector retrieval into the optimizer, execution engine, security model, and query-processing infrastructure that production workloads already depend on.<\/p>\n<p>By treating vectors as a first-class SQL data type, Azure SQL allows semantic retrieval to participate in decades of database innovation:<\/p>\n<ul>\n<li>Cost-based optimization<\/li>\n<li>Adaptive execution<\/li>\n<li>Security and governance<\/li>\n<li>Transactional consistency<\/li>\n<li>Relational processing at scale<\/li>\n<\/ul>\n<p>The result is not simply vector search inside a database. <strong>It is vector search that behaves like SQL. <\/strong><\/p>\n<p>As AI applications increasingly operate over live operational data, that distinction becomes more important than the vector index alone.<\/p>\n<p>&nbsp;<\/p>\n<h2>Get started<\/h2>\n<p>Ready to modernize your retrieval stack? Explore first-class vector support and iterative filtering through one of these two paths.<\/p>\n<h4><strong>Try it locally with Azure SQL Developer<\/strong><\/h4>\n<p>Start without provisioning cloud resources. <a href=\"https:\/\/devblogs.microsoft.com\/azure-sql\/azure-sql-developer-prpr\/\">Azure SQL Developer<\/a> brings the Azure SQL Database engine to your laptop in a container. It is free for local development and CI, requires no Azure subscription or credit card, and supports native vector capabilities for local prototyping.<\/p>\n<h4>Try it in Azure SQL Database for free<\/h4>\n<p>Want to try the complete cloud experience? The <a href=\"https:\/\/learn.microsoft.com\/en-us\/azure\/azure-sql\/database\/free-offer?view=azuresql\">Azure SQL Database free offer<\/a> provides 100,000 vCore seconds, 32 GB of data storage, and 32 GB of backup storage per database each month.<\/p>\n<p><strong>Quick start:<\/strong> <a href=\"https:\/\/github.com\/Azure-Samples\/azure-sql-db-vector-search\/blob\/main\/DiskANN\/diskann-quickstart-azure-sql-improvements.sql\">Run the DiskANN improvements sample<\/a><\/p>\n<h3>Related reading<\/h3>\n<ul>\n<li><a href=\"https:\/\/devblogs.microsoft.com\/azure-sql\/diskann-vector-index-improvements\/\">DiskANN Vector Index Improvements: Azure SQL Dev Corner<\/a><\/li>\n<li><a href=\"https:\/\/www.microsoft.com\/en-us\/research\/project\/project-akupara-approximate-nearest-neighbor-search-for-large-scale-semantic-search\/\">DiskANN: Vector Search for All<\/a><\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Why production AI retrieval depends on more than vector index performance.\u00a0 It&#8217;s easy to think of AI retrieval as a vector search problem. For many developers, the first conversation starts with vector index benchmarks: How many queries per second can it handle? What&#8217;s the latency? What&#8217;s the recall? How well does it scale? Those metrics [&hellip;]<\/p>\n","protected":false},"author":159391,"featured_media":7503,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[601,599,1,594,582,619,615],"tags":[510,676,569,677,591],"class_list":["post-7435","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-ai","category-azure-openai","category-azure-sql","category-hyperscale","category-openai","category-t-sql","category-vectors","tag-azure-sql-database","tag-diskann","tag-vector","tag-vector-index","tag-vector-search"],"acf":[],"blog_post_summary":"<p>Why production AI retrieval depends on more than vector index performance.\u00a0 It&#8217;s easy to think of AI retrieval as a vector search problem. For many developers, the first conversation starts with vector index benchmarks: How many queries per second can it handle? What&#8217;s the latency? What&#8217;s the recall? How well does it scale? Those metrics [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/azure-sql\/wp-json\/wp\/v2\/posts\/7435","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/azure-sql\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/azure-sql\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/azure-sql\/wp-json\/wp\/v2\/users\/159391"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/azure-sql\/wp-json\/wp\/v2\/comments?post=7435"}],"version-history":[{"count":2,"href":"https:\/\/devblogs.microsoft.com\/azure-sql\/wp-json\/wp\/v2\/posts\/7435\/revisions"}],"predecessor-version":[{"id":7439,"href":"https:\/\/devblogs.microsoft.com\/azure-sql\/wp-json\/wp\/v2\/posts\/7435\/revisions\/7439"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/azure-sql\/wp-json\/wp\/v2\/media\/7503"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/azure-sql\/wp-json\/wp\/v2\/media?parent=7435"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/azure-sql\/wp-json\/wp\/v2\/categories?post=7435"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/azure-sql\/wp-json\/wp\/v2\/tags?post=7435"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}