我在读Hadoop:汤姆·怀特的权威指南。在第13.6章"HBase vs RDMS“中,他说,如果您有大量的数据,即使是像最近获得10项这样的简单查询也是非常昂贵的,它们必须使用python /SQL重写它们。
他以以下查询为例:
SELECT id, stamp, type FROM streams
WHERE type IN ('type1','type2','type3','type4',...,'typeN')
ORDER BY stamp DESC LIMIT 10 OFFSET 0;并说:“RDBMS查询计划器将此查询处理如下:
MERGE (
SELECT id, stamp, type FROM streams
WHERE type = 'type1' ORDER BY stamp DESC,
...,
SELECT id, stamp, type FROM streams
WHERE type = 'typeK' ORDER BY stamp DESC
) ORDER BY stamp DESC LIMIT 10 OFFSET 0;这里的问题是,我们只需要前10个is,但是查询计划器实际上实现了整个合并,然后在最后进行限制。……实际上,我们甚至编写了一个执行堆排序的定制PL/Python脚本。..。几乎在所有情况下,这都优于本机SQL实现和查询计划器的策略.
预期穿孔与专家结果
我无法想象数据集会导致这样的问题,您必须编写pl/python才能正确地进行这样简单的查询。因此,我对这个问题进行了一段时间的讨论,并提出了以下观察:
这类查询的性能受O(KlogN)限制。因为它可以被翻译成这样,如下所示:
SELECT * FROM (
SELECT id, stamp, type FROM streams
WHERE type = 'type1' ORDER BY stamp DESC LIMIT 10,
UNION
...,
SELECT id, stamp, type FROM streams
WHERE type = 'typeK' ORDER BY stamp DESC LIMIT 10
) t ORDER BY stamp DESC LIMIT 10;(请注意每个查询的“限制10”。顺便说一句,我知道我不能限制和订购联合,但为了可读性,我已经去掉了包装选择)
每个子查询的运行速度应该与在索引O(logN)中找到正确位置并返回10个项一样快。如果我们重复K次,我们得到O(KlogN)。
而且,即使查询计划器太差,以至于无法优化第一个查询,我们仍然可以将其转换为带有联合的查询,并获得所需的性能,而无需在pl/python中写入任何内容。
为了再次检查我的计算,我在一个postgresql上面运行了包含9,000,000个测试记录的查询。结果证实了我的预期,第一次查询为100 my,第二次查询为300 my(有工会的查询)。
因此,如果对9,000,000 (logn=23)记录的查询在100 it内运行,那么对于9,000,000,000 (logn=33)记录,它应该在140 it中运行。
问题
您看到上述推理中有什么缺陷吗? pl/python?
发布于 2010-11-27 16:36:04
他们关于RDMBS查询计划器将该解决方案用于查询的断言是不正确的,至少对于Postgresql 9.0是这样,我也可以想象其他平台也是如此。我用类似的查询做了一个快速测试:
explain select * from client_attribute where client_attribute_type_code in ('UAG', 'RFR', 'IPA', 'FVD') order by client_attribute_id desc limit 10;
QUERY PLAN
-----------------------------------------------------------------------------------------------------------------------
Limit (cost=0.00..0.93 rows=10 width=85)
-> Index Scan Backward using client_attribute_pkey on client_attribute (cost=0.00..15516.47 rows=167234 width=85)
Filter: (client_attribute_type_code = ANY ('{UAG,RFR,IPA,FVD}'::bpchar[]))
(3 rows)在这里,client_attribute_id是索引的,所以它完全按照需要执行--遍历索引,应用过滤器,并在输出达到极限时停止。
如果未对排序列进行索引,则表扫描和排序将被请求,但只有一个表扫描:
explain analyze select * from client_attribute where client_attribute_type_code in ('UAG', 'RFR', 'IPA', 'FVD') order by updated desc limit 10;
QUERY PLAN
---------------------------------------------------------------------------------------------------------------------------------------
Limit (cost=13647.00..13647.03 rows=10 width=85) (actual time=180.961..180.964 rows=10 loops=1)
-> Sort (cost=13647.00..14065.09 rows=167234 width=85) (actual time=180.960..180.961 rows=10 loops=1)
Sort Key: updated
Sort Method: top-N heapsort Memory: 26kB
-> Seq Scan on client_attribute (cost=0.00..10033.14 rows=167234 width=85) (actual time=0.010..106.791 rows=208325 loops=1)
Filter: (client_attribute_type_code = ANY ('{UAG,RFR,IPA,FVD}'::bpchar[]))这使用堆排序,通过顺序扫描来维护前十名的结果,这听起来就像他们自己写的解决方案。
发布于 2010-11-26 23:11:53
我不认为that是在说关系数据库是“坏的”;对于非关系的、非基于集合的数据,它们并不是最优的。
很长一段时间以来,深对象图不能很好地用于关系数据库,这是众所周知的。它们通常出现在一些问题中,比如几何数据的CAD表示,其中组件是由零件的组件组成的。参考链确实很长。
对象和图形数据库自从我在90年代初意识到它们以来,就一直是解决这类问题的方法。
关系数据库对于基于关系的基于集合的数据来说是很棒的.但并不是所有的数据都属于这一类。这就是为什么NoSQL正在获得思想分享的原因。
我认为这就是你所举的例子。
发布于 2010-11-26 23:31:51
RDBMS用于您没有想到的查询。一旦你完全确定了你想要的东西,你就可以应用最优的解决方案。
https://stackoverflow.com/questions/4289079
复制相似问题