使用英语很难描述这个问题,所以我将给出一些例子.
我有一张名为Games的桌子.每个游戏由游戏编号和玩家组成,分为两列:GameNum,PlayerNum.
我的问题是,我想选择那些只参加过比赛的球员,而不是其他人.
以下是一些示例数据:
GameNum PlayerNum
1 100
1 101
2 102
2 103
3 102
3 104
4 105
4 106
5 106
5 107
6 100
6 101
Run Code Online (Sandbox Code Playgroud)
我想找回结果:
PlayerNum1 PlayerNum2
100 101
Run Code Online (Sandbox Code Playgroud)
这是因为我们可以看到玩家100和101是唯一一个彼此玩游戏的玩家,而没有其他玩家.102也玩了104,所以我们排除102和104.虽然105只玩了106的游戏,106也玩了107游戏,所以我们排除玩家105和106(因此107)的结果.这让我们只有玩家100和101.
每个GameNum只会在表格中出现两次(即每个游戏总是会有两个玩家).另请注意,我们并不关心玩家是否一起玩过多个游戏(例如GameNum 1和6) - 前提是他们只是互相玩过这些游戏.
我尝试使用min/max进行类似下面的查询,但我无法弄清楚如何排除与其他玩家玩过游戏的玩家.
SELECT *
FROM
(
SELECT AU1.PlayerNum AS PlayerNum1, AU2.PlayerNum AS PlayerNum2
FROM
(
SELECT GameNum, MIN(PlayerNum) AS PlayerNum
FROM GAMES
GROUP BY GameNum
HAVING count(GameNum) = 2
) AU1
INNER JOIN
(
SELECT GameNum, MAX(PlayerNum) …Run Code Online (Sandbox Code Playgroud) 问题
最近,我一直在考虑如何抓取某个大型跨国网站的内容,以获取该公司出售的产品的具体详细信息。该网站没有 API,但您可以通过将带有产品 ID 的 GET 请求发送到特定 URL 来下载每个产品的一些 XML。所以至少是这样。
问题在于,可能存在数亿个潜在产品 ID(例如,000000001 到 500000000 之间),但实际存在的产品只有几十万个。而且不可能知道哪些产品 ID 是有效的。
方便的是,向产品 URL 发送 HEAD 请求会根据产品 ID 是否有效(即产品实际存在)产生不同的响应。一旦我们知道该产品确实存在,我们就可以下载完整的 XML 并从中获取所需的数据位。
显然,如果在单个服务器上运行,发送数亿个 HEAD 请求将花费大量时间才能完成,因此我想借此机会学习如何开发某种分布式应用程序(对于我)。在这一点上,我应该提到这个特定的网站可以轻松地每秒处理大量传入请求,而不会出现 DOS 风险。我不想透露该网站的名称,但它每天很容易获得数百万次点击。该抓取工具对网站性能的影响可以忽略不计。不过,如果公司投诉,我会立即制止。
该设计
我不知道这是否是正确的方法,但我当前的想法是启动一个“协调服务器”,以及一些与该服务器通信并执行抓取的节点,所有这些都作为 EC2 实例运行。
每个节点将启动一定数量的进程,并且每个进程将由协调服务器指定一个作业,其中包含要抓取的不同范围的潜在产品ID(例如产品ID 00001 到10000)。这些作业将存储在协调服务器上的数据库表中。每个作业将包含以下信息:
当节点启动时,查询将被发送到协调服务器,询问一些配置数据以及要处理的作业。当节点完成作业时,将发送一个查询来更新刚刚完成的作业的状态,并发送另一个查询来请求执行新作业。每个作业都有一个到期时间,因此如果进程崩溃,或者节点因任何原因发生故障,另一个节点可以接管过期的作业并重试。
为了最大限度地提高系统性能,我需要计算出应立即启动多少个节点、每个节点有多少个进程、发送 HTTP 请求的速率以及哪种 EC2 实例类型将提供最大的性价比(我猜测高网络性能、高 CPU 性能和高磁盘 I/O 将是关键因素?)。
目前,计划是用 Python 编写抓取工具,在 Ubuntu EC2 实例上运行,可能在 Docker 容器中启动,并使用某种键值存储数据库来保存协调服务器(MongoDB?)上的作业。关系数据库也应该可以工作,因为作业表的 I/O 应该相当低。
我很想知道更有经验的工程师这是否是正确的方法,或者我是否完全忽略了完成此任务的更好方法?
非常感谢,谢谢!