Optimized way to read settings from database only once in PHP - php

I'm working on a big project with several http servers that use one main sql database.
The project has many settings that are frequently used(almost every request).
The settings are stored in the main sql database.
I wanted to know, if there is some way to initialize settings only once in php, because it makes no sense for every request to go and read same setting from sql server over and over again, it feels like a waste of resources.
Thanks in advance

2 solutions:
Create a (perhaps also PHP) script that exports settings from database into a plain text file, and includes that file on every http server;
use a memory cache server like http://memcached.org/ and preload data there from an external script, then have http servers connect to memcache instead of SQL.
Edit: Other than that, PHP does not give you a real web application, where you "run" your application and it has its own memory and persistant, global variables. This is one of the reasons I personally got tired of PHP and moved to Python (and Django, specifically).

Hard code these settings in your PHP code.
// Your current code, somthing like this:
$setting_1 = getDataFromMySQL('setting1');
// Hard coded
$setting_1 = TRUE;

You can use shared memory in php if it is compiled that way.
Another possibility is that you store a combined value of your settings as PHP code in one field (a PHP array for example), then you can read them all with only one query to the DB server. Of course this cached value have to be updated when settings change.

APC is the best solution if you are using a single server, otherwise I would go with memcached. However, you may also consider a MYSQL memory table, it is very efficient for fast reads and writes. Another solution is using Linux to keep and call settings with Linux exec. However, this might be a trouble and there might be some security issues. Also let me remind you that efficient INNODB indexes can help you a lot. MYISAM is also considered a good "read" performer, however my benchmarks show me that INNODB indexes are faster.

You can store the settings in the user's session -
session_start();
if (!isset($_SESSION['settings'])) {
$settings_array = //pulled from database
$_SESSION['settings'] = $settings_array;
}
That way, it'll only query once per user

You could use a session to store those settings.

Related

When to use PHP $_SESSION and Cache or when not to use both?

I am developing a website and after the login authentication, i am using $_SESSION super global array to pass my data to other pages and display when required. This is how i am doing this. Its my own little MVC framework.
//please ignore the syntax errors
$recieved_data = $this->registry->{auth_login}($username, $password);
//$recieved_data holds records like (fname,lname,email,username,password)
$_SESSION = $recieved_data;
//Or should i choose PHP cache instead at this point?
My website will have a huge traffic after some time. In this particular case, should i choose php cache or keep continue using $_SESSION?
I know i cannot ignore the use of sessions completely but what are the right options in my case?
Today, i surprised when i set the $_SESSION array with different index names in all the projects and used print_r($_SESSION) function to check the available sessions in $_SESSION Array in any one of the project.
It showed me all active sessions belonging to different project folders. Is it fine if the $_SESSION are globally available in all other projects or its my fault somewhere?
I am using Xampp 1.8.3 with PHP version 5.5.3 and Netbeans 7.4 (candidate release) for writing code. I would be thankful for expert guideline.
Basic rule: Don't abuse the session as a cache!
Here's why: The session data is read every time a request is made. All of it. And it is written back every time a request ends.
So if you write some data into it as a cache, that isn't used in every request, you are constantly reading and writing data that is not needed in this request.
Low amount of data will not affect performance significantly, but serializing, unserializing and disk or network I/O of huge amounts of data will affect it. And you miss the opportunity to use that data shared between multiple sessions.
On the other hand, a cache is no session storage, for obvious reasons: It is shared between all sessions and cannot really contain private data.
Regarding optimization for more traffic: You cannot optimize right now. Whatever usage pattern will evolve, you will only then see where performance is really needed. And you probably will want to scale - with the easiest way being to scale with some sort of cloud service instead of hosting it on your own hardware.

Basic Memcache Questions in PHP

