【问题标题】:Iterating through a large table with performance in mind在考虑性能的情况下遍历一个大表
【发布时间】:2009-06-10 16:45:35
【问题描述】:

如果我需要检查整个表以查看某个条件是否为真(例如,每个 Ticket 列都有一个带有特定后缀的 ID)。

在性能方面,什么是解决这个问题的好方法?该表非常大,所以如果我遍历每一行,就会有很多时间访问数据库。光标很慢,所以这不是一个优雅的解决方案

此外,对于未来,您始终可以验证您的参数,但在过去的这种情况下,情况并非如此。

【问题讨论】:

    标签: c# sql sql-server-2005 performance


    【解决方案1】:

    伪 sql(适用于 Oracle,其他 RDBMS 的语法可能有所不同)

     select * from tab where col1 not like '%suffix'
    

    这将为您提供所有没有所需后缀的行。

    【讨论】:

      【解决方案2】:

      你想对这些行做什么?

      如果只是:

      SELECT COUNT(*)
      FROM tbl
      WHERE col NOT LIKE '%suffix'
      

      这可能是表扫描或索引扫描。

      它仍然只是对数据库的一次调用,最多返回一行。数据库将比任何替代方案更快地完成这项工作。

      如果您的数据库正在发生变化,并且您需要能够定期管理此条件,并且愿意在 INSERT 和 UPDATE 期间权衡一点空间和处理,则可以使用持久计算列:

      CASE WHERE col LIKE '%suffix' THEN 1 ELSE 0 END
      

      并在其上创建一个索引。

      ALTER TABLE tbl
      ADD COLUMN IsSuffix AS (
          CASE WHERE col LIKE '%suffix' THEN 1 ELSE 0 END
      ) PERSISTED NOT NULL
      

      然后在该列上CREATE INDEX

      【讨论】:

      • 如何在查询中创建索引?我需要做的就是检查值(对于前缀)。谢谢
      • 这将是表中的一个持久列,您将使用该列在表上创建一个索引。如果它是前缀而不是后缀(LIKE 'prefix%'),则将使用该列上的索引,这是不必要的。
      【解决方案3】:

      如果您一直这样做,请在 REVERSE(YourColumn) 上创建一个计算列,并添加一个索引:

      ALTER TABLE dbo.YourTable ADD
          ReverseColumn  AS REVERSE(YourColumn)
      GO
      CREATE NONCLUSTERED INDEX IX_YourTable_ReverseColumn ON dbo.YourTable 
          (
          ReverseColumn
          ) WITH( STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
      

      这样使用:

      DECLARE @Suffix  varchar(10)
      SET @Suffix='abc'
      
      SET @Suffix=REVERSE(@Suffix)+'%'
      SELECT * FROM YourTable where ReverseColumn LIKE @Suffix
      

      【讨论】:

      • 我已经为用户搜索长字母数字产品代码但只想输入最后几位数字的列执行此操作。他们在搜索结果中返回了一些错误的行,但可以轻松挑选出正确的行。
      【解决方案4】:

      针对表的精心设计的数据库查询(带有索引的查询会更快)比尝试遍历每一行或检索整个表要高效得多,而且要好得多。 SQL 'like' 运算符会按照您的描述进行操作。

      【讨论】:

        【解决方案5】:

        我不确定您是在寻找 SQL 还是 C# 中的建议。如果你想在 C# 中使用 LINQ,你可以这样做

        pTable.Any(pRow => pRow.Column == someValue)
        

        【讨论】:

          【解决方案6】:

          查看@Vasu Balakrishnan的解决方案产生的SQL,如果你只想知道是否有任何无效行,你可以这样做:

          SELECT 
              (CASE 
                  WHEN EXISTS(
                      SELECT NULL AS [Empty]
                      FROM [Ticket]
                      WHERE [ID] NOT LIKE '%_SUFFIX'
                      ) THEN 0
                  ELSE 1
               END) AS [AllColumnsAreValid]
          

          【讨论】:

            【解决方案7】:

            关于性能和将 suffix 与 LIKE 运算符匹配 - 这将相对较慢,因为后缀匹配不能使用索引。

            如果您需要经常这样做,请修改表以包含一个字段,其中包含您的 TickedID 字符串反向并为其添加索引。例如,您可以添加一个在插入后执行该操作的触发器。也可以在计算列上放置索引。

            SELECT * FROM tab WHERE TicketIDReverse LIKE REVERSE('%suffix')
            

            实际上匹配了一个前缀,所以它可以使用索引并且应该比:

            SELECT * FROM tab WHERE TicketID LIKE '%suffix'
            

            【讨论】:

              猜你喜欢
              • 2010-12-31
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2010-11-26
              相关资源
              最近更新 更多