Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/76.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 如何利用索引优化select查询_Sql_Sql Server_Indexing_Query Optimization - Fatal编程技术网

Sql 如何利用索引优化select查询

Sql 如何利用索引优化select查询,sql,sql-server,indexing,query-optimization,Sql,Sql Server,Indexing,Query Optimization,我不是专家。 我有以下查询,其中包含10个表 MainTable有10个字段,9个表中的第一个主键和其余外键称为Table1-10 下面的查询正在每个表中进行外部联接,我想使用索引优化此查询 我想知道,我们如何使用索引优化查询,这个查询在36秒内获取10个LAC(100万)记录,我们可以减少多少时间 主表包含10条LAC(100万条)记录,表1-9每个表包含5000条记录 select M.RecID, M.E1, E1.Descr as E1_D, M.E2, E2.Descr as E2

我不是专家。 我有以下查询,其中包含10个表 MainTable有10个字段,9个表中的第一个主键和其余外键称为Table1-10

下面的查询正在每个表中进行外部联接,我想使用索引优化此查询

我想知道,我们如何使用索引优化查询,这个查询在36秒内获取10个LAC(100万)记录,我们可以减少多少时间

主表包含10条LAC(100万条)记录,表1-9每个表包含5000条记录

select M.RecID, 
M.E1, E1.Descr as E1_D, 
M.E2, E2.Descr as E2_D, 
M.E3, E3.Descr as E3_D, 
M.E4, E4.Descr as E4_D, 
M.E5, E5.Descr as E5_D, 
M.E6, E6.Descr as E6_D, 
M.E7, E7.Descr as E7_D, 
M.E8, E8.Descr as E8_D, 
M.E9, E9.Descr as E9_D
from ((((((((tableMain M  
    Left Outer Join TableE1 E1 ON (E1.RecID = M.E1) )
    Left Outer Join TableE2 E2 ON (E2.RecID = M.E2) )
    Left Outer Join TableE3 E3 ON (E3.RecID = M.E3) )
    Left Outer Join TableE4 E4 ON (E4.RecID = M.E4) )
    Left Outer Join TableE5 E5 ON (E5.RecID = M.E5) )
    Left Outer Join TableE6 E6 ON (E6.RecID = M.E6) )
    Left Outer Join TableE7 E7 ON (E7.RecID = M.E7) )
    Left Outer Join TableE8 E8 ON (E8.RecID = M.E8) )
    Left Outer Join TableE9 E9 ON (E9.RecID = M.E9)
Order by RecID

如果您的表
table1
-
table9
有大量记录,则需要在所有九个表的
RecID
上创建索引。
我猜您当前有很多记录,但没有索引,因为对于这样一个简单的查询,30秒的时间实在太慢了。

让我们尝试一下以下步骤

  • 在包含所有列(E1到E9)的主表上创建非聚集索引
  • 在RecID列上的每个子表上创建非集群索引

让我知道注释/结果。

索引可能对该查询没有多大帮助,因为该查询没有过滤功能。你正在检索一百万条记录。查询花费了多少时间来检索值,以及处理查询花费了多少时间

SQLServer有一个很好的优化器,它将使用复杂的连接算法进行连接。即使没有索引,查询也很可能运行得很好

这就是说,在每个“E”表上同时包含
RecId
Descr
的索引可以帮助查询:
E1(RecId,Descr)
E2(RecId,Descr)
,等等。这些是覆盖索引。对于此查询,SQL Server将使用这些索引,而无需从数据页读取。仅索引
RecId
也不起作用,因为仍然需要在数据页上查找
Descr
数据

请注意,如果
RecId
已经是主键,并且
Descr
是表中唯一的列,则这些索引将是不必要的(冗余的)

编辑:

(我认为)这篇评论太长了

以下是优化此查询的一些想法:

首先,所有行都是必需的吗?例如,您是否可以添加一个
TOP1000
,以获得您需要的?很多时间都花在将行传回应用程序上。考虑将它们放入一个临时表(<代码>选择为)。这可能会运行得更快

其次,
订单需要多少时间?尝试在不使用排序依据的情况下运行查询,以查看这是否占主导地位

第三,
descr
字段有多长?如果它们很长,即使只有几千条也可能占据数据量的主导地位。注意这里的“很长”表示很多KB,而不是几百字节