I have never used memcache before now so please excuse my inexperience. Although it is pretty self explanatory, I would like to make sure I am using the built in functions correctly as I am creating a class that will be used commercially so it must be correctly coded and efficient.
I have several questions but as they are very basic I felt it would be alright to combine them into one Stackoverflow question.
If they require an essay answer, please dont bother and I will post it up as a separate question
When would I need to use memcache::addServer and what is the difference between this and memcache::connect?
Does memcache overwrite stored values if it runs out of memory, even if the item has not yet expired?
What would I use memcache::getExtendedStats for?
How do I check to see if a connection to memcache already exists and if not, create a connection?
If I have my usual memcache server of 'localhost' set up, how would I go about setting up another memcache server on my same dedicated server?
Apart from more memory, what is the benefit of having more than one memcache server?
Should I check for memcache server updates regularly?
Does it use a lot of memory to run memcache::connect at the beginning of each page, even if I am not using it?
When am I likely to return errors and how do I catch these?
Most importantly, if I am using memcache within another class that has several methods that may be called more then once per script, how should I go about initialising the object and connecting to the server within each method?
My guess for the last question would be to do it like so:
class test {
public function blah(){
// Make sure the memcache object is accessible
global $memcache;
// Do something ...
// Save result in memcache
$memcache->set(...);
}
public function foo(){
// Do something ...
// No use for memcache
}
}
// Initialise each class
$test = new test;
$memcache = new memcache;
$memcache->connect(...);
// Call some methods from the test class
$test->blah();
$test->foo();
$test->blah();
As you can see in the above example, I connect to the memcache server at the beginning of the script. If I was to include this at the beginning of every page, even on pages that do not use memcache, would this increase the response time a lot or minimal amounts? Hence, question 8!
You might need some coffee or something before you read this:
You'd want to use Memcache::addServer when you need to add more Memcached servers. For example, if you had a really busy website or web app... you'd probably want to have more than one Memcached server running1. Memcache::connect is used when you want to start a connection to one of your Memcached servers. Also, according to the Memcache::addServer docs, another difference between Memcache::addServer and Memcache::connect is that with Memcache::addServer, the connection is not established until actually needed2.
If Memcached runs out of RAM, it will discard the oldest values3.
Memcache::getExtendedStats is used to check information about your Memcached server. For example, if you need to find out how long the server has been up (uptime,) how many connections the server has, or general server usage4, this is a great tool.
Probably the easiest way to check if a connection to Memcached already exists is to check your $memcache connection variable to see if it returns TRUE5. If you need to have a persistent connection (that keeps on going even after your script ends,) there is the option to use Memcache::pconnect6.
If you want to have two Memcached servers going on... and your first server is already your localhost, you will most likely need to have a separate, distinct server for the second7.
At least one other benefit of having more than one Memcached server is the idea that whenever you diversify your data (or servers,) even when one server goes down... you still have however many other servers there to pick up the pieces. Memcached looks8 like it is distributed over however many servers you have running... so if a server goes down, you are still losing that part of the cache. But, you do still have other servers up and running to help keep going.
In general, it's not a bad idea to keep almost any type of software up to date. It looks like Memcached is still a highly active project9 so you may want to update it when you can. But the essence of Memcached doesn't seem to change a whole lot over past versions... so, it might not be as critical to update it compared to something like operating system software.
It sounds like the way that Memcached allocates memory for TCP connections (when you make a call to your Memcached server via Memcache::connect,) does end up costing you memory10. If you are sure you aren't going to need that connection on some of your pages, you may want to avoid making that connect call.
Hard to say what type of errors might come up in your code. But, with something like Memcached, you may find errors coming up when you are running out of memory11.
Like the answer to question eight, I would still recommend trying to only call that $memcache->connect() in areas where you absolutely need it. You might be using Memcached in a lot of your application or scripts; but there still will probably be places where you won't need it.
As far as your code idea for question 10 goes, it's really up to you as far as the implementation goes. In general, it's good to try to avoid global variables12 when possible, though. Instead, like that article (12) in the footnote talks about, it's easier to just use a singleton class call for a connection... and then just call that each time you want to make a connection.
Wow, my eyes are tired. I hope this helps, man...!
1 http://en.wikipedia.org/wiki/Memcached (see Architecture section)
2 http://www.php.net/manual/en/memcache.addserver.php
3 http://en.wikipedia.org/wiki/Memcached (see Architecture section)
4 http://www.php.net/manual/en/memcache.getextendedstats.php
5 http://www.php.net/manual/en/memcache.connect.php (see Return Values section)
6 http://www.php.net/manual/en/memcache.pconnect.php
7 http://www.php.net/manual/en/memcache.addserver.php#101194
8 Benefits of multiple memcached instances
9 http://code.google.com/p/memcached/
10 http://www.facebook.com/note.php?note_id=39391378919 (from Facebook's point of view)
11 http://groups.google.com/group/memcached/browse_thread/thread/9ce1e2691efb283b
12 How to avoid using PHP global objects?

Is there a variable scope that is accessible anywhere in PHP?

I'd like to create something like a very basic chat application. I don't want to use a database, since it'd cause a heavy load on an already strained db. I also don't want to use a flat file, because it have a feeling that it'd become a mess or that it'll have lots of read/writes...
So, I'm wondering if there is a way to have a variable that is accessible in any file and at any time.
Well if you don't want a file, you're left with shared memory.
You could try PHP's shared memory functions, or use an extension like memcache or APC.
You can't share variable values among separate requests - think of each request like the entire program is starting and finishing each time, even if there are several requests happening at once.
You could look into storing data in a cache layer (for example, memcached) however it sounds like you need to cache your database if it's under heavy load. I'd recommend caching your database (again memcached or file-based storage; serialize() data first) and then when that problem is solved store the chat data in the database (which is in turn cached). You need to store it persistently somewhere.
There isn't such thing. Try creating a basic file that saves serialized/json'd version of the variable you want, use php's flock to manage access to that file, cycle the file every hour/day. Since it's no big traffic simple app, I think this will be okay.

Security implications of writing files using PHP

I'm currently trying to create a CMS using PHP, purely in the interest of education. I want the administrators to be able to create content, which will be parsed and saved on the server storage in pure HTML form to avoid the overhead that executing PHP script would incur. Unfortunately, I could only think of a few ways of doing so:
Setting write permission on every directory where the CMS should want to write a file. This sounds like quite a bad idea.
Setting write permissions on a single cached directory. A PHP script could then include or fopen/fread/echo the content from a file in the cached directory at request-time. This could perhaps be carried out in a Mediawiki-esque fashion: something like index.php?page=xyz could read and echo content from cached/xyz.html at runtime. However, I'll need to ensure the sanity of $_GET['page'] to prevent nasty variations like index.php?page=http://www.bad-site.org/malicious-script.js.
I'm personally not too thrilled by the second idea, but the first one sounds very insecure. Could someone please suggest a good way of getting this done?
EDIT: I'm not in the favour of fetching data from the database. The only time I would want to fetch data from the database would be when the content is cached. Secondly, I do not have access to memcached or any PHP accelerator.
Since you're building a CMS, you'll have to accept that if the user wants to do evil things to visitors, they very likely can. That's true regardless of where you store your content.
If the public site is all static content, there's nothing wrong with letting the CMS write the files directly. However, you'll want to configure the web server to not execute anything in any directory writable by the CMS.
Even though you don't want to hit the database every time, you can set up a cache to minimize database reads. Zend_Cache works very nicely for this, and can be used quite effectively as a stand-alone component.
You should put your pages in a database and retrieve them using parameterized SQL queries.
I'd go with the second option but modify it so the files are retrieved using mod_rewrite rather than a custom php function.

Best practice for storing global data in PHP?

I'm running a web application that allows a user to log in. The user can add/remove content to his/her 'library' which is displayed on a page called "library.php". Instead of querying the database for the contents of the users library everytime they load "library.php", I want to store it globally for PHP when the user logs in, so that the query is only run once. Is there a best practice for doing this? fx. storing their library in an array in a session?
Thanks for your time
If you store each user's library in a $_SESSION as an array, as you suggested (which is definitely possible) you will have to make sure that any updates the user makes to the library are instantly reflected to that session variable.
Honestly, unless there is some seriously heavy querying going on to fetch a library, or you have tons of traffic, I would just stick to 'execute query whenever the user hits library.php'.
Consider the size of the data. Multiply that by the maximum number of concurrent users.
Then compare that the to memory avaiable on your server. Also consider whether or not this is a shared server; other sites needs resources too.
Based on this, it is probably best to either create a file that can be used (as per Remi's comment), or remain in the default stateless form and read every time. I doubt that reading the data each time is creating much of an overhead.
When the user login you can generate a xml file (USER_ID.xml for instance) that you display with xslt.
http://php.net/manual/en/book.xslt.php
Each PHP script dies when it completes, so data can not be kept permanentely live in a web application as you would do in a PC application.
One way could be sessions, but it depends on the amount of data you want to save. According to your example you are talking about a library, so it sounds to me like big quantity of data need to be saved, in such case the DB is the way to go, and yes you have to query it each time.
Another way could be to save them in an array inside a php file, but in the same way you have to query the DB each time, you would have to include such php file each time.
Since this is a db performance optimization, I would suggest that you take a look at memcached which matches your problem perfectly:
memcached is [..] intended for use in speeding
up dynamic web applications by
alleviating database load.
I think it would be best to store it in a Session.
It the user logs in, the Session is being created and you can save data in it using the superglobal:
$_SESSION['key'] = "value";
You can also store Arrays or everything else there and it can be cleared if the user logs out.
you care for performance; Please note:
Session may use database or file to store data.
database is here to be used instead of files, for it's performance and abilities.
use database, it is designed to be used exactly in such situations!

Categories