Reuse Existing Queries and Statements Whenever Possible
Creating a new query is an "expensive" operation. If possible, create the queries ahead of time (in a startup function), then keep reusing those existing query definitions in new statements.
(See Lifecycle of a Query—Use of Query Functions for more details)
For example, you could create a query in a startup function. That query may use bind variables, for more flexibility (see Bind Variables in Query Text. Then, in a preprocessor rule function, you could create a new statement using that query, set values in the statement for all the bind variables of the query using the data in the event, and execute the statement. As a result, the query would be customized and executed for each event reaching the preprocessor.
Depending on your situation, it might be possible to create a single statement, and keep reusing that same statement, executing it multiple times.