目の前に面白い問題があります。年間100万から200万の成長が見込まれる100万ユーザーアカウントのデータベースがあります。データベースは強力なTPTですが、この特定のクエリと関連するテーブルはTPTコンテンツのいずれにも触れません。
Sprocとビューの現在の設計では、2番目のデータポイント(電子メールアドレス、姓、会社など)を指定するときに、実行に最大15秒(x2)かかります。データベースはSQL Azure P11ですが、DTUバインドクエリではなく、利用可能な最高のオファリング(P15)にアップグレードしても結果に影響はありません。
以下は、sproc、ビュー、および実行計画です。すべてのインデックスが過去24時間以内に再構築または再編成され、すべての統計が更新されました。たとえば、データを見る場合、履歴メールアドレス(1..N)の概念は現在CROSS APPLY
最新のものを取得します。これにより、インデックス付きビューが回避され、履歴電子メールアドレスを単純に連結して解決し、それらを単一の列に保持できます。
多くのデータベースは、nvarchar(4000-max)列でJSONを利用します。これらの列にはすべて、計算された列が値を公開し、インデックスを有効にします。パラダイムはページングをサポートする必要があり、それを最適化する方法に関するフィードバック/アドバイスを探しています。
テーブル構造を変更することは、現時点では実行可能なオプションではありませんが、少し操作するだけで前向きなパスを確認できます。私が最初にどこを見るべきかについて誰かが何か考えを持っていますか?私は、unknownの再コンパイルと最適化の両方をテストして、影響があったかどうかを確認しました。
注:一部のビジネスロジック(独自の列名は削除または変更されています。sprocおよびビューはそのままでは実行できませんが、機能的にはソースと同じです。
CREATE PROCEDURE [dbo].[spGetUserDetailsDynamic] @JsonFilter NVARCHAR(MAX)
AS /* Page number*/
DECLARE @Page AS INT = JSON_VALUE(@JsonFilter, '$.requestPaging.page');
/* Number of records on the page*/
DECLARE @Size AS INT = JSON_VALUE(@JsonFilter, '$.requestPaging.size');
IF (@Page = -1)
SET @Page = 1;
IF (@Size = -1)
SET @Size = 32767;
/* Sort direction ASC or DESC*/
DECLARE @SortDirection AS VARCHAR(10) = JSON_VALUE(@JsonFilter, '$.requestSorting.direction');
/* Order By Column */
DECLARE @SortColumn AS VARCHAR(200) = JSON_QUERY(@JsonFilter, '$.requestSorting.keys');
SET @SortColumn = REPLACE(@SortColumn, '"', '');
SET @SortColumn = REPLACE(@SortColumn, '[', '');
SET @SortColumn = REPLACE(@SortColumn, ']', '');
/* Filters*/
DECLARE @RequestorApplicationIdFilterValue AS TINYINT
= JSON_VALUE(@JsonFilter, '$.requestFiltering.applicationIdValue');
DECLARE @CompanyAssignedKeyFilterValue AS NVARCHAR(200)
= JSON_VALUE(@JsonFilter, '$.requestFiltering.companyAssignedKeyValue');
DECLARE @CompanyAssignedKeyFilterOperation AS NVARCHAR(200)
= JSON_VALUE(@JsonFilter, '$.requestFiltering.companyAssignedKeyOperation');
DECLARE @EmailFilterValue AS NVARCHAR(200) = JSON_VALUE(@JsonFilter, '$.requestFiltering.emailValue');
DECLARE @EmailFilterOperation AS NVARCHAR(200) = JSON_VALUE(@JsonFilter, '$.requestFiltering.emailOperation');
DECLARE @LastNameFilterValue AS NVARCHAR(200) = JSON_VALUE(@JsonFilter, '$.requestFiltering.lastNameValue');
DECLARE @LastNameFilterOperation AS NVARCHAR(200) = JSON_VALUE(@JsonFilter, '$.requestFiltering.lastNameOperation');
DECLARE @FirstNameFilterValue AS NVARCHAR(200) = JSON_VALUE(@JsonFilter, '$.requestFiltering.firstNameValue');
DECLARE @FirstNameFilterOperation AS NVARCHAR(200) = JSON_VALUE(@JsonFilter, '$.requestFiltering.firstNameOperation');
DECLARE @PhoneNumberFilterValue AS NVARCHAR(200) = JSON_VALUE(@JsonFilter, '$.requestFiltering.phoneNumberValue');
DECLARE @PhoneNumberFilterOperation AS NVARCHAR(200)
= JSON_VALUE(@JsonFilter, '$.requestFiltering.phoneNumberOperation');
DECLARE @StreetAddressFilterValue AS NVARCHAR(200) = JSON_VALUE(@JsonFilter, '$.requestFiltering.streetAddressValue');
DECLARE @StreetAddressFilterOperation AS NVARCHAR(200)
= JSON_VALUE(@JsonFilter, '$.requestFiltering.streetAddressOperation');
DECLARE @CityFilterValue AS NVARCHAR(200) = JSON_VALUE(@JsonFilter, '$.requestFiltering.cityValue');
DECLARE @CityFilterOperation AS NVARCHAR(200) = JSON_VALUE(@JsonFilter, '$.requestFiltering.cityOperation');
DECLARE @RegionFilterValue AS NVARCHAR(200) = JSON_VALUE(@JsonFilter, '$.requestFiltering.regionValue');
DECLARE @RegionFilterOperation AS NVARCHAR(200) = JSON_VALUE(@JsonFilter, '$.requestFiltering.regionOperation');
DECLARE @PostalCodeFilterValue AS NVARCHAR(200) = JSON_VALUE(@JsonFilter, '$.requestFiltering.postalCodeValue');
DECLARE @PostalCodeFilterOperation AS NVARCHAR(200)
= JSON_VALUE(@JsonFilter, '$.requestFiltering.postalCodeOperation');
DECLARE @CountryFilterValue AS NVARCHAR(200) = JSON_VALUE(@JsonFilter, '$.requestFiltering.countryValue');
DECLARE @HasCompletedRegistrationFilterValue AS NVARCHAR(200)
= JSON_VALUE(@JsonFilter, '$.requestFiltering.completedRegistrationValue');
DECLARE @HasCompletedRegistrationBitValue AS BIT = NULL;
IF (@HasCompletedRegistrationFilterValue IS NOT NULL)
BEGIN
IF (@HasCompletedRegistrationFilterValue = 'true')
SET @HasCompletedRegistrationBitValue = 1;
ELSE
SET @HasCompletedRegistrationBitValue = 0;
END;
DECLARE @HasApplicationAccountsFilterValue AS NVARCHAR(200)
= JSON_VALUE(@JsonFilter, '$.requestFiltering.haveApplicationAccountsValue');
DECLARE @HasApplicationAccountsBitValue AS BIT = NULL;
IF (@HasApplicationAccountsFilterValue IS NOT NULL)
BEGIN
IF (@HasApplicationAccountsFilterValue = 'true')
SET @HasApplicationAccountsBitValue = 1;
ELSE
SET @HasApplicationAccountsBitValue = 0;
END;
DECLARE @HasProcessorAccountsFilterValue AS NVARCHAR(200)
= JSON_VALUE(@JsonFilter, '$.requestFiltering.haveProcessorAccountsValue');
DECLARE @HasProcessorAccountsBitValue AS BIT = NULL;
IF (@HasProcessorAccountsFilterValue IS NOT NULL)
BEGIN
IF (@HasProcessorAccountsFilterValue = 'true')
SET @HasProcessorAccountsBitValue = 1;
ELSE
SET @HasProcessorAccountsBitValue = 0;
END;
DECLARE @TargetApplicationIdFilterValue AS NVARCHAR(200) = JSON_VALUE(@JsonFilter, '$.requestFiltering.userTypeValue');
DECLARE @CompanyPublicIdValue AS NVARCHAR(200) = JSON_VALUE(@JsonFilter, '$.requestFiltering.companyPublicIdValue');
DECLARE @CompanyUserIdValue INT = NULL;
IF (@CompanyPublicIdValue IS NOT NULL)
BEGIN
SET @CompanyUserIdValue =
(
SELECT UserId
FROM Application.Users
WHERE UserPublicId = @CompanyPublicIdValue
);
END;
DECLARE @AccountPublicIdFilterValue AS VARCHAR(32)
= JSON_VALUE(@JsonFilter, '$.requestFiltering.accountPublicIdValue');
DECLARE @AccountIdFilterValue AS INT = JSON_VALUE(@JsonFilter, '$.requestFiltering.accountIdValue');
-- User Public ID
DECLARE @UserPublicIdFilterValue AS VARCHAR(32) = JSON_VALUE(@JsonFilter, '$.requestFiltering.userPublicIdValue');
DECLARE @UserIdFilterValue AS INT = JSON_VALUE(@JsonFilter, '$.requestFiltering.userIdValue');
IF (@UserPublicIdFilterValue IS NOT NULL AND @UserIdFilterValue IS NULL)
SET @UserIdFilterValue =
(
SELECT UserId
FROM Application.Users
WHERE UserPublicId = @UserPublicIdFilterValue
) ;
DECLARE @UserRegistrationProgressStateFilterValue AS VARCHAR(32)
= JSON_VALUE(@JsonFilter, '$.requestFiltering.userRegistrationProgressStateValue');
DECLARE @UserRegistrationProgressStateValue AS NVARCHAR(200) = NULL;
IF (@UserRegistrationProgressStateFilterValue IS NOT NULL)
BEGIN
IF (@UserRegistrationProgressStateFilterValue = '4')
SET @UserRegistrationProgressStateValue = '1,2';
ELSE
SET @UserRegistrationProgressStateValue = @UserRegistrationProgressStateFilterValue;
END;
DECLARE @TotalRecordCount INT;
DECLARE @WHERE AS NVARCHAR(MAX) = '';
DECLARE @GROUPBY AS NVARCHAR(MAX) = '';
DECLARE @SQLViewCount AS NVARCHAR(MAX)
= '
SELECT @_TotalRecordCount = SUM(S.Total)
FROM (
SELECT 1 AS Total
FROM Application.vwUserDetails T ';
DECLARE @SQL AS NVARCHAR(MAX)
= '
SELECT [Application_UserInvitations_ApplicationId]
,[Application_UserInvitations_EmailAddress]
,[Application_UserInvitations_InvitationStatusTypeId]
,[Application_UserInvitations_InvitationKey]
,[Application_UserInvitations_CompanyUserId]
,[Application_UserInvitations_Created]
,[Application_UserInvitations_Expires]
,[Application_Users_UserPublicId]
,[Application_Users_UserId]
,[Application_Users_UserCompanyAssignedKey]
,[Application_Users_FirstName]
,[Application_Users_LastName]
,[Application_Users_Created]
,[Application_Users_CompanyUserId]
,[Application_Users_ApplicationId]
,[Application_UserEmailAddresses_VerifiedEmailAddress]
,[Application_UserEmailAddresses_UnverifiedEmailAddress]
,[Application_UserInvitationRegistrationInformation_UserCompanyAssignedKey]
,[Application_UserInvitationRegistrationInformation_FirstName]
,[Application_UserInvitationRegistrationInformation_LastName]
,[Application_Companies_Name]
,[Application_Companies_UserTitleSubscriptionKey]
,[Application_Companies_CompanyUserId]
,[Application_Companies_CompanyId]
,[Application_Users_EvaluatedEmailAddress]
,[Application_Users_EvaluatedFirstName]
,[Application_Users_EvaluatedLastName]
,[Application_Users_EvaluatedUserCompanyAssignedKey]
,[Application_UserProfiles_PrimaryPhoneNumber]
,[Application_UserProfiles_MobilePhoneNumber]
,[UserHasApplicationAccount]
,[UserHasFinancialProcessorAccount]
,[Application_RegisterDate]
,[Application_Registration_Progress]
,[Application_Evaluated_User_Registration_Progress_Step]
,[Application_EvaluatedPhoneNumberCountry]
FROM [Application].[vwUserDetails] T ';
DECLARE @SQLOrderBy AS NVARCHAR(200)
= '
ORDER BY
' + ' ' + @SortColumn + ' ' + @SortDirection
+ '
OFFSET (@_Page-1)*@_Size ROWS
FETCH NEXT @_Size ROWS ONLY
';
/* Based off of requesting application, build the where clause, first with application specific filters, followed by general.*/
IF (
@RequestorApplicationIdFilterValue IS NULL
OR @RequestorApplicationIdFilterValue NOT IN ( 1, 2, 3 )
)
BEGIN
THROW 60000, 'ApplicationIdFilterValue is null or out of range', 1;
END;
IF (@CountryFilterValue IS NOT NULL)
BEGIN
SET @WHERE
= @WHERE + 'AND Application_UserAccountAddressCountryCode IN (''' + CAST(@CountryFilterValue AS VARCHAR(100))
+ ''') ';
END;
IF (@TargetApplicationIdFilterValue IS NOT NULL)
BEGIN
SET @WHERE
= @WHERE + 'AND Application_UserInvitations_ApplicationId IN ('
+ CAST(@TargetApplicationIdFilterValue AS VARCHAR(100)) + ') ';
END;
IF (@CompanyUserIdValue IS NOT NULL)
BEGIN
SET @WHERE
= @WHERE + 'AND Application_UserInvitations_CompanyUserId IN (' + CAST(@CompanyUserIdValue AS VARCHAR(100)) + ') ';
END;
IF (@HasProcessorAccountsBitValue IS NOT NULL)
BEGIN
SET @WHERE
= @WHERE + 'AND UserHasFinancialProcessorAccount = ' + CAST(@HasProcessorAccountsBitValue AS VARCHAR(100))
+ ' ';
END;
IF (@HasApplicationAccountsBitValue IS NOT NULL)
BEGIN
SET @WHERE = @WHERE + 'AND UserHasApplicationAccount = ' + CAST(@HasApplicationAccountsBitValue AS VARCHAR(100)) + ' ';
END;
IF (@UserRegistrationProgressStateValue IS NOT NULL)
BEGIN
SET @WHERE = @WHERE + 'AND Application_Registration_Progress IN (' + @UserRegistrationProgressStateValue + ') ';
END;
/* Fuzzy Text Search */
IF (@EmailFilterValue IS NOT NULL AND @EmailFilterOperation IS NOT NULL)
BEGIN
-- IsEqualTo
IF (@EmailFilterOperation = 0)
SET @WHERE = @WHERE + 'AND (Application_Users_EvaluatedEmailAddress = ''' + @EmailFilterValue + ''')';
-- StartsWith
ELSE IF (@EmailFilterOperation = 2)
SET @WHERE = @WHERE + 'AND (Application_Users_EvaluatedEmailAddress LIKE ''' + @EmailFilterValue + '%'')';
-- Contains
ELSE IF (@EmailFilterOperation = 3)
SET @WHERE = @WHERE + 'AND (Application_Users_EvaluatedEmailAddress LIKE ''%' + @EmailFilterValue + '%'')';
-- EndsWith
ELSE IF (@EmailFilterOperation = 5)
SET @WHERE = @WHERE + 'AND (Application_Users_EvaluatedEmailAddress LIKE ''%' + @EmailFilterValue + ''')';
END;
IF (
@CompanyAssignedKeyFilterValue IS NOT NULL
AND @CompanyAssignedKeyFilterOperation IS NOT NULL
)
BEGIN
-- IsEqualTo
IF (@CompanyAssignedKeyFilterOperation = 0)
SET @WHERE
= @WHERE + 'AND (Application_Users_EvaluatedUserCompanyAssignedKey = ''' + @CompanyAssignedKeyFilterValue
+ ''')';
-- StartsWith
ELSE IF (@CompanyAssignedKeyFilterOperation = 2)
SET @WHERE
= @WHERE + 'AND (Application_Users_EvaluatedUserCompanyAssignedKey LIKE ''' + @CompanyAssignedKeyFilterValue
+ '%'')';
-- Contains
ELSE IF (@CompanyAssignedKeyFilterOperation = 3)
SET @WHERE
= @WHERE + 'AND (Application_Users_EvaluatedUserCompanyAssignedKey LIKE ''%' + @CompanyAssignedKeyFilterValue
+ '%'')';
-- EndsWith
ELSE IF (@CompanyAssignedKeyFilterOperation = 5)
SET @WHERE
= @WHERE + 'AND (Application_Users_EvaluatedUserCompanyAssignedKey LIKE ''%' + @CompanyAssignedKeyFilterValue
+ ''')';
END;
IF (
@FirstNameFilterValue IS NOT NULL
AND @FirstNameFilterOperation IS NOT NULL
)
BEGIN
-- IsEqualTo
IF (@FirstNameFilterOperation = 0)
SET @WHERE = @WHERE + 'AND (Application_Users_EvaluatedFirstName = ''' + @FirstNameFilterValue + ''')';
-- StartsWith
ELSE IF (@FirstNameFilterOperation = 2)
SET @WHERE = @WHERE + 'AND (Application_Users_EvaluatedFirstName LIKE ''' + @FirstNameFilterValue + '%'')';
-- Contains
ELSE IF (@FirstNameFilterOperation = 3)
SET @WHERE = @WHERE + 'AND (Application_Users_EvaluatedFirstName LIKE ''%' + @FirstNameFilterValue + '%'')';
-- EndsWith
ELSE IF (@FirstNameFilterOperation = 5)
SET @WHERE = @WHERE + 'AND (Application_Users_EvaluatedFirstName LIKE ''%' + @FirstNameFilterValue + ''')';
END;
IF (
@LastNameFilterValue IS NOT NULL
AND @LastNameFilterOperation IS NOT NULL
)
BEGIN
-- IsEqualTo
IF (@LastNameFilterOperation = 0)
SET @WHERE = @WHERE + 'AND (Application_Users_EvaluatedLastName = ''' + @LastNameFilterValue + ''')';
-- StartsWith
ELSE IF (@LastNameFilterOperation = 2)
SET @WHERE = @WHERE + 'AND (Application_Users_EvaluatedLastName LIKE ''' + @LastNameFilterValue + '%'')';
-- Contains
ELSE IF (@LastNameFilterOperation = 3)
SET @WHERE = @WHERE + 'AND (Application_Users_EvaluatedLastName LIKE ''%' + @LastNameFilterValue + '%'')';
-- EndsWith
ELSE IF (@LastNameFilterOperation = 5)
SET @WHERE = @WHERE + 'AND (Application_Users_EvaluatedLastName LIKE ''%' + @LastNameFilterValue + ''')';
END;
IF (@CityFilterValue IS NOT NULL AND @CityFilterOperation IS NOT NULL)
BEGIN
-- IsEqualTo
IF (@CityFilterOperation = 0)
SET @WHERE = @WHERE + 'AND (Application_UserAccountAddresses_City = ''' + @CityFilterValue + ''')';
-- StartsWith
ELSE IF (@CityFilterOperation = 2)
SET @WHERE = @WHERE + 'AND (Application_UserAccountAddresses_City LIKE ''' + @CityFilterValue + '%'')';
-- Contains
ELSE IF (@CityFilterOperation = 3)
SET @WHERE = @WHERE + 'AND (Application_UserAccountAddresses_City LIKE ''%' + @CityFilterValue + '%'')';
-- EndsWith
ELSE IF (@CityFilterOperation = 5)
SET @WHERE = @WHERE + 'AND (Application_UserAccountAddresses_City LIKE ''%' + @CityFilterValue + ''')';
END;
IF (@RegionFilterValue IS NOT NULL AND @RegionFilterOperation IS NOT NULL)
BEGIN
-- IsEqualTo
IF (@RegionFilterOperation = 0)
SET @WHERE = @WHERE + 'AND (Application_UserAccountAddresses_Region = ''' + @RegionFilterValue + ''')';
-- StartsWith
ELSE IF (@RegionFilterOperation = 2)
SET @WHERE = @WHERE + 'AND (Application_UserAccountAddresses_Region LIKE ''' + @RegionFilterValue + '%'')';
-- Contains
ELSE IF (@RegionFilterOperation = 3)
SET @WHERE = @WHERE + 'AND (Application_UserAccountAddresses_Region LIKE ''%' + @RegionFilterValue + '%'')';
-- EndsWith
ELSE IF (@RegionFilterOperation = 5)
SET @WHERE = @WHERE + 'AND (Application_UserAccountAddresses_Region LIKE ''%' + @RegionFilterValue + ''')';
END;
IF (
@PostalCodeFilterValue IS NOT NULL
AND @PostalCodeFilterOperation IS NOT NULL
)
BEGIN
-- IsEqualTo
IF (@PostalCodeFilterOperation = 0)
SET @WHERE = @WHERE + 'AND (Application_UserAccountAddresses_PostalCode = ''' + @PostalCodeFilterValue + ''')';
-- StartsWith
ELSE IF (@PostalCodeFilterOperation = 2)
SET @WHERE
= @WHERE + 'AND (Application_UserAccountAddresses_PostalCode LIKE ''' + @PostalCodeFilterValue + '%'')';
-- Contains
ELSE IF (@PostalCodeFilterOperation = 3)
SET @WHERE
= @WHERE + 'AND (Application_UserAccountAddresses_PostalCode LIKE ''%' + @PostalCodeFilterValue + '%'')';
-- EndsWith
ELSE IF (@PostalCodeFilterOperation = 5)
SET @WHERE
= @WHERE + 'AND (Application_UserAccountAddresses_PostalCode LIKE ''%' + @PostalCodeFilterValue + ''')';
END;
IF (
@StreetAddressFilterValue IS NOT NULL
AND @StreetAddressFilterOperation IS NOT NULL
)
BEGIN
-- IsEqualTo
IF (@StreetAddressFilterOperation = 0)
SET @WHERE
= @WHERE + 'AND (Application_UserAccountAddresses_StreetAddress1 = ''' + @StreetAddressFilterValue
+ ''' OR Application_UserAccountAddresses_StreetAddress2 = ''' + @StreetAddressFilterValue
+ ''' OR Application_UserAccountAddresses_StreetAddress3 = ''' + @StreetAddressFilterValue + ''')';
-- StartsWith
ELSE IF (@StreetAddressFilterOperation = 2)
SET @WHERE
= @WHERE + 'AND (Application_UserAccountAddresses_StreetAddress1 LIKE ''' + @StreetAddressFilterValue
+ '%'' OR Application_UserAccountAddresses_StreetAddress2 LIKE ''' + @StreetAddressFilterValue
+ '%'' OR Application_UserAccountAddresses_StreetAddress3 LIKE ''' + @StreetAddressFilterValue + '%'')';
-- Contains
ELSE IF (@StreetAddressFilterOperation = 3)
SET @WHERE
= @WHERE + 'AND (Application_UserAccountAddresses_StreetAddress1 LIKE ''%' + @StreetAddressFilterValue
+ '%'' OR Application_UserAccountAddresses_StreetAddress2 LIKE ''%' + @StreetAddressFilterValue
+ '%'' OR Application_UserAccountAddresses_StreetAddress3 LIKE ''%' + @StreetAddressFilterValue + '%'')';
-- EndsWith
ELSE IF (@StreetAddressFilterOperation = 5)
SET @WHERE
= @WHERE + 'AND (Application_UserAccountAddresses_StreetAddress1 LIKE ''%' + @StreetAddressFilterValue
+ ''' OR Application_UserAccountAddresses_StreetAddress2 LIKE ''%' + @StreetAddressFilterValue
+ ''' OR Application_UserAccountAddresses_StreetAddress3 LIKE ''%' + @StreetAddressFilterValue + ''')';
END;
IF (
@PhoneNumberFilterValue IS NOT NULL
AND @PhoneNumberFilterOperation IS NOT NULL
)
BEGIN
-- IsEqualTo
IF (@PhoneNumberFilterOperation = 0)
SET @WHERE
= @WHERE + 'AND (Application_UserProfiles_Profile_vPrimaryTelephone_Numeric = ''' + @PhoneNumberFilterValue
+ ''' OR Application_UserProfiles_Profile_vMobileTelephone_Numeric = ''' + @PhoneNumberFilterValue + ''')';
-- StartsWith
ELSE IF (@PhoneNumberFilterOperation = 2)
SET @WHERE
= @WHERE + 'AND (Application_UserProfiles_Profile_vPrimaryTelephone_Numeric LIKE ''' + @PhoneNumberFilterValue
+ ''' OR Application_UserProfiles_Profile_vMobileTelephone_Numeric LIKE ''' + @PhoneNumberFilterValue
+ '%'')';
-- Contains
ELSE IF (@PhoneNumberFilterOperation = 3)
SET @WHERE
= @WHERE + 'AND (Application_UserProfiles_Profile_vPrimaryTelephone_Numeric LIKE ''%'
+ @PhoneNumberFilterValue + '%'' OR Application_UserProfiles_Profile_vMobileTelephone_Numeric LIKE ''%'
+ @PhoneNumberFilterValue + '%'')';
-- EndsWith
ELSE IF (@PhoneNumberFilterOperation = 5)
SET @WHERE
= @WHERE + 'AND (Application_UserProfiles_Profile_vPrimaryTelephone_Numeric LIKE ''%'
+ @PhoneNumberFilterValue + ''' OR Application_UserProfiles_Profile_vMobileTelephone_Numeric LIKE ''%'
+ @PhoneNumberFilterValue + ''')';
END;
SET @GROUPBY
= '[Application_UserInvitations_ApplicationId]
,[Application_UserInvitations_EmailAddress]
,[Application_UserInvitations_InvitationStatusTypeId]
,[Application_UserInvitations_InvitationKey]
,[Application_UserInvitations_Created]
,[Application_UserInvitations_Expires]
,[Application_UserInvitations_CompanyUserId]
,[Application_Users_UserPublicId]
,[Application_Users_UserId]
,[Application_Users_UserCompanyAssignedKey]
,[Application_Users_FirstName]
,[Application_Users_LastName]
,[Application_Users_Created]
,[Application_Users_CompanyUserId]
,[Application_Users_ApplicationId]
,[Application_UserEmailAddresses_VerifiedEmailAddress]
,[Application_UserEmailAddresses_UnverifiedEmailAddress]
,[Application_UserInvitationRegistrationInformation_UserCompanyAssignedKey]
,[Application_UserInvitationRegistrationInformation_FirstName]
,[Application_UserInvitationRegistrationInformation_LastName]
,[Application_Companies_Name]
,[Application_Companies_UserTitleSubscriptionKey]
,[Application_Companies_CompanyUserId]
,[Application_Companies_CompanyId]
,[Application_Users_EvaluatedEmailAddress]
,[Application_Users_EvaluatedFirstName]
,[Application_Users_EvaluatedLastName]
,[Application_Users_EvaluatedUserCompanyAssignedKey]
,[Application_UserProfiles_PrimaryPhoneNumber]
,[Application_UserProfiles_MobilePhoneNumber]
,[UserHasApplicationAccount]
,[UserHasFinancialProcessorAccount]
,[Application_RegisterDate]
,[Application_Registration_Progress]
,[Application_Evaluated_User_Registration_Progress_Step]
,[Application_EvaluatedPhoneNumberCountry]';
/* Always hide cloaked*/
SET @WHERE = @WHERE + 'AND Application_UserInvitations_InvitationStatusTypeId != 4 ';
/* Build SQL and dynamic WHERE clause */
IF LEN(@WHERE) > 0
BEGIN
-- Where clause
SET @SQLViewCount = @SQLViewCount + ' WHERE ' + RIGHT(@WHERE, LEN(@WHERE) - 3);
-- Group by
SET @SQLViewCount = @SQLViewCount + ' GROUP BY ' + RIGHT(@GROUPBY, LEN(@GROUPBY) - 0);
SET @SQLViewCount = @SQLViewCount + ') S';
-- Main SELECT dynamic SQL
SET @SQL = @SQL + ' WHERE ' + RIGHT(@WHERE, LEN(@WHERE) - 3);
SET @SQL = @SQL + ' GROUP BY ' + RIGHT(@GROUPBY, LEN(@GROUPBY) - 0) + ' ' + @SQLOrderBy;
-- Execute View Total Record Count
EXEC sp_executesql @SQLViewCount,
N'@_TotalRecordCount
INT OUTPUT',
@_TotalRecordCount = @TotalRecordCount OUTPUT;
-- Summarise Counts, Size and Page (resultset 1)
SELECT CAST(CEILING((CAST(@TotalRecordCount AS FLOAT) / (CAST(@Size AS FLOAT)))) AS INT) AS TotalPages,
@TotalRecordCount AS TotalRecordCount,
CASE
WHEN @Size = 32767 THEN
@TotalRecordCount
ELSE
@Size
END AS PageSize,
@Page AS PageNumber;
-- Execute main SELECT (resultset 2)
EXEC sp_executesql @SQL,
N'@_Page
INT,
@_Size
INT,
@_SortColumn
VARCHAR(40)',
@_Page = @Page,
@_Size = @Size,
@_SortColumn = @SortColumn;
END;
2つの簡単な改善:
_@CompanyPublicIdValue
_をUserPublicIdと同じ型にキャストして、このクエリを修正します。 _@CompanyPublicIdValue
_はnvarchar(32)
であり、列の型よりも データ型の優先順位 が高くなります。したがって、比較ではすべての行で変換が必要です。
それは高価であり、そうすべきではありません。
_SET @CompanyUserIdValue =
(
SELECT UserId
FROM Application.Users
WHERE UserPublicId = @CompanyPublicIdValue
)
_
1つのクエリで行をカウントして次のクエリで返すのではなく、最初のクエリでキー値を一時テーブル/テーブル変数にフェッチし、2番目のクエリで結合します。
次に、返されるキーを識別するクエリの改善に取り組みます。おそらく、そのクエリは、ベーステーブルまたはインデックス付きビューに直接アクセスできます。次に、最後のクエリは既存のビューをキー値の一時テーブルに結合します。
実行計画には18 CONVERT_IMPLICIT
があります。それぞれを見つけて、1つずつ修正してください。
NVARCHARとVARCHARは非常に頻繁に交換可能に使用されます。VARCHARを使用し、サイズをできるだけ制限する必要があると思います。
プロシージャに**SET NOCOUNT ON**
がありません。
ページングのため、プロシージャはまだ高速です。
表示される主な問題はGroup By
です。GroupByを使用して重複レコードを排除しているようです。
したがって、クエリが間違っている場合は、どの結合が多くのレコードを引き起こしているのかを見つけます。
または、ROW_NUMBER(ウィンドウ関数)を使用して重複レコードを削除します。
Group BYが不要な場合は、パフォーマンスが向上していなくても削除してください。後でその向上が見られます。
実際、LEFT JOIN
とOUTER APPLY
のみを使用している場合は、それぞれINNER
とCROSS APPLY
に変換できるかどうかを確認してください。
登録および招待されたニーズ
これはあなたの要件かもしれませんが、すべての結合を徹底的に調べ、左結合を排除する必要があります。
必要以上のレコードを取得していると思いますので、Group By
を使用しています。これがそうである場合、これがパフォーマンスの低下の背後にある理由です。
ビューで2を除くすべての結合にコメントを付け、プロシージャでGroup Byを削除してテストとデバッグを開始し、正しい行数を取得して、一度に1つの結合をゆっくり削除することをお勧めします。
たとえば、このOUTER APPLYで、
OUTER APPLY
(
SELECT TOP 1 RAAA.Application_AccountAddresses_AddressDetails_vCountry
FROM Application.Accounts RACA
JOIN Application.AccountAddresses RAAA
ON RAAA.AccountId = RACA.AccountId
WHERE RACA.UserId = U.UserId
AND RAAA.AddressTypeId = 1
ORDER BY RAAA.AccountAddressId DESC
) AS ResidentialAddressCountry
ここでは両方のテーブルがINNER JOIN
ですが、メインクエリの同じテーブルはLEFT JOIN
です。
それが正しいか ?
ResidentialAddressCountry
およびBusinessAddressCountry
のOUTER APPLY
は必要ですか?
代わりに、
CASE
WHEN AddressTypeId = 1
AND AA.Application_AccountAddresses_AddressDetails_vCountry IS NOT NULL
THEN ResidentialAddressCountry.Application_AccountAddresses_AddressDetails_vCountry
WHEN AddressTypeId = 3
AND AA.BusinessAddressCountry.Application_AccountAddresses_AddressDetails_vCountry IS NOT NULL
THEN BusinessAddressCountry.Application_AccountAddresses_AddressDetails_vCountry
ELSE NULL
END Application_EvaluatedPhoneNumberCountry
そして、両方の外側のコメントをコメントし、理解を深めるためにテーブルのエイリアスに注意してください。
Application.fnRemoveNonNumericCharacters
同じビューを使用したいが、非数値を削除したくない、または連結したくない場合は、新しいビューを作成する必要がありますか?
ユーザーがこれらの小さな問題について決定するようにします。Secondly UDF
は悪名高い悪パフォーマンスです。
そのため、ビューからUDFを削除します。procでインラインで「数字以外の文字の削除作業」を実行します
値をフェッチした後、これを上に安全に書き込むことができます。
IF (
@RequestorApplicationIdFilterValue IS NULL
OR @RequestorApplicationIdFilterValue NOT IN ( 1, 2, 3 )
)
BEGIN
THROW 60000, 'ApplicationIdFilterValue is null or out of range', 1;
END;