我创建了一个创建随机地址的函数,但每次调用花费的时间太长(大约10 - 20秒)。我必须在超过900,000条记录上运行此功能,并且通过我对此功能的计时的计算,这需要120天给予或接受。这是功能:
CREATE function dbo.fn_GetAddress2 (@state NVARCHAR(20))
returns @NewAddress TABLE
(
Address1 NVARCHAR(MAX),
Address2 NVARCHAR(MAX),
City NVARCHAR(MAX),
Postcode NVARCHAR(MAX)
)
AS
BEGIN
DECLARE @Address1 NVARCHAR(MAX)
DECLARE @Address2 NVARCHAR(MAX)
DECLARE @City NVARCHAR(MAX)
DECLARE @Postcode NVARCHAR(MAX)
DECLARE @StreetPID NVARCHAR(MAX)
DECLARE @newID1 NVARCHAR(36)
SELECT @StreetPID =
( SELECT TOP 1 g.street_locality_pid AS StreetPID
FROM [GNAF].dbo.Street_Locality g
INNER JOIN [GNAF].dbo.Address_Detail aD ON g.street_locality_pid = aD.street_locality_pid
WHERE g.street_name IS NOT NULL AND g.state != @state AND aD.flat_number IS NOT NULL
ORDER BY (SELECT new_id FROM getNewID ))
SELECT @Address1 =
( SELECT TOP 1 CAST(aD.flat_number AS VARCHAR(20)) + ' ' + g.Street_name + ' ' + g.street_type_code AS Address1
FROM [GNAF].dbo.Street_Locality g
INNER JOIN [GNAF].dbo.Address_Detail aD ON g.street_locality_pid = aD.street_locality_pid
WHERE g.street_name IS NOT NULL AND g.state != @state AND aD.flat_number IS NOT NULL
AND g.street_locality_pid = @StreetPID
ORDER BY (SELECT new_id FROM getNewID ))
SELECT @postcode =
( SELECT TOP 1 aD.postcode AS postcode
FROM [GNAF].dbo.Street_Locality g
INNER JOIN [GNAF].dbo.Address_Detail aD ON g.street_locality_pid = aD.street_locality_pid
WHERE g.street_name IS NOT NULL AND g.state != @state AND aD.flat_number IS NOT NULL
AND g.street_locality_pid = @StreetPID
ORDER BY (SELECT new_id FROM getNewID ))
SELECT @City =
( SELECT TOP 1 l.locality_name AS city
FROM [GNAF].dbo.Street_Locality g
INNER JOIN [GNAF].dbo.Address_Detail aD ON g.street_locality_pid = aD.street_locality_pid
INNER JOIN [GNAF].dbo.Locality l ON aD.locality_pid = l.locality_pid
WHERE g.street_name IS NOT NULL AND g.state != @state AND aD.flat_number IS NOT NULL
AND g.street_locality_pid = @StreetPID
ORDER BY (SELECT new_id FROM getNewID ))
IF @Address1 IS NOT NULL
BEGIN
INSERT @NewAddress
SELECT @Address1, @Address2, @city, @postcode;
END;
Return;
END
GO
[GNAF]数据库是一个庞大的数据库,充满了澳大利亚的每一个地址。函数和newid()对我来说是全新的。
我尝试过几种不同的方法,包括CTE:
SET @State = 'NSW'
;WITH CTE AS (
SELECT TOP 1 CAST(aD.flat_number AS VARCHAR(20)) + ' ' + g.Street_name + ' ' + g.street_type_code AS Address1
, aD.postcode AS postcode
FROM [GNAF].dbo.Street_Locality g
INNER JOIN [GNAF].dbo.Address_Detail aD ON g.street_locality_pid = aD.street_locality_pid
WHERE g.street_name IS NOT NULL AND g.state != @state AND aD.flat_number IS NOT NULL
ORDER BY (SELECT new_id FROM getNewID )
)
SELECT @Address1 = ( SELECT Address1 FROM CTE )
,@postcode = ( SELECT postcode FROM CTE )
SELECT @Address1
, @postcode
这实际上比较慢。对此有任何帮助将非常感激。
答案 0 :(得分:1)
这里有适合你的东西。请注意:我只是创建了5个新表,每个地址部分对应一个表,并使用地址表中的数据填充它们,而不是来回到完整的地址表。除了状态表之外,我使用了2000。您可以使用更多或更少,只需确保更改函数中的模数值以匹配您在每个表中的行数。
在任何情况下,它都很快......我将发布SET STATISTICS IO,TIME数字基于10,000,100,000&正在生成1,000,000行。
USE tempdb;
GO
-- Populate a series of individual tables one for each part of the address...
CREATE TABLE dbo.a1 (ID INT NOT NULL IDENTITY (1,1) PRIMARY KEY CLUSTERED, Address1 VARCHAR(60) );
INSERT dbo.a1 (Address1)
SELECT TOP 2000 b.PhysAddr1 FROM Xyz.dbo.ContactBranch b WHERE b.PhysAddr1 LIKE '[0-Z ][0-Z ][0-Z ][0-Z ][0-Z ]%';
CREATE TABLE dbo.a2 (ID INT NOT NULL IDENTITY (1,1) PRIMARY KEY CLUSTERED, Address2 VARCHAR(50) );
INSERT dbo.a2 (Address2)
SELECT TOP 2000 ISNULL(b.PhysAddr2, '') FROM Xyz.dbo.ContactBranch b;
CREATE TABLE dbo.cty (ID INT NOT NULL IDENTITY (1,1) PRIMARY KEY CLUSTERED, City VARCHAR(50) );
INSERT dbo.cty (City)
SELECT TOP 2000 b.PhysCity FROM Xyz.dbo.ContactBranch b WHERE b.PhysCity LIKE '[0-Z ][0-Z ][0-Z ][0-Z ][0-Z ]%';
CREATE TABLE dbo.st (ID INT NOT NULL IDENTITY (1,1) PRIMARY KEY CLUSTERED, State CHAR(2));
INSERT dbo.st (State)
SELECT s.Description FROM Xyz.dbo.LK_States s WHERE s.Description LIKE '[a-Z][a-Z]';
CREATE TABLE dbo.zip (ID INT NOT NULL IDENTITY (1,1) PRIMARY KEY CLUSTERED, Zip VARCHAR(5) );
INSERT dbo.zip (Zip)
SELECT TOP 2000 LEFT(b.PhysZip10, 5) FROM Xyz.dbo.ContactBranch b WHERE b.PhysZip10 LIKE '[0-Z ][0-Z ][0-Z ][0-Z ][0-Z ]%';
/* DROP TABLE dbo.a1; DROP TABLE dbo.a2; DROP TABLE dbo.cty; DROP TABLE dbo.st; DROP TABLE dbo.zip; */
/*
(2000 rows affected)
(2000 rows affected)
(2000 rows affected)
(52 rows affected)
(2000 rows affected)
*/
功能代码......
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_NULLS ON
GO
CREATE FUNCTION dbo.tfn_AddressGenerator
/* ===================================================================
10/06/2017 JL, Created: to randomly generate random addresses.
The general premmise is based on the Ben-Gan" or inline Tally table.
=================================================================== */
--===== Define I/O parameters
(
@State CHAR(2),
@NumToCreate INT
)
RETURNS TABLE WITH SCHEMABINDING AS
RETURN
WITH
cte_n1 (n) AS (SELECT 1 FROM (VALUES (1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) n (n)), --rows
cte_n2 (n) AS (SELECT 1 FROM cte_n1 a CROSS JOIN cte_n1 b), -- 100 rows
cte_n3 (n) AS (SELECT 1 FROM cte_n2 a CROSS JOIN cte_n2 b), -- 10,000 rows
cte_Tally (n) AS (
SELECT TOP (@NumToCreate)
ROW_NUMBER() OVER (ORDER BY (SELECT NULL))
FROM
cte_n3 a CROSS JOIN cte_n3 b -- 100,000,000 rows
)
SELECT
a1.Address1,
a2.Address2,
c.City,
State = IIF(s1.State = @State, s2.State, s1.State),
z.Zip
FROM
cte_Tally t
CROSS APPLY ( VALUES (
ABS(CHECKSUM(t.n)) % 2000 + 1, ABS(CHECKSUM(t.n)) % 1528 + 1,
ABS(CHECKSUM(t.n)) % 2000 + 1, ABS(CHECKSUM(t.n)) % 52 + 1,
ABS(CHECKSUM(t.n)) % 52 + 1, ABS(CHECKSUM(t.n)) % 2000 + 1
) ) x (Add1, Add2, City, State1, State2, Zip)
CROSS APPLY (SELECT TOP 1 dbo.a1.Address1 FROM dbo.a1 WHERE x.Add1 = dbo.a1.ID) a1
CROSS APPLY (SELECT TOP 1 dbo.a2.Address2 FROM dbo.a2 WHERE x.Add2 = dbo.a2.ID) a2
CROSS APPLY (SELECT TOP 1 dbo.cty.City FROM dbo.cty WHERE x.City = dbo.cty.ID) c
CROSS APPLY (SELECT TOP 1 dbo.st.State FROM dbo.st WHERE x.State1 = dbo.st.ID) s1
CROSS APPLY (SELECT TOP 1 dbo.st.State FROM dbo.st WHERE x.State2 = dbo.st.ID) s2
CROSS APPLY (SELECT TOP 1 dbo.Zip.Zip FROM dbo.zip WHERE x.Zip = dbo.zip.ID) z;
GO
该功能的实际执行......
SELECT ag.Address1, ag.Address2, ag.City,ag.State, ag.Zip
FROM dbo.tfn_AddressGenerator('FL',10000) ag;
示例输出......
Address1 Address2 City State Zip
--------------------------- ----------- ---------------- ----- -----
111 CONGRESSIONAL BLVD ATLANTA AL 30042
414 Eagle Rock Ave # 100 STE 400 MARIETTA AR 70816
414 Eagle Rock Ave Ste 107 Suite 300 NORCROSS AZ 72116
3931 HIGHWAY 78 W STE B200 SAVANNAH CA 31702
4728 Joseph Eli Dr STE 6 STONE MOUNTAIN CO 30338
29620 IH10 West DULUTH CT 63026
4666 El Camino Real ATLANTA DC 60555
3700 Thomas Rd Ste 215 STE 100 ATLANTA DE 32241
3700 Thomas Rd Ste 215 STE B-2190 ALPHARETTA FL 36117
2615 East West Connector ALPHARETTA GA 35201
10,000行结果......
SQL Server parse and compile time:
CPU time = 0 ms, elapsed time = 0 ms.
(10000 rows affected)
Table 'zip'. Scan count 0, logical reads 20000, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'st'. Scan count 0, logical reads 40000, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'cty'. Scan count 0, logical reads 20000, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'a2'. Scan count 0, logical reads 20000, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'a1'. Scan count 0, logical reads 20000, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
SQL Server Execution Times:
CPU time = 94 ms, elapsed time = 93 ms.
100,000行结果......
SQL Server parse and compile time:
CPU time = 0 ms, elapsed time = 0 ms.
(100000 rows affected)
Table 'zip'. Scan count 0, logical reads 200000, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'st'. Scan count 0, logical reads 400000, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'cty'. Scan count 0, logical reads 200000, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'a2'. Scan count 0, logical reads 200000, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'a1'. Scan count 0, logical reads 200000, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
SQL Server Execution Times:
CPU time = 907 ms, elapsed time = 948 ms.
1,000,000行结果......
SQL Server parse and compile time:
CPU time = 0 ms, elapsed time = 1 ms.
SQL Server parse and compile time:
CPU time = 31 ms, elapsed time = 51 ms.
(1000000 rows affected)
Table 'a1'. Scan count 0, logical reads 4000, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'Worktable'. Scan count 0, logical reads 0, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'a2'. Scan count 0, logical reads 3056, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'cty'. Scan count 0, logical reads 4000, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'st'. Scan count 0, logical reads 208, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'zip'. Scan count 0, logical reads 4000, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
SQL Server Execution Times:
CPU time = 10921 ms, elapsed time = 15743 ms.
不到一秒钟内100K行&在~15秒内有100万行...
答案 1 :(得分:0)
想想最简单的方法是使用金额变量对每个州运行它,这里是代码:
DECLARE @states TABLE (name NVARCHAR(50));
INSERT INTO @states (name)
SELECT DISTINCT
State
FROM anon_AddressChange
DECLARE @count INT
DECLARE @i INT
SET @i = 0
SET @count = (SELECT COUNT(*) FROM @states)
while @i < @count
BEGIN
DECLARE @state NVARCHAR(MAX)
SET @State = ( SELECT top 1 name from @states order by name )
DECLARE @amount INT
SET @amount = ( SELECT count(*) FROM anon_addresschange where state = @state )
;WITH CTE AS (
SELECT TOP (@amount) CAST(aD.flat_number AS VARCHAR(20)) + ' ' + g.Street_name + ' ' + g.street_type_code AS Address1
, aD.postcode AS postcode
, l.locality_name AS city
FROM [GNAF].dbo.Street_Locality g
INNER JOIN [GNAF].dbo.Address_Detail aD ON g.street_locality_pid = aD.street_locality_pid
INNER JOIN [GNAF].dbo.Locality l ON aD.locality_pid = l.locality_pid
WHERE g.street_name IS NOT NULL AND g.state = @state AND aD.flat_number IS NOT NULL
AND g.state NOT IN ('OT', 'NT' ,'TAS' ,'VIC' ,'ACT')
ORDER BY (SELECT new_id FROM getNewID )
)
UPDATE anon_addresschange SET
newStreet1 = UPPER(LEFT(a.Address1,1))+LOWER(SUBSTRING(a.Address1,2,LEN(a.Address1)))
,newCity = UPPER(LEFT(a.city,1))+LOWER(SUBSTRING(a.city,2,LEN(a.city)))
,newPostcode = a.postcode
,newState = @state
,newCountry = 'Australia'
FROM (
SELECT *, ROW_NUMBER() OVER (ORDER BY CAST(GETDATE() AS TIMESTAMP)) AS RowNumber from cte ) a
CROSS APPLY (
SELECT *, ROW_NUMBER() OVER (ORDER BY CAST(GETDATE() AS TIMESTAMP)) AS RowNumber FROM anon_AddressChange
WHERE state = @state) b
WHERE a.Rownumber = b.Rownumber
AND anon_addresschange.personID = b.personID
SET @i = @i + 1
delete from @states WHERE NAME IN ( SELECT TOP 1 name FROM @states order by name )
END
我真正需要做的就是在更新/插入语句中使用它。
这需要2秒才能运行1003条记录,因此1,000,000条记录需要33分钟。