January 26, 2011 at 9:59 pm
First off, I didn't write this but did try to make it faster...I've tried looping through it snagging say a TOP 500 records and updating those, then fetching another 500 and so on but it really had no impact.
I'd think that updating a table with only a few columns, having less than 3,000,000 rows should only take a minute or two?
Any suggestions on how to make this faster would be greating appreciated!
/* Snippet */
DECLARE @mindate datetime SET @mindate = '2010-01-01 00:00:00.000'
DECLARE @maxdate datetime SET @maxdate = '2010-01-31 23:59:59.000'
CREATE TABLE #Update (id int identity,
tranid [varchar](20) NULL,
fleetnumber [varchar](20) NULL,
odometer [int] DEFAULT(0),
pan [varchar](32) NULL,
unit [varchar](40) NULL,
trantime [datetime] NULL,
prevodometer int NULL,
)
INSERT INTO #Update
SELECT DISTINCT
tranid, fleetnumber, odometer, pan, unit, trantime, prevodometer
FROM DW_LOAD.[dbo].[Mileage_Table] --> This table has about 3,000,000 rows
WHERE Odometer > 0
AND (prevodometer = 0 OR prevodometer IS NULL)
AND trantime BETWEEN @mindate AND @maxdate
-- This inserts about 175,000 rows into #Update
BEGIN TRANSACTION
UPDATE a
SET a.prevodometer =
CASE
WHEN (dbo.fx_GetLastOdometer(b.trantime,b.pan,b.unit,b.tranid,b.odometer) < 1) THEN 1
ELSE ISNULL(dbo.fx_GetLastOdometer(b.trantime,b.pan,b.unit,b.tranid,b.odometer), 1)
END
FROM dbo.Mileage_Table a
JOIN #Update b ON
a.tranid = b.tranid
AND a.pan = b.pan
WHERE
a.trantime BETWEEN @minDate AND @maxDate
AND (a.prevodometer IS NULL OR a.prevodometer = 0)
IF @@ERROR = 0
BEGIN
COMMIT TRANSACTION
END
ELSE
BEGIN
/* Send Email */
EXECUTE msdb.dbo.sp_send_dbmail @recipients = 'me@hotmail.com'
,@subject='There was an error - transaction failed'
,@body = ''
ROLLBACK TRANSACTION
END
DROP TABLE #Update
______________________________________________________________________________Never argue with an idiot; Theyll drag you down to their level and beat you with experience
January 26, 2011 at 10:04 pm
Could you post some sample data, about 10 to 20 rows, as a series of INSERT INTO statements for the source table (and if you haven't provided the CREATE TABLE statement for the source table, please provide that as well). Also, then provide the expected results based on the sample data.
I have an idea as to what you are trying to accomplish, but it will help to actually see it.
January 26, 2011 at 10:41 pm
It will also help to see the code and DDL for the tables referenced in the fx_GetLastOdometer function.
(I think that this might be your culprit...)
Wayne
Microsoft Certified Master: SQL Server 2008
Author - SQL Server T-SQL Recipes
January 26, 2011 at 10:55 pm
WayneS (1/26/2011)
It will also help to see the code and DDL for the tables referenced in the fx_GetLastOdometer function.(I think that this might be your culprit...)
Good call on the extra code. I guess I missed it in the jumble of code.
January 27, 2011 at 10:39 am
Sorry! Yes I guess that would help 🙂
CREATE FUNCTION [dbo].[fx_GetLastOdometer]
(@date varchar(40)
,@pan VARCHAR(32)
,@tranid int)
RETURNS int
AS
BEGIN
DECLARE @Odometer int
SET @Odometer = (
SELECT TOP 1 odometer
FROM dbo.[Mileage_Table] WITH(INDEX(idx_TranTime))
WHERE tranid <> @tranid
AND pan=@pan
AND trantime < @date
)
RETURN @Odometer
END
Here's some sample data:
CREATE TABLE #Mileage_Table (id int identity,
tranid [varchar](20) NULL,
fleetnumber [varchar](20) NULL,
odometer [int] DEFAULT(0),
pan [varchar](32) NULL,
unit [varchar](40) NULL,
trantime [datetime] NULL,
prevodometer int NULL,
)
INSERT INTO #Mileage_Table VALUES
('101104','433172', '200369', '5014861143317200022', '3273', '2010-07-08 15:10:59.000', NULL)
INSERT INTO #Mileage_Table VALUES
('101124', '430943', '11164', '5014861143094300045', '8608', '2010-07-08 15:10:59.000', NULL)
INSERT INTO #Mileage_Table VALUES
('101128', '433462', '305', '5014861143346200043', '0305', '2010-07-08 15:10:59.000', NULL)
INSERT INTO #Mileage_Table VALUES
('101135', '434867', '126452', '5014861143486700018', '9685', '2010-07-08 15:10:59.000', NULL)
INSERT INTO #Mileage_Table VALUES
('101157', '430034', '501618', '5014861143003400027', '4321', '2010-07-08 15:11:59.000', NULL)
INSERT INTO #Mileage_Table VALUES
('101162', '431788', '11111', '5014861143178800027', '1010', '2010-07-08 15:11:59.000', NULL)
INSERT INTO #Mileage_Table VALUES
('101169', '430943', '11179', '5014861143094300045', '8608', '2010-07-08 15:11:59.000', NULL)
INSERT INTO #Mileage_Table VALUES
('101171', '431266', '38544', '5014861143126600016', '2549', '2010-07-08 15:11:59.000', NULL)
INSERT INTO #Mileage_Table VALUES
('101172', '434002', '101405', '5014861143400200012', '7081', '2010-07-08 15:11:59.000', NULL)
INSERT INTO #Mileage_Table VALUES
('101182', '436143', '99000', '5014861143614300046', '9570', '2010-07-08 15:11:59.000', NULL)
INSERT INTO #Mileage_Table VALUES
('101208', '430378', '260590', '5014861143037800036', '0003', '2010-07-08 15:12:59.000', NULL)
INSERT INTO #Mileage_Table VALUES
('101287', '433659', '10560', '5014861143365900010', '3185', '2010-07-08 15:14:59.000', NULL)
INSERT INTO #Mileage_Table VALUES
('101371', '437416', '405', '5014861143741600219', '0816', '2010-07-08 15:15:59.000', NULL)
INSERT INTO #Mileage_Table VALUES
('101377', '435158', '135101', '5014861143515800136', '0013', '2010-07-08 15:15:59.000', NULL)
INSERT INTO #Mileage_Table VALUES
('101387', '430361', '59092', '5014861143036100024', '4358', '2010-07-08 15:16:59.000', NULL)
INSERT INTO #Mileage_Table VALUES
('101392', '430791', '8000', '5014861143079100097', '7792', '2010-07-08 15:16:59.000', NULL)
INSERT INTO #Mileage_Table VALUES
('101436', '433728', '231610', '5014861143372800435', '1950', '2010-07-08 15:17:59.000', NULL)
INSERT INTO #Mileage_Table VALUES
('101457', '434923', '512806', '5014861143492300035', '6608', '2010-07-08 15:17:59.000', NULL)
INSERT INTO #Mileage_Table VALUES
('101466', '432431', '75000', '5014861143243100049', '0004', '2010-07-08 15:17:59.000', NULL)
INSERT INTO #Mileage_Table VALUES
('101467', '433566', '67900', '5014861143356600025', '8039', '2010-07-08 15:17:59.000', NULL)
INSERT INTO #Mileage_Table VALUES
('101511', '431687', '86532', '5014861143168700013', '0349', '2010-07-08 15:19:59.000', NULL)
INSERT INTO #Mileage_Table VALUES
('101523', '436602', '92831', '5014861143660200116', '9441', '2010-07-08 15:19:59.000', NULL)
INSERT INTO #Mileage_Table VALUES
('101532', '430216', '43711', '5014861143021600012', '3000', '2010-07-08 15:19:59.000', NULL)
INSERT INTO #Mileage_Table VALUES
('101537', '433508', '200173', '5014861143350800035', '4321', '2010-07-08 15:19:59.000',NULL)
INSERT INTO #Mileage_Table VALUES
('101551', '430885', '1289', '5014861143088500030', '1289', '2010-07-08 15:20:59.000', NULL)
-- DROP TABLE #Mileage_Table
______________________________________________________________________________Never argue with an idiot; Theyll drag you down to their level and beat you with experience
January 27, 2011 at 5:49 pm
Still missing the expected results based on the sample data. If everything runs correctly, what should the data look like?
January 27, 2011 at 8:58 pm
Lynn, sorry I missed that request. The expected result would be an integer value in the prevodometer column for each record in the table.
I don't fully understand why they wrote it this way but my understanding is that there are about 1 yearr's worth of odometer readings in that main table. He pulls in a month's worth into the temp table and then updates the main table with the previous odometer's reading for each date/record present in the temp table.
When it's normally run, there are about 160,000 records in the temp table (which I know is a lot for a temp table).
Thanks so much for your patience.
______________________________________________________________________________Never argue with an idiot; Theyll drag you down to their level and beat you with experience
January 27, 2011 at 10:14 pm
You need to determine what the results should be and provide that. This is used to test our results as well as to understand the process that needs to be completed.
January 29, 2011 at 12:43 pm
Serge,
Just a quick note on your scalar function - fx_GetLastOdometer. This type of scalar function in a query causes hidden RBAR (Row By Agonizing Row) type processing. The function is doing a select on a table to return a value. This select is done for each row the query. The optimizer doesn't know the table or how to access it when the main query is optimized and so you get a black hole in the query plan - you can't even see that something is non-optimum. I recall that Gail Shaw has an article or two on this in this forum.
The type of data you want from the function can easily be done with a CROSS APPLY or OUTER APPLY (if there are no records matching) in-line with your query. Paul White has some excellent articles on APPLY in this forum. Using an APPLY will allow the Query Optimizer to figure out the best way to access the table to get the column value you want. This is especially effective if you have a covering index on the ORDER BY column of the TOP 1 (in this case the odometer reading) since you get a straight index seek with no key lookup.
Todd Fifield
Viewing 9 posts - 1 through 8 (of 8 total)
You must be logged in to reply to this topic. Login to reply