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

有没有方法优化下面给出的查询

  •  -1
  • rsapru  · 技术社区  · 16 年前

    我有以下查询,我需要该查询根据someothertable中的筛选条件从sometable中获取数据。如果someothertable中没有任何内容,则查询应返回sometable中的所有数据。

    SQL Server 2005

    SomeOtherTable没有任何索引或约束所有字段都是char(50)

    下面的查询对我的需求很好,但是当我有很多参数时,它会导致性能问题。

    由于客户的某些要求,我们必须将所有WHERE子句数据保存在其他表中。根据子ID的不同,数据将与sometable中的一列联接。

    例如,查询可以是

    SELECT
        *
    FROM
        SomeTable
    WHERE
        1=1 
    AND
    (
    SomeTable.ID in (SELECT DISTINCT ID FROM SomeOtherTable  WHERE Name = 'ABC' and subid = 'EF')
    OR
    0=(SELECT Count(1) FROM SomeOtherTable WHERE spName = 'ABC' and subid = 'EF')
    )
    
    AND 
        (
        SomeTable.date =(SELECT date FROM SomeOtherTable  WHERE Name = 'ABC' and subid = 'Date')
        OR
        0=(SELECT Count(1) FROM SomeOtherTable WHERE spName = 'ABC' and subid = 'Date')
        )
    

    编辑————————————————————————————————————————————

    我想我可能需要详细解释我的问题:

    我们开发了一个用于调用参数化Crystal Reports的ASP.NET应用程序,Crystal Reports的参数不会使用默认Crystal Reports方法传递。

    在ASP.NET应用程序中,我们创建了用于将参数传递给报表的向导,这些参数不会直接由Crystal报表使用,而是由嵌入Crystal报表中的查询或Crystal报表中使用的存储过程使用。

    这是通过使用一个表(someothertable)实现的,该表保存参数数据,只要报表运行之后数据被删除,因此我们可以假设someothertable在任何给定时间点最多有2到3行。

    因此,如果我们查看上面的查询,可以假定查询的初始部分是报表查询,并且使用WHERE子句从someothertable表中获取用户输入。

    所以我认为创建索引等(可能是我错了)是没有用的。

    9 回复  |  直到 13 年前
        1
  •  3
  •   Dave Markle    16 年前

    其他表没有 索引或任何约束所有字段 是CHAR(50)

    好吧,这是你的问题。对于这样的查询,您没有什么可以做的,如果您这样创建它,它将提高性能。

    • 您需要在所有表上指定适当的主键或其他候选键。也就是说,表上至少需要一个唯一索引。可以通过将一个或多个字段指定为pk来实现这一点,也可以添加唯一约束或索引。

    • 您需要正确定义字段。字段是否存储整数?那么,一个int字段可能比一个char(50)更好。

    不能“优化”基于不健全架构的查询。

        2
  •  2
  •   CoolBeans Jake    13 年前

    尝试:

    SELECT
        *
    FROM
        SomeTable
    LEFT JOIN SomeOtherTable ON SomeTable.ID=SomeOtherTable.ID AND Name = 'ABC'
    WHERE
        1=1 
    AND
    (
    SomeOtherTable.ID IS NOT NULL
    OR
    0=(SELECT Count(1) FROM SomeOtherTable WHERE spName = 'ABC')
    )
    
        3
  •  1
  •   usman shaheen    16 年前

    在每个表名后面加上'with(nolock)'以提高性能

        4
  •  1
  •   James Anderson    16 年前

    以下可能会加快您的速度

    SELECT * 
    FROM SomeTable 
    WHERE
       SomeTable.ID in 
            (SELECT DISTINCT ID FROM SomeOtherTable Where Name = 'ABC')
    UNION
    SELECT * 
    FROM SomeTable 
    Where 
       NOT EXISTS (Select spName From SomeOtherTable Where spName = 'ABC')
    

    联合将有效地将其分为两个更简单的查询,这两个查询可以分别进行选择(这在很大程度上取决于DBMS、表大小等,这是否会真正提高性能——但它始终值得一试)。

    “exists”关键字比“select count(1)”更有效,因为一旦遇到第一行,它就会返回true。

        5
  •  1
  •   Ken Yao    16 年前

    或者先检查该值是否存在于db中 您可以删除查询中的distinct关键字,它在这里是无用的。

    如果存在(从spname='abc'的其他表中选择spname) 开始 选择* 从某种意义上说 哪里 SomeTable.ID在 (从someOtherTable中选择id,其中name='abc') 结束 其他的 开始 选择* 从某种意义上说 结束

        6
  •  0
  •   edosoft    16 年前

    阿罗哈

    尝试

    select t.* from SomeTable t
        left outer join SomeOtherTable o
            on t.id = o.id
    where (not exists (select id from SomeOtherTable where spname = 'adbc')
    OR spname = 'adbc')
    

    -爱德华

        7
  •  0
  •   Mladen Prajdic    16 年前

    将Where部分中的所有Select语句更改为内部jon。 OR条件应该是统一的。 还要确保索引正常。

    有时候,为临时结果准备一个中间表是值得的,您可以将其加入其中。

        8
  •  0
  •   rsapru    16 年前

    谢谢大家的建议。我将坚持我最初的询问。

        9
  •  0
  •   stalepretzel    16 年前

    在我看来,您的查询中不需要“1=1”和“1=1”。1=1将始终评估为真,留下软件来评估下一部分…为什么不跳过1=1并评估多汁部分呢?