我们的系统面临从 3800 万行表中选择行的性能问题。
这个包含 3800 万行的表存储来自客户/供应商等的信息。这些信息出现在许多其他表中,例如 Invoices。
主要问题是我们的数据库远未标准化。Clients_Suppliers 表有一个由 3 列组成的复合键,即 Code - varchar2(16)、Category - char(2),最后一个是 up_date,一个日期。一个客户地址的每一次更改都存储在同一个表中,并带有一个新的日期。所以我们可以有这样的记录:
code ca up_date
---------------- -- --------
1234567890123456 CL 01/01/09
1234567890123456 CL 01/01/10
1234567890123456 CL 01/01/11
1234567890123456 CL 01/01/12
6543210987654321 SU 01/01/10
6543210987654321 SU 08/03/11
最糟糕的是,在每个使用客户信息的表中,而不是完整的复合键,只存储代码和类别。例如,发票有自己的密钥,包括发行日期。所以我们可以有这样的东西:
invoice_no serial_no emission code ca
---------- --------- -------- ---------------- --
1234567890 12345 05/02/12 1234567890123456 CL
我的具体问题是我必须生成在给定期间为其创建发票的客户列表。由于我必须从客户那里获取最新信息,因此我必须使用 max(up_date)。
所以这是我的查询(在 Oracle 中):
SELECT
CL.CODE,
CL.CATEGORY,
-- other address fields
FROM
CLIENTS_SUPPLIERS CL
INVOICES I
WHERE
CL.CODE = I.CODE AND
CL.CATEGORY = I.CATEGORY AND
CL.UP_DATE =
(SELECT
MAX(CL2.UP_DATE)
FROM
CLIENTS_SUPPLIERS CL2
WHERE
CL2.CODE = I.CODE AND
CL2.CATEGORY = I.CATEGORY AND
CL2.UP_DATE <= I.EMISSION
) AND
I.EMISSION BETWEEN DATE1 AND DATE2
选择 178,000 行最多需要 7 个小时。Invoices 在 DATE1 和 DATE2 之间有 300,000 行。
这是一个(非常、非常、非常)糟糕的设计,我提出了我们应该通过规范化表格来改进它的事实。这将涉及为客户端创建一个表,其中每对代码/类别有一个新的 int 主键,另一个用于 Adresses(客户端主键作为外键),然后在每个相关的表中使用 Adresses 的主键给客户。
但这意味着要改变整个系统,所以我的建议被回避了。我需要找到一种不同的方法来提高性能(显然只使用 SQL)。
我尝试过索引、视图、临时表,但没有一个对性能有任何显着改善。我没有想法,有人有解决方案吗?
提前致谢!