第四,是
descr
字段
varchar()
char()
(或
nvarchar()
nchar()
char()
nchar()
是非常糟糕的选择,因为它们在结果集中占用了大量空间

第五(可能应该是第一),看看执行计划。您已经给出了一个非常简单的场景,因此我假设执行计划是对第一个表的扫描,并对每个表进行索引查找。如果计划看起来不像这样,那么可能会有优化的机会

编辑二:

我重复一遍。从服务器向应用程序传输数百兆字节需要时间,30秒也不是不合理的。(返回集有10个ID=40个字节加上描述字段,每个记录可能有100个字节。)问题在于数据库和应用程序之间的层设计,而不是数据库性能

试试这个:

SELECT  pvt.*
FROM 
(
    SELECT z.RecID, /*z.ID1, z.ID2, z.ID3 ...,*/ z.FK_ID_Type, t.Descr
    FROM 
    (
        SELECT  x.RecID, /*x.ID1, x.ID2, x.ID3 ...,*/ y.*
        FROM    dbo.MainTable x 
        CROSS APPLY 
        (
            SELECT  x.E1, CONVERT(TINYINT, 1) -- E1
            UNION ALL 
            SELECT  x.E2, CONVERT(TINYINT, 2) -- E2
            UNION ALL 
            SELECT  x.E3, CONVERT(TINYINT, 3) -- E4
            UNION ALL 
            SELECT  x.E4, CONVERT(TINYINT, 4) -- E4
            UNION ALL 
            SELECT  x.E5, CONVERT(TINYINT, 5) -- E5
            UNION ALL 
            SELECT  x.E6, CONVERT(TINYINT, 6) -- E6
            UNION ALL 
            SELECT  x.E7, CONVERT(TINYINT, 7) -- E7
            UNION ALL 
            SELECT  x.E8, CONVERT(TINYINT, 8) -- E8
            UNION ALL 
            SELECT  x.E9, CONVERT(TINYINT, 9) -- E9
        ) y (FK_ID, [FK_ID_Type])
    ) z INNER HASH JOIN -- or INNER MERGE JOIN
    (
        SELECT t1.RecID, t1.Descr, CONVERT(TINYINT, 1) FROM dbo.TableE1 t1
        UNION ALL 
        SELECT t2.RecID, t2.Descr, CONVERT(TINYINT, 2) FROM dbo.TableE2 t2
        UNION ALL 
        SELECT t3.RecID, t3.Descr, CONVERT(TINYINT, 3) FROM dbo.TableE3 t3
        UNION ALL 
        SELECT t4.RecID, t4.Descr, CONVERT(TINYINT, 4) FROM dbo.TableE4 t4
        UNION ALL
        SELECT t5.RecID, t5.Descr, CONVERT(TINYINT, 5) FROM dbo.TableE5 t5
        UNION ALL
        SELECT t6.RecID, t6.Descr, CONVERT(TINYINT, 6) FROM dbo.TableE6 t6
        UNION ALL
        SELECT t7.RecID, t7.Descr, CONVERT(TINYINT, 7) FROM dbo.TableE7 t7
        UNION ALL
        SELECT t8.RecID, t8.Descr, CONVERT(TINYINT, 8) FROM dbo.TableE8 t8
        UNION ALL
        SELECT t9.RecID, t9.Descr, CONVERT(TINYINT, 9) FROM dbo.TableE9 t9
    ) t(ID, Descr, [Type]) ON z.FK_ID = t.ID AND z.FK_ID_Type = t.[Type]
) v
PIVOT( MAX(v.Descr) FOR v.FK_ID_Type IN ([1], [2], [3], [4], [5], [6], [7], [8], [9]) ) pvt;

我对所有PrimeKey(表1-9)进行了聚集索引,每个表包含5000条记录。我对所有PrimeKey(表1-9)进行了聚集索引,每个表包含5000条记录。聚集索引值得吗?或者我必须只创建非聚集索引i创建您描述的索引,但仍然需要相同的时间OK。删除子表上的非聚集索引。只保留第一个,然后再试一次。相同的结果,没有任何更改将主表结果保留在临时表中,并用它连接所有表。yes RecID是主键,descr是表中唯一的字段,尽管我应该使用(RecID,descr)进行索引吗?在按照您所述创建索引后,仍然使用相同的值time@HaiderAliWajihi . . . 正如我在回答中所说,如果表中只有这些字段,那么就不需要索引。查询的性能是由处理的数据量决定的。@HaiderAliWajihi。如果您要将一百万行从数据库传输到应用程序中,那么我的第一个猜测是您的应用程序设计很差。您至少应该在数据库中进行一些处理。@HaiderAliWajihi。我重复一遍。从服务器向应用程序传输数百兆字节需要时间,30秒也不是不合理的。(返回集有10个ID=40字节加上描述字段。)问题在于数据库和应用程序之间的层的设计,而不是数据库性能。我想在我的应用程序中的datagridview中显示这一点。对于回复,您可能已经花了时间编写此sql,我欣赏您的回复。但是这个sql门槛现在需要31秒解决方案的持续时间是多少?您能否发布您的解决方案和我的解决方案的实际执行计划(使用XML格式)?我的查询耗时36秒。这两个解决方案的执行计划(XML格式)可能会有所帮助。执行计划太长,无法附加在此处