SQL:内连接两个海量表

标签 sql sql-server sql-server-2008 query-optimization inner-join

我有两个巨大的表,每个表约有 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/

相关文章:

mysql - SQL 连接表并在右表中显示不匹配记录的默认值

sql - 如何将动态 sql 中的值存储到变量中?

sql - 如何在 SQL Server 和 Oracle SQL 中基于固定字符选择直到第 N 个空格的子字符串

c# - 错误 ID 的伪增量数会成为问题吗?

sql-server - SQL Server 08 - 枢轴 - 更改列名

sql-server - 从字符串中打印斜杠 '/' 前后的子字符串

mysql - 如何只在满足特定条件的情况下现场下订单?

sql - 有一种方法可以使用 WHERE date = MAX(date) 发出请求

mysql - 获取组中最新日期的行?

python - 无法从 Linux 机器通过 python 连接 SQL 服务器