You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

从SQL表匹配联系人:聊天应用服务器查询优化方案咨询

Optimizing Contact Matching for Your Chat App Server

Hey there! Great question—optimizing database calls for contact matching is critical for keeping your chat app responsive, especially as user bases grow. Let’s break down why your current approach has room for improvement, then dive into concrete, efficient solutions.

Why Your Current Method Isn’t Ideal

Right now, you’re using a N+1 query pattern: looping through each phone number and running a separate SELECT for each. Even with .NET’s connection pool managing connections (so you’re not actually opening a new physical connection every time), each query still incurs network round-trip overhead, and the database has to parse and execute multiple small queries instead of one optimized batch. This adds up fast with large contact lists.

Top Efficient Solutions

1. Batch Queries with Table-Valued Parameters (TVPs) – Best for Large Lists

SQL Server’s Table-Valued Parameters let you pass an entire list of phone numbers as a single parameter to your query. This eliminates repeated network trips and lets the database optimize the query execution plan for the full dataset.

First, create a user-defined table type in your SQL database:

CREATE TYPE dbo.PhoneNumberList AS TABLE (Number NVARCHAR(20) NOT NULL)

Then, use this in your C# code to pass the contact list in one go:

using (var conn = new SqlConnection(connectionString))
{
    conn.Open();

    // Populate a DataTable with your contact numbers
    var phoneTable = new DataTable();
    phoneTable.Columns.Add("Number", typeof(string));
    foreach (var number in contactNumbers)
    {
        phoneTable.Rows.Add(number);
    }

    using (var cmd = new SqlCommand(@"
        SELECT u.* 
        FROM Users u
        JOIN @PhoneNumbers p ON u.Number = p.Number
    ", conn))
    {
        // Add the table-valued parameter
        cmd.Parameters.Add(new SqlParameter("@PhoneNumbers", SqlDbType.Structured)
        {
            TypeName = "dbo.PhoneNumberList",
            Value = phoneTable
        });

        // Read and process the results
        using (var reader = cmd.ExecuteReader())
        {
            while (reader.Read())
            {
                // Extract user data (e.g., reader["Id"], reader["Number"], etc.)
                // Map to your registered contact model
            }
        }
    }
}

TVPs work seamlessly with large lists (way beyond the 2100-parameter limit of IN clauses) and keep your code clean and secure (no risk of SQL injection).

2. Batch Queries with Parameterized IN Clauses – Good for Smaller Lists

If you’re dealing with smaller contact lists (under 2100 entries, the default limit for SQL Server’s IN clause), a parameterized IN query is a simpler alternative. Avoid concatenating raw values into the query (this opens you up to SQL injection)! Instead, generate parameter placeholders dynamically:

using (var conn = new SqlConnection(connectionString))
{
    conn.Open();

    // Generate unique parameter names (e.g., @p0, @p1, ...)
    var paramNames = contactNumbers.Select((_, idx) => $"@p{idx}").ToList();
    var inClause = string.Join(", ", paramNames);

    using (var cmd = new SqlCommand($"SELECT * FROM Users WHERE Number IN ({inClause})", conn))
    {
        // Add each phone number as a parameter
        for (int i = 0; i < contactNumbers.Count; i++)
        {
            cmd.Parameters.AddWithValue($"@p{i}", contactNumbers[i]);
        }

        // Process results
        using (var reader = cmd.ExecuteReader())
        {
            // Your logic here
        }
    }
}

If your list exceeds 2100 entries, split it into chunks of 2000 and run multiple batch queries—still way faster than individual lookups.

3. Reuse Connections (Wisely)

While .NET’s connection pool does a great job of managing connections, you can reduce overhead by reusing a single connection for your batch query instead of creating a new one per lookup. The using statement ensures the connection is returned to the pool when done, but using one connection for the entire batch cuts down on pool-related overhead.

4. Add a Database Index

Don’t overlook the basics! Make sure you have a non-clustered index on the Number column of your Users table. This turns your WHERE or JOIN operation from a full table scan into a fast index seek:

CREATE NONCLUSTERED INDEX IX_Users_Number ON Users (Number)

This will drastically speed up any query filtering by phone number, regardless of the batch method you choose.

Final Notes

  • Always use parameterized queries to avoid SQL injection (both TVPs and parameterized IN clauses handle this).
  • TVPs are the most scalable option for large contact lists.
  • Combine batch queries with an indexed Number column for maximum performance.

内容的提问来源于stack exchange,提问作者Max R.

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 09:10:26