|
Почему ораклисты так не любят MS SQL?
#33399207
Ссылка:
Ссылка на сообщение:
Ссылка с названием темы:
Ссылка на профиль пользователя:
|
Участник
Откуда: Москва (Муром)
Сообщения: 78 075
|
|
softwarerА каков самый оптимальный подход?
...
Для обеих связок?
Это очень сильно завист от запроса. Например, сравним:
1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30.
SELECT
*
FROM
tblProducts P
INNER JOIN tblProdNomenclature N ON
P.colProductID = N.colProductID
INNER JOIN tblSpecifications S ON
N.colProductID = S.colProductID
|--Merge Join(Inner Join, MERGE:([N].[colProductID])=([S].[colProductID]), RESIDUAL:([N].[colProductID]=[S].[colProductID]))
|--Merge Join(Inner Join, MERGE:([N].[colProductID])=([P].[colProductID]), RESIDUAL:([P].[colProductID]=[N].[colProductID]))
| |--Clustered Index Scan(OBJECT:([data].[dbo].[tblProdNomenclature].[PK_tblProdNomenclature] AS [N]), ORDERED FORWARD)
| |--Clustered Index Scan(OBJECT:([data].[dbo].[tblProducts].[PK_tblProducts] AS [P]), ORDERED FORWARD)
|--Clustered Index Scan(OBJECT:([data].[dbo].[tblSpecifications].[PK_tblSpecifications] AS [S]), ORDERED FORWARD)
SELECT
*
FROM
tblProducts P
INNER JOIN tblProdNomenclature N ON
P.colProductID = N.colProductID
INNER JOIN tblSpecifications S ON
N.colProductID = S.colProductID
WHERE
N.colRailTypeID = 1
|--Merge Join(Inner Join, MERGE:([N].[colProductID])=([S].[colProductID]), RESIDUAL:([N].[colProductID]=[S].[colProductID]))
|--Nested Loops(Inner Join, OUTER REFERENCES:([N].[colProductID]) WITH PREFETCH)
| |--Clustered Index Scan(OBJECT:([data].[dbo].[tblProdNomenclature].[PK_tblProdNomenclature] AS [N]), WHERE:([N].[colRailTypeID]=1) ORDERED FORWARD)
| |--Clustered Index Seek(OBJECT:([data].[dbo].[tblProducts].[PK_tblProducts] AS [P]), SEEK:([P].[colProductID]=[N].[colProductID]) ORDERED FORWARD)
|--Clustered Index Scan(OBJECT:([data].[dbo].[tblSpecifications].[PK_tblSpecifications] AS [S]), ORDERED FORWARD)
Т.е. Merge Join эффективен, когда объем объединяемых данных велик и они могут получены пресортированными, например из существующего индекса. Сам смысл Merge Join - получение строки из одного пресортированного набора и сравнение его с другим пресортированным набором.
Nested Loops эффективен в случаи, когда один из наборов велик, по сравнению с другим набором, причем последний индексирован.
Т.е. при запросах, возвращающие большие результирующие наборы эффективнее Merge (или Hash) джоины, для "маленьких" запросов Nested Loops.
Аналогичное поведение и для запросов по схеме "звезда".
1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41. 42. 43. 44. 45. 46. 47. 48. 49. 50. 51. 52. 53. 54. 55. 56. 57. 58. 59. 60. 61. 62. 63. 64. 65. 66. 67. 68. 69. 70. 71. 72. 73. 74. 75. 76. 77. 78. 79. 80. 81. 82. 83. 84. 85. 86. 87. 88. 89. 90. 91. 92. 93. 94. 95. 96. 97. 98. 99. 100. 101. 102. 103. 104. 105. 106.
DECLARE @DepartmentID int, @DocTypeID int
SELECT tblDocuments.colDocumentID,
tblDocuments.colPeriod,
tblDocuments.colTaskID,
tblDocuments.colDocumentTypeID,
tblDocuments.colDocDate,
tblDocuments.colDocNumber,
tblDocuments.colDocCheck,
tblOperationsType.colOperationName,
colFigurant = CAST((case when tblDocuments.colSupplier IS NOT NULL then
usv_ContragentsList.colFullContrName
when tblDocuments.colRecipient IS NOT NULL then
usv_ContragentsList1.colFullContrName
when tblDocuments.colContrDepartmentID IS NOT NULL then
usv_DepartmentsList.colDepartmentCode
end) AS varchar( 255 )),
tblDocuments.colDocumentSum,
tblDocumentsType.colDocName
FROM tblDocuments
INNER JOIN tblOperationsType ON
tblDocuments.colOperationCode = tblOperationsType.colOperationCode
INNER JOIN tblDocumentsType ON
tblDocuments.colDocumentTypeID = tblDocumentsType.colDocumentTypeID
INNER JOIN usv_ContragentsList ON
tblDocuments.colSupplier = usv_ContragentsList.colContragentID
INNER JOIN usv_ContragentsList usv_ContragentsList1 ON
tblDocuments.colRecipient = usv_ContragentsList1.colContragentID
INNER JOIN usv_DepartmentsList ON
tblDocuments.colContrDepartmentID = usv_DepartmentsList.colDepartmentID
WHERE
(tblDocuments.colTaskID = 1 ) AND
(tblDocuments.colDepartmentID = @DepartmentID) AND
(tblDocuments.colDocumentTypeID = @DocTypeID)
ORDER BY tblDocuments.colDocDate DESC
|--Compute Scalar(DEFINE:([Expr1016]=Convert(If 1 then ([tblTowns].[colTownName]+' - '+[tblContragents].[colContragentName]) else If 1 then ([tblTowns].[colTownName]+' - '+[tblContragents].[colContragentName]) else If 1 then Convert((substring([tblDepart
|--Nested Loops(Inner Join, OUTER REFERENCES:([tblContragents].[colTownID]))
|--Bookmark Lookup(BOOKMARK:([Bmk1006]), OBJECT:([data].[dbo].[tblContragents]))
| |--Nested Loops(Inner Join, OUTER REFERENCES:([tblDocuments].[colSupplier]) WITH PREFETCH)
| |--Nested Loops(Inner Join, OUTER REFERENCES:([tblContragents].[colTownID]))
| | |--Bookmark Lookup(BOOKMARK:([Bmk1008]), OBJECT:([data].[dbo].[tblContragents]))
| | | |--Nested Loops(Inner Join, OUTER REFERENCES:([tblDocuments].[colRecipient]) WITH PREFETCH)
| | | |--Nested Loops(Inner Join, OUTER REFERENCES:([tblDocuments].[colContrDepartmentID]))
| | | | |--Bookmark Lookup(BOOKMARK:([Bmk1002]), OBJECT:([data].[dbo].[tblOperationsType]))
| | | | | |--Nested Loops(Inner Join, OUTER REFERENCES:([tblDocuments].[colOperationCode]))
| | | | | |--Nested Loops(Inner Join)
| | | | | | |--Index Seek(OBJECT:([data].[dbo].[tblDocumentsType].[PK_tblDocumentsType]), SEEK:([tblDocumentsType].[colDocumentTypeID]=[@DocTypeID]) ORDERED FORWARD)
| | | | | | |--Sort(ORDER BY:([tblDocuments].[colDocDate] DESC))
| | | | | | |--Filter(WHERE:([tblDocuments].[colTaskID]=1))
| | | | | | |--Bookmark Lookup(BOOKMARK:([Bmk1000]), OBJECT:([data].[dbo].[tblDocuments]))
| | | | | | |--Hash Match(Inner Join, HASH:([Bmk1000])=([Bmk1000]), RESIDUAL:([Bmk1000]=[Bmk1000]))
| | | | | | |--Index Seek(OBJECT:([data].[dbo].[tblDocuments].[IX_tblDocuments_5]), SEEK:([tblDocuments].[colDepartmentID]=[@DepartmentID]) ORDERED FORWARD)
| | | | | | |--Index Seek(OBJECT:([data].[dbo].[tblDocuments].[IX_tblDocuments_9]), SEEK:([tblDocuments].[colDocumentTypeID]=[@DocTypeID]) ORDERED FORWARD)
| | | | | |--Index Seek(OBJECT:([data].[dbo].[tblOperationsType].[PK_tblOperationsType]), SEEK:([tblOperationsType].[colOperationCode]=[tblDocuments].[colOperationCode]) ORDERED FORWARD)
| | | | |--Clustered Index Seek(OBJECT:([data].[dbo].[tblDepartments].[PK_tblDepartments]), SEEK:([tblDepartments].[colDepartmentID]=[tblDocuments].[colContrDepartmentID]) ORDERED FORWARD)
| | | |--Index Seek(OBJECT:([data].[dbo].[tblContragents].[PK_tblContragents]), SEEK:([tblContragents].[colContragentID]=[tblDocuments].[colRecipient]) ORDERED FORWARD)
| | |--Clustered Index Seek(OBJECT:([data].[dbo].[tblTowns].[PK_tblTowns]), SEEK:([tblTowns].[colTownID]=[tblContragents].[colTownID]) ORDERED FORWARD)
| |--Index Seek(OBJECT:([data].[dbo].[tblContragents].[PK_tblContragents]), SEEK:([tblContragents].[colContragentID]=[tblDocuments].[colSupplier]) ORDERED FORWARD)
|--Clustered Index Seek(OBJECT:([data].[dbo].[tblTowns].[PK_tblTowns]), SEEK:([tblTowns].[colTownID]=[tblContragents].[colTownID]) ORDERED FORWARD)
SELECT tblDocuments.colDocumentID,
tblDocuments.colPeriod,
tblDocuments.colTaskID,
tblDocuments.colDocumentTypeID,
tblDocuments.colDocDate,
tblDocuments.colDocNumber,
tblDocuments.colDocCheck,
tblOperationsType.colOperationName,
colFigurant = CAST((case when tblDocuments.colSupplier IS NOT NULL then
usv_ContragentsList.colFullContrName
when tblDocuments.colRecipient IS NOT NULL then
usv_ContragentsList1.colFullContrName
when tblDocuments.colContrDepartmentID IS NOT NULL then
usv_DepartmentsList.colDepartmentCode
end) AS varchar( 255 )),
tblDocuments.colDocumentSum,
tblDocumentsType.colDocName
FROM tblDocuments
INNER JOIN tblOperationsType ON
tblDocuments.colOperationCode = tblOperationsType.colOperationCode
INNER JOIN tblDocumentsType ON
tblDocuments.colDocumentTypeID = tblDocumentsType.colDocumentTypeID
INNER JOIN usv_ContragentsList ON
tblDocuments.colSupplier = usv_ContragentsList.colContragentID
INNER JOIN usv_ContragentsList usv_ContragentsList1 ON
tblDocuments.colRecipient = usv_ContragentsList1.colContragentID
INNER JOIN usv_DepartmentsList ON
tblDocuments.colContrDepartmentID = usv_DepartmentsList.colDepartmentID
ORDER BY tblDocuments.colDocDate DESC
|--Sort(ORDER BY:([tblDocuments].[colDocDate] DESC))
|--Compute Scalar(DEFINE:([Expr1016]=Convert(If 1 then ([tblTowns].[colTownName]+' - '+[tblContragents].[colContragentName]) else If 1 then ([tblTowns].[colTownName]+' - '+[tblContragents].[colContragentName]) else If 1 then Convert((substring([tblD
|--Hash Match(Inner Join, HASH:([tblDocumentsType].[colDocumentTypeID])=([tblDocuments].[colDocumentTypeID]))
|--Index Scan(OBJECT:([data].[dbo].[tblDocumentsType].[PK_tblDocumentsType]))
|--Hash Match(Inner Join, HASH:([tblOperationsType].[colOperationCode])=([tblDocuments].[colOperationCode]), RESIDUAL:([tblDocuments].[colOperationCode]=[tblOperationsType].[colOperationCode]))
|--Table Scan(OBJECT:([data].[dbo].[tblOperationsType]))
|--Hash Match(Inner Join, HASH:([tblDepartments].[colDepartmentID])=([tblDocuments].[colContrDepartmentID]), RESIDUAL:([tblDocuments].[colContrDepartmentID]=[tblDepartments].[colDepartmentID]))
|--Clustered Index Scan(OBJECT:([data].[dbo].[tblDepartments].[PK_tblDepartments]))
|--Hash Match(Inner Join, HASH:([tblTowns].[colTownID])=([tblContragents].[colTownID]))
|--Index Scan(OBJECT:([data].[dbo].[tblTowns].[IX_tblTownsByRegions]))
|--Hash Match(Inner Join, HASH:([tblContragents].[colContragentID])=([tblDocuments].[colSupplier]), RESIDUAL:([tblContragents].[colContragentID]=[tblDocuments].[colSupplier]))
|--Clustered Index Scan(OBJECT:([data].[dbo].[tblContragents].[IX_tblContragentsByName]))
|--Hash Match(Inner Join, HASH:([tblContragents].[colContragentID])=([tblDocuments].[colRecipient]), RESIDUAL:([tblContragents].[colContragentID]=[tblDocuments].[colRecipient]))
|--Hash Match(Inner Join, HASH:([tblTowns].[colTownID])=([tblContragents].[colTownID]))
| |--Index Scan(OBJECT:([data].[dbo].[tblTowns].[IX_tblTownsByRegions]))
| |--Clustered Index Scan(OBJECT:([data].[dbo].[tblContragents].[IX_tblContragentsByName]))
|--Table Scan(OBJECT:([data].[dbo].[tblDocuments]))
|
|
|