PDO prepared statement vs. query generated from array - php

I have a 2-dimensional array that I need to insert into MySQL table. I know I can either use PDO prepared statement and loop through the array to pass the values into the prepared statement or I can generate a huge sql statement looping through the array and using implode function on the array. I've seen both methods described in this forum. My question is, which one is faster, why would you use one method versus the other one.
Note: The array I will be inserting has thousands of rows which, if I use method 2 would generate a huge SQL statement. Is there any limit as to how long the sql statement can be?

Related

Prepared statement when only read

Is there a point to use prepared statement when you just want to select all rows in a table? There are notning to bind compared if you used WHERE name = ? in the query.
$stmt->prepare("SELECT * FROM countries ORDER BY name");
Is it better to use the MySQLi without Prepared Statements like
$sql = "SELECT * FROM countries ORDER BY name";
Prepared statements are preferable to plain SQL queries when you are using parameters to dynamically generate the query. In your example, your SQL contains no variables, so using a plain query or prepared statement are functionally equivalent.
Prepared Statements
To answer your question directly, no. And in many languages the prepared statement library wouldn't even work with a query like that due to the method signatures of that library. I am going to give a background of prepare statements and database management systems because they are both essential to understanding the efficiencies generated by prepared statements.
Queries and Database's
When you execute a statement in any database management systems you trigger an execution of steps. At a very high level the database management system does the following things.
Query is received by the DBMS
SQL is interpreted
Query parsing
Query optimization
Resultset returned
Prepared Statements and Database's
A prepared statement is similar to any other SQL query issued to a database management system except with a few caveats.
First, a prepared statement template (without parametic values) is sent to the database management system from the application. After interpreting the SQL the database system then begins query parsing and query optimization where it validates the syntax and semantics, and begins the process of finding the best query plan, respectively.
A query plan is a set of executions used to run the supplied query. In most cases a query can have multiple query planes. It is part of the database management system to pick the most efficient plane.
Query optimizer continues to generate a variety of query plans and assigned then a cost and a value.
This process so far is mostly the same for both prepared statements and regular statements.
So to understand why your query would not benefit from being a prepared statement (besides the fact that prepared statements are defined as necessarily having parameters), let's take a closer look into the prepared statement optimization.
Optimizing
We stayed before that the query optimizer picks from a list of query plans for the most efficient one. However, we didn't discuss how it actually does this. For a non parametic statement the optimizer assign each plan a scalar cost value.
However, for a parametic query the optimizer associates each query plant to a function that maps multi dimensional parameter space to cost space, respectively. Basic to get all optimal queries for any given input.
This is a costly process, however on successive runs is very quick because the answer is known instead of calculates.
.

Can you omit PDO prepare if there's no placeholder/dynamic data in a query?

I'm working on an application at the moment that uses PDO with a MySQL database.
I'm seeing some queries, which are just very simple SELECT statements, e.g.
SELECT * FROM table ORDER BY name ASC
The code does not use prepare, for example:
$sql = "SELECT * FROM " . $this->table . " ORDER BY name ASC";
$stmt = $this->db->query($sql);
$results = $stmt->fetchAll(PDO::FETCH_ASSOC);
return $results;
Is it ok to do this, i.e. without using prepare, if there's no placeholders in the query?
The reason I've asked this is because according to the documentation it says
The SQL statement can contain zero or more named (:name) or question mark (?) parameter markers
which makes me wonder why you'd use this in the case of having no (zero) parameter markers?
Yes, because the use of prepared statements have 2 main causes:
Enhance running the same query with different parameters.
Prevent sql injection by separating sql code from the parameters.
Since you have no parameters that could be handled by a prepared statement (table names cannot be a parameter), you do not gain anything by pushing the query through as a prepared statement.
You still need to make sure that whatever is returned by $this->table will not cause any issues with the generated sql code.
Of course you can omit prepare if there is no dynamic data in your query.
But prepared statements have more advantages than only securing your queries.
According to http://php.net/manual/en/pdo.prepared-statements.php a second advantage is, that statements can be prepared once and executed multiple times.
The query only needs to be parsed (or prepared) once, but can be executed multiple times with the same or different parameters. When the query is prepared, the database will analyze, compile and optimize its plan for executing the query. For complex queries this process can take up enough time that it will noticeably slow down an application if there is a need to repeat the same query many times with different parameters. By using a prepared statement the application avoids repeating the analyze/compile/optimize cycle. This means that prepared statements use fewer resources and thus run faster.
Nevertheless, if you run your query only once and there is no dynamic data inside your query, omitting prepare is also fine.
In reality, you have to run such a query extremely seldom. A few tables with configuration-like options may be.
In all other cases at least LIMIT clause is obligatory.
So the question is rather a theoretical one.

Selecting columns from array in Doctrine QueryBuilder

I want to select the columns given in an array and then group based on those columns but I can't figure out how to pass array values through select() in Doctrine. I've tried a bunch of different variations of this and I can't get it to work. $factors is just a standard array with column names as values.
$qb->select(":factors")
->from("Table")
->where("type = :type")
->groupBy(":factors")
->setParameter("factors", $factors)
->setParameter("type", $type);
Parameters are not ment to be used in a SELECT statement. Read about prepared statements in PDO, Doctrine is just using this functionallity.
They are only used to compare with stored database values, not column or table names. Prepared statements basically help you escape those values used in a query, which could be a bit difficult for strings containing " or '.
If you want to use your $factors array for variable select statments you could just do
$qb->select(implode(',', $factors))
but in that case you have to prevent injections attacks by yourself. Best would be to have a whitelist of allowed values in $factors.
Same holds for GROUP BY statement.

Does Mysqli_multi_query improve performance

I am updating mysql data through php script. I am looking to use mysqli_multi_query() instead of mysql_query. I have N number of update queries to execute. Please suggest if multi query will help in better execution time.
A. Updating data using mysql_query(), Firing single single queries N times.
B. Concatinating All Update queries with ";" and firing once using multi query.
Please Suggest if Technique "B" will help in performance.
Thanks.
C. Use prepared statements and if possible (InnoDB) within a transaction.
A multiquery will save you some client-server roundups, but the queries are still executed one by one.
If you use prepared statement together with transactions, the query is checked once by the parser after that just values are pasted to server. Transaction prevents indexes being rebuild after each update.
Multiple insert statements can be rewritten as a single bulk insert statement:
INSERT INTO t1 (c1,c2,c3) VALUES (1,2,3), (3,4,5) --etc

Caching PDO prepared statements

Is there any point in saving PDO prepared statements for reuse in a session?
I'm building a site that uses MySQL fulltext queries, which I'm putting together in my PHP, like
SELECT * FROM table
WHERE MATCH (title) AGAINST ($search_string IN BOOLEAN MODE) AND
MATCH (keywords) AGAINST ($keywords IN BOOLEAN MODE)
ORDER BY $order_by $asc_desc
It seems to take a lot longer to run this kind of query when I prepare and execute it with bound parameters, than when I just prepare and execute a query string with the values included. But I need to use prepared statements to prevent the risk of SQL injection.
In any session I would very likely run the same query several times, with different parameter values. Would it make sense for me to save the PDOStatement object once it's been created (for example in the session)? If so, what would be the best way to do that? Would it be good practice to save each prepared statement in an associative array as it's created, with the SQL query string as the key for each?
On further reading I found you can't use bound params for the ORDER BY and ASC / DESC part of a statement. When I replace these with fixed values the performance improves.
There is no benefits to store prepare statement into session for reusable purpose,
the expensive cost is on the query execution itself.
If the data you are grabbing constantly changes, then caching the resultset may no longer be valid shortly after you retrieve them.
However, if your data appears to be static:
session_start();
$_SESSION['cachedResultSet'] = $fetchedResultset;
echo $_SESSION['cachedResultSet'][0][0];
# above statement `echo ...` depends on how your result is, be it an array or object
I think it would be acceptable to a degree to store resultsets in session variables, but perhaps it would depend (sorry to be redundant) whether the data changes quickly or on how often you grab this particular resultset, etc...

Categories