-2

Consider a large table, which of the below would be faster?

Both queries will select rows where time is greater than the current time.

Calling NOW() within the WHERE clause:

SELECT          *
FROM            myTable
WHERE           time > NOW()

Wrapping the call to NOW() in a sub query:

SELECT          *
FROM            myTable
LEFT JOIN       (
                    SELECT NOW() AS currentTime
                ) AS currentTimeTable ON TRUE                   
WHERE           time > currentTime
Drahcir
  • 11,772
  • 24
  • 86
  • 128

2 Answers2

2

"Both queries will select rows where time is no older than 10 days."

Sorry, but your query is incorrect. I tested it in MySQL and got this:

mysql> SELECT DATE(NOW() - 10);
+------------------+
| DATE(NOW() - 10) |
+------------------+
| 2013-11-21       |
+------------------+

21.11.2013 - is the current date and not now() minus 10 days.

You should use DATE_SUB function:

mysql> SELECT DATE_SUB( NOW(), INTERVAL 10 DAY );
+-------------------------------------+
| DATE_SUB( NOW() , INTERVAL 10 DAY ) |
+-------------------------------------+
| 2013-11-11 19:40:38                 |
+-------------------------------------+

Something like this:

SELECT *
FROM   `myTable`
WHERE  `time` > DATE_SUB(NOW(), INTERVAL 10 DAY );

Here is the analysis of both of your query types:

EXPLAIN 
SELECT 
    *
FROM
    users
WHERE
    created > now();

Test data

I tried users table from my Drupal installation.

mysql> EXPLAIN SELECT * FROM users WHERE created < NOW();

+----+-------------+-------+-------+---------------+---------+---------+------+------+-------------+
| id | select_type | table | type  | possible_keys | key     | key_len | ref  | rows | Extra       |
+----+-------------+-------+-------+---------------+---------+---------+------+------+-------------+
|  1 | SIMPLE      | users | range | created       | created | 4       | NULL |    1 | Using where |
+----+-------------+-------+-------+---------------+---------+---------+------+------+-------------+
1 row in set (0.00 sec)



EXPLAIN
SELECT 
    *
FROM
    users
LEFT JOIN (
                    SELECT NOW() AS currentTime
          ) AS tbl ON TRUE
WHERE created < tbl.currentTime;

+----+-------------+------------+--------+---------------+---------+---------+------+------+----------------+
| id | select_type | table      | type   | possible_keys | key     | key_len | ref  | rows | Extra          |
+----+-------------+------------+--------+---------------+---------+---------+------+------+----------------+
|  1 | PRIMARY     | <derived2> | system | NULL          | NULL    | NULL    | NULL |    1 |                |
|  1 | PRIMARY     | users      | range  | created       | created | 4       | NULL |    1 | Using where    |
|  2 | DERIVED     | NULL       | NULL   | NULL          | NULL    | NULL    | NULL | NULL | No tables used |
+----+-------------+------------+--------+---------------+---------+---------+------+------+----------------+
3 rows in set (0.02 sec)

Conclusion

Obviously, the 1-st query is better, as it doesn't require creating any temporary tables. Even with my little sample data, it took 0 seconds to execute the 1-st query and 0,02 secs for the 2-nd.

user4035
  • 22,508
  • 11
  • 59
  • 94
  • I hope you're using `SELECT *` for demonstration – Kermit Nov 21 '13 at 15:45
  • @FreshPrinceOfSO Yes, for demonstration – user4035 Nov 21 '13 at 15:45
  • OK whoops, my query doesn't do exactly what I wanted. Although my question still stands – Drahcir Nov 21 '13 at 15:45
  • My question is more about "is it more efficient to call the function within the where clause or within a sub query?", The question is not "how can I find time within 10 days?" - that was just an example – Drahcir Nov 21 '13 at 15:47
  • @Drahcir If you give us your table structure with sample data via sqlfiddle, we'll be able to analyze EXPLAIN results. – user4035 Nov 21 '13 at 15:48
  • Thanks for the testing. I am suprised by the results, I was expecting that the 1st query would execute `NOW()` for all rows, and the 2nd query would only execute once. I expected the 2nd query to be faster, thanks for proving me wrong – Drahcir Nov 21 '13 at 16:13
0

1) When you talk about date optimisation, using timestamps is the way to go.

2) I suggest instead of calling a function to do the math, create another column for each rows with their timestamps

3) As PeeHaa said on this thread: « When talking about which piece of code is faster (in your OP) you're talking about micro-optimization and is really something you shouldn't have to worry about. ☺

The real question is which piece of code is: better maintainable, readable, understandable. »

I understand what is very large database management but once you've optimised indexes and datatypes you most likely will be good enough.

Community
  • 1
  • 1
  • Thanks but your answer doesn't apply in this case. **1)** Am already using timestamps, `time` column is a `datetime` format. **2)** I wanted to compare my column with the current time (`NOW()`), so that's not really possible. **3)** This question is about PHP's function vs MySQL's `NOW` function, mine is all about MySQL. – Drahcir Nov 21 '13 at 16:18