Jef*_*eff 4 database performance scaling join
我目前正面临一个性能(它可能会导致以后的缩放问题)问题。我正在处理的应用程序非常复杂,它在 SQL Server 2005 上运行。我需要连接 6-7 个表才能获得所需的数据。到目前为止,每个表包含超过 100,000 行数据。数据库架构不能更改(必须保持原样)。所以我只能尽量优化。我想到了两件事:
尽量不要加入数据库,让应用服务器使用 LINQ 进行过滤:
应用服务器保持原样并尽可能优化 SQL 查询(更多索引、频繁重建索引等):
基本上缓存目前不是我的解决方案(硬件问题,托管问题等),这就是我最初没有提出它的原因。但我确实知道缓存会给我带来什么好处,并且已经多次使用它。
一般来说,在DBMS中进行加入。如果您在应用程序服务器中执行此操作,那么您肯定会比编写 DBMS 的人在优化连接方面做得更好,并且(进一步)您可以通过足以抵消其成本来超越他们的最大努力通过网络传输未连接的数据。
现在,如果您要对两个宽表(假设它们是 T1,宽度为 W1 的 N1 行,宽度为 W1 的 N1 行和宽度为 W2 的 N2 行的 T2)进行交叉乘积,那么 DBMS 必须创建并通过线路发送 N1 * N2 * (W1 + W2) 字节的数据,而您可以将表格分别作为 N1 * W1 + N2 * W2 字节的数据进行处理。如果 N1 = N2 = 1M 且 W1 = W2 = 100,那么 200 TB 与 200 MB 的数据传输有利于在应用服务器中进行交叉产品。但这对 DBMS 并不完全公平。大多数查询都不是那么愚蠢——它们加入列并应用条件,并且 DBMS 优化器将竭尽全力(并且自动地)尽量减少已完成的工作。此外,它只会将相关数据发回给您;它不必发送与您的条件不匹配的所有行。
为了展示另一种情况(有利于 DBMS),考虑这样一种情况,其中 T1 有 N1 = 1M 行,宽度 W1 = 100,但 T2 有 N2 = 100K 行,宽度 W2 = 50。两个表之间有一个连接一个整数列,因此,对于 T2 中的每一行,T1 中有 10 行。假设您将所有 T1 和 T2 都下载到应用服务器:这需要 N1 * W1 + N2 * W2 = 105 MB 的数据。但是过滤条件将数据限制为 T2 中行的 1/10,并且对于与 T2 中的一行匹配的 T1 中的每一行,实际上只有 2 行与过滤条件匹配。现在 DBMS 将只传输 N2 * (W1 + W2) / 5 = 3 MB,DBMS 节省了超过 100 MB 的数据传输。现在,如果您设法聪明地仅下载与 T2 中的值对应的 N2 * W2 / 10 = 500 KB 数据,您仍然需要让 DBMS 对您想要从 T1 获取正确行到应用服务器的值执行 T1 的“半连接”。如果您只需要列的一个子集,则可以节省另一组。DBMS 往往有相当聪明的排序包;你需要在你的应用服务器中使用一个好的排序包来以正确的顺序显示数据。
对于加入 DBMS 来说,这通常应该是一个不折不扣的胜利。如果不是,那是因为您要求服务器做的工作超出了它的处理能力。在这种情况下,您需要查看复制数据库服务器是否有意义,或者添加更多内核、更多网络带宽或更多主内存是否可以完成这项工作。