FROM 子句中嵌套 select 语句?内连接语句?或者只是表名?

发布于 2024-12-22 15:37:12 字数 2947 浏览 1 评论 0原文

我正在构建一个需要来自 5 个表的数据的查询。 过去一位 DBA 告诉我,从某些性能/内存方面来看,指定列列表与获取所有列 (*) 相比是首选。 我还被告知,当 FROM 子句中有一系列表时,数据库会在幕后执行 JOIN 操作,以创建一个表(或视图)。

目前现有数据库的数据非常少,因为我们正处于一个非常初始的阶段。所以不确定我是否可以衡量实践中的性能影响。 我不是数据库专家。我可以获得我需要的数据。难题是,价格是多少。

补充:目前我正在使用 MS SQL Server 2008 R2。

我的问题是:

  1. 以下各项之间是否存在性能差异及其原因: 一个。为了简单起见,SELECT ... FROM tbl1、tbl2、tbl3 等? (不知怎的,我觉得这可能会影响性能) b. SELECT ... FROM tbl1 inner join tbl2 on ... inner join tbl3 on ... 等等(这对服务器来说会更明确并节省性能/内存)? c. SELECT ... FROM (select x,y,z from tbl1) as t1 inner join ...等(这会节省任何东西吗?或者它只是额外的选择语句,为服务器和我们创造更多工作)?

  2. 还有更好的方法吗?

下面是两个查询,它们都获取我需要的数据片段。一种包括更多嵌套的选择语句。

如果它们没有以标准形式编写或过于复杂,我深表歉意 - 希望您能解读。我尽量让它们井井有条。

见解也将受到高度赞赏。 感谢您查看此内容。

5 个表:devicepool、users、trips、TripTracker 和 order

查询 1(更多 select 语句):

SELECT
      username, 
      base.devid devid, 
      tripstatus, 
      stops, 
      stopnumber, 
      [time], 
      [orderstatus], 
      [destaddress]

FROM    
((
 (  SELECT 
           username, 
           devicepool.devid devid,
           groupid
    FROM
           devicepool INNER JOIN users 
           ON devicepool.userid = users.userid 

     WHERE devicepool.groupid = 1
 ) 
 AS [base] 

 INNER JOIN

 (
      SELECT 
              tripid, 
              [status] tripstatus, 
              stops, 
              devid,
              groupid

      FROM 
              trips 
 ) 
 AS [base2]

 ON base.devid = base2.devid AND base2.groupid = base.groupid

 INNER JOIN

 (
     SELECT 
            stopnumber, 
            devid, 
            [time], 
            MAX([time]) OVER (PARTITION BY devid) latesttime 
     FROM 
            TripTracker
 ) 

 AS [tracker] 
 ON tracker.devid = base.devid AND [time] = latesttime)

 INNER JOIN

 (
      SELECT 
            [status] [orderstatus], 
            [address] [destaddress], 
            [tripid], 
            stopnumber orderstopnumber 
      FROM [order]
 ) 
 AS [orders] 

 ON orders.orderstopnumber = tracker.stopnumber)

查询 2:

SELECT
      username, 
      base.devid devid, 
      tripstatus, 
      stops, 
      stopnumber, 
      [time], 
      [orderstatus], 
      [destaddress]

FROM    
((
 (  SELECT 
           username, 
           devicepool.devid devid,
           groupid
    FROM
           devicepool INNER JOIN users 
           ON devicepool.userid = users.userid 

     WHERE devicepool.groupid = 1
 ) 
 AS [base] 

 INNER JOIN

     trips

 ON base.devid = trips.devid AND trips.groupid = base.groupid

 INNER JOIN

 (
     SELECT 
            stopnumber, 
            devid, 
            [time], 
            MAX([time]) OVER (PARTITION BY devid) latesttime 
     FROM 
            TripTracker
 ) 

 AS [tracker] 
 ON tracker.devid = base.devid AND [time] = latesttime)

 INNER JOIN

    [order]

 ON [order].stopnumber = tracker.stopnumber)

I'm building a query that needs data from 5 tables.
I've been told by a DBA in the past that specifying a list of columns vs getting all columns (*) is preferred from some performance/memory aspect.
I've also been told that the database performs a JOIN operation behind the scenes when there's a list of tables in the FROM clause, to create one table (or view).

The existing database has very little data at the moment, as we're at a very initial point. So not sure I can measure the performance hit in practice.
I am not a database pro. I can get what data I need. The dillema is, at what price.

Added: At the moment I'm working with MS SQL Server 2008 R2.

My questions are:

  1. Is there a performance difference and why, between the following:
    a. SELECT ... FROM tbl1, tbl2, tbl3 etc for simplicity? (somehow I feel that this might be a performance hit)
    b. SELECT ... FROM tbl1 inner join tbl2 on ... inner join tbl3 on ... etc (would this be more explicit to the server and save on performance/memory)?
    c. SELECT ... FROM (select x,y,z from tbl1) as t1 inner join ... etc (would this save anythig? or is it just extra select statements that create more work for the server and for us)?

  2. Is there yet a better way to do this?

