For your rudimentary example of object-relational mapping below, yes, performance is going to be atrocious. That's because you're not taking any advantage of the features that using OOP gives you. One could write a dissertation on this problem, but I will just give you some general guidelines. (All code examples below assume PHP 5.) 1) OOP has overhead. In most situations, if you can write something in a fully OOP fashion or a direct procedural fashion, the direct procedural will perform faster. How much faster depends on the situation and the experience level of the programmer. What OOP can get you is flexibility. There are cases where OOP code is faster than the corresponding procedural, but none of them involve SQL. :-) 2) Burn some memory on private variables. That's what they're there for. Eg: public class Foo { private $id=0; private $bar=0; private $baz=''; function __construct($id) { // Do your type checking and escaping here $result = mysql_query("SELECT * FROM Foo WHERE id={$id}"); $record = mysql_fetch_object($result); $this->id = record->id; $this->bar = record->bar; $this->baz = record->baz; } function getBaz() { return $this->baz; } } You'll want to be a lot smarter than the code above to avoid drudge work in the code, but you get the idea. Front-load as much of the object's information has you can in the constructor, within reason. A good rule of thumb is that anything you can get in the initial query (like above) you should and then cache. That saves you putting wasteful SQL queries in your getters. 3) Data you have to load later from another table, delay until you need to get it but then cache that as well. function getRevenue ($id,$department,$month,$year) { if (!$this->revenue) { $result = mysql_query ("SELECT revenue FROM customer_revenue WHERE customer_id = '$id' AND department = '$department' AND month = '$month' AND year = '$year'"); $this->revenue = mysql_result ($result, 0); } return $this->revenue; } Again, pull extra data if you can. A somewhat larger result set is (usually) better than multiple queries. How much you want to front-load in your object and how much you want to defer to later depends on your specific problem and how frequently the data will be used. 4) You can optimize your SQL structure for easier object usage. Often that just means proper normalization, sometimes you'll want to denormalize in specific places to improve performance. Again, depends on your situation. 5) If you need to grab 100 objects at once, but just need basic data out of them, use a factory. Vis, $myobjects = Foo::getObjects(array(1, 2, 3)); class Foo { static function getObjects($ids) { $return = array(); $result = mysql_query("SELECT * FROM Foo WHERE id IN (" . implode(',', $ids) . ")"); while ($record = mysql_fetch_object($result)) { $foo = new Foo(); $foo->setProperties($record); $return[] = clone($foo); } return $return; } function setProperties($properties) { // Left as an exercise to the reader } } 6) If you need to do a complex query with a couple of joins and such, then don't waste your time or the computer's trying to shoe-horn it into SQL. SQL is not inherently OO to start with! Just write your query and loop it and be happy. OOP is not the answer to all problems. Sometimes it does just make matters worse, no matter what Sun tries to tell you. :-) > I want my data to _only_ be accessed from the black box called an OOP > class. That will work and is achievable in about 30% of all situations. For the other 70%, you will have to just hunker down and *gasp* write SQL specific to the task at hand at least some of the time. How much of the time once again depends on your situation and the problem you're trying to solve. On Tuesday 10 October 2006 18:14, Chris de Vidal wrote: > I think perhaps I'm using classes and OOP incorrectly. The last time I > used them, they were slow. > > I want to create a "customer" class which fetches its attributes from a > MySQL database. Something like this pseudocode: > > class customer > { > ... > getName ($id) > { > $result = mysql_query ("SELECT name FROM customers WHERE id = > '$id'"); return mysql_result ($result, 0); > } > getRevenue ($id,$department,$month,$year) > { > $result = mysql_query ("SELECT revenue FROM customer_revenue WHERE > customer_id = '$id' AND department = '$department' AND month = '$month' AND > year = '$year'"); return mysql_result ($result, 0); > } > ... > } > > (Again, that's just psedocode. Haven't written anything yet.) > > > That works great for just one revenue result, but what if I want to return > several results? What if I want to build a report with hundreds of > customers' revenues for a month? For several months? For an entire year? > Doesn't it slow wayyyy down? It seemed to in the past. The method above > doesn't seem to scale well. > > I did something like the above a few years ago. It was slow, and I think > it's because it was doing this for each single row: > * Instantiate the class > * Perform a query for the name > * Perform a query for the first department > * Perform a query for the next department > * Perform a query for the next department > * Perform a query for the next department > * Perform a query for the next department > * Perform a query for the next department > * Perform a query for the next department > ... > * Destroy the instantiation > * Start over > > I love using object-oriented programming, but it seems to me that's ALOT of > performance burden when I could just do something like this: > SELECT customers.name, > customer_revenue.revenue > FROM customers > INNER JOIN customer_revenue > ON customers.id = customer_revenue.customer_id > WHERE customer_revenue.department = '$department' > AND customer_revenue.month = '$month' > AND customer_revenue.year = '$year' > > (PHP loop to display all results) > > > That seems like it would perform 20x faster. > > It seems that the SQL economies of scale (ability to rapidly slurp large > sets of data) are completely bypassed when using OOP to view ALOT of > objects together on one screen. It seems if I want decent performance I > would have to ignore OOP rules of method hiding and access the data > directly when using anything more than just a few objects on one page. > > > A workaround -- I thought that perhaps I could fetch ALL of the data for a > customer into memory upon initial instantiation, wherein I perform > something like this: SELECT * > FROM customers > INNER JOIN customer_revenue > ON customers.id = customer_revenue.customer_id > WHERE customers.id = '$id' > > And then use the results from memory as-needed. It would be all data for a > customer from all years across all departments. > > That might perform better but it'd suck ALOT of data into memory, and what > if I add more than just revenue to my customer class? Each customer could > potentially represent a limitless set of data. So this doesn't seem like an > optimal solution. > > > * Where am I going wrong? > * Tell me how YOU fetch data from multiple objects to generate reports. > * Is this an instance where it's better to just ignore OOP rules and go > straight to the data? Whew, that's not fun to think about, particularly if > my queries ever get to be more complex. > > Feedback, please. The goal is to maintain complex queries in just one > place -- inside a class. I want my data to _only_ be accessed from the > black box called an OOP class. > > CD > > Think you're a good person? Yeah, right! ;-) > Prove it and get ten thousand dollars: > TenThousandDollarOffer.com -- Larry Garfield AIM: LOLG42 larry@xxxxxxxxxxxxxxxx ICQ: 6817012 "If nature has made any one thing less susceptible than all others of exclusive property, it is the action of the thinking power called an idea, which an individual may exclusively possess as long as he keeps it to himself; but the moment it is divulged, it forces itself into the possession of every one, and the receiver cannot dispossess himself of it." -- Thomas Jefferson -- PHP General Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php