30

May

Filed in Disqus, Django, PostgreSQL, Work |

As many you of know I joined Disqus last month. This was a pretty big move for me, and definitely a great one. They have some amazing challenges, and the company has a great group of people willing to solve them.

I’ve always been a big advocate of MySQL. Not because it’s the best relational database, but because it works, and it works well. However, moving to Disqus had one big change which I had to adjust to, and that was PostgreSQL. Not only that, but the size of the data in their databases more than tripled anything I had previously worked with (and that’s not even including the load, just raw data).

So, going on a month now at this amazing workplace, I’ve learned some pretty cool things regarding PGSQL. Let’s talk about a few of those, and the pros and cons.

First up, scalability, as it’s the biggy. For a long time PostgreSQL has been looked at as an alternative to MySQL. For most of that time, however, there just was no way to scale it to the level of which MySQL could achieve. In the last few years the problem has all but vanished, and there’s been many interesting, widely adopted tools for PG. Two of them which we use at Disqus are Slony, and pgbouncer. Slony allows us to replicate data (as well as partition in, in some cases), and pgbouncer solves persistent connections and pooling.

Next up, let’s move on to the language itself. I had the pleasure this week of learning how to use recursive queries within PGSQL 8.4, and holy shit are they powerful. Here’s what I really want to talk about with this blog post. MySQL allows you to do things, and do them well, but you must do them within the constructs of the engine. Now while this holds true within PG as well, you have much more freedom in the choices you can make. So, now I want to talk about our problem, threaded comments.

As you all know, Disqus is not only the largest Django site (we are closing in on a billion page views each month), but it also the largest service provider for comments on the web. We provide many features, to many thousands of websites, the basics of which being threaded comments.

PostgreSQL offers several solutions to threading. There’s obviously the most common (and fairly efficient) method which is trickily named modified preorder tree traversal. To summarize, this adds a left order, and a right order, which may be updated on insertion of a comment into the tree. Now there is also the other standard approach (which for some reason Reddit finds oh so fun to use), which is “select everything and deal with it in memory”. Well, turns out, it’s not just Reddit doing that :)

Moving on to what PGSQL actually offers, we have two more options (within 8.4 at least). One of those is a contrib module within PG called ltree. It allows you to store the full path (all parents) to a node as well as searching and selecting on it with standard SQL statements. This is extremely useful if you just want a basic “order by oldest” as it becomes a simple “order by ltree_column”. However, Disqus, as always, isn’t that simple.

Our second solution is the new recursive queries. Now this took me a few hours to really wrap my head around how it was working, but once I did, I was amazed at the possibilities. Including things like the OVER() modifier, Postgres offers some very interesting concepts that weren’t available to me within MySQL. The best part? They actually perform VERY well.

Let’s get down to our situation, which is a big one. Right now, Disqus handles threading just like Reddit, which handles it just like many other solutions on the internet, that is, very poorly. And I don’t mean poorly as in its badly written, it’s just not optimized nearly as well as it could be. This doesn’t become a problem until certain people (I’m looking at you Mr. Obama) start using your application, and everybody and anybody wants to reply to a comment. Again, we’re pulling them down to Django (even if its incrementally) and grouping them withint he application logic.

As of 8.4 this can truly be handled by recursive queries (in any situation we’ve come across, even if it’s a bit complex to do it). It’s even pretty simple to do.

So let’s take a basic example. We have a comment model, which looks a bit like this:

CREATE TABLE comments (
	id SERIAL PRIMARY KEY,
	message VARCHAR,
	author VARCHAR,
	parent_id INTEGER REFERENCES comments(id)
);
INSERT INTO comments (message, author, parent_id)
VALUES ('This thread is really cool!', 'David', NULL), ('Ya David, we love it!', 'Jason', 1), ('I agree David!', 'Daniel', 1), ('gift Jason', 'Anton', 2),
('Very interesting post!', 'thedz', NULL), ('You sir, are wrong', 'Chris', 5), ('Agreed', 'G', 5), ('Fo sho, Yall', 'Mac', 5);

What we’ve done now, is setup a basic comment model. We’ve included the message, the author, and the parent comment (which is optional). Now let’s learn how to use a recursive query to easily re-order this datd, showing us a fully threaded view, sorted in ascending order by id.

WITH RECURSIVE cte (id, message, author, path, parent_id, depth)  AS (
  SELECT  id, 
          message,
          author,
          array[id] AS path,
          parent_id, 
          1 AS depth
  FROM    comments
  WHERE   parent_id IS NULL
 
  UNION ALL
 
  SELECT  comments.id, 
          comments.message, 
          comments.author,
          cte.path || comments.id,
          comments.parent_id, 
          cte.depth + 1 AS depth
  FROM    comments
          JOIN cte ON comments.parent_id = cte.id
)
SELECT id, message, author, path, depth FROM cte
ORDER BY path;

Pretty sweet huh? Oh wait, confused? So was I, and the query I was looking at was a whole lot more complex. Public shout-out to the amazing folks at pgexperts for pointing us on the right path.

Now I’m not going to drill into this too much, because there are much better tutorials for dealing with recursive queries in this pattern, but let’s finish up with our results.

We deal with an enormous set of information, and some threads have literally thousands of repies. Pulling this down into memory isn’t a problem when 99% of threads only have a hundred replies, but when they start to peak we end up wasting a lot of time. Recursion within PGSQL allows us to easily pass off this work to the database (which just so happens to be able to do it faster than we ever could), and save us a ton of network traffic and web processing time in the process.

To give you an idea of the effect this will have (pending everything works out), we’ve seen savings of up to 500% on some large datasets, just for the SQL processing time (returning 25 results, rather than 1000). This doesn’t even represent the cost in our application layer. Yes, you heard that right, the SQL statement is 5x more performant at the database level alone.

Wrapping all of this up, for a MySQL advocate, I’m pretty damn impressed with the performance, scalability, and the general flexibility that Disqus has achieved with PostgreSQL. I’m definitely looking forward to what else we can do with the platform, and the many challenges that await us.

(And yes, for those wondering, I’m “back”, and will continue blogging about random awesome/crazy/forbidden things that we get to treat ourselves to)

  • http://www.brandonkonkle.com/ Brandon Konkle

    Great post! I know this was just a side topic of your post, but your mention of slony and pgbouncer was very helpful. We have been looking into replication and pooling for PegasusNews.com, so I'll definitely be looking into both of those.

  • http://www.mellowmorning.com Thierry Schellenbach

    Over at YouTellMe.nl we have switched from mysql to postgres about a year ago. The flexibility with triggers and automated data denormalization makes scaling your app so much easier.

  • Tom

    I thought disqus uses MongoDB?

  • Matthew W

    Any pointers on why the ltree approach didn't work for you?

    It's an approach I've used in the past (in MYSQL actually) with some relatively-high-traffic message boards, but not on the scale of Disqus.

  • http://blog.nodnod.net dz

    Comments and related data have always been powered by Postgres

  • http://blog.nodnod.net dz

    MySQL can do that too though, but it's true that Postgres has matured rapidly into a featureful *and* fast/stable platform.

  • http://blog.nodnod.net dz

    MySQL can do that too though, but it's true that Postgres has matured rapidly into a featureful *and* fast/stable platform.

  • David

    And why don't you use the nested set approach?

    http://en.wikipedia.org/wiki/Nested_set_model

  • http://tjoozey.com/?p=5552 Postgresql’s new recursive queries at Disqus: 500% speedup

    [...] full post on Hacker News If you enjoyed this article, please consider sharing it! [...]

  • http://popular.econsultant.com/scaling-threaded-comments-on-django-at-disqus-david-cramers-blog/ Scaling Threaded Comments on Django at Disqus | David Cramer’s Blog : Popular Links : eConsultant

    [...] the rest here: Scaling Threaded Comments on Django at Disqus | David Cramer’s Blog 29 May 2010 | Uncategorized | Trackback | del.icio.us | Stumble it! | View Count : 0 Next Post [...]

  • https://tabo.pe/ tabo

    Another great option that needs DB functions/sprocs is Nested Intervals with Farey Fractions: http://arxiv.org/html/cs/0401014

    I have ben planning to add support for this in django-treebeard for a long time. My guess (haven't actually measured) is that it would be faster and less db intensive than recursive queries.

    And yes the pgexperts guys are amazing :)

    EDIT: disqus won't let me login with opened, it 's throwing this error:

    “Unfortunately, we could not initiate OpenID process. Please, close this window and try again.”

  • http://www.alberton.info Lorenzo Alberton

    I gave a presentation last year about these topics, and all the different approaches to store a tree data structure in the database, including recursive queries:

    http://www.slideshare.net/quipo/trees-in-the-da...

    And if you are interested in really crazy stuff you can do with CTEs, have a look at this one as well:

    http://www.slideshare.net/quipo/rdbms-in-the-so...

    HTH

  • Chris Allen

    I look forward to you continuing to post content. :)

  • http://www.davidcramer.net David Cramer

    The reason materialized paths is that it simply doesnt fit our use case. We are lucky enough to have the need to sort by more than just a static ordered pattern. Our “Most Popular” sort method, for example, calculates information based on a liking pattern and datetime information. This is a much more complicated query than shown above (via the recursion), but still doable.

  • http://www.davidcramer.net David Cramer

    The reasons we didn't use nested sets is because they are much more write heavy, and at this point we're not ready to put that load on the database cluster. It's something we've talked about pretty heavily, and may eventually move to it. However, this solution doesn't require any database alterations, so deployment is as easy as upgrading to Postgres 8.4.

  • http://dismalsci.wordpress.com/2010/05/30/links-for-2010-05-30/ links for 2010-05-30 « that dismal science

    [...] Scaling Threaded Comments on Django at Disqus (tags: disqus postgres postgresql scalability) [...]

  • http://sahuguet.wordpress.com/2010/05/30/scaling-threaded-comments-on-django-at-disqus-david-cramers-blog/ Scaling Threaded Comments on Django at Disqus | David Cramer’s Blog « The other side of the firewall

    [...] [From Scaling Threaded Comments on Django at Disqus | David Cramer's Blog] [...]

  • http://www.prada-outlet-store.com prada outlet

    Well , the view of the passage is totally correct ,your details is really reasonable and you guy give us valuable informative post, I totally agree the standpoint of upstairs. I often surfing on this forum when I m free and I find there are so much good information we can learn in this forum!

  • http://blog.thequeue.net/link-dump-for-may-30th/ Link dump for May 30th | The Queue Blog

    [...] Scaling Threaded Comments on Django at Disqus | David Cramer’s Blog – recursive queries in pg. this is where database agnosticism falls down. hard. [...]

  • https://tabo.pe/ tabo

    David,

    I think you're confusing Nested Sets with Nested Intervals. Nested Intervals don't have that horrible Nested Sets behavior of potentially running an UPDATE on every node of the tree on a write.

    They're both very different implementations, and Nested Intervals do need sprocs/functions in the DB.

    (I couldn't reply to your comment, it kept saying that my comment was empty, using safari4)

  • http://www.davidcramer.net David Cramer

    What we did before (at Curse), I believe were Nested Sets (though I will do some more reading). Basically we checked some logic to confirm we needed to do an update (usually on insert, it was just two updates, no extra logic).

    From what I read I thought this was simple what Nested Sets did? You store a left and right order, and simply order by that column. Am I mistaken that for Nested Intervals? If not, can you tell me the primary difference?

  • Charles

    I'd like to see some benchmarks on the difference between something like https://tabo.pe/projects/django-treebeard/docs/... and the use of recursion.

    Seems to me that using wildcard matching on a tree path field would be more performant.

  • https://tabo.pe/ tabo

    David,

    I'll do my best explaining this without graphics. It's complicated enough _with_ graphics, but here we go.

    Basically, with nested sets in it's basic form, every node has 2 numbers: the left and right position. If rgt-lft==1, then the node is a leaf. If rgt-lft>1, then the node has children. The root node has lft=1 and rgt=latest sequential number.

    Imagine that you have an empty tree and add a root node. The root node would have lft=1 and rgt=2.

    Now you add a child to the root node: it'd have lft=2, rgt=3, and you'd need to update rgt in the root node to rgt=4.

    So you see, with nested sets, just by inserting ONE node in an almost empty tree, you need to UPDATE another node.

    Now imagine you have a 100 nodes tree, and you insert a node as a first child of the root node (a worst case scenario). You'd insert the new node as lft=2/rgt=3 AND then update lft=lft+1 where lft>1 and rgt=rgt+1 where rgt>2. That means updating at least one property in EVERY node of the tree.

    That sucks :)

    Traditional nested sets are not very good for frequently written trees. Celko describes some Nested Sets variants that are more write friendly in his Trees in Sql book. Basically, instead of having contiguous lft/rgt properties, you leave gaps. Depending on the knowledge of your trees, let's say you define a gap of 1000 between nodes, so if you insert a node, most of the time, you won't need to update other nodes. The problem with this is that you lose a lot of cool properties of traditional nested sets trees, like an O(1) way to know the number of children of a node ((rgt-lft)/2), easily finding nodes/branches, etc.

    Nested Intervals were originally proposed by Tropahsko and also suggested by Celko as a frequent insertion tree. Nested intervals are even more complicated than nested sets to understand/explain, but basically, every node also has to numbers, but instead of being “ids” in a sequence, they are used in a division, like X/Y. So let's say you have to nodes 2/5 and 3/5, how many rational numbers can you have between those 2 numbers that can be represented as the division of 2 integers? Infinite. So a number between 2/5 and 3/5 would be 4/7. This way you can insert whatever you want between 2 nodes (since modern DBs support ridiculously long integers and rational operations) without expensive reordering operations like with nested sets.

    The model you're using with CTEs is an adjacency list (AL): it has very efficient writes, but bad read performance. You're using CTEs, that means that you're not using a lot of SELECTs from your app layer (or doing expensive reorderings), but your database is still doing all those recursive JOINs on every read.

    I measured CTEs against efficient tree implementations last year for a discussion in reddit (see http://www.reddit.com/r/programming/comments/8q... ), basically:

    – non-naive (non AL) trees are several times faster than CTE powered AL trees in read operations.

    – if you need to use AL trees, CTEs are A LOT faster

    – CTEs in postgres are several times faster than CTEs in sql server :)

    - tabo

  • endeven

    Really a nice code and article here

  • Jacek Komasda

    Well, for threaded comments there is nice old trick which isn't so known. All posts should have column with its path from root comment in the form “LXLXLXLX” where L is length (one digits) of the X part. X part is L digits decimal number of ID of root post, next L,X pair is lenght of ID and ID of next post in the thread path.
    Next index on this key and sort using lexicographical ordering.
    For example simple threading structure:
    “233″ [33]
    “233235″ [33,35]
    “233235236″ [33,35,36]
    “233237″ [33,37]
    “234″ [34]
    “3101″ [101]
    “31013103″ [101,103]
    Quite simple and just works and IS FAST.
    PS. If one digit for L is not enaugh (it is enaugh for up to 1,000,000,000 – 1 posts, then one can switch to hexidecimal numbers).

  • http://www.davidcramer.net David Cramer

    What you're referring to is a materialized path, and can be handled in PostgreSQL as an array or using the ltree module.

  • http://www.air-jordan-10.com/ air jordan 10

    Well , the view of the passage is totally correct ,your details is really reasonable and you guy give us valuable informative post, I totally agree the standpoint of upstairs. I often surfing on this forum when I m free and I find there are so much good information we can learn in this forum! http://kite8.net/

  • Jacek Komasda

    Well yes, in PostgreSQl it is simpler becuase we have custom data types, array, and custom ordering rules. This adds some overhead to all posts but as far there is no rediculusly deep nesting of threads in lots of posts it is working very well.

  • http://www.operation-scarx.blogspot.com operation scar

    very nice share

  • http://www.nike-air-force-one.com Nike air force

    It looks good,I have learn a recruit!
    Recently,I found an excellent online store, the
    http://www.Vintage-Bags.net
    are completely various, good quality and cheap price,it’s worth buying!

  • John

    Interesting

  • Smthcierra

    he many challenges that await us

  • Smthcierra

    the SQL statement is 5x more performant at the database level alone.
    E66 Dual SIM
    dual sim 9700

  • http://www.chaneloutletstores.com chanel outlet

    It's wonderful to read about a female poet coming of age in this era, especially with Anne Sexton as a mentor for a short while, but so many other poetic luminaries as well. I'm also finding it encouraging to know, being 38 myself, that one can jumpstart her career at this age. Thank you for this inspiring interview, Julie Kane. http://Like-Acer.com
    write's unique point.It is useful and benefit to your daily life.You can go those
    http://www.chaneloutletstores.com

  • http://www.uggs-outlet-store.com UGG boots

    I am also a XX fan who really like this! I also like XX, and purchase lots of it every time,
    <a href=” http://www.eeadie.com“ >eeadie
    like-minded friends can have a look ,we can communicate by the way~~

  • http://www.uggs-outlet-store.com UGG boots

    I am also a XX fan who really like this! I also like XX, and purchase lots of it every time,
    <a href=” http://www.eeadie.com“ >eeadie
    like-minded friends can have a look ,we can communicate by the way~~

  • http://www.uggs-outlet-store.com UGG boots

    I am also a XX fan who really like this! I also like XX, and purchase lots of it every time,
    <a href=” http://www.eeadie.com“ >eeadie
    like-minded friends can have a look ,we can communicate by the way~~

  • http://www.air-jordan-8.com/ air jordan 8

    Well , the view of the passage is totally correct ,your details is really reasonable and you guy give us valuable informative post, I totally agree the standpoint of upstairs. I often surfing on this forum when I m free and I find there are so much good information we can learn in this forum! http://www.globalcommuni-cation.com/

  • http://game-android.blogspot.com/ Android Game

    Oh this topic… And why don't you use the nested set approach?

    http://en.wikipedia.org/wiki/Nested_set_model

    Nice to visit your site. Wish you post another good topic like this. I will wait to read it.

  • http://www.nicecargames.com Car Games

    Disqus has always been my favorite commenting system. The speed of it always amazes me.Disqus is under active development.it is a listen to user feedback.

  • http://www.nicegirlgames.com Girl Games

    I think the Disqus comment system is the best way to follow a conversation.Disqus has ability to import existing comments as well as export comments. I didn't lose any comments when I moved to Disqus.

  • http://softwaremaniacs.org/forum/django/22672/ ??????????? ???????????. NS, Mptt

    [...] 0 0 ?????????http://www.davidcramer.net/code/django/6939/scaling-threaded-comments-on-django-at-disqus.html [...]

  • http://www.nike-air-force-one.com air force 1 shoes

    I am agree with landlord, many of us are not too concerned about sports news. As the World Cup. Many of us are also don't know what it is.I believe once you go to see some sports news,you will love sports.By the way ,I know some websites content is very well.But I don’t know how to choose.Can you help me?The website are Air force 1 high

  • http://www.discount-coach-outlet.com/coach-watches.html coach clothing

    I've been looking for a similar http://www.all-carefully.net to this post. Not only extensively but also detailly. We can learn a lot from the post. I recommend to you , you can come communication in here. Let us grow up together.On the other hand ,I know some websites content is very well.you can go and see.Such as http://www.romantisongs.com

  • http://www.discount-coach-outlet.com coach outlet

    I am a gamer.When I come in the http://www.who-wanted.com post,Iloved it. Various pictures and perfect plot let me fall in love.If you love play game,you should come in.On the other hand ,there are some websites http://www.romantisongs.com content is very exciting,you can go and see.Like http://www.all-carefully.net

  • http://www.cheap-nikeshox.com/nike-shox-TL3.html air force 1 shoes

    The post of content is very interesting and exciting. I learned a lot from here.The content from simple to complex, so all of you can come in . No matter you want to see what can Nike air force be found

  • http://www.nicecargames.com Car Games

    Really a nice code and article here

  • http://netpol.eu Kasy fiskalne Gda?sk

    OO super article, I looking for that .

  • http://www.salenewbalance.com new balance

    “Here air jordan 21 products xx, has fashion model, superior quality and service, cheap price and updates quickly.I support strongly always! I want to buy XX, I hesitate to select which style more better.Hope your unique recommends.

  • http://www.mbt-outlet-store.com mbt shoes

    Thanks a landlord it! I acquired yet some insight. Life is so colorful, we should be able to live in, such as Korea and honor the planet. Human life is like rivers, slowly flowing, flowing rivers, flowing through the snow, flows through the prairie and ultimately into the sea, return to the embrace of nature, start a new reincarnation. Allow us to feel the meaning of life will come only to those you have those memories http://www.cheap-nikeshox.com/nike-shox-TL1.html

  • rob

    Hi David,

    You mentioned you do more complicated sorting at Disqus. How would you go about changing the sort order of the above example. For example if you wanted threaded comments, but sorted by author?

  • http://www.davidcramer.net David Cramer

    We stored a chunk of information in the path array, and used it like a recursive sort. So for example, you could have the array be array[author_id, id] rather than just the id.

  • ugo

    thats bad now not to much link to oure bost as befor

  • http://www.suskunsair.wordpress.com Sesli Chat Www.hasretgulu.com
  • http://yohan06.student.ipb.ac.id Yohan

    thanks for the code :)

  • http://www.stagweekends.co.uk/birmingham-weekend birmingham paintballing

    I used these for a commenting system as well, they're really quite amazing. There's basically three options when storing a tree in a relational database – adjacency lists which are slow to read, nested sets which are slow for writes, and materialized path, which is slow for moving around nodes. It's good to have a fourth option which is straightforward to implement and has excellent performance.

  • http://www.henweekends.net/nottingham-weekend nottingham hen nights

    I have threaded my eyebrows twice now, and I can handle the pain, but the place is too far to drive to. I have a little salon right next to me that I can go to to wax my eyebrows,but is it more painful than threading for those of you that have tried it?

  • timberland shoes

    now,Timberlandlive is online store that professional supply best and newest timberland mens boots,Women timberland boots and Kid’s Timberland Boots and Shoes.We have over 10 years online shopping expeciences,our timberland shoes are no wonder your best choice,we promised to offer you genuince Timberland Boots uk,waterproof boots.We are firmly hold the “Customer is God” and “Your Satisfactions,Our Pursuit”princicals,we have a good Customer service teams and best after-service.We hope our professional can satisfy your requirments.Now cheap Timberland Boots sale,We have Timberland 6 Inch Boots,timberland uk,Timberland Chukka Boots and others 2010 newest Timberland work shoes for you!It’s a good chance to order now.Hope you have a good experience on shopping form us.

  • jordan shoes

    The air Jordan brand is a household name and people of all ages and social strata line up eagerly for the release of the latest model. Some of this success can be attributed to the fact that the shoes, from the Jordan III to the most recent model, have always started with their namesake, Michael Jordan. The designers take his ideas, hobbies, and life into account and incorporate these feelings into the air jordan shoes .The “jumpman” is the logo of jordan shoes.Now, we sell cheap jordan shoes. You can find wholesale jordan shoes.for example lebron james shoes ,kobe bryant shoes ,michael jordan shoes and so on, Welcome to our homepage.

  • nike air max

    air max shoes is an extremely comfortable shoe that uses a large air cushioning unit that can be seen from the side. This technology combined with the design of the shoe which is meant to compliment the spinal cord makes. Air Max shoes the ideal shoe for walking, running, playing basketball, or any other sport. nike air max ,nike air max 2009, nike air max 95, nike air max 90 and so on.Nike introduced its Air Cushioning Technology in 1979. By embedding Air Cushioning in the midsoles of its running shoes, it changed the way athletes approached and reacted to athletic performance forever.

  • http://www.henorita.com hen parties

    I love comment on it much better than any other system. When I am searching for a blog to read, this is one of the things I am looking for.

  • http://www.printmyemotions.com variable data printing

    This adds some overhead to all posts but as far there is no ridiculously deep nesting of threads in lots of posts it is working very well…

  • china wholesale

    This collection is superb! I love all of them and http://www.cmonc.com this before and after presentation is very helpful! Thanks for sharing

  • http://www.laptopbatteriesinc.com.au/laptop-battery/hp/hp-pavilion-dv2000-battery hp batteries

    Celko describes some Nested Sets variants that are more write friendly in his Trees in Sql book. Basically, instead of having contiguous lft/rgt properties, you leave gaps. Depending on the knowledge of your trees, let’s say you define a gap of 1000 between nodes, so if you insert a node, most of the time, you won’t need to update other nodes.

  • http://www.freecomputerrepairservices.com/software/ten-free-registry-repair-software-reviews.html free registry repair

    I’v seen many blog installed disqus, i think this is a good idea, could save people’s time without registry much user name when post a comment,

  • http://www.laptopbatteriesinc.com.au/laptop-battery/dell/dell-inspiron-6400-battery Dell Inspiron 6400 battery

    so nice post,disqus is an excellent systerm,i like it very much.

  • http://www.mmbatteries.com laptop battery

    for example, calculates information based on a liking pattern and datetime information. This is a much more complicated query than shown above (via the recursion), but still doable.

  • http://www.jerseyoem.com/ NFL jerseys

    can anyone explain to me what is that Django?

  • http://www.mmbatteries.com laptop battery

    This adds some overhead to all posts but as far there is no rediculusly deep nesting of threads in lots of posts it is working very well.

  • http://www.ibsi-us.com IB Systems

    great points… to me DISQUS is the greatest invention for bloggers and social netwrking

  • http://socialsubmit.info social bookmarking service

    You’re using CTEs, that means that you’re not using a lot of SELECTs from your app layer (or doing expensive reorderings), but your database is still doing all those recursive JOINs on every read.but when they start to peak we end up wasting a lot of time.

blog comments powered by Disqus