Below are two queries that both get the slice of data that I need. One includes more nested select statements.

I apologize if they are not written in a standard form or helplessly overcomplicated - hopefully you can decipher. I try to keep them organized as much as possible.

Insights would be most appreciated as well.
Thanks for checking this out.

5 tables: devicepool, users, trips, TripTracker, and order

Query 1 (more select statements):

SELECT
      username, 
      base.devid devid, 
      tripstatus, 
      stops, 
      stopnumber, 
      [time], 
      [orderstatus], 
      [destaddress]

FROM    
((
 (  SELECT 
           username, 
           devicepool.devid devid,
           groupid
    FROM
           devicepool INNER JOIN users 
           ON devicepool.userid = users.userid 

     WHERE devicepool.groupid = 1
 ) 
 AS [base] 

 INNER JOIN

 (
      SELECT 
              tripid, 
              [status] tripstatus, 
              stops, 
              devid,
              groupid

      FROM 
              trips 
 ) 
 AS [base2]

 ON base.devid = base2.devid AND base2.groupid = base.groupid

 INNER JOIN

 (
     SELECT 
            stopnumber, 
            devid, 
            [time], 
            MAX([time]) OVER (PARTITION BY devid) latesttime 
     FROM 
            TripTracker
 ) 

 AS [tracker] 
 ON tracker.devid = base.devid AND [time] = latesttime)

 INNER JOIN

 (
      SELECT 
            [status] [orderstatus], 
            [address] [destaddress], 
            [tripid], 
            stopnumber orderstopnumber 
      FROM [order]
 ) 
 AS [orders] 

 ON orders.orderstopnumber = tracker.stopnumber)

Query 2:

SELECT
      username, 
      base.devid devid, 
      tripstatus, 
      stops, 
      stopnumber, 
      [time], 
      [orderstatus], 
      [destaddress]

FROM    
((
 (  SELECT 
           username, 
           devicepool.devid devid,
           groupid
    FROM
           devicepool INNER JOIN users 
           ON devicepool.userid = users.userid 

     WHERE devicepool.groupid = 1
 ) 
 AS [base] 

 INNER JOIN

     trips

 ON base.devid = trips.devid AND trips.groupid = base.groupid

 INNER JOIN

 (
     SELECT 
            stopnumber, 
            devid, 
            [time], 
            MAX([time]) OVER (PARTITION BY devid) latesttime 
     FROM 
            TripTracker
 ) 

 AS [tracker] 
 ON tracker.devid = base.devid AND [time] = latesttime)

 INNER JOIN

    [order]

 ON [order].stopnumber = tracker.stopnumber)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

毁梦 2024-12-29 15:37:12

以下各项之间是否存在性能差异及其原因:
为了简单起见,SELECT ... FROM tbl1、tbl2、tbl3 等? (不知何故我觉得
这可能会影响性能) b. SELECT ... FROM tbl1 内部
join tbl2 on ... inside join tbl3 on ... 等等(这会更多吗?
对服务器显式并节省性能/内存)? c.选择 ...
FROM (从 tbl1 选择 x,y,z) 作为 t1 内连接...等(这会吗
保存任何东西吗?或者只是额外的 select 语句来创建更多
为服务器和我们工作)?

a) 和 b) 应该产生相同的查询计划(尽管这是特定于数据库的)。就可移植性和可读性而言,b) 比 a) 更受青睐。 c) 是一个可怕的想法,它会损害可读性,并且会导致性能更差。让我们永远不再谈论它。

还有更好的方法吗?

b) 是标准方法。一般来说,编写最简单的 ANSI SQL 将获得最佳性能,因为它允许查询解析器轻松理解您要执行的操作。尝试用技巧智胜编译器可能在给定情况下有效,但这并不意味着当数据基数或数据量发生变化或数据库引擎升级时它仍然有效。因此,除非绝对被迫,否则请避免这样做。

Is there a performance difference and why, between the following: a.
SELECT ... FROM tbl1, tbl2, tbl3 etc for simplicity? (somehow I feel
that this might be a performance hit) b. SELECT ... FROM tbl1 inner
join tbl2 on ... inner join tbl3 on ... etc (would this be more
explicit to the server and save on performance/memory)? c. SELECT ...
FROM (select x,y,z from tbl1) as t1 inner join ... etc (would this
save anythig? or is it just extra select statements that create more
work for the server and for us)?

a) and b) should result in the same query plan (although this is db-specific). b) is much preferred for portability and readability over a). c) is a horrible idea, that hurts readability and if anything will result in worse peformance. Let us never speak of it again.

Is there yet a better way to do this?

b) is the standard approach. In general, writing the plainest ANSI SQL will result in the best performance, as it allows the query parser to easily understand what you are trying to do. Trying to outsmart the compiler with tricks may work in a given situation, but does not mean that it will still work when the cardinality or amount of data changes, or the database engine is upgraded. So, avoid doing that unless you are absolutely forced to.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文