Which approach should I take in this case?
I have implemented the Data Mapper pattern with the Identity Map pattern. In short: When I want to have 2000 objects from the database, the mapper checks the result set against an hash map which contains references to already created objects. If an id is already in the hash map, the old object is added to the return array instead. Otherwise a new object is created and added to the return array. The return array will contain 2000 objects.
Note: This numbers are theoretical! The platform may be highly frequented, so this may happen many times per minute or even second.
Question: Which option is better and why?
A) Retrieve all 2000 objects from the database. Iterate over the record set (2000 rows), and check every id against the iden开发者_StackOverflow中文版tity map. If it's in there, add the referenced object of the identity map to the object array. If not, create a new object and add it to the result array.
B) Create a (maybe HUGE) sql query which excludes all id's which are in the identity map. Get a record set that contains only data for new objects. Create new objects without checking the identity map for every row. Incorporates a lot of string concatenation operations to build the query, but may save a whole bunch of hash map lookups.
Which approach would you take? (yes I know, I should just implement both versions and make a performance test, but maybe someone can answer this from practical experience)
I'd go with B.
I don't think this will take complicated string concatenation. Assuming your IDs are plain array keys, you could simply do:
$ids = implode(',', array_keys($hashmap));
$query = sprintf('SELECT * from records WHERE id NOT IN (%s)', $ids);
You might want to add some sanitizing for the query string though.
If you are already using SplObjectStorage for a hashmap, you'd have to iterate over the map to get the IDs from the stored objects. Depending on the amount of items already in there and the amount to fetch, you might be better of with A or B. It depends. But with SplObjectStorage you wouldn't have to bother about attaching already existing objects as this is taken care of already natively, e.g.
$map = new SplObjectStorage;
$one = new StdObject;
$map->attach($one);
$map->attach($one);
$map->count(); // returns 1
So, yes. I guess it's a benchmarking question and dependent on your specific scenario.
精彩评论