{"id":4190,"date":"2025-02-04T08:00:33","date_gmt":"2025-02-04T16:00:33","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/azure-sql\/?p=4190"},"modified":"2025-05-06T08:03:43","modified_gmt":"2025-05-06T15:03:43","slug":"storing-querying-and-keeping-embeddings-updated-options-and-best-practices","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/azure-sql\/storing-querying-and-keeping-embeddings-updated-options-and-best-practices\/","title":{"rendered":"Storing, querying and keeping embeddings updated: options and best practices"},"content":{"rendered":"<p>Embeddings and vectors are becoming common terms not only for engineers involved in AI-related activities but also for those using databases. Some common points of discussion that frequently arise among users familiar with vectors and embeddings include:<\/p>\n<ul>\n<li><a href=\"https:\/\/devblogs.microsoft.com\/azure-sql\/storing-querying-and-keeping-embeddings-updated-options-and-best-practices\/\">How can I quickly &#8220;vectorize&#8221; the content already present in my database?<\/a> <em>(this post)<\/em><\/li>\n<li><a href=\"https:\/\/devblogs.microsoft.com\/azure-sql\/database-and-ai-solutions-for-keeping-embeddings-updated\/\">How can I keep the vectors updated whenever there is a change to the content from which they have been generated?<\/a><\/li>\n<li><a href=\"https:\/\/devblogs.microsoft.com\/azure-sql\/efficiently-and-elegantly-modeling-embeddings-in-azure-sql-and-sql-server\/\">What if I have more than one column that I would like to use for generating embeddings?<\/a><\/li>\n<li>Are there any best practices for storing and querying vectors in modern relational databases?<\/li>\n<\/ul>\n<p>Let\u2019s tackle each one of these questions one by one starting from the very first. In the next blog posts I\u2019ll discuss about the other questions.<\/p>\n<h2>Quickly vectorize existing data<\/h2>\n<p>This is a straightforward question. While the answer is often &#8220;it depends,&#8221; in this case, there is a clear and direct solution: to efficiently vectorize data, batching requests is essential. The OpenAI API\u2014and by extension, the Azure OpenAI service\u2014supports receiving an array of strings for vectorization, thereby minimizing REST call overhead:<\/p>\n<p><a href=\"https:\/\/platform.openai.com\/docs\/api-reference\/embeddings\">https:\/\/platform.openai.com\/docs\/api-reference\/embeddings<\/a><\/p>\n<p>The OpenAI API is rapidly becoming the standard, so it is highly likely that even if you plan to use your own model with an on-premises inference server, batch support for embedding processing is also available. For instance, Ollama already supports this feature:<\/p>\n<p><a href=\"https:\/\/github.com\/ollama\/ollama\/blob\/main\/docs\/api.md#generate-embeddings\">https:\/\/github.com\/ollama\/ollama\/blob\/main\/docs\/api.md#generate-embeddings<\/a><\/p>\n<p>Having established the optimal strategy, how can it be implemented? Several options exist, ranging from Azure Data Factory to Apache Spark. Essentially, any tool capable of reading from Azure SQL, batching requests, and making REST calls is suitable.<\/p>\n<h2>Parallelize and scale<\/h2>\n<p>However, turning text into embeddings at scale presents complexities. For instance, if the text to be vectorized is too lengthy, it must be chunked to ensure the generated embeddings accurately represent the underlying concepts. Additionally, embedding models may have inherent limitations, such as restrictions on the amount of text (in terms of tokens) that can be vectorized simultaneously.<\/p>\n<p>To address these limitations and enhance scalability, one option is to scale out by deploying multiple embedding models in parallel. By distributing arrays of text to different models simultaneously, the solution can easily be scaled by adding more instances of the desired embedding model.<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/azure-sql\/wp-content\/uploads\/sites\/56\/2025\/02\/vectorized-high-level-architecture.jpg\"><img decoding=\"async\" class=\"aligncenter wp-image-4192 size-full\" src=\"https:\/\/devblogs.microsoft.com\/azure-sql\/wp-content\/uploads\/sites\/56\/2025\/02\/vectorized-high-level-architecture.jpg\" alt=\"Image vectorized high level architecture\" width=\"800\" height=\"478\" srcset=\"https:\/\/devblogs.microsoft.com\/azure-sql\/wp-content\/uploads\/sites\/56\/2025\/02\/vectorized-high-level-architecture.jpg 800w, https:\/\/devblogs.microsoft.com\/azure-sql\/wp-content\/uploads\/sites\/56\/2025\/02\/vectorized-high-level-architecture-300x179.jpg 300w, https:\/\/devblogs.microsoft.com\/azure-sql\/wp-content\/uploads\/sites\/56\/2025\/02\/vectorized-high-level-architecture-768x459.jpg 768w\" sizes=\"(max-width: 800px) 100vw, 800px\" \/><\/a><\/p>\n<h2>A working example<\/h2>\n<p>At a certain point, I was required to vectorize approximately 10 million rows of text and needed to complete this task as efficiently as possible. Therefore, I developed a sample to facilitate all the necessary processes. To ensure maximum customization and adaptability to various scenarios, I opted to use .NET and implemented everything from scratch utilizing the <code>ConcurrentQueue<\/code> class, which supports scaling out and parallelism to the greatest extent possible.<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/azure-sql\/wp-content\/uploads\/sites\/56\/2025\/02\/sample-screenshot.jpg\"><img decoding=\"async\" class=\"aligncenter wp-image-4196 size-full\" src=\"https:\/\/devblogs.microsoft.com\/azure-sql\/wp-content\/uploads\/sites\/56\/2025\/02\/sample-screenshot.jpg\" alt=\"Image sample screenshot\" width=\"1192\" height=\"452\" srcset=\"https:\/\/devblogs.microsoft.com\/azure-sql\/wp-content\/uploads\/sites\/56\/2025\/02\/sample-screenshot.jpg 1192w, https:\/\/devblogs.microsoft.com\/azure-sql\/wp-content\/uploads\/sites\/56\/2025\/02\/sample-screenshot-300x114.jpg 300w, https:\/\/devblogs.microsoft.com\/azure-sql\/wp-content\/uploads\/sites\/56\/2025\/02\/sample-screenshot-1024x388.jpg 1024w, https:\/\/devblogs.microsoft.com\/azure-sql\/wp-content\/uploads\/sites\/56\/2025\/02\/sample-screenshot-768x291.jpg 768w\" sizes=\"(max-width: 1192px) 100vw, 1192px\" \/><\/a><\/p>\n<p>The sample \u2013 that can be used as a standalone tool if you don\u2019t need any custom behavior, otherwise feel free to contribute to it \ud83d\ude42 \u2013 is available on GitHub:<\/p>\n<p><a href=\"https:\/\/github.com\/Azure-Samples\/azure-sql-db-vectorizer\">https:\/\/github.com\/Azure-Samples\/azure-sql-db-vectorizer<\/a><\/p>\n<p>The reason why vectorized data is stored in a dedicated table will be explained in the next blog post. Stay tuned!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Embeddings and vectors are becoming common terms not only for engineers involved in AI-related activities but also for those using databases. Some common points of discussion that frequently arise among users familiar with vectors and embeddings include: How can I quickly &#8220;vectorize&#8221; the content already present in my database? (this post) How can I keep [&hellip;]<\/p>\n","protected":false},"author":24720,"featured_media":4192,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[601,615],"tags":[640,569,644],"class_list":["post-4190","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-ai","category-vectors","tag-embeddings","tag-vector","tag-vectorize"],"acf":[],"blog_post_summary":"<p>Embeddings and vectors are becoming common terms not only for engineers involved in AI-related activities but also for those using databases. Some common points of discussion that frequently arise among users familiar with vectors and embeddings include: How can I quickly &#8220;vectorize&#8221; the content already present in my database? (this post) How can I keep [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/azure-sql\/wp-json\/wp\/v2\/posts\/4190","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\/24720"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/azure-sql\/wp-json\/wp\/v2\/comments?post=4190"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/azure-sql\/wp-json\/wp\/v2\/posts\/4190\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/azure-sql\/wp-json\/wp\/v2\/media\/4192"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/azure-sql\/wp-json\/wp\/v2\/media?parent=4190"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/azure-sql\/wp-json\/wp\/v2\/categories?post=4190"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/azure-sql\/wp-json\/wp\/v2\/tags?post=4190"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}