代码之家  ›  专栏  ›  技术社区  ›  Carvellis

如何使用单独的字符串表有效地联接记录

  •  1
  • Carvellis  · 技术社区  · 15 年前

    我有一个大表,其中有很多重复的字符串数据。为了节省空间,我将字符串数据移动到了一个单独的表中。我的桌子现在看起来像这样:

    MyRecords
    RecordId (int) | FieldA (int) | FieldB (datetime) | FieldC (...) | MyString1Id (int) | MyString2Id (int) | MyString3Id (int) | ...
    
    MyStrings
    StringId (int) | StringValue (varchar)
    

    这个 MyRecords 表有大约10个到字符串表的外键。我有一个存储过程 GetMyRecords 它检索具有实际字符串值的记录列表。对于每个字符串关系,该SP现在有10个到字符串表的联接:

    SELECT [Field1], [Field2], [Field3], ..., [Strings1].[StringValue], [Strings2].[StringValue], ...
     FROM MyRecords INNER JOIN
       MyStrings AS Strings1 ON MyRecords.MyString1Id = Strings1.StringId INNER JOIN
       MyStrings AS Strings2 ON MyRecords.MyString2Id = Strings2.StringId INNER JOIN
       MyStrings AS Strings3 ON MyRecords.MyString3Id = Strings3.StringId INNER JOIN
                (more joins)
        WHERE [Field1] = @Field1 AND [Field2] = @Field2
    

    盖特唱片公司 因为所有的连接,速度比我想要的慢很多。如何提高此SP的性能?我能把它变成一个单独的连接吗?

    字符串表具有上的聚集主键 StringId 以及所有的where字段在 我的唱片 表。

    3 回复  |  直到 15 年前
        1
  •  2
  •   Jeffrey L Whitledge    15 年前

    我能把它变成一个单独的连接吗?

    如果相同的情况很常见 结合 在多行上发生的字符串 MyRecords 然后将这些组合存储在单独的表中是有意义的。然后您可以进行一次加入。

    只要只存储单个字符串,就不可能在单个联接中执行此操作,因为它必须分别搜索每个字符串。

    通过创建包含所有联接的表视图,可以使查询更易于读取和写入。这不会提高性能,但会使您的查询看起来更好。

    如何提高此SP的性能?

    根据数据的形式,您可以做一些事情。

    如果一个字段中的字符串包含(大部分)不同于另一个字段的信息,那么您可以尝试将它们放入不同的表中。如果一个字段的最大长度比另一个字段小得多,或者一个字段的不同值的数目比另一个字段小得多,则有可能提高性能。

        2
  •  4
  •   Andrew    15 年前

    您可能应该向规范化迈进一步,创建一个联接表。而不是 MyStringNId MyRecords ,第三张桌子:

    CREATE TABLE RecordsStrings (
        RecordId [theDataType] NOT NULL REFERENCES MyRecords (RecordId),
        StringId [theDataType] NOT NULL REFERENCES MyStrings (StringId)
    )
    

    那么,将所有字符串都放在 SELECT (尽管可能有一种方法可以通过Pivot实现这一点),所以最好重新构造调用代码,以处理从以下位置返回的结果:

    SELECT [StringValue]
    FROM   [MyStrings] s
    INNER JOIN [RecordsStrings] rs ON rs.StringId = s.StringId
    INNER JOIN [MyRecords] r ON rs.RecordId = r.RecordId
    WHERE  r.Field1 = @Field1 AND r.Field2 = @Field2
    

    如果您需要其他字段 我的唱片 您也可以选择它们,尽管它们会出现在每个相关行中。不过,如果在field1和field2上有多个匹配项,这可能会有所帮助。

        3
  •  1
  •   ChrisLively    15 年前

    第一步是运行性能分析,看看问题在哪里。

    不过,在百灵鸟上,您可以通过在连接的表上使用(nolock)来获得一点性能提升。