最小化所选属性的数量是否会提高性能?

时间:2018-01-22 02:06:43

标签: sql sql-server

在我的SQL Server脚本中,我将一个表连接到一个大表。选择的项目数是否与SQL性能有关?

我的两个选择是:

SELECT
    tu.Time,
    tu.Machine_id,             
    AVG(tu.cpu_rate) AS cpu_usage,      
    AVG(tu.canonical_memory_usage) AS memory_usage,
    AVG(tu.cpu_rate) / [dbo].[FnGetCpuInfoWithfailMachineId](tu.machine_id, tu.sampling_start_time) AS cpu_utilization,
    AVG(tu.canonical_memory_usage) / dbo.[FnGetMemoryInfoWithfailMachineId](tu.machine_id, tu.sampling_start_time) AS memory_utilization,
    [dbo].[FnGetCpuRequestTotalWithfailMachineId](tu.machine_id, tu.sampling_start_time) AS cpu_request_total,
    [dbo].[FnGetMemoryRequestTotalWithfailMachineId](tu.machine_id, tu.sampling_start_time) AS memory_request_total,
    [dbo].[FnGetPerformanceInfoWithfailMachineId](tu.machine_id, tu.sampling_start_time, AVG(tu.cycles_per_instruction)) AS performance
FROM
    [dbo].[failure_host_machine_events] AS h 
INNER JOIN
    [dbo].[Failed_hosts_task_usage] AS tu ON h.machine_id = tu.machine_id

group by tu.machine_id, tu.time

OR

SELECT
    tu.Time,
    tu.Machine_id,
    [dbo].[FnGetPerformanceInfoWithfailMachineId](tu.machine_id, tu.sampling_start_time, AVG(tu.cycles_per_instruction)) AS performance
FROM
    [dbo].[failure_host_machine_events] AS h 
INNER JOIN
    [dbo].[Failed_hosts_task_usage] AS tu ON h.machine_id = tu.machine_id
group by tu.machine_id, tu.time

非常大的桌子是[dbo].[Failed_hosts_task_usage]。如果这两个脚本的性能和时间消耗不同,那么有什么想法?或者,因为我加入了这两个表,所以我选择了多少属性

2 个答案:

答案 0 :(得分:2)

一般来说,存在差异。两个主要原因:

  1. 从服务器传递到客户端的数据较少,导致网络利用率降低等。
  2. 可能更便宜的查询计划。
  3. 让我详细说明第二点......假设你有这样的结构:

    -- Create a test table...
    
    CREATE TABLE T (
        ID int IDENTITY PRIMARY KEY,
        NAME nvarchar(255),
        FOO int
    );
    
    CREATE INDEX THE_INDEX ON T(NAME);
    
    -- Fill it with some data...
    
    WITH DIGIT(N) AS (
        SELECT 0
        UNION ALL
        SELECT 1
        UNION ALL
        SELECT 2
        UNION ALL
        SELECT 3
        UNION ALL
        SELECT 4
        UNION ALL
        SELECT 5
        UNION ALL
        SELECT 6
        UNION ALL
        SELECT 7
        UNION ALL
        SELECT 8
        UNION ALL
        SELECT 9
    ),
    NUMBER(N) AS (
        SELECT
            D4.N * 10000 + D3.N * 1000 + D2.N * 100 + D1.N * 10 + D0.N NUMBER
        FROM
            DIGIT D0
            CROSS JOIN DIGIT D1
            CROSS JOIN DIGIT D2
            CROSS JOIN DIGIT D3
            CROSS JOIN DIGIT D4
    )
    INSERT INTO T(NAME, FOO)
    SELECT N, N FROM NUMBER;
    

    现在,考虑两个几乎相同的查询之间的执行计划差异:

    SELECT ID, NAME FROM T WHERE NAME = '50000';
    SELECT * FROM T WHERE NAME = '50000';
    

    enter image description here

    请注意,第二个查询的工作原理基本上是两倍,因为选择列表中存在FOO!原因是THE_INDEX不是FOO covered,因此对于每个找到的行,数据库必须进行额外的查找才能检索FOO。 (另一方面,ID是PK,因此自动包含在THE_INDEX中。)

    结论:努力在SELECT列表中包含您实际需要的属性。

    这是否会对您的特定案例带来有意义的改进是另一回事......唯一可靠的方法是对代表性的数据量衡量。< / p>

答案 1 :(得分:1)

您的查询在语法上不正确,因为它们应该有group by。但我仍然认为我理解这个问题。

通常,查询的性能主要取决于访问数据,进行连接和聚合。作为一般规则,属性的数量对性能的影响相对较小。这就是为什么性能优化的大部分工作都集中在选择适当的连接和分组算法上。

尽管如此,有些情况下所选择的内容确实会产生影响。例如:

  • count(distinct)比其他聚合更昂贵(for xml path)。
  • 字符串操作 - 尤其是长字符串 - 可能很昂贵。
  • 一些复杂的表达方式需要时间。对于某些用户定义的函数尤其如此。
  • 任何真正的大字段都会对性能产生影响。

毫无疑问,其他情况也是如此。但在您的情况下,joingroup by可能会主导性能,您应该集中精力提高速度(如果您关心性能)。