andrew3 at r3dsolutions.com
Fri Jan 18 14:43:42 CET 2013
On 01/18/2013 08:47 AM, Stefan Behnel wrote:
> Andrew Robinson, 18.01.2013 00:59:
>> I have a problem which may fit in a mysql database
> Everything fits in a MySQL database - not a reason to use it, though. Py2.5
> and later ship with sqlite3 and if you go for an external database, why use
> MySQL if you can have PostgreSQL for the same price?
MySQL is provided by the present server host. It's pretty standard at
web hosting sites.
It works through "import MySQLdb" -- and it means an IP call for every
Postgre isn't available :( otherwise, I'd use it....
I'm mildly concerned about scaling issues.... but don't have a lot of
time (just a few days) to come to a decision. I don't need high
performance, just no grotesque degradation when the system is scaled up,
and no maintenance nightmare. The votes table is going to get
monsterous if all votes are held in one table....
Your comment about sqlite is interesting; I've never used it before.
At a glance, it uses individual files as databases, which is good... But it wants to lock the entire database against reads as well as writes when any access of the database happens. Which is bad...
> ... XML files are a rather static thing and meant to be
> processed from start to end on each run. That adds up if the changes are
> small and local while the file is ever growing. You seem to propose one
> file per article, which might work. That's unlikely to become too huge to
> process, and Python's cElementTree is a very fast XML processor.
Yes, that's exactly what I was thinking.... one file/article.
It's attractive, I think, because many Python programs are allowed to
read the XML file concurrently, but only one periodically updates it as
a batch/chron/or triggered process; eg: the number/frequency of update
is actually controllable.
eg: MySQL accumulates a list of new votes and vote changes and python
occasionally flushes the database into the archive file. That way, MySQL
only maintains a small database of real-time changes, and the
speed/accuracy of the vote tally can be tailored to the user's need.
> However, your problem sounds a lot like you could map it to one of the dbm
> databases that Python ships. They work like dicts, just on disk.
Doing a Google search, I see some of these that you are mentioning --
yes, they may have some potential.
> IIUC, you want to keep track of comments and their associated votes, maybe
> also keep a top-N list of the highest voted comments. So, keep each comment
> and its votes in a dbm record, referenced by the comment's ID (which, I
> assume, you keep a list of in the article that it comments on).
The comments themselves are just ancillary information; the votes only
apply to the article itself at this time. The two pieces of feedback
information are independent, occasionally having a user that gives both
kinds. Statistically, there are many votes -- and few comments.
Each archive file has the same filename as the article that is being
commented or voted on; but with a different extension (eg: xml, or
.db,or...) so there's no need to store article information on each vote
or comment; (unlike the MySQL database, which has to store all that
information for every vote.... ugh....!)
> You can use
> pickle (see the shelve module) or JSON or whatever you like for storing
> that record. Then, on each votes update, look up the comment, change its
> votes and store it back. If you keep a top-N list for an article, update it
> at the same time. Consider storing it either as part of the article or in
> another record referenced by the article, depending of how you normally
> access it. You can also store the votes independent of the comment (i.e. in
> a separate record for each comment), in case you don't normally care about
> the votes but read the comments frequently. It's just a matter of adding an
> indirection for things that you use less frequently and/or that you use in
> more than one place (not in your case, where comments and votes are unique
> to an article).
> You see, lots of options, even just using the stdlib...
Yes, lots of options....
Let's see... you've noticed just about everything important, and have
lots of helpful thoughts; thank you.
There are implementation details I'm not aware of regarding how the
file-system dictionaries (dbm) work; and I wouldn't know how to compare
it to XML access speed either.... but I do know some general information
about how the data might be handled algorithmically; and which might
suggest a better Python import to use?
If I were to sort all votes by voter ID (a 32 bit number), and append
the vote value (A 4 to 8bit number); Then a vote becomes a chunk of 40
bits, fixed length; and I can stack one right after another in a compact
Blocks of compacted votes are ideal for binary searching; since they
have fixed length... and if I am only wanting to change a vote, I don't
need to re-write the entire file, because a changed vote doesn't change
the file length. ( So, now I have COMPACT + FASTER ).
If I were to wish to insert new votes, in this sorted list of votes -- I
would need to do something like a merge sort; which means changing the
length of the file by a bulk copy of most of it to open up a "little"
space for 1 or two votes; BUT:
It's also possible to break the vote list up into compact ranges of
voter ID's; And perhaps using indirection like you suggested.... and I
was thinking it might not be hard to add *some* limited blank space in
the file -- like this XML example:
<vblock start="125" end="550">
<vblock start="560" end="620">
So that inserting a vote to block "125" could be done by a simultaneous
deleting of some of the padding characters "...." and therefore, the
whole file rarely needs a re-write.
I don't want to waste a large amount of time optimizing this, as a fast
C-api COPY in one library might make merge sort tons faster than a
python interpreter based blank space shrink-expand; But, do any of the
possible optimizations I just gave suggest one standard Python library
might be better suited than another?
Thanks for the help. :)
More information about the Python-list