简体   繁体   中英

mySQL - A faster way to increment page views?

Currently im using UPDATE pages SET hits = hits+1 WHERE id=:id to increment page hits with PDO, but while profiling the script its taking on average between 30ms & 65ms to update.

Is there a faster way to increment, hits is also a INDEX within the table: Here is an example dump:

[queries] => Array
(
 [0] => Array
   (
    [sql] => SELECT * FROM `settings`
    [time] => 0.22602081298828
   )

 [1] => Array
    (
    [sql] => SELECT * FROM `menu_links` WHERE `active`="1" ORDER BY position ASC
    [time] => 0.2291202545166
    )

 [2] => Array
    (
    [sql] => SELECT * FROM `pages` WHERE `url`=:field AND active='1'
    [time] => 0.27203559875488
    )

 [3] => Array
   (
    [sql] => SELECT * FROM `pages` WHERE `menu_link`=:field AND active='1'
    [time] => 0.24008750915527
   )

 [4] => Array
  (
   [sql] => UPDATE pages SET hits = hits+1 WHERE id=:id
   [time] => 31.989107131958
  )
)

UPDATE

It seems that using a LIMIT 1 clause has sped it up by 10-15ms

[4] => Array
  (
   [sql] => UPDATE `pages` SET hits = hits+1 WHERE id=1 LIMIT 1
   [time] => Between 15 & 25ms
  )

with LOW_PRIORITY

[4] => Array
  (
   [sql] => UPDATE LOW_PRIORITY `pages` SET hits = hits+1 WHERE id=1 LIMIT 1
   [time] => Between 17 & 30ms
  )

An index on a column will actually make the column slower to update , because the index needs to be modified too.

Using pure MySQL, there is not much you can do, except tweak the server settings: hold more operations in temporary memory, write less often to disk. But still, the server will need to log the operation to one logfile. ACID does not come cheaply.

Most servers therefore use another kind of temporary storage, like a memcached or something. This way, the values are stored in RAM, and only when the value reaches a certain threshold, it is written to the database.

It is the best way of doing that.

And obviously update takes more time than select because it implies storage modifications, while selects usually use various caches and buffers.

If the speed is very important to you - you can set up any queue software and add incrementing task to the queue and refresh the data in a bulk manner by some backgound worker. This solution would be much more efficient but only applicable if you don't need your changes to be available immediately.

In general, updates are much slower than reads. Given that id is indexed and the data set that you are working with is large, there's not much more that you can do. The following page describes ways that you can improve your performance or by adding a LIMIT clause.

Another way to get fast updates is to delay updates and then do many updates in a row later. Performing multiple updates together is much quicker than doing one at a time if you lock the table.

http://dev.mysql.com/doc/refman/5.0/en/update-speed.html

If you are only after reducing page load times and your server is set up with php-fpm/FastCGI you can call fastcgi_finish_request() and after that you update the hit counter, see http://php-fpm.org/wiki/Features#fastcgi_finish_request.28.29

Basically this flushes the output to client and closes the connection, and then continues to execute the PHP script, so the client doesn't have to wait for the counter update operation. This doesn't offload the server though, just the access times for the clients...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM