Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/27.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 server 自联接、子查询或其他什么?_Sql Server_Tsql_Query Optimization - Fatal编程技术网

Sql server 自联接、子查询或其他什么?

Sql server 自联接、子查询或其他什么?,sql-server,tsql,query-optimization,Sql Server,Tsql,Query Optimization,好的,所以我需要找出在数据库中执行一些动态构建查询的最佳方法 我有两个表MA_对象和MA_属性MA_Objects包含用户列表,并具有表示与该用户相关的单值属性的列。(例如,名字、姓氏)MA_属性包含该用户的多值属性(例如电子邮件地址) MA_Attributes存储由强制属性名称和属性值列组成的值对,这取决于其数据类型。所以每一列都有一个attributeName,如果该属性是字符串,那么它的值将在attributeValueString中。其他attributeValue*列必须为空 表结构

好的,所以我需要找出在数据库中执行一些动态构建查询的最佳方法

我有两个表
MA_对象
MA_属性
MA_Objects
包含用户列表,并具有表示与该用户相关的单值属性的列。(例如,名字、姓氏)
MA_属性
包含该用户的多值属性(例如电子邮件地址)

MA_Attributes存储由强制属性名称和属性值列组成的值对,这取决于其数据类型。所以每一列都有一个attributeName,如果该属性是字符串,那么它的值将在attributeValueString中。其他attributeValue*列必须为空

表结构如下所示

CREATE TABLE [dbo].[MA_Objects](
    [id] [uniqueidentifier] ROWGUIDCOL  NOT NULL,
    [firstName] [nvarchar](400) NULL,
    [givenNames] [nvarchar](400) NULL,
    [middleName] [nvarchar](400) NULL,
    [surname] [nvarchar](400) NULL,
    [objectclass] [nvarchar](400) NULL,
    [supervisor] [uniqueidentifier] NULL

CREATE TABLE [dbo].[MA_Attributes](
    [id] [uniqueidentifier] ROWGUIDCOL  NOT NULL,
    [objectId] [uniqueidentifier] NOT NULL,
    [attributeName] [nvarchar](30) NOT NULL,
    [attributeValueString] [nvarchar](400) NULL,
    [attributeValueInt] [bigint] NULL,
    [attributeValueBinary] [varbinary](800) NULL,
    [attributeValueReference] [uniqueidentifier] NULL
[MA_Attributes].[objectId]
是指向
[MA_Objects].[id]

因此,该应用程序需要能够通过查询这些属性值,从MA_Objects表中找到对象ID。搜索可能很简单,只需找到具有邮件地址的用户“test@test.com或者它可能是存储在两个表中的属性的复杂组合(使用AND和or条件的组合)

MA_Objects表中约有500k条记录。MA_Attributes表将包含数千万条记录。表现很重要

我的问题是,我最好使用嵌套的SELECT子查询,还是使用一系列自连接来实现这一点?还是完全不同的东西?这两种方法似乎都有效,我很难理解实际的查询计划来查看引擎盖下发生了什么

这是两种格式的相同查询

子查询模型

select distinct 
    [o].[id] 
from [dbo].[MA_Objects] [o] 
left join [dbo].[MA_Attributes] [a] 
on ([o].[id] = [a].[objectId]) 
where 
(
    [o].[objectClass] = N'user' 
and
    (
        (
            [o].[supervisor] in ('6213F48A-A97F-48E2-AFD7-2EF830C4DAA8', '0917EC45-CA23-41F5-911C-B92A90140AFD', '69B1DA67-4E3C-406E-8B78-B4633800B491')
        ) 
    and 
        (   
        [o].[id] in 
            (
                select [a].[objectId] 
                from [dbo].[MA_Attributes] [a] 
                where
                (
                    (
                        [a].[attributeName] = N'mailAlternateAddresses' 
                    and 
                        [a].[attributeValueString] in (N'test.test@test.com', N'test3.test3@test.com')
                    )
                )
            )
        )
    and 
        (   
        [o].[id] in 
            (
                select [a].[objectId] 
                from [dbo].[MA_Attributes] [a] 
                where
                (
                    (
                        [a].[attributeName] = N'objectSids'
                    and 
                        [a].[attributeValueBinary] in (0x0001020304, 0x0007070707)
                    )
                )
            )
        )
    and 
        (   
        [o].[id] in 
            (
                select [a].[objectId] 
                from [dbo].[MA_Attributes] [a] 
                where
                (
                    (
                        [a].[attributeName] = N'expiryDates' 
                    and
                        [a].[attributeValueInt] in (44, 77, 99)
                    )
                )
            )
        )
    )
)
自连接模型

select distinct 
    [o].[id] 
from [dbo].[MA_Objects] [o] 
left join [dbo].[MA_Attributes] [a] 
on ([o].[id] = [a].[objectId]) 
where 
(
    [o].[objectClass] = N'user' 
and
    (
        (
            [o].[supervisor] in ('6213F48A-A97F-48E2-AFD7-2EF830C4DAA8', '0917EC45-CA23-41F5-911C-B92A90140AFD', '69B1DA67-4E3C-406E-8B78-B4633800B491')
        ) 
        and 
        (   
            [o].[id] in 
            (
                select [a].[objectId] 
                from [dbo].[MA_Attributes] [a] 
                left join [dbo].[MA_Attributes] [a0] on ([a].[objectId] = [a0].[objectId]) 
                left join [dbo].[MA_Attributes] [a1] on ([a].[objectId] = [a1].[objectId]) 
                left join [dbo].[MA_Attributes] [a2] on ([a].[objectId] = [a2].[objectId]) 
                where 
                (
                    [a].[objectId] = [a0].[objectId]
                and 
                    [a].[id] <> [a0].[id] 
                and 
                    [a].[objectId] = [a1].[objectId] 
                and 
                    [a].[id] <> [a1].[id] 
                and 
                    [a].[objectId] = [a2].[objectId] 
                and 
                    [a].[id] <> [a2].[id] 
                and 
                    (
                        (
                            [a0].[attributeName] = N'mailAlternateAddresses' 
                        and 
                            [a0].[attributeValueString] in (N'test.test@test.com', N'test3.test3@test.com')
                        )
                    and 
                        (
                            [a1].[attributeName] = N'objectSids'
                        and 
                            [a1].[attributeValueBinary] in (0x0001020304, 0x0007070707)
                        )
                    and 
                        (
                            [a2].[attributeName] = N'expiryDates' 
                        and
                            [a2].[attributeValueInt] in (44, 77, 99)
                        )
                    )
                )
            )
        )
    )
)
选择distinct
[o] [id]
来自[dbo]。[MA_Objects][o]
左连接[dbo].[MA_属性][a]
在([o].[id]=[a].[objectId])
哪里
(
[o] [objectClass]=N'user'
和
(
(
[o] [supervisor]in('6213F48A-A97F-48E2-AFD7-2EF830C4DAA8','0917EC45-CA23-41F5-911C-B92A90140AFD','69B1DA67-4E3C-406E-8B78-B4633800B491')
) 
及
(   
[o] [id]in
(
选择[a].[objectId]
from[dbo].[MA_属性][a]
[a].[objectId]=[a0].[objectId]上的左联接[dbo].[MA_属性][a0]
[a].[objectId]=[a1].[objectId]上的左联接[dbo].[MA_属性][a1]
[a].[objectId]=[a2].[objectId]上的左联接[dbo].[MA_属性][a2]
哪里
(
[a] [objectId]=[a0]。[objectId]
及
[a] [id][a0]。[id]
及
[a] [objectId]=[a1]。[objectId]
及
[a] [id][a1]。[id]
及
[a] [objectId]=[a2]。[objectId]
及
[a] [id][a2]。[id]
及
(
(
[a0].[attributeName]=N'mailAlternateAddresses'
及
(N'test)中的[a0].[attributeValueString]。test@test.com",N"test3。test3@test.com')
)
及
(
[a1].[attributeName]=N'ObjectSID'
及
(0x0001020304、0x00070707)中的[a1].[attributeValueBinary]
)
及
(
[a2].[attributeName]=N'expiryDates'
和
[a2].[attributeValueInt]in(44,77,99)
)
)
)
)
)
)
)

嵌套的select语句几乎保证性能最差,SQL Server每次都需要跟踪表

您的self-join语句仍然是sub-select,您应该按照如下所示重写它

SELECT o.*
    FROM @MA_Objects AS o
    LEFT OUTER JOIN @MA_Attributes AS at1
        ON o.id = at1.objectId
    LEFT OUTER JOIN @MA_Attributes AS at2
        ON o.id = at2.objectId
    LEFT OUTER JOIN @MA_Attributes AS at3
        ON o.id = at3.objectId
    WHERE o.objectclass = N'user'
        AND o.supervisor IN ( '6213F48A-A97F-48E2-AFD7-2EF830C4DAA8', '0917EC45-CA23-41F5-911C-B92A90140AFD',
                              '69B1DA67-4E3C-406E-8B78-B4633800B491' )
        AND (
              at1.attributeName = N'mailAlternateAddresses'
              AND at1.attributeValueString IN ( N'test.test@test.com', N'test3.test3@test.com' ) )
        AND (
              at2.attributeName = N'objectSids'
              AND at2.attributeValueBinary IN ( 0x0001020304, 0x0007070707 ) )
        AND (
              at3.attributeName = N'expiryDates'
              AND at3.attributeValueInt IN ( 44, 77, 99 ) )
Join
操作将比操作中的
更快。这样,您将只在每个
JOIN
中的有限行数之后进行操作,只有与
o.id
匹配的行才会被返回和计算

当您想要编写出色的性能查询时,您应该尝试尽快减少行数,并且只处理您需要的子集

因此,根据您需要搜索的信息,您需要相应地重写查询,以尽快减少记录数,以保持高性能


注意:忘了提到我将您的表更改为表变量以使用intellisense

好的,这样看起来和感觉都好多了。有趣的是,该查询产生的执行计划与我运行的其他一些实验查询相同,但这更具可读性,也更易于构建。