2

我需要在 SQL 中存储十亿个直方图。这些直方图具有相同的桶,但它们的计数可能有很大的变化,但是,大多数桶很多时候都是 0。

我最初的尝试是为每个直方图设置一行,其中每列代表一个桶。

我对我的数据类型非常小心,但表看起来仍然超出了为其分配的存储空间。

我想知道在我必须请求更多硬件之前,是否有人遇到过在 MS SQL 中存储值范围(其中 0 是最常见的情况)的有效解决方案。

提前致谢。

总。

4

4 回答 4

6
CREATE TABLE Histogram (
    HistogramID BIGINT /* INT only goes to 2bn */ IDENTITY NOT NULL CONSTRAINT PK_Histogram PRIMARY KEY
    -- Other metadata like the date and time or whatever
)

CREATE TABLE Bucket (
    BucketID INT /* or smaller */ IDENTITY NOT NULL CONSTRAINT PK_Bucket PRIMARY KEY
    -- Other metadata like the range it applies to
)

CREATE TABLE HistogramValue (
    HistogramID BIGINT NOT NULL
    ,BucketID INT NOT NULL
    ,Counter BIGINT /* or smaller datatype */ NOT NULL
    ,CONSTRAINT PK_HistogramValue PRIMARY KEY (HistogramID, BucketID)
    ,CONSTRAINT FK_Histogram FOREIGN KEY REFERENCES Histogram(HistogramID)
    ,CONSTRAINT FK_Bucket FOREIGN KEY REFERENCES Bucket(BucketID)
)

HistogramValue表将是稀疏的。Bucket您可以将表格从表格左连接到HistogramValue特定直方图的表格以获得“整个”直方图:

SELECT b.Range
       ,COALESCE(hv.Counter, 0) AS Counter
FROM Bucket b
LEFT JOIN HistogramValue hv
    ON hv.HistogramID = @HistogramID
    AND hv.BucketID = b.BucketID

这是一个典型的标准化模型,相对容易维护、加载和导出。

于 2013-03-11T17:45:03.470 回答
2

从数据管理的角度来看,直方图是原子的吗?我的意思是:您是否总是将整个直方图作为数据库中的一个不可分割的单元来读取或写入?

如果,只需将其序列化为 BLOB。您甚至可以在写入 BLOB 之前通过一些压缩库将其扫过,这是一个很好的衡量标准。

如果没有,请考虑使用以下内容:

CREATE TABLE HISTOGRAM (
    HISTOGRAM_ID int PRIMARY KEY
    -- Other fields...
);

CREATE TABLE HISTOGRAM_VALUE (
    HISTOGRAM_ID int REFERENCES HISTOGRAM (HISTOGRAM_ID),
    BUCKET_NO smallint,
    VALUE decimal NOT NULL, -- Or whatever type is appropriate.
    PRIMARY KEY (HISTOGRAM_ID, BUCKET_NO)
);

(注意:如果你绝对肯定你永远不需要超过 256 个桶,你甚至可以使用tinyintfor BUCKET_NO,以挤出更多的空间效率。)

请记住,InnoDB 表始终是集群的,所以HISTOGRAM_VALUE上面的表只是一个 B-tree,没有表堆或其他 B-tree(因为没有二级索引 - FOREIGN KEY 可以直接从主索引满足)。这与使用 InnoDB 表获得的存储效率差不多。

为了节省空间,只需省略值为 0 的桶,除非直方图以这样的桶开始或结束。例如...

0   0   14.7    -12.9   0   0   55.1    0   0   0

...可以表示为:

HISTOGRAM_ID    BUCKET_NO    VALUE
1               1            0
1               3            14.7
1               4            -12.9
1               7            55.1
1               10           0
于 2013-03-12T10:22:40.563 回答
1

在任何其他情况下,我都不会想到建议这样做,但由于空间是这里最重要的问题,你可能想尝试一下......

将每个直方图存储在单个 varchar 字段中可能是有效的,每个桶中的数量由一些分隔符分隔,例如

“1,,23,,,789789789” 表示第一个存储桶中的 1,第二个存储桶中的 0,依此类推。

于 2013-03-12T08:55:25.017 回答
1

Actually, we can solve this question by creating only one table. If create more than one tables, we must use join operator. It is ineffective to get the histogram we want when we need to use it.

CREATE TABLE HISTOGRAM_VALUE
{
  HISTOGRAM_ID INT,
  BUCKET_ID INT,
  BUCKET_MIN_VALUE INT,  //or whatever value type you want
  BUCKET_HEIGHT INT,
  // other metadata
  PRIMARY KEY(HISTOGRAM_ID,BUCKET_ID,BUCKET_MIN_VALUE)
};

the BUCKET_MIN_VALUE is the min_value (or we can understand the left boundary of a bucket range) of each bucket.

于 2016-12-08T07:07:33.893 回答