WordPress has some really awesome functions and classes for retrieving data from the database: WP_Query, WP_User_Query, get_comments(), get_the_terms(), and many, many more. Most of the time these are the functions and classes you should use when querying data from the database–they have some great benefits, such as caching–but there are times when it is actually better to write your own SQL query to retrieve the information and then use the global $wpdb class to execute the query.
The most obvious reason to write your own SQL queries is when your plugin uses custom tables for storing data, such as Restrict Content Pro does for storing payment information. For example, Restrict Content Pro has a member function of a class that is used to retrieve a specific payment from the database, and it looks like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | /** * Retrieve a specific payment * * @access public * @since 1.5 */ public function get_payment( $payment_id = 0 ) { global $wpdb; $payment = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM {$this->db_name} WHERE id = %d", absint( $payment_id ) ) ); return $payment; } |
Core WordPress functions and classes are generally excellent when it comes to performance, but there are cases where the “performance boosting aspects” of these actually have an inverse effect. For example, the get_post_meta() function is mostly a wrapper to the get_metadata() function, which takes care of retrieving the requested value from the cache (if it exists) and updating the cache with the requested value if it wasn’t already in the cache. This is excellent for cases where you need to retrieve the same value multiple times, such as subsequent page loads. But what if you just need one single value and you only need it one time, and you want it to be as fast as possible? In this case, it is actually better to write your own custom SQL query so that it bypasses the calls to update_meta_cache().
For example, in Easy Digital Downloads we have a table that shows file downloads by customers, and one of the pieces of data we have to retrieve is the list of files attached to a product. For various reasons, it was faster for us to simply pull the data directly from wp_postmeta than it was to call get_post_meta(). Our $wpdb call looks like this:
1 | $wpdb->get_var( $wpdb->prepare( "SELECT meta_value from $wpdb->postmeta WHERE post_id = %d and meta_key = 'edd_download_files'", $log->post_parent ) ); |
As a general rule of thumb, I’d always recommend sticking with the core WordPress functions for retrieving data, since they are highly optimized and have been tested on a massive scale, but if you know what you’re doing and you fully understand why a direct $wpdb call could be better, go for it.