I am using Yii framework and I have a Post that has many comments, I need to get a list of posts, and each post should hold the latest 5 comments with it.
First Option: Is to make a join between posts and comments table and in the PHP code I should normalize the posts list to remove the duplicates and put the commets inside each related post.
Second Option: Is to load the posts list, then in PHP code iterate over these posts list and load the comments for each post using a separate sql hit.
Which one has the best performance and is there any better way to do it?
You should never have incremental hits on your database because of the data. Therefore, the first option would be the wisest one. If you do a join and then filter away the stuff you do not need, your program will be a lot faster than if you do one more database lookup for each row the previous query returned.
For more information, have a look on lazy and eager loading here: http://www.yiiframework.com/forum/index.php/topic/34412-eager-loading-vs-lazy-loading/
Related
Im programming my own simple blog with comments in php and mysql. I have one database, and I have one table for posts, (called posts) and for each post I make I manually create a new table called comments1,comments2,comments3, etc. Each blog post has an id and when I retrieve the comments for a post I use a query like:
SELECT * FROM `comments".$id."`"
When I add user text to a comment I use:
htmlspecialchars(mysql_real_escape_string($_POST['name']));
Is this structure ok or is there a better way I'm missing?
Also, would creating a different database for comments be a better practice than grouping it with the posts database? Does having 2 dbconnect functions in one file slow down performance by a lot? And one last worry: how do i make absolutely sure that my php files aren't served to the user as plaintext, because then they could see db login info and such.
Thanks for the help.
No, this is TERRIBLE structure.
Make one comments table and store all comments in there, along with corresponding post_id.
Add an index on post_id and you'll be able to quickly get all comments for a given post.
With PHP & MYSQL, I need a scalable way to show a few comments for each post just like in facebook. For all the posts in my application I need to print the most recent comments beneath the post. The problem is that I dont want to put a SQL query in a loop and have to run 20 SQL queries per page. Is there one SQL query that I can use to get the 2 most recent comments for each post that I get from the posts table.
I believe you can retrieve all the comments using one query and then store them in an array. You can then iterate over the array to organize them.
I'm trying to make a facebook style news feed on my webpage that combines user input from multiple tables into a feed.
Would the best way to approach this be:
(1) Using mySQL Join Queries
(2) Using mySQL single queries from multiple tables into an Array.
(3) Another way?
Thanks.
Edit:
The structure of my Databases are as follows:
1 User (Table: User)
Mutliple Blogs per user (Table: Blog)
Mutliple Content Upload per user (Table: Content)
What I am trying to achieve is a query that will collect the defined users ID's blog post and content uploads and display them in chronological order.
Thanks for the replies!
This is difficult to answer without knowing anything about your database schema (consider editing your question to add some details), but you may wish to consider creating a View that you could then retrieve and present your news feed from with a single, simple query.
If there is going to be a lot of data it is good to have a separate table that holds your "feed". That way, you don't have a lot of overhead each time you do your query.
I have a CakePHP application where I am trying to get a count of how many of each type of post a user has. I am also using the paginate helper to display all the user's posts on their profile.
I could:
1) Make a find('all', $conditions) request for all the user's posts then parse that for the counts I need (by going post by post and checking if it matches what I'm looking for).
2) Make multiplie find('count', $conditions) requests, getting all the counts I need individually.
3) Maintain new columns in the user's table to track these numbers when the posts are created (put that would involve writing to the user account whenever a new post is made).
Which one would be the best choice?
Fetching all records from the database and counting them in PHP is hugely wasteful nonsense. That's exactly what databases are for.
A find('count') just makes an SQL query like SELECT COUNT(*) FROM … WHERE …, which is really the fastest way to go. Add appropriate conditions to get the count you want, you may need to brush up on your SQL to know what conditions these are.
There's also the special of counter-caching, which you might want to look into if you're counting hasMany relations.
You should modify your find call to include a group by condition to aggregate the count by type. See here for more info: http://debuggable.com/posts/how-to-group-by-in-cakephps-new-release-part-2:4850d2c9-edbc-4f0e-9e0e-07d64834cda3
With reference to this post: How to implement tag counting
I have implemented the suggested 3 table tagging system completely. To count the number of Articles per tag, i am using another column named tagArticleCount in the tag definition table. (other columns are tagId, tagText, tagUrl, tagArticleCount).
If i implement realtime editing of this table, so that whenever user adds another tag to article or deletes an existing tag, the tag_definition_table is updated to update the counter of the added/removed tag. This will cost an extra query each time any modification is made. (at the same time, related link entry for tag and article is deleted from tagLinkTable).
An alternative to this is not allowing any real time editing to the counter, instead use CRONs to update counter of each tag after a specified time period. Here comes the problem that i want to discuss. This can be seen as caching the article count in database. Can you please help me find a way to present the articles in a list when a tag is explored and when the article counter for that tag is not up to date. For example:
1. Counter shows 50 articles, but there are infact 55 entries in the tag link table (that links tags and articles).
2. Counter shows 50 articles, but there are infact 45 extries in the tag link table.
How to handle these 2 scenerios given in example. I am going to use APC to keep cache of these counters. Consider it too in your solution. Also discuss performance in the realtime / CRONNED counter updates.
It all comes down to the needs of your application. How crucial is it for the information to be up to date? In most cases, I would think that it would be worth the extra query to have real-time data.
I actually recently faced the same challenge on a system I am developing, but ultimately decided that the solution which used a field for storing a tag-count would not work. It might be worth considering the reason I went another way, in case it is applicable to your situation:
With the field-based method, you only have one count available. For my system, I wanted to be able to have several levels of depth available. So, using the tags on this article as an example, I wanted to know more than the overall counts of 'php', 'mysql', 'best-practices', 'performance', and 'tagging'. I also wanted to know the counts of various combinations.
The solution I went with was to use a count(*) as follows:
SELECT count(*)
FROM items i, categories c
WHERE c.Id = i.Id
AND (c.category IN ('php', 'mysql', 'tagging'))
GROUP BY i.Id
HAVING COUNT( i.Id )=3
To mitigate the possibility of this getting slow, I use AJAX to populate the page segments into which the related data is displayed.