Есть ли способ получить разные результаты для одного и того же запроса SQL, если данные остаются одинаковыми? - PullRequest
4 голосов
/ 19 августа 2011

При выполнении этого запроса я периодически получаю другой набор результатов ... иногда он дает 1363, иногда 1365, а иногда 1366 результатов. Данные не меняются. Что может быть причиной этого и есть ли способ предотвратить это? Запрос выглядит примерно так:

SELECT * 
FROM 
    (
            SELECT  
                        RC.UserGroupId,
                        RC.UserGroup,
                        RC.ClientId AS CLID,                     
                        CASE WHEN T1.MultipleClients = 1 THEN RC.Salutation1 ELSE RC.DisplayName1 END AS szDisplayName,
                        T1.MultipleClients,
                        RC.IsPrimaryRecord,
                        RC.RecordTypeId,
                        RC.ClientTypeId,
                        RC.ClientType,
                        RC.IsDeleted,
                        RC.IsCompany,                                            
                        RC.KnownAs,
                        RC.Salutation1,
                        RC.FirstName, 
                        RC.Surname,                   
                        Relationship, 
                        C.DisplayName Client,
                        RC.DisplayName RelatedClient, 
                        E.Email,                                                            
                        RC.DisplayName  + ' is the ' + R.Relationship + ' of ' + C.DisplayName Description,
                        ROW_NUMBER() OVER (PARTITION BY E.Email ORDER BY Relationship DESC) AS sequence_id


            FROM 
                        SSDS.Client.ClientExtended C 
                                                                              INNER JOIN 
                        SSDS.Client.ClientRelationship R WITH (NOLOCK)ON C.ClientId = R.ClientID 
                                                                              INNER JOIN 
                        SSDS.Client.ClientExtended RC WITH (NOLOCK)ON R.RelatedClientId = RC.ClientId
                                                                              LEFT OUTER JOIN
                        SSDS.Client.Email E WITH (NOLOCK)ON RC.ClientId = E.ClientId                 
                                                                              LEFT OUTER JOIN 
                        SSDS.Client.UserDefinedData UD WITH (NOLOCK)ON C.ClientId = UD.ClientId AND C.UserGroupId = UD.UserGroupId 
                                                                              INNER JOIN                                                                 

                        (
                              SELECT 
                                          E.Email, 
                                          CASE WHEN (COUNT(DISTINCT RC.DisplayName) > 1) THEN 1 ELSE 0 END AS MultipleClients 

                              FROM
                                          SSDS.Client.ClientExtended C 
                                                                                                INNER JOIN 
                                          SSDS.Client.ClientRelationship R WITH (NOLOCK)ON C.ClientId = R.ClientID 
                                                                                                INNER JOIN 
                                          SSDS.Client.ClientExtended RC WITH (NOLOCK)ON R.RelatedClientId = RC.ClientId
                                                                                                LEFT OUTER JOIN
                                          SSDS.Client.Email E WITH (NOLOCK)ON RC.ClientId = E.ClientId                 
                                                                                                LEFT OUTER JOIN 
                                          SSDS.Client.UserDefinedData UD WITH (NOLOCK)ON C.ClientId = UD.ClientId AND C.UserGroupId = UD.UserGroupId

                              WHERE 
                                          Relationship IN ('z-Group Principle', 'z-Group Member ')           
                                          AND E.Email IS NOT NULL

                              GROUP BY E.Email 

                        ) T1 ON E.Email = T1.Email


            WHERE 

                                                Relationship IN ('z-Group Principle', 'z-Group Member ')           
                                                AND E.Email IS NOT NULL                                         
    ) T


WHERE       
            sequence_id = 1
            AND T.UserGroupId IN (Select * from iCentral.dbo.GetSubUserGroups('471b9cbd-2312-4a8a-bb20-35ea53d30340',0))         
            AND T.IsDeleted = 0           
            AND T.RecordTypeId = 1 
            AND T.ClientTypeId IN
            (
                        '1',              --Client
                        '-1652203805'    --NTU                      
            )        

        AND T.CLID NOT IN
          (
            SELECT DISTINCT  
                               UDDF.CLID
            FROM
                   SLacsis_SLM.dbo.T_UserDef UD WITH (NOLOCK) 
                          INNER JOIN
                   SLacsis_SLM.dbo.T_UserDefData UDDF WITH (NOLOCK)
                   ON UD.UserDef_ID = UDDF.UserDef_ID
                          INNER JOIN
                   SLacsis_SLM.dbo.T_Client CLL WITH (NOLOCK)
                   ON CLL.CLID = UDDF.CLID AND CLL.UserGroup_CLID = UD.UserID

            WHERE 
                           UD.UserDef_ID in    
                                    (
                                    'F68F31CE-525B-4455-9D50-6DA77C66FEE5',                                    
                                    'A7CECB03-866C-4F1F-9E1A-CEB09474FE47'  
                                    )

                           AND UDDF.Data = 'NO'
           ) 


ORDER BY T.Surname

EDIT:

Я удалил все NOLOCK (в том числе в представлениях и UDF), и у меня все еще остается та же проблема. Я получаю одни и те же результаты каждый раз для вложенного выбора (T), и если я помещаю набор результатов T во временную таблицу в начале запроса и присоединяюсь к временной таблице вместо вложенного выбора, то конечный набор результатов то же самое каждый раз, когда я запускаю запрос.

EDIT2:

Я продолжал читать ROW_NUMBER () ... Я разбиваю по электронной почте (из которых есть дубликаты) и упорядочиваю по Отношениям (где есть только 1 из 2 отношений). Может ли это привести к тому, что запрос будет недетерминированным и будет ли способ это исправить?

EDIT3:

Вот фактические планы выполнения, если кому-то это интересно. http://www.mediafire.com/?qo5gkh5dftxf0ml. Можно ли увидеть, что он выполняется в режиме чтения, зафиксированном в плане выполнения? Я сравнил файлы с помощью WinMerge, и единственные различия, кажется, заключаются в подсчете (ActualRows = "").

EDIT4:

Это работает:

SELECT * FROM 
(
   SELECT *, 
             ROW_NUMBER() OVER (PARTITION BY B.Email ORDER BY Relationship DESC) AS sequence_id
             FROM
            (

                                    SELECT DISTINCT  
                                    RC.UserGroupId,
                                    ...
            ) B...

EDIT5:

При выполнении одного и того же запроса ROW_NUMBER () (T в исходном вопросе, просто выбирая RC.DisplayName и ROW_NUMBER) дважды подряд, я получаю разные звания для некоторых людей:

enter image description here

Есть ли у кого-нибудь хорошее объяснение / пример того, почему или как ROW_NUMBER () для набора результатов, который содержит дубликаты, может по-разному ранжироваться при каждом запуске и, в конечном итоге, изменять количество результатов?

EDIT6:

Хорошо, я думаю, теперь это имеет смысл для меня. Это происходит, когда люди 2 человека имеют одинаковый адрес электронной почты (например, пара мужа и жены) и отношения. Я полагаю, что в этом случае их рейтинг ROW_NUMBER () является произвольным и может меняться при каждом запуске.

Ответы [ 6 ]

10 голосов
/ 19 августа 2011

Использование NOLOCK повсеместно означает, что вы выполняете грязное чтение и увидите незафиксированные данные, данные, которые будут откатаны, временные и противоречивые данные и т. Д.

Снимите их, попробуйте еще раз, сообщите о просьбах

Редактировать: некоторые опции с удаленными NOLOCKS

  1. Данные действительно меняются
  2. Изменяется некоторый параметр или фильтр (например, GETDATE)
  3. Некоторые сравнения с плавающей запятойкаждый раз работает на разных ядрах
    См. это на dba.se https://dba.stackexchange.com/q/4810/630
  4. Встроенные NOLOCK в udf или представлениях (например, iCentral.dbo.GetSubUserGroups)
  5. ...
4 голосов
/ 24 августа 2011

Я думаю, что ваша проблема в первом ряду над разделом не является детерминированной.Я подозреваю, что электронная почта и отношения не уникальны.

    ROW_NUMBER() OVER (PARTITION BY E.Email ORDER BY Relationship DESC) AS sequence_id 

Позже вы изучите первую строку раздела.

    WHERE   T.sequence_id = 1
        AND T.UserGroupId ... 

Если эта первая строка является произвольной, то вы получите произвольное сравнение.Вам необходимо добавить в ORDER BY, чтобы включить полный уникальный ключ.Если нет уникального ключа, то вам нужно создать его или жить с произвольными результатами.Даже для таблицы с кластеризованным PK порядок выбора строк не гарантируется, если только PK не находится в предложении sort.

4 голосов
/ 24 августа 2011

Как я сказал вчера в комментариях, нумерация строк для строк с повторяющимися значениями E.Email, Relationship будет произвольной.

Чтобы сделать его детерминированным, вам нужно будет сделать PARTITION BY B.Email ORDER BY Relationship DESC, SomeUniqueColumn. Интересно, что он меняется между запусками, хотя используется один и тот же план выполнения. Я предполагаю, что это является следствием хеш-соединения.

3 голосов
/ 24 августа 2011

Это, вероятно, связано с заказом. У вас есть sequence_id, определенный как row_number, упорядоченный по Relationship. Вы всегда получите разумный порядок по отношениям, но кроме этого ваш row_number будет случайным. Таким образом, вы можете получать разные строки с sequence_id 1 каждый раз. Это, в свою очередь, повлияет на ваше предложение where, и вы можете получить различное количество результатов. Чтобы исправить это, чтобы получить непротиворечивый результат, добавьте еще одно поле к порядку вашего row_number. Используйте первичный ключ, чтобы быть уверенным в последовательных результатах.

2 голосов
/ 24 августа 2011

Недавно в КБ были устранены проблемы с ROW_NUMBER () ... см. ИСПРАВЛЕНИЕ: вы получаете неверный результат при выполнении запроса, который использует функцию row_number в SQL Server 2008 для получения подробной информации.

Однако этот KB указывает на проблему, когда параллелизм вызывается для выполнения, и, глядя на ваши планы выполнения, я не вижу, как это происходит. Но тот факт, что MS обнаружила проблему с ним в одной ситуации, делаетЯ немного насторожен - то есть, может ли та же проблема возникнуть для достаточно сложного запроса (и ваш план выполнения выглядит достаточно большим).

Так что, возможно, стоит проверить уровни исправлений SQL Server 2008.

0 голосов
/ 29 марта 2013

U Должен использовать только

Order by

без prtition by.

ROW_NUMBER() OVER (ORDER BY Relationship DESC) AS sequence_id 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...