Davide Ciao,
dmauri:
Riesci a creare uno script come quello che ho postato che permetta di fare prove comparabili?
Sono riuscito a creare uno script con cui riprodurre il problema, è questo:
/*
Test opzione ANSI_NULLS
*/
-- Drop table OrderDetail
IF (OBJECT_ID('OrderDetail', 'U') IS NOT NULL)
DROP TABLE dbo.OrderDetail
GO
-- Create table OrderDetail
CREATE TABLE dbo.OrderDetail
(OrderDetailID INT IDENTITY(1, 1) NOT NULL,
OrderHeaderID INT NOT NULL,
ProductID INT NOT NULL,
RigNumber AS (OrderDetailID * 2) ,
UnitPrice MONEY DEFAULT 0 NOT NULL
PRIMARY KEY(OrderDetailID)
)
-- Drop table OrderHeader
IF (OBJECT_ID('OrderHeader', 'U') IS NOT NULL)
DROP TABLE dbo.OrderHeader
GO
-- Create table OrderHeader
CREATE TABLE dbo.OrderHeader
(OrderID INT IDENTITY(1, 1) NOT NULL,
OrderDATE DATETIME DEFAULT GETDATE() NOT NULL,
OrderNUMBER AS (ISNULL(N'SO' + CONVERT([nvarchar](23), [OrderID], 0), N'*** ERROR ***')),
CustomerID INT DEFAULT 1 NOT NULL,
ShipName VARCHAR(20) DEFAULT 'Name',
ShipAddress VARCHAR(40) DEFAULT 'Address',
ShipVia VARCHAR(40) DEFAULT 'Via',
ShipCity VARCHAR(20) DEFAULT 'City',
ShipRegion VARCHAR(20) DEFAULT 'Region',
ShipPostalCode VARCHAR(20) DEFAULT 'Postal code',
ShipCountry VARCHAR(20) DEFAULT 'Country'
PRIMARY KEY(OrderID)
)
-- ALTER TABLE ADD CONSTRAINT
ALTER TABLE [dbo].[OrderDetail] WITH CHECK ADD CONSTRAINT [FK_OrderHeaderID]
FOREIGN KEY ([OrderHeaderID]) REFERENCES [dbo].[OrderHeader] ([OrderID])
-- CREATE NONCLUSTERED INDEX
CREATE NONCLUSTERED INDEX [IDX_OrderHeader_CustomerID] ON dbo.OrderHeader
(
[CustomerID] ASC
)
DECLARE @i AS INT
SET @i = 0
--219131
WHILE (@i < 250000)
BEGIN
SET NOCOUNT ON
-- Insert OrderHeader
INSERT INTO dbo.OrderHeader DEFAULT VALUES
-- Insert OrderDetail
INSERT INTO dbo.OrderDetail
(
OrderHeaderID,
ProductID,
UnitPrice
)
SELECT
(
SELECT
MAX(OrderID)
FROM
dbo.OrderHeader
),
(@i * 2)+1,
((@i * 2)+1)/2
SET @i = (@i + 1)
SET NOCOUNT ON
END
SET STATISTICS IO ON
-- TEST ANSI_NULLS
SET ANSI_NULLS ON
go
DECLARE @P1 INT,
@P2 INT
SET @P1 = 1
SET @P2 = 1100
EXEC sp_executesql N'Select OH.OrderID, Max(OH.OrderDATE), OH.OrderNUMBER, OH.CustomerID, OH.ShipName, OH.ShipAddress, OH.ShipVia, OH.ShipCity, OH.ShipRegion, OH.ShipPostalCode, OH.ShipCountry, SUM(OD.UnitPrice) From dbo.OrderHeader OH Left Outer Join dbo.OrderDetail OD ON OD.OrderHeaderID = OH.OrderID Where (OH.CustomerID = @P1) and (OD.OrderHeaderID = @P2) GROUP BY OH.OrderID, OH.OrderNUMBER, OH.CustomerID, OH.ShipName, OH.ShipAddress, OH.ShipVia, OH.ShipCity, OH.ShipRegion, OH.ShipPostalCode, OH.ShipCountry', N'@P1 int, @P2 int', @P1, @P2
go
DBCC DROPCLEANBUFFERS
SET ANSI_NULLS OFF
go
DECLARE @P1 INT,
@P2 INT
SET @P1 = 1
SET @P2 = 1100
EXEC sp_executesql N'Select OH.OrderID, Max(OH.OrderDATE), OH.OrderNUMBER, OH.CustomerID, OH.ShipName, OH.ShipAddress, OH.ShipVia, OH.ShipCity, OH.ShipRegion, OH.ShipPostalCode, OH.ShipCountry, SUM(OD.UnitPrice) From dbo.OrderHeader OH Left Outer Join dbo.OrderDetail OD ON OD.OrderHeaderID = OH.OrderID Where (OH.CustomerID = @P1) and (OD.OrderHeaderID = @P2) GROUP BY OH.OrderID, OH.OrderNUMBER, OH.CustomerID, OH.ShipName, OH.ShipAddress, OH.ShipVia, OH.ShipCity, OH.ShipRegion, OH.ShipPostalCode, OH.ShipCountry', N'@P1 int, @P2 int', @P1, @P2
dmauri:Un'altra cosa: hai svuotato la cache dei piani di esecuzione, per esser sicuro che non ci sia in cache un piano di esecuzione relativo all'impostazione SET ANSI NULL impostata o meno che viene ri-utilizzato e quindi impedendo il ricalcolo dell'execution plan ottimale?
Dopo la prima chiamata a sp_executesql ho eseguito DBCC DROPCLEANBUFFERS, ma ho provato anche a ricostruire gli indici delle due tabelle (il rebuild dell'indice dovrebbe forzare la free della cache dei piani di esecuzione. Dico bene ?) con:
DBCC DBREINDEX(OrderHeader)
UPDATE STATISTICS OrderHeader
DBCC DBREINDEX(OrderDetail)
UPDATE STATISTICS OrderDetail
Con ANSI_NULLS impostato a ON ottengo:
Table 'OrderDetail'. Scan count 1, logical reads 899, physical reads 0, read-ahead reads 0.
Table 'OrderHeader'. Scan count 1, logical reads 5, physical reads 2, read-ahead reads 0.
Con ANSI_NULLS impostato a OFF ottengo:
Table 'OrderHeader'. Scan count 1, logical reads 2607, physical reads 0, read-ahead reads 0.
Table 'OrderDetail'. Scan count 1, logical reads 899, physical reads 0, read-ahead reads 0.
dmauri:Ultima cosa: ho visto il tuo post su Sql Server Central....
Un po' l'avevo immaginato, grazie Davide del chiarimento
.
Grazie ancora.
Sergio