【发布时间】:2010-12-17 12:36:53
【问题描述】:
我有两个巨大的表,每个表大约有 1 亿条记录,恐怕我需要在两者之间执行内部联接。现在,两张表都非常简单;这是描述:
BioEntity 表:
- BioEntityId (int)
- 名称(nvarchar 4000,虽然这有点矫枉过正)
- TypeId (int)
EGM 表(一个辅助表,实际上是批量导入操作的结果):
- EMGId (int)
- PId (int)
- 名称(nvarchar 4000,虽然这有点矫枉过正)
- TypeId (int)
- LastModified(日期)
我需要获得一个匹配的名称,以便将 BioEntityId 与 EGM 表中的 PId 相关联。最初,我尝试使用单个内部连接来完成所有操作,但查询似乎花费的时间太长,并且数据库的日志文件(在简单恢复模式下)设法耗尽了所有可用的磁盘空间(刚刚超过 200 GB,当数据库占用18GB时),如果我没记错的话,等待两天后查询会失败。我设法阻止日志增长(现在只有 33 MB),但查询已经连续运行了 6 天,而且看起来不会很快停止。
我在一台相当不错的计算机(4GB RAM,Core 2 Duo (E8400) 3GHz,Windows Server 2008,SQL Server 2008)上运行它,我注意到计算机每隔 30 秒就会卡顿一次(给或取) 几秒钟。这使得它很难用于其他任何事情,这真的让我很紧张。
现在,这是查询:
SELECT EGM.Name, BioEntity.BioEntityId INTO AUX
FROM EGM INNER JOIN BioEntity
ON EGM.name LIKE BioEntity.Name AND EGM.TypeId = BioEntity.TypeId
我手动设置了一些索引; EGM 和 BioEntity 都有一个包含 TypeId 和 Name 的非聚集覆盖索引。然而,查询运行了五天,它也没有结束,所以我尝试运行 Database Tuning Advisor 以使事情正常工作。它建议删除我的旧索引并创建统计信息和两个聚集索引(每个表上一个,只包含我觉得很奇怪的 TypeId - 或者只是简单的愚蠢 - 但我还是试了一下)。
它已经运行了 6 天,我仍然不知道该怎么办... 有什么想法吗?我怎样才能使它更快(或者,至少是有限的)?
更新: - 好的,我已取消查询并重新启动服务器以使操作系统重新启动并运行 - 我正在使用您提出的更改重新运行工作流程,特别是将 nvarchar 字段裁剪为更小的大小并将“like”替换为“=”。这至少需要两个小时,所以我稍后会发布进一步的更新
更新 2(格林威治标准时间下午 1 点,2009 年 11 月 18 日): - 估计的执行计划显示 67% 的表扫描成本,然后是 33% 的哈希匹配。接下来是 0% 并行度(这不是很奇怪吗?这是我第一次使用估计的执行计划,但这个特别的事实让我大吃一惊),0% 哈希匹配,更多 0% 并行度,0% 顶部,0 % 表插入,最后是另一个 0% 选择。似乎索引是垃圾,正如预期的那样,所以我将制作手动索引并丢弃蹩脚的建议索引。
【问题讨论】:
-
只是好奇...为什么您需要返回 100+ 百万行以及您打算如何处理所有这些数据??
-
您的 4k 名称字段中存储的最大值是多少?如果它大大小于 4k,则减少每个表中的大小。
-
它应该比 4k 小得多,只是认为因为它是一个 Nvarchar 字段,它并不重要......我想我可能可以将它减少到少于 200 个字符,也许。
-
@Hal - 是的,我可以看到,但我认为没有任何程序能够吞下这么多数据并存活下来。必须缺少“where”子句。
-
真的应该是海量数据; “where”子句通过强制限制数据本身的性质(在 TypeId 字段中定义)来应用。
标签: sql sql-server sql-server-2008 query-optimization inner-join