比如一个一句,select * from tb where id>1直接执行和用动态sql exec('select * from tb where id>1')
在动态sql里面,是不是索引就无法起作用?如果不是,同样的语句,动态sql的效率为什么很低啊?

解决方案 »

  1.   

    sql exec('select * from tb where id>1')
    是要执行2次的,因此效率可能比较低,数据量大的话比较明显.
    索引是依然起作用的.
    "(...)"括号里的sql执行一次,然后sql exec()在执行其结果,当然就慢了.
      

  2.   

    索引起作用个人理解动态sql的执行:先将exec里面的语句解析为一条可执行的sql再执行对应的sql语句
    我也用动态sql,不会出现楼上说的很慢'select * from tb where id>1'个人建议:select 最好不要引用*,只列举有用的字段就可以了
    如果tb表中有30个字段,当然慢。
    select * from tb where id>1 
    select 字段1 from tb where id>1
      

  3.   

    相同的语句在无论是作为动态执行,还是作为静态执行,其生成的执行计划都是相同的,因此效率应该也是相同的。
    如果说有不同,就是动态语句是一个独立的作用域,在执行动态语句时会从当前的会话作用域切换到动态作用域,执行完毕再切换回来(PUSH/POP)。可能还有其他的,请大家补充。
    另外,在存储过程中,动态语句只会在执行存储过程时被分析/编译,而不是与存储过程作为一个整体执行计划缓存在 SQL Server 的过程缓存中。但是,正是这个原因,动态语句会根据用户的输入对查询进行动态筛选,生成合适的执行计划,而不是像静态语句那样总是使用缓存中的执行计划,无论其是否适合当前用户的输入,这个是动态语句性能优于静态语句的地方。下面是一个测试,可以一目了然。当然,这个不是动态语句正确的用法。-- 清空过程缓存
    dbcc freeproccache-- 执行语句
    -- 静态
    select * from SalesLT.Customer where CustomerID>10;
    -- 动态
    exec('select * from SalesLT.Customer where CustomerID>10');-- 检查执行计划和统计信息
    select t.text,p.query_plan,
    q.creation_time,q.last_execution_time,q.execution_count,
    q.total_physical_reads,q.total_logical_reads,q.total_logical_writes,
    q.total_elapsed_time,q.total_worker_time
    from sys.dm_exec_query_stats q cross apply
    sys.dm_exec_query_plan(q.plan_handle) p cross apply
    sys.dm_exec_sql_text(q.sql_handle) t;