> You can use parameterized queries to protect against SQL injection,
No, that't not what parameterized queries are for. That's just a side benefit.
Parameterized queries are so that the database doesn't have to parse the data from SQL to do the query. It's stupid to turn all the data to text, send the text over the wire, escaped and quoted as appropriate, then parse it back to whatever form it was in originally when you can just send it binary straight to the database.
And if you are doing many similar queries with different results, e.g. inserts as here, or maybe querying the user table by user id every page load, the database doesn't have to parse any SQL each time and can even reuse the query plan.
This may be why psycopg3 performed better than pandas df.to_sql() function in the single row insert case.