--

BDMS 的数据访问



SQL 的 query

假设你有这么几个 data table:


1. Bar
  name(primary key)
  addr
  license


2. Beers
   name(primary key)
   manf


3. Sells
   bar
   beer
   price



4. Drinkers
   name
   addr
   phone



5. Frequents
   drinker
   beer



6. Likes
   drinker
   beer

利用 SQL 我们可以
1. 获取 heineken 生产的所有啤酒产品
  
SELECT name FROM Beer WHERE manf = 'heineken'


2. 获取所有的高价啤酒
  
SELECT DISTINCT beer, price FROM Sells WHERE price > 15


3. 获取所有在 San Diago 以及执照上时间为32 的酒吧
  
SELECT name FROM Bars WHERE addr LIKE '%SD%' AND license LIKE '32%' LIMIT 5

BDMS query

但是 BDMS 中,数据会非常多,而且会被划分到不同的机器上去,这时如何进行查询?

Beers table 被按照一定的序列分配在了不同的机器上(range partition),比如,
以字母A - B 打头的分配在第一台机器,C - D 分配到第二台机器,E 分配到了第三台、第四台机器上

1. 获取所有以Am 打头的 Beer 产品
由于我们已经知道了 partitioning 的规则,我们知道以A 打头的 beer 都在partition 1,所以我们只要在partition 1 进行querey

2. 获取所有 heineken 生产的 啤酒产品
我们对每一个parition 进行query,然后把所有的结果合起来。

3. 找到 那些最喜欢 Great American Bar 的客户最常喝的啤酒
  
SELECT DISTINCET beer FROM Likes L, Frequents F WHERE F.bar = 'Great American Bar' AND F.drinker = L.drinker
这里用的是一个临时的 join table 的数据,然后在这个临时的 join 数据上进行下一步操作。

但是如果是在一个分布式系统中,要用到的是semijoin,完成的操作步骤如下:
1. Project R on attribute A and call it R[A] -- the drinkers column
2. Ship this projection (a semijoin projection) from the site of R to the site of S
3. Reduce S to S' by eliminating tuples where attribute A are not matching any value in R[A]

  
SELECT L.beer from Likes L, Frequents F 
WHERE 
  F.bar = 'Great American Bar' 
  AND F.drinker = L.drinker



这里完成的是 F.drinker = L.drinker 一步。
因为 F 和 L 在不同的机器上,
1. 从 F 当中 project 出一个 drinker 的 子 table
2. 把来自于 F 的 drinker 子数据table 从 F 所在的机器上转移到 Likes 所在的机器上
3. 对 L table 完成 = 的比较操作,获得进一步操作后的数据

sub query

我们要是想要完成一个查询:
找到符合条件的酒吧,在这些酒吧里,他们卖的miller 啤酒的价钱要比 TBAG酒吧里 bud 的售价便宜。
我们可以分两步完成这个查询:
1. 找到 TBAG 酒吧的 bud的售价
2. 找到 符合条件的酒吧(miller 售价比1 要便宜)

  
SELECT bar FROM Ssells 
WHERE 
  beer = 'Miller' 
  AND
  price <= (
    SELECT price FROM Ssells WHERE bar = 'TBAG' AND beer = 'bud')


再来一个较为复杂的例子:
找到酒吧里那些售价高于该酒吧啤酒售价平均值的酒和价格
  
SELECT beer, price FROM Ssells s1
WHERE price > 
  (SELECT AVG(price) FROM Sells s2
  WHERE s1.bar = s2.bar)