I am working on a jQuery Mobile Web App where a company will have the ability to message certain groups of users (based on their profile preferences).
I am debating on what is the most efficient way to mark when each user has read the latest messages. I have considered using a session to try and keep track of the last time they opened the messages page, and comparing that to the post times of the messages. I have also considered a table with the message_id and the user_id, marking each one as read when they open the page.
I think both would work, but I am trying to balance the pros and cons. Keeping in a database would allow me to keep a history (especially if i added a timestamp column to know when they read the message), but if it is going to hurt the app performance due to the table size, then it may not be worth it. The app will potentially have 10's of thousands of users.
One thing I should probably mention is that the users may use the app on multiple devices and the app will have very long session times, potentially allowing the user to stay logged in for months. I like the idea that if they read it on one device then it would mark it read on all devices, which may make sessions difficult to work with, right?
Ok, I'm gonna put everything I said in the comments into one solid answer.
Short Answer: You should be using the database to store 'read' notifications
Logic behind it:
It should be a negligable performance hit with decent servers and optimized code (couple of ms max) even with hundreds of thousands of users
It is highly maintainable
You can track it and sync it across devices
Specifically why you shouldn't use sessions
Sessions were designed to store temporary user data (think ram), they're not supposed to log stuff.
You should not be keeping sessions for months. It is highly insecure as it opens up a much larger window for session hijacking. Rather you should be generating a new session each time the app is accessed, and using a different "remember me" cookie or something each time to authenticate them.
Even if you do make your session persist for months, after those months won't the user all of a sudden get a bajillion "unread" notifications?
How to store it in the database
This is called a many-to-many relationship (from the message perspective) OR a one-to-many relationship (from the user perspective)
Table 1: messages
ID, message, timestamp
Table 2: messages_users
ID, user_id, message_id, read
Table 3: users
(Do user business as usual)
I can do one thing, if no problem with one user or 100 of user, you create one column named readUnread with more than 63,999 Characters in which you use put every user your message with 0 and 1 assign like {jeff:0,kevin:1,Sal:0} when read update from 0 to 1 and when you open this on the screen, split it with current user and ";", this will help you (this is the logic which inhance your performance).
Related
I have a web app running on Laravel php 5.2
To check my user's activity and returning users, I have implemented a last_login field in my users table and a listener that will update it at every login.
All is good, but what happens is I have a 'remember me' token, and when the user has already logged in, and returns to the application with the token, the last_login is not updated.
I thought on updating this field on every user action, but it seems not so optimized, and will cause some performance issues. Any ideas on how I could implement this 'last_active' thing, having little impact on performance
As you suggest yourself, I would (and do) update a last active timestamp with every pageload/and ajax calls that affect a User ... You will need to be talking about millions of concurrent users for it to be an issue... but then you'd be into the arena of load balancing Web and DB serevrs anyway.
If you're idea of a high load is, hundreds or even thousands of concurrent users, updating a timestamp will have little impact, just make sure the user table is kept simple and well sensibly indexed.
Also, another good way to keep this in good shape (depending on you're architecture) is using 2 connections ... one for read-only queries and one for updates, inserts etc.
So I have been playing around with a forum I am building and have been stuck on one aspect of it for a while, how to track unread posts and notifications without storing loads of data in the database. After looking at some solutions I believe I came up with a solution that may suit my needs but need a set of fresh eyes to point out what I didn't think of. Here is the architecture of my idea.
1) When a user logs in, check for posts made between current time() and last login time().
2) If posts found, add to array, then serialize() array and save to member row in database.
3) Output array to user if not empty.
This way it will only check for unread posts and store on users who actually log in to the forum, instead of taking up unnecessary space holding unread IDs of inactive users. I'm still wondering if this isn't such a good idea since if the user doesn't read posts then the serialization in the database might become too large to manage.
Does anyone see a problem in my way of thinking? If so please let me know.
Don't worry about the space until there's actually a problem. A table storing the post ID (integer) and the user ID (another integer) will be small. Even if you have thousands of posts and thousands of users, you can safely assume that:
a large part of the users will be inactive (one-time registrations to post something and forget the whole issue)
even the active members will not read all the posts, but rather only a (relatively small) part of the ones that are in topics that interest them.
One other thing: don't store unread posts if you really want to minimise space. Store only the last read post in each thread. That's one record per thread per user, and only assuming the user has ever opened the thread.
If the user logs in, but does not read posts, your scheme still marks them as read.
If the user logs in twice at once (as from a desktop computer and an iPad), what will happen?
What is the problem with keeping each user's view of the forum with a flag to indicate whether they read each one? Such a mechanism is obviously useful to expand into upvoting, favorites, etc.
the users registered in a web site will have the possibility to send invitations to the friends. I want to add a daily limit for the number of invitations that a user may send.
Initially I've just added a limit (40) in the php file, but then I thought it would be better to give to the administrators the possibility to change this limit, so I've added this limit in the database. But now every time a user want to send invitations the database will be used. Would this affect the performance?
How would you configure this feature?
TL;DR: just put it in the database. :)
Complete story: It should not be a performance hit. Everything (the user itself, the usernames of the recipient, loads of stuff from your page) will be coming from your database. you shouldn't care.
If you have a REALLY big userbase, and it becomes an issue, I'm sure there are other places to do performance updates (like use memcached for all sorts of stuff). But if you want to "cache" it, I guess you could retrieve it once while loggin in and put it in the session. Use this value to substract and check etc. then ALSO check once against the database (in the background) to make sure there isn't any sort of freakish thing going on for this user. But this can be async, and does not have as big of an impact for the user-experience.
In the rare case the session says it's ok, but the database says it isn't, just send the user an error. The other way around, might need the user to re-login. But it will be rare or even impossible if you implement it correctly :)
It depends a bit on hardware but a 400,000 row table (10,000 * 40) isn't that huge in MySQL standards. I think you'll be fine.
Just make sure that you've built it sensibly and from how you've described it that there's an index on the column that stores the unique invite code.
I have been creating a web app and am looking to expand. In my web app I have a table for users which includes privileges in order to track whether a user is an administrator, a very small table for a dynamic content section of a page, and a table for tracking "events" on the website.
Being not very experienced with web application creation, I'm not really sure about how professionals would create systems of databases and tables for a web application. In my web app, I plan to add further user settings for each member of the website and even a messaging system. I currently use PHP with a MySQL database that I query for all of my commands, but I would be willing to change any of this if necessary. What would be the best wat to track content such as messages that are interpersonal and also specific user settings for each user. Would I want to have multiple databases at any point? Would I want to have multiple tables for each user, perhaps? Any information on how this is done or should be done would be quite helpful.
I'm sorry about the broadness of the question, but I've been wanting to reform this web app since I feel that my ideas for table usage are not on par with those that experienced programmers have.
Here's my seemingly long, hopefully not too convoluted answer to your question. I think I've covered most, if not all of your queries.
For your web app, you could have a table of users called "Users", settings table called "UserSettings" or something equally as descriptive, and messages in "PrivateMessages" table. Then there could be child tables that store extra data that is required.
User security can be a tricky thing to design and implement. Do you want to do it by groups (if you plan on having many users, making it easier to manage their permissions), or just assign individually due to a small user base? For security alone, you'd end up with 4 tables:
Users
UserSettings
UserGroups
UserAssignedGroups
That way you can have user info, settings, groups they can be assigned to and what they ARE assigned to separated properly. This gives you a decent amount of flexibility and conforms to normalization standards (as mentioned above by DrSAR).
With your messages, don't store them with the username, but rather the User ID. For instance, in your PrivateMessages table, you would have a MessageID, SenderUserID, RecipientUserID, Subject, Body and DateSent to store the most basic info. That way, when a user wants to check their received messages, you can query the table saying:
SELECT * FROM PrivateMessages WHERE RecipientUserID = 123556
A list of tables for your messages could be as such:
PrivateMessages
MessageReplies
The PrivateMessages table can store the parent message, and then the MessageReplies table can store the subsequent replies. You could store it all in one table, but depending on traffic and possibly writing recursive functions to retrieve all messages and replies from one table, a two table approach would be simplest I feel.
If I were you, I'd sit down with a pencil and paper, and write down/draw what I want to track in my database. That way you can then draw links between what you want to store, and see how it will come together. It helps me when I'm trying to visualise things.
For the scope of your web app you don't need multiple databases. You do need, however, multiple tables to store your data efficiently.
For user settings, always use a separate table. You want your "main" users table as lean as possible, since it will be accessed (= searched) every time a user will try to log in. Store IDs, username, password (hashed, of course) and any other field that you need to access when authenticating. Put all the extra information in a separate table. That way your login will only query a smaller table and once the user is authenticated you can use its ID to get all other information from the secondary table(s).
Messages can be trickier because they're a bigger order of magnitude - you might have tens or hundreds for each user. You need to design you table structure based on your application's logic. A table for each user is clearly not a feasible solution, so go for a general messages table but implement procedures to keep it to a manageable size. An example would be "archiving" messages older than X days, which would move them to another table (which works well if your users aren't likely to access their old messages too often). But like I said, it depends on your application.
Good luck!
Along the lines of Cristian Radu's comments: you need to split your data into different tables. The lean user table will (in fact, should) have one unique ID per user. This (unique) key should be repeated in the secondary tables. It will then be called a foreign key. Obviously, you want a key that's unique. If your username can be guaranteed to be unique (i.e. you require user be identified by their email address), then you can use that. If user names are real names (e.g. Firstname Sirname), then you don't have that guarantee and you need to keep a userid which becomes your key. Similarly, the table containing your posts could (but doesn't have to) have a field with unique userids indicating who wrote it etc.
You might want to read a bit about database design and the concept of normalization: (http://dev.mysql.com/tech-resources/articles/intro-to-normalization.html) No need to get bogged down with the n-th form of normalization but it will help you at this stage where you need to figure out the database design.
Good luck and report back ;-)
I have many polls on my site, and I want to prevent users from re-voting many times. As far as I know, I can either keep a IP log of visitors, or store cookies. I tried using an IP log into mySQL database, but theres one problem: All visitors behind a router have the same external IP so only one person behind the router can vote on a certain poll.
So now I'm switching my code to use cookies unless there are better solutions. Since there will eventually be hundreds or thousands of polls, and I think there is a 20 cookie limit, how can I store values for each poll? The values can just be binary values, for example poll1=0 if not yet voted, poll1=1 if voted.
Also, if it helps, each poll immediately shows the results using jquery. I'm assuming I can set/modify the cookie in the jquery resonse.
Any ideas? Thanks! (btw, I realize cookies can be deleted)
If you really want to restrict per-user, you need to implement user identification, which means you need user registration, login and session management. Once you have that, it's not at all difficult. Just implement a many-to-many relation between your user records and your poll records with a join record created when a user takes a poll and checked to determine whether they've already taken it.
Trying to implement a limit on the activities of users without implementing a way of really identifying users will never work well.
Even though you may have hundreds of polls, it is reasonable to expect that each user will only vote in a few of those. So you can just have a single cookie with a comma-separated list of poll IDs in which the user has voted.
Of course, cookies don't provide any sort of protection since they can be deleted or tampered with, but they are also the only practical way to store such information and they work well in most cases.