1

假设我有一张表,上面有 5 个可以为空的外键。对于每一行,其中只有 1 个具有值。

现在,这个表已经增长了很多,并且包含了大约 220 万条记录。

在大多数情况下,我只对查询表 cq 的“部分”感兴趣,即某个可为空的外键具有值的那些记录。毫不奇怪,仅获取所需的子集需要很长时间,使用下面的查询:28 秒来获取一个特定子集的 1.7m 条记录。

SELECT * FROM Table WHERE Col IS NOT NULL

我真的对如何加快速度非常感兴趣,尤其是在不更改数据模型的情况下是否可以实现这一点。

4

4 回答 4

1

如果我无法更改基表,我将创建一个 VIEW 将五个非规范化列转换为两列:origin 和 value。所以假设你有这个:

Table notNormal (
primaryKey,
someValue,
foreignNotNormal01,
foreignNotNormal02,
foreignNotNormal03,
foreignNotNormal04,
foreignNotNormal05
)

我会创建这个:

CREATE MATERIALIZED VIEW fixedThis AS
SELECT primaryKey, someValue, 'FKCOL01' AS foreignNotNormalOrigin, foreignNotNormal01 AS foreignNotNormalColValue
WHERE foreignNotNormal01 IS NOT NULL
UNION
 ...
 ...
SELECT primaryKey, someValue, 'FKCOL01' AS foreignNotNormalOrigin, foreignNotNormal05 AS foreignNotNormalColValue
WHERE foreignNotNormal05 IS NOT NULL

然后我对 fixedThis 的 SELECTS 只显示外键列中的值的结果,无论它们可能是什么。

如果您只是想要一个简单的加速,那么索引是可行的方法,但实际上,您需要修复数据模型。

于 2013-03-06T13:44:49.207 回答
1

唯一可以加速的东西

SELECT * FROM Table WHERE Col IS NOT NULL

是上校的索引。

但是,将 170 万条记录从服务器传输到数据库客户端可能需要一段时间,尤其是通过网络传输时。您唯一能做的就是减少您发送的数据量,例如仅在 SELECT 中指定您需要的字段。

于 2013-03-06T13:34:22.227 回答
0

如果您要根据这些表是否为空来对数据进行分区,您可能会加快速度——所有数据Col != NULL都将位于一个分区中。当然,这假设这 5 列是该表中最重要的部分。

CREATE PARTITION FUNCTION MyCol1 (int)
AS RANGE LEFT FOR VALUES (NULL)

CREATE PARTITION SCHEME MySchemeForCol1
AS PARTITION MyCol1
TO Col1FileGroup

不过,重构表会有所改善,而且我会在投入太多时间对数据进行分区之前先去那里。像这样的分区仍然会将事物保留在同一个表中,但会在磁盘上隔离......但是将表重构为一系列链接表可能会更划算。

但是,如果您对分区有任何运气,请让每个人都知道并发布解决方案。

于 2013-03-06T18:59:15.503 回答
0

您是否尝试过将该表与相关外键引用的另一个表连接起来?这将删除外键为空的所有条目。
我希望加入运行非常缓慢,但您可能会感到惊喜。

另外,您是否有相关外键的索引?

于 2013-03-07T20:41:08.667 回答