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

Use executemany from backends #371

Closed
wants to merge 6 commits into from
Closed

Conversation

aminalaee
Copy link
Member

@aminalaee aminalaee commented Aug 18, 2021

Closes #284

Some of the backends support executemany and instead of running multiple single queries we can use executemany.
asyncpg, aiosqlite and aiomysql support executemany but aiopg doesn't support it.

@aminalaee aminalaee marked this pull request as draft August 18, 2021 09:23
@aminalaee aminalaee marked this pull request as ready for review August 19, 2021 06:28
@aminalaee aminalaee requested review from a team, euri10 and rafalp August 19, 2021 06:28
Copy link
Member

@PrettyWood PrettyWood left a comment

Choose a reason for hiding this comment

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

I would have expected a change in
https://github.com/encode/databases/blob/master/databases/core.py#L281-L286
instead of creating multiple queries to take again the first one afterwards
Do I miss something? 🤔

databases/backends/mysql.py Outdated Show resolved Hide resolved
Co-authored-by: Eric Jolibois <em.jolibois@gmail.com>
@aminalaee
Copy link
Member Author

aminalaee commented Sep 2, 2021

@PrettyWood Yeah I actually thought that would be more efficient too. If I understand your comment correctly, you want to avoid building all the queries in core and you suggest we build only the first query and pass the values with query to the backends?

I tried that before and there's a limitation.
In each database backend we're doing a _compile which builds the query and parameters from a ClauseElement instance.
https://github.com/encode/databases/blob/master/databases/backends/sqlite.py#L157

If we build only the first query in core.py, and pass the values around to the database backends, we will be calling executemany method with a compiled query string which is correct but the paramters are not coming from a compiled query meaning they're not coming from the output of _compile method.

Even if we could make this work with SQLAlchemy orm I think it won't work well with raw queries. For building raw queries we're using bindparams https://docs.sqlalchemy.org/en/14/core/sqlelement.html#sqlalchemy.sql.expression.TextClause.bindparams which doesn't seem to work with list of parameters, compared to SQLAlchemy orm .values() method that can accept list of dicts.

tldr; I think if we want to avoid building all queries and compiling queries and params, we would have to build query params ourself and not use SQLAlchemy for that. SQLAlchemy seems to favor it's own executemany style: https://docs.sqlalchemy.org/en/14/core/tutorial.html#execute-multiple

I'm really interested to improve this and get it through. So feel free to dig deeper and let me know if we can improve it.

@aminalaee
Copy link
Member Author

Closing it as stale.

@aminalaee aminalaee closed this Dec 1, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Inserting to database using execute_many much slower than using fetch_all
2 participants