Description:
The NativeDriver's ReadColumnValue method performs very poorly due to the repeated construction of the GUID regex (see code below and at https://github.com/mysql/mysql-connector-net/blob/8.0/MySQL.Data/src/NativeDriver.cs). In my benchmarking, more than 95% of the time in MySqlDataReader.Read seems to be taken by that constructor.
<code>
public IMySqlValue ReadColumnValue(int index, MySqlField field, IMySqlValue valObject)
{
long length = -1;
bool isNull;
Regex regex = new Regex(@"(?i)^[0-9A-F]{8}[-](?:[0-9A-F]{4}[-]){3}[0-9A-F]{12}$"); // check for GUID format
if (nullMap != null)
{
isNull = nullMap[index + 2];
if (!MySqlField.GetIMySqlValue(field.Type).GetType().Equals(valObject.GetType()) && !field.IsUnsigned)
length = packet.ReadFieldLength();
}
else
{
length = packet.ReadFieldLength();
isNull = length == -1;
}
if ((valObject.MySqlDbType is MySqlDbType.Guid && !Settings.OldGuids) &&
!regex.IsMatch(Encoding.GetString(packet.Buffer, packet.Position, (int)length)))
{
field.Type = MySqlDbType.String;
valObject = field.GetValueObject();
}
packet.Encoding = field.Encoding;
packet.Version = version;
var val = valObject.ReadValue(packet, length, isNull);
if (val is MySqlDateTime d)
{
d.TimezoneOffset = field.driver.timeZoneOffset;
return d;
}
return val;
}
</code>
How to repeat:
This affects any read query, although obviously the fraction of runtime will vary based on the specifics of the query, database deployment, etc.
Suggested fix:
Making the regex a static field of the NativeDriver class would fix repeated construction on every call of ReadColumnValue. This shouldn't be a problem, as Regex instances are thread-safe and immutable (see https://docs.microsoft.com/en-us/dotnet/standard/base-types/thread-safety-in-regular-expre...)