我有两个巨大的表,每个表约有 1 亿条记录,恐怕我需要在两者之间执行 Inner Join。现在,两个表都非常简单;描述如下:
生物实体表:
- BioEntityId(整数)
- 名称(nvarchar 4000,尽管这有点过分)
- 类型 ID(整数)
EGM表(一个辅助表,实际上是批量导入操作的结果):
- EMGId(整数)
- PID(整数)
- 名称(nvarchar 4000,尽管这有点过分)
- 类型 ID(整数)
- 上次修改时间(日期)
我需要获取匹配的名称,以便将 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(格林尼治标准时间 18 月 11 日,2009 年下午 1 点): - 估计的执行计划显示表扫描的成本为 67%,其次是 33% 的哈希匹配。接下来是 0% 并行度(这不是很奇怪吗?这是我第一次使用估计执行计划,但这个特殊事实让我大吃一惊)、0% 哈希匹配、更多 0% 并行度、0% 顶部、0 % 表插入,最后另一个 0% 选择进入。正如预期的那样,索引似乎很糟糕,所以我将制作手动索引并丢弃糟糕的建议索引。
最佳答案
我不是 SQL 调优专家,但在我所知道的任何数据库系统中,在 VARCHAR 字段上连接数亿行听起来都不是一个好主意。
您可以尝试向每个表添加一个整数列,并在 NAME 字段上计算一个哈希值,这样在引擎必须查看实际的 VARCHAR 数据之前,应该将可能的匹配项获取到合理的数字。
关于SQL:内连接两个海量表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1750001/