Skip to content

Use sql_select_limit for CommandBehavior.SingleRow #679

@segor

Description

@segor

During migration from Mysql.Data we got performance issue in code that reads the first row from a SQL query using Dapper method QueryFirstOrDefaultAsync. With Oracle driver execution time is about 600 ms but with MySqlConnector execution time is about 50 seconds.
After some investigation I found that the problem is inside MySqlCommand.ExecuteReaderAsync. Here is the app I use to reproduce the issue:

using System;
using System.Data;
using System.Diagnostics;
using System.Threading.Tasks;
using MySql.Data.MySqlClient;

namespace MysqlConnIssue
{
    class Program
    {
        static async Task Main(string[] args)
        {
            object result = null;
            var rand = new Random(); 
            using (var conn = new MySqlConnection("you conn str"))
            {
                await conn.OpenAsync();
                // table users contains 400K rows , _Ids - 1K rows
                //  a random value is used to disable query caching in mysql 
                using (var cmd = new MySqlCommand($@"
                SELECT IntegerValue 
                FROM _Ids
                WHERE IntegerValue NOT IN
                   (SELECT userid FROM users  WHERE userid <> {rand.Next()})", conn))
                {
                    var sw = new Stopwatch();
                    sw.Start();
                    // ExecuteReaderAsync is about 100 times slower when MySqlConnector is referenced
                    var reader = await cmd.ExecuteReaderAsync(CommandBehavior.SingleRow);
                    Console.WriteLine($"ExecuteReader: {sw.ElapsedMilliseconds}ms");
                    sw.Restart();
                    if (await reader.ReadAsync())
                    {
                        result = reader[0];
                    }
                    Console.WriteLine($"Read: {sw.ElapsedMilliseconds}ms");
                }
            }

            Console.WriteLine($"Result: {result}");
        }
    }
}

Workaround is adding LIMIT 1 to the query but it will require to review all code we have

Metadata

Metadata

Assignees

No fields configured for Feature.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions