创建一个实现Disqus评论模版的MySQL模型

在很长一段时间内,PostgreSQL都被认为是MySQL的替代品。但是,在那段时间里,根本没有办法使他达到MySQL所能达到的水平。最近几年里,这些问题都无法解决,并且产生了许多有趣的工具来弥补PG。我们在Disqus中使用了两个Slony和pgbouncer。Slony让我们可以复制数据(有时候也可以分区),而pgbouncer为我们解决了保持链接和连接池的问题。

另外,让我们看看他们的语言:我这个星期很高兴能够学会如何在PGSQL8.4中使用递归查询,他们实在太强大了。这就是我这篇文章所真正想要和大家讨论的东西。MySQL让我们可以工作,并且工作的很好,但你只能在引擎的结构内完成。虽然在PG中依然如此,但你有了更多的选择。因此,我想讲讲树的线索化的问题。

大家都知道Disqus不仅仅是最大的Django网站(我们每个月有近100万的访问量),同时,他也是他也是一个最大的网上评论系统。我们为上千个网站提供了许多功能,最基本的就是评论作为树状结构的线索化。

PostgreSQL提供了许多个关于线索化的解决方案。最常用的(也是最高效的)方法就是改良版的前序遍历。简单的说,他增加了一个左序,一个右序,他们会在你添加评论时被更新。我们还有另一个标准的方法(Reddit使用的很欢乐),那就是“取出所有的东西,然后在内存中完成操作”。实际上,不仅仅只有Reddit这样做。

继续看看PGSQL为我们提供的东西,我们还可以找到两个选项(最低在8.4版本)。其中一个是使用PG的内建模块称为ltree。他允许你将一个节点的完整路径(所有父结点)存储下来,同时允许你通过标准的sql语句查询他们。当你需要按照“最早发布”排序的时候,它会非常有用,因为这样以来,就变为了简单的按照“ltree——column”排序。然而,和大部分时候一样,Disqus的情况没有这么简单。

我们的第二个解决方案就是递归查询。他花了我很长一段时间来理解他是怎么工作的,但是当我理解后,我被他的能力深深的吸引了。Postgre提供了许多MySQL所没有的特性,比如over()修饰符。他们真的表现的非常好。

让我们继续深入我们的问题,这会是一个大问题。现在,Disqus和Reddit处理多线程的方法一样,都是和网上其他的解决方案一样,非常的简陋。我说的是简陋不是说代码写的不好,而是他的优化没有做到他应该做到的。直到某些人(就是你,Obama同学)开始使用这个程序,并且所有人都想回复他的话,我们才发现出问题了。我们再一次想到了Django(即使他们越来越大)并且通过业务逻辑将他们分组。

自从8.4开始,我们就可以使用递归查询来解决这个问题(在许多情况下我们已经自己开始这么做了,虽然会有点复杂)这个相当的简单。

因此,让我们一个基本的例子。我们有一个的评论模型,它看起来有点像这样:

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);

我们现在所做的,是建立一个基本的评价模型。我们的消息,笔者父评论(这是可选的)。现在,让我们来学习如何使用递归查询可以轻松地重新订购本datd中,由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;

很甜蜜吧?哦,等等,有困惑?所以我一直在寻找的查询更复杂的是一大堆惊人的bug.
pgexperts为我们指向正确的道路。

现在,我不会钻到太多,因为有更好的教程,在此模式中处理递归查询,但我们完成了我们的结果。

我们要处理一个巨大信息集,并且有些评论有将近几千个回复。如果99%的评论都只有100个回复,那么将他们放入内存中并不是什么问题,但当他们开始增加时,我们最终会浪费很多时间。PGSQL中的递归查询可以让我们很简单的把这项工作交给数据库(有时候他们处理的比我们快的多),并且给我们节省了很多花费在网络传播和web处理的时间和资源。

有一个例子可以让你更直观的理解他是多么的高效,我们曾经见过仅在大型数据库的SQL处理时间这一项上(返回25个结果,而不是1000个)就将近节省了500%的时间。这甚至没有包括我们在程序级上的花费。是的,没错,这些SQL语句仅在数据库层上就比其他数据库快5倍

总而言之,作为一个MySQL的拥护者,我对Disqus使用PostgreSQL所达到的性能,规模,以及灵活性表示十分震惊。我十分期待去发现通过这个平台我们还能做什么,去寻找还在等待我们的挑战。

(0)

相关推荐

  • 创建一个实现Disqus评论模版的MySQL模型

    在很长一段时间内,PostgreSQL都被认为是MySQL的替代品.但是,在那段时间里,根本没有办法使他达到MySQL所能达到的水平.最近几年里,这些问题都无法解决,并且产生了许多有趣的工具来弥补PG.我们在Disqus中使用了两个Slony和pgbouncer.Slony让我们可以复制数据(有时候也可以分区),而pgbouncer为我们解决了保持链接和连接池的问题. 另外,让我们看看他们的语言:我这个星期很高兴能够学会如何在PGSQL8.4中使用递归查询,他们实在太强大了.这就是我这篇文章所真

  • 如何创建一个创建MySQL数据库中的datetime类型

    目录 一.domain用法及示例 二.创建MySQL中datetime类型 三.create type用法及示例 环境系统平台:Microsoft Windows (64-bit) 10版本:4.5 瀚高数据库中支持使用以下语句创建用户定义的数据类型: ​CREATE DOMAIN​:它创建了一个用户定义的数据类型,可以有可选的约束,基于其他基本类型,实质是定义一个域. ​CREATE TYPE​:它通常用于使用存储过程创建复合类型(两种或多种数据类型混合的数据类型). 一.domain用法及示

  • 亲手教你怎样创建一个简单的mysql数据库

    目录 一.创建数据库 二.创建数据库 什么是数据库?数据库是存放数据的“仓库”,维基百科对此形象地描述为“电子化文件柜”. 什么是数据库管理系统?数据库管理系统是操纵和管理数据库的软件.我现在学习的数据库管理系统是Mysql,它属于关系型数据库管理系统,目前被普遍使用.关系型数据库是由相互联结的二维表格组成的数据库. 学习java到数据库操作章节后发现没有数据库,折腾了1天总算弄好了学习所需要的数据库,感觉好开心. 一.创建数据库 注:已经安装好mysql. windows下运行cmd进入命令窗

  • java如何创建一个jdbc程序详解

    JDBC简介 Java数据库连接(Java Database Connectivity,JDBC),是一种用于执行SQL语句的Java API,它由一组用Java编程语言编写的类和接口组成. JDBC为数据库开发人员提供了一个标准的API,使他们能够用纯Java API来编写数据库应用程序. 使用JDBC编写的程序能够自动地将SQL语句传送给相应的数据库管理系统. JDBC扩展了Java的功能,由于Java语言本身的特点,使得JDBC具有简单.健壮.安全.可移植.获取方便等优势. 我们在没有JD

  • oracle创建一个数据库三步走

    以前开发的时候用得比较多的是mysql和sql server,oracle用的比较少,用起来比较生疏,mysql和sql server用起来比较类似,就oracle的使用方式和他们不同,oracle在创建数据库的时候要对应一个用户,数据库和用户一般一一对应,mysql和sql server 直接通过create databse "数据库名" 就可以直接创建数据库了,而oracle创建一个数据库需要以下三个步骤: 创建两个数据库的文件 创建用户与上面创建的文件形成映射关系 给用户添加权限

  • jquery创建一个ajax关键词数据搜索实现思路

    在web开发过程当中,我们经常需要在前台页面输入关键词进行数据的搜索,我们通常使用的搜索方式是将搜索结果用另一个页面显示,这样的方式对于搭建高性能网站来说不是最合适的,今天给大家分享一下如何使用 jQuery,MySQL 和 Ajax创建简单和有吸引力的 Ajax 搜索,这是继<使用jQuery打造一个实用的数据传输模态弹出窗体>第二篇jquery项目实际运用的教程,希望大家在开发项目的时候能够根据自己的实际情况灵活运用 点击搜索默认显示所有的结果 输入A之后显示的搜索结果 输入 p之后显示的

  • pycharm+django创建一个搜索网页实例代码

    本文主要研究的是pycharm+django创建一个搜索网页的实例代码,具体步骤和代码示例如下. 创建工程 比如,我创建的工程目录结构如下: 命令行 进入windows命令行,进入根目录: python manage.py startapp django_web 接着你会在pycharm中发现,多了一个django_web文件夹.如下将截图: 创建一个test.html <!DOCTYPE html> <html> <head> <title>开始搜索<

  • 使用.NET Core3.0创建一个Windows服务的方法

    在.NET Core 3.0 中,我们引入了一种名为 Worker Service 的新型应用程序模板.此模板旨在为您在 .NET Core 中编写长时间运行的服务的提供一个起点.在本演练中,我们将创建一个 worker 并将其作为 Windows 服务运行. 创建一个 Worker 注意:在我们的预览版中,worker 模板与 Web 模板位于同一级菜单中.这将在未来的版本中发生变化.我们打算将 Worker Service 模板直接放在"创建新项目"菜单中. 在 Visual St

  • IDEA 中 30 秒创建一个 Spring Cloud Alibaba 工程

    如果你想使用 Spring Cloud Alibaba,那么你遇到的第一个问题一定是如何快速的创建一个脚手架工程. 近日,阿里巴巴发布了 Spring 的国内脚手架定制版 Aliyun Java Initializer,因为全中文界面和流畅速度,被广大开发者热传.Spring 脚手架为开发者提供了丰富的可选组件,并且可以选择多种打包方式,大大方便了开发人员的使用.Web 端 Spring 脚手架可以帮助用户快速上手,但很多开发者也面临一个问题:在 Web 版本 Spring 脚手架生成工程最终要

  • 如何创建一个Flask项目并进行简单配置

    安装的依赖包 flask pymysql flask_script flask_migrate flask_sqlalchemy 创建Flask项目(项目目录结构) flaskexample |---static |---templates |---app.py 在项目下创建settings文件,进行配置 setting.py class DevelopmentConfig: DEBUG = True SQLALCHEMY_DATABASE_URI=mysql+pymysql://用户:密码@h

随机推荐