Sql 选择案例绩效
假设我们有这个表:Sql 选择案例绩效,sql,sql-server,database,rdbms,Sql,Sql Server,Database,Rdbms,假设我们有这个表: |------------------------------| | col | data type | |------------------------------| | id | bigint | | first_name | nvarchar | | last_name | nvarchar | | photo | binary | |-------
|------------------------------|
| col | data type |
|------------------------------|
| id | bigint |
| first_name | nvarchar |
| last_name | nvarchar |
| photo | binary |
|------------------------------|
好的,现在我们需要对该表进行两个查询:
|------------------------------|
| col | data type |
|------------------------------|
| id | bigint |
| first_name | nvarchar |
| last_name | nvarchar |
| photo | binary |
|------------------------------|
- 列出不带照片列的所有表行(加载为空)
- 使用照片列加载特定行
SELECT Top 50
id,
first_name,
last_name,
CASE WHEN @id IS NULL THEN null ELSE photo END as photo
FROM MyTable
WHERE @id IS NULL OR id=@id
SELECT
id,
first_name,
last_name,
photo
FROM MyTable
WHERE id=COALESCE(@id,id)
第二种方法是:
IF (@id IS NULL)
SELECT Top 50
id,
first_name,
last_name,
null as photo
FROM MyTable
ELSE
SELECT
id,
first_name,
last_name,
photo
FROM MyTable
WHERE id=@id
END
第二种方法显然是一次性检查if条件并完成工作
但我喜欢编写类似SPs的第一种方法,我不知道sql server是否会在@id为NULL时检查每行的大小写,或者查询优化器是否会在没有大小写的情况下优化查询
编辑1:
我想知道第一个查询是否总是在没有大小写的情况下执行?因为它正在检查一个不改变值且与任何列值都不相关的变量。您可以尝试这样做,这样可以避免出现情况以及IF
。不过,我承认这有点神秘
SELECT Top 50
id,
first_name,
last_name,
null as photo
FROM MyTable
WHERE @id IS NULL
UNION ALL
SELECT id,
first_name,
last_name,
photo
FROM MyTable
WHERE id = @id
您可以尝试这样做,这样可以避免出现案例
,也可以避免出现IF
。不过,我承认这有点神秘
SELECT Top 50
id,
first_name,
last_name,
null as photo
FROM MyTable
WHERE @id IS NULL
UNION ALL
SELECT id,
first_name,
last_name,
photo
FROM MyTable
WHERE id = @id
执行此操作的标准方法(将null参数默认值设为all)如下所示:
SELECT Top 50
id,
first_name,
last_name,
CASE WHEN @id IS NULL THEN null ELSE photo END as photo
FROM MyTable
WHERE @id IS NULL OR id=@id
SELECT
id,
first_name,
last_name,
photo
FROM MyTable
WHERE id=COALESCE(@id,id)
根据我的经验,如果ID上有索引,那么这在所有主要平台上都能提供良好的性能。执行此操作的标准方法(将null参数默认值设置为all)如下所示:
SELECT Top 50
id,
first_name,
last_name,
CASE WHEN @id IS NULL THEN null ELSE photo END as photo
FROM MyTable
WHERE @id IS NULL OR id=@id
SELECT
id,
first_name,
last_name,
photo
FROM MyTable
WHERE id=COALESCE(@id,id)
根据我的经验,如果ID上有一个索引,那么它在所有主要平台上都有很好的性能。因为有些答案已经发布了,所以我决定亲自检查一下
SQL Server 2014上的安装程序
执行时间:13秒
执行计划:
查询#2-ELSE子句中OP的查询:
执行时间:0秒
执行计划:
查询#3-@Ann的查询:
执行时间:0秒
执行计划:
查询#4-@霍根的查询:
执行时间:14秒
执行计划:
结论
对于@id
有值的情况,您和Hogan在单个查询中统一逻辑的尝试都不如单独进行查询。在这两种情况下,您都可以看到查询实际上是扫描整个聚集索引,而不是执行更直接的索引查找
有趣的是,尽管Ann的执行计划似乎是所有计划中最复杂的,但性能表明优化器不知何故能够检测到@id
不是空的,并在这种情况下缩短了昂贵的集群索引扫描
尽管如此,由于您已经在存储过程中,在我看来,您应该坚持使用if-else
方法。这似乎是最安全的方法。因为有些答案已经贴出来了,我决定自己去看看
SQL Server 2014上的安装程序
执行时间:13秒
执行计划:
查询#2-ELSE子句中OP的查询:
执行时间:0秒
执行计划:
查询#3-@Ann的查询:
执行时间:0秒
执行计划:
查询#4-@霍根的查询:
执行时间:14秒
执行计划:
结论
对于@id
有值的情况,您和Hogan在单个查询中统一逻辑的尝试都不如单独进行查询。在这两种情况下,您都可以看到查询实际上是扫描整个聚集索引,而不是执行更直接的索引查找
有趣的是,尽管Ann的执行计划似乎是所有计划中最复杂的,但性能表明优化器不知何故能够检测到@id
不是空的,并在这种情况下缩短了昂贵的集群索引扫描
尽管如此,由于您已经在存储过程中,在我看来,您应该坚持使用if-else
方法。这似乎是最安全的方法。检查执行计划并进行比较。是的,你是对的,但我的问题是如何优化?这只是一个例子。thx@sstan示例中的执行计划不会回答您关于如何优化类似内容的问题吗?即使这只是一个例子,@sstan告诉我们的。但是根据我的经验,有两个独立的查询可能会有更好的性能。SQL Server或任何其他RDBMS都不喜欢或
子句。我尝试了执行计划,但无法找到它。检查执行计划并进行比较。是的,你是对的,但我的问题是如何对其进行优化?这只是一个例子。thx@sstan示例中的执行计划不会回答您关于如何优化类似内容的问题吗?即使这只是一个例子,@sstan告诉我们的。但是根据我的经验,有两个独立的查询可能会有更好的性能。SQL Server或任何其他RDBMS都不太喜欢或子句。我尝试过执行计划,但无法理解。谢谢详细的回答谢谢详细的回答