मैं रैंड के खिलाफ 2 सेट आधारित यादृच्छिकीकरण तरीकों का परीक्षण किया() प्रत्येक के साथ 100,000,000 पंक्तियों उत्पन्न करके की तरह कुछ है। फ़ील्ड को स्तरित करने के लिए आउटपुट 0-1 के बीच रैंड() की नकल है। कोड के अधिकांश बुनियादी ढांचे परीक्षण कर रहा है तो मैं एल्गोरिदम यहाँ संक्षेप में प्रस्तुत:
-- Try #1 used
(CAST(CRYPT_GEN_RANDOM(8) AS BIGINT)%500000000000000000+500000000000000000.0)/1000000000000000000 AS Val
-- Try #2 used
RAND(Checksum(NewId()))
-- and to have a baseline to compare output with I used
RAND() -- this required executing 100000000 separate insert statements
CRYPT_GEN_RANDOM का उपयोग करते हुए स्पष्ट रूप से सबसे यादृच्छिक के बाद से वहाँ भी 1 डुप्लिकेट जब एक से 10^8 संख्या तोड़ देखने का केवल एक ०.००००००००१% मौका है था 10^18 संख्याओं का सेट। आइओ हमें किसी भी डुप्लीकेट नहीं दिखना चाहिए था और इसमें कोई नहीं था! इस सेट में मेरे लैपटॉप पर उत्पन्न होने के लिए 44 सेकंड लग गए।
Cnt Pct
----- ----
1 100.000000 --No duplicates
एसक्यूएल सर्वर निष्पादन समय: CPU समय = 134,795 एमएस, बीता हुआ समय = 39,274 एमएस।
IF OBJECT_ID('tempdb..#T0') IS NOT NULL DROP TABLE #T0;
GO
WITH L0 AS (SELECT c FROM (VALUES (1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) AS D(c)) -- 2^4
,L1 AS (SELECT 1 AS c FROM L0 AS A CROSS JOIN L0 AS B) -- 2^8
,L2 AS (SELECT 1 AS c FROM L1 AS A CROSS JOIN L1 AS B) -- 2^16
,L3 AS (SELECT 1 AS c FROM L2 AS A CROSS JOIN L2 AS B) -- 2^32
SELECT TOP 100000000 (CAST(CRYPT_GEN_RANDOM(8) AS BIGINT)%500000000000000000+500000000000000000.0)/1000000000000000000 AS Val
INTO #T0
FROM L3;
WITH x AS (
SELECT Val,COUNT(*) Cnt
FROM #T0
GROUP BY Val
)
SELECT x.Cnt,COUNT(*)/(SELECT COUNT(*)/100 FROM #T0) Pct
FROM X
GROUP BY x.Cnt;
पर लगभग 15 परिमाण कम यादृच्छिक इस पद्धति काफी दोगुनी गति से नहीं था, केवल 23 सेकंड लेने 100M संख्या उत्पन्न करने के लिए।
Cnt Pct
---- ----
1 95.450254 -- only 95% unique is absolutely horrible
2 02.222167 -- If this line were the only problem I'd say DON'T USE THIS!
3 00.034582
4 00.000409 -- 409 numbers appeared 4 times
5 00.000006 -- 6 numbers actually appeared 5 times
एसक्यूएल सर्वर निष्पादन समय: CPU समय = 77,156 एमएस, बीता हुआ समय = 24,613 एमएस।
IF OBJECT_ID('tempdb..#T1') IS NOT NULL DROP TABLE #T1;
GO
WITH L0 AS (SELECT c FROM (VALUES (1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) AS D(c)) -- 2^4
,L1 AS (SELECT 1 AS c FROM L0 AS A CROSS JOIN L0 AS B) -- 2^8
,L2 AS (SELECT 1 AS c FROM L1 AS A CROSS JOIN L1 AS B) -- 2^16
,L3 AS (SELECT 1 AS c FROM L2 AS A CROSS JOIN L2 AS B) -- 2^32
SELECT TOP 100000000 RAND(Checksum(NewId())) AS Val
INTO #T1
FROM L3;
WITH x AS (
SELECT Val,COUNT(*) Cnt
FROM #T1
GROUP BY Val
)
SELECT x.Cnt,COUNT(*)*1.0/(SELECT COUNT(*)/100 FROM #T1) Pct
FROM X
GROUP BY x.Cnt;
RAND() अकेले 6 घंटे से अधिक ले लिया और अंत में उत्पादन पंक्तियों की सही संख्या प्राप्त करने के लिए कई बार पुन: प्रारंभ करने के लिए किया था सेट आधारित पीढ़ी तो अनियमितता की तुलना के लिए आधारभूत पैदा करने के लिए बेकार है। यह भी लगता है कि यादृच्छिकता वांछित होने के लिए बहुत कुछ छोड़ देती है हालांकि यह प्रत्येक पंक्ति को संशोधित करने के लिए चेकसम (नया()) का उपयोग करने से बेहतर है।
Cnt Pct
---- ----
1 99.768020
2 00.115840
3 00.000100 -- at least there were comparitively few values returned 3 times
पुनरारंभ करने के कारण, निष्पादन समय पर कब्जा नहीं किया जा सका।
IF OBJECT_ID('tempdb..#T2') IS NOT NULL DROP TABLE #T2;
GO
CREATE TABLE #T2 (Val FLOAT);
GO
SET NOCOUNT ON;
GO
INSERT INTO #T2(Val) VALUES(RAND());
GO 100000000
WITH x AS (
SELECT Val,COUNT(*) Cnt
FROM #T2
GROUP BY Val
)
SELECT x.Cnt,COUNT(*)*1.0/(SELECT COUNT(*)/100 FROM #T2) Pct
FROM X
GROUP BY x.Cnt;
इस प्रश्न/उत्तर सहायक हो सकता है: http://stackoverflow.com/a/9039661/47226 –