【问题标题】:SELECT without FROM<table> but with APPLY / JOINSELECT 没有 FROM<table> 但有 APPLY / JOIN
【发布时间】:2017-08-09 13:27:12
【问题描述】:

我写了一个程序,需要几个外键ID来做进一步的操作

md_machines

+----+-------+
| id | name  |
+----+-------+
| 1  | c432  |
| 2  | c431  |
| n  | ...   |
+----+-------+

我在我的程序中的查询:

SELECT TOP 1  
@m1 = m1.id,  
@m2 = m2.id,  
@m3 = m3.id,  
@m4 = m4.id  
FROM md_machines  
OUTER APPLY(SELECT TOP 1 id FROM md_machines WHERE name = @p1) m1  
OUTER APPLY(SELECT TOP 1 id FROM md_machines WHERE name = @p2) m2  
OUTER APPLY(SELECT TOP 1 id FROM md_machines WHERE name = @p3) m3  
OUTER APPLY(SELECT TOP 1 id FROM md_machines WHERE name = @p4) m4  

一切正常,但md_machines 有超过 300k 行。当我用空表替换 FROM md_machines 时,这个查询大约快 10%。
我怎样才能避免FROM md_machines?对我来说没有必要。

【问题讨论】:

    标签: sql sql-server performance optimization


    【解决方案1】:

    使用简单的变量赋值:

    SET @m1 = (SELECT TOP 1 id FROM md_machines WHERE name = @p1);
    SET @m2 = (SELECT TOP 1 id FROM md_machines WHERE name = @p2);
    SET @m3 = (SELECT TOP 1 id FROM md_machines WHERE name = @p3);
    SET @m4 = (SELECT TOP 1 id FROM md_machines WHERE name = @p4);
    

    TOP 1 没有明确的ORDER BY 是不稳定的。

    【讨论】:

    • 是的,这是我的第一个代码版本。但是多个查询正在消耗更多的性能。所以我打算加入/申请
    【解决方案2】:

    选择一次

    SELECT name, min(id) 
    FROM md_machines 
    WHERE (name = @p1 or name = @p2 or name = @p3 or name = @p4)
    group by name
    

    然后使用WITH上面的查询

    WITH sub (name, id)  
    AS  
    (  
        the suquery  
    )
    
    SELECT TOP 1
    @m1 = m1.id,
    @m2 = m2.id,
    @m3 = m3.id,
    @m4 = m4.id
    FROM (SELECT TOP 1 id FROM sub WHERE name = @p1) m1,
         (SELECT TOP 1 id FROM sub WHERE name = @p2) m2,
         (SELECT TOP 1 id FROM sub WHERE name = @p3) m3,
         (SELECT TOP 1 id FROM sub WHERE name = @p4) m4
    

    顺便说一句:在name 列上有索引会很好

    更新:我认为这个也可以

    SELECT TOP 1
    @m1 = m1.id,
    @m2 = m2.id,
    @m3 = m3.id,
    @m4 = m4.id
    FROM (SELECT TOP 1 id FROM md_machines WHERE name = @p1) m1,
         (SELECT TOP 1 id FROM md_machines WHERE name = @p2) m2,
         (SELECT TOP 1 id FROM md_machines WHERE name = @p3) m3,
         (SELECT TOP 1 id FROM md_machines WHERE name = @p4) m4
    

    【讨论】:

    • 不错的解决方案/解决方法。我会记住它,特别是因为 mingroup 用于其他项目。这里我使用唯一索引 namecolumn 和主键 id
    猜你喜欢
    • 1970-01-01
    • 2021-07-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多