Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

On connect, set all variables in a single SET statement #1099

Conversation

dolmen
Copy link
Contributor

@dolmen dolmen commented May 13, 2020

Description

For faster connection startup this patch use (almost) a single SET statement to set all variables at once instead of a SET statement for each variable.

MySQL doc about the SET statement: https://dev.mysql.com/doc/refman/8.0/en/set-variable.html

Before:

  • SET <variable1>=<value1>
  • SET NAMES utf8mb4
  • SET <variable2>=<value2>
  • SET <variable3>=<value3>

Now:

  • SET NAMES utf8mb4
  • SET <variable1>=<value1>,<variable2>=<value2>,<variable3>=<value3>

This patch should make establishing new connection must faster as it reduce the number of roundtrips necessary before the first query when multiple variables are defined in the DSN.

As a side effect, the SET NAMES statement is always executed first. This will fix the possibility of some SET statements being executed before the right charset is set (for the case where the database default charset is not the one we want to use for the connection, e.g. Latin1).

Here is how to test this patch with your own Go project built with Go modules:

$ go mod edit -replace=github.com/go-sql-driver/mysql=github.com/dolmen/[email protected]

Background: on MySQL 5.7 database hosted on Amazon RDS we noticed that in Performance Insights that some costly queries were hidden by SET statements. Sometimes we saw a SET time_zone=..., sometimes a SET group_concat_max_len=..., sometimes SET sql_mode='TRADITIONAL'.

Checklist

When opening a connection, instead of iterating on all variables and
calling "SET <variable>=<value>" for each, we now use a single SET statement
with all pairs using a comma as separator:
  SET <variable1>=<value1>,<variable2>=<value2>,...

MySQL doc about the SET statement: https://dev.mysql.com/doc/refman/8.0/en/set-variable.html
Copy link
Member

@julienschmidt julienschmidt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thanks!

Travis is driving me a little crazy lately... I have no idea why we have two status checks here now and how to make it pass. Restarting the job it is blocked on just updates the other status check.
Could you try to rebase this on the current master before I disable Travis as a required check?

if err != nil {
return
}
params = append(params, param+"="+val)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nitpick (not a must): This allocates a new string for every param. Maybe using strings.Builder (and adding the , here) is the better approach?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know there are improvement in this area. For this important pull request I wanted to apply the minimum change required. The string concatenation problem was in the original code, so I didn't want to change that and divert the reviewers from the main issue.

Now that this structural change is merged (thanks!), I am now able to propose some further implementation improvements.

@julienschmidt julienschmidt added this to the v1.6.0 milestone May 16, 2020
@julienschmidt julienschmidt merged commit 3f51e4e into go-sql-driver:master May 19, 2020
tz70s pushed a commit to tz70s/mysql that referenced this pull request Sep 5, 2020
…r#1099)

When opening a connection, instead of iterating on all variables and
calling "SET <variable>=<value>" for each, we now use a single SET statement
with all pairs using a comma as separator:
  SET <variable1>=<value1>,<variable2>=<value2>,...
tz70s pushed a commit to tz70s/mysql that referenced this pull request Sep 5, 2020
…r#1099)

When opening a connection, instead of iterating on all variables and
calling "SET <variable>=<value>" for each, we now use a single SET statement
with all pairs using a comma as separator:
  SET <variable1>=<value1>,<variable2>=<value2>,...
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants