ํƒœ๊ทธ ๋ณด๊ด€๋ฌผ: query-performance

query-performance

์ฒ˜์Œ 1 ์–ต ๊ฐœ์˜ ์–‘์˜ ์ •์ˆ˜๋ฅผ ์–ด๋–ป๊ฒŒ ๋ฌธ์ž์—ด๋กœ ๋ณ€ํ™˜ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ? โ•‘ โ•‘

์ด๊ฒƒ์€ ์‹ค์ œ ๋ฌธ์ œ์—์„œ ์•ฝ๊ฐ„ ๋ฒ—์–ด๋‚œ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ปจํ…์ŠคํŠธ ์ œ๊ณต์ด ๋„์›€์ด๋˜๋Š” ๊ฒฝ์šฐ์ด ๋ฐ์ดํ„ฐ ์ƒ์„ฑ์€ ๋ฌธ์ž์—ด ์ฒ˜๋ฆฌ ์„ฑ๋Šฅ ํ…Œ์ŠคํŠธ ๋ฐฉ๋ฒ•, ์ปค์„œ ๋‚ด์—์„œ ์ผ๋ถ€ ์ž‘์—…์„ ์ ์šฉํ•ด์•ผํ•˜๋Š” ๋ฌธ์ž์—ด ์ƒ์„ฑ ๋˜๋Š” ์ค‘์š”ํ•œ ๋ฐ์ดํ„ฐ์— ๋Œ€ํ•œ ๊ณ ์œ  ํ•œ ์ต๋ช… ์ด๋ฆ„ ๋Œ€์ฒด๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๋ฐ ์œ ์šฉ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. SQL Server์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ์ƒ์„ฑํ•˜๋Š” ํšจ์œจ์ ์ธ ๋ฐฉ๋ฒ•์— ๊ด€์‹ฌ์ด ์žˆ์Šต๋‹ˆ๋‹ค.์ด ๋ฐ์ดํ„ฐ๋ฅผ ์ƒ์„ฑํ•ด์•ผํ•˜๋Š” ์ด์œ ๋ฅผ ๋ฌป์ง€ ๋งˆ์‹ญ์‹œ์˜ค.

๋‚˜๋Š” ๋‹ค์†Œ ๊ณต์‹์ ์ธ ์ •์˜๋กœ ์‹œ์ž‘ํ•˜๋ ค๊ณ ํ•ฉ๋‹ˆ๋‹ค. ๋ฌธ์ž์—ด์€ A-Z์˜ ๋Œ€๋ฌธ์ž๋กœ๋งŒ ๊ตฌ์„ฑ๋œ ๊ฒฝ์šฐ ์‹œ๋ฆฌ์ฆˆ์— ํฌํ•จ๋ฉ๋‹ˆ๋‹ค. ์‹œ๋ฆฌ์ฆˆ์˜ ์ฒซ ๋ฒˆ์งธ ์šฉ์–ด๋Š” โ€œAโ€์ž…๋‹ˆ๋‹ค. ์ด ์‹œ๋ฆฌ์ฆˆ๋Š” ๊ธธ์ด๊ฐ€ ๋จผ์ € ์ •๋ ฌ๋˜๊ณ  ์•ŒํŒŒ๋ฒณ ์ˆœ์„œ๊ฐ€ ์•ŒํŒŒ๋ฒณ์ˆœ์œผ๋กœ ์ •๋ ฌ ๋œ ์œ ํšจํ•œ ๋ชจ๋“  ๋ฌธ์ž์—ด๋กœ ๊ตฌ์„ฑ๋ฉ๋‹ˆ๋‹ค. ๋ฌธ์ž์—ด์ด์ด๋ผ๋Š” ์—ด์˜ ํ…Œ์ด๋ธ”์— ์žˆ์œผ๋ฉด STRING_COL์ˆœ์„œ๋Š” T-SQL์—์„œ๋กœ ์ •์˜ ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค ORDER BY LEN(STRING_COL) ASC, STRING_COL ASC.

๋œ ๊ณต์‹์ ์œผ๋กœ ์ •์˜ํ•˜๋ ค๋ฉด ์•ŒํŒŒ๋ฒณ ์—ด ๋จธ๋ฆฌ๊ธ€์„ Excel๋กœ ์‚ดํŽด๋ณด์‹ญ์‹œ์˜ค. ์‹œ๋ฆฌ์ฆˆ๋Š” ๊ฐ™์€ ํŒจํ„ด์ž…๋‹ˆ๋‹ค. ์ •์ˆ˜๋ฅผ ๊ธฐ๋ณธ 26 ์ˆซ์ž๋กœ ๋ณ€ํ™˜ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ๊ณ ๋ คํ•˜์‹ญ์‹œ์˜ค.

1-> A, 2-> B, 3-> C, โ€ฆ, 25-> Y, 26-> Z, 27-> AA, 28-> AB, โ€ฆ

โ€œAโ€๊ฐ€ ๊ธฐ๋ณธ 10์—์„œ 0๊ณผ ๋‹ค๋ฅด๊ฒŒ ํ–‰๋™ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋น„์œ ๋Š” ์™„๋ฒฝํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋‹ค์Œ์€ ํฌ๋ง์ ์œผ๋กœ๋ณด๋‹ค ๋ช…ํ™•ํ•˜๊ฒŒํ•˜๊ธฐ ์œ„ํ•ด ์„ ํƒ๋œ ๊ฐ’์˜ ํ‘œ์ž…๋‹ˆ๋‹ค.

โ•”โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•ฆโ•โ•โ•โ•โ•โ•โ•โ•โ•—
โ•‘ ROW_NUMBER โ•‘ STRING โ•‘
โ• โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•ฌโ•โ•โ•โ•โ•โ•โ•โ•โ•ฃ
โ•‘          1 โ•‘ A      โ•‘
โ•‘          2 โ•‘ B      โ•‘
โ•‘         25 โ•‘ Y      โ•‘
โ•‘         26 โ•‘ Z      โ•‘
โ•‘         27 โ•‘ AA     โ•‘
โ•‘         28 โ•‘ AB     โ•‘
โ•‘         51 โ•‘ AY     โ•‘
โ•‘         52 โ•‘ AZ     โ•‘
โ•‘         53 โ•‘ BA     โ•‘
โ•‘         54 โ•‘ BB     โ•‘
โ•‘      18278 โ•‘ ZZZ    โ•‘
โ•‘      18279 โ•‘ AAAA   โ•‘
โ•‘     475253 โ•‘ ZZZY   โ•‘
โ•‘     475254 โ•‘ ZZZZ   โ•‘
โ•‘     475255 โ•‘ AAAAA  โ•‘
โ•‘  100000000 โ•‘ HJUNYV โ•‘
โ•šโ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•ฉโ•โ•โ•โ•โ•โ•โ•โ•โ•

๋ชฉํ‘œ๋Š” SELECT์œ„์— ์ •์˜ ๋œ ์ˆœ์„œ๋Œ€๋กœ ์ฒ˜์Œ 100000000 ๊ฐœ์˜ ๋ฌธ์ž์—ด์„ ๋ฐ˜ํ™˜ ํ•˜๋Š” ์ฟผ๋ฆฌ ๋ฅผ ์ž‘์„ฑํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค . SSMS์—์„œ ์ฟผ๋ฆฌ๋ฅผ ์‹คํ–‰ํ•˜์—ฌ ํ…Œ์ด๋ธ”์— ์ €์žฅํ•˜๋Š” ๋Œ€์‹  ๊ฒฐ๊ณผ ์ง‘ํ•ฉ์„ ์‚ญ์ œํ•˜์—ฌ ํ…Œ์ŠคํŠธ๋ฅผ ์ˆ˜ํ–‰ํ–ˆ์Šต๋‹ˆ๋‹ค.

๊ฒฐ๊ณผ ์„ธํŠธ ์‚ญ์ œ

์ด์ƒ์ ์œผ๋กœ๋Š” ์ฟผ๋ฆฌ๊ฐ€ ์ƒ๋‹นํžˆ ํšจ์œจ์ ์ž…๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์„œ๋Š” ์ง๋ ฌ ์ฟผ๋ฆฌ์˜ CPU ์‹œ๊ฐ„๊ณผ ๋ณ‘๋ ฌ ์ฟผ๋ฆฌ์˜ ๊ฒฝ๊ณผ ์‹œ๊ฐ„์„ ํšจ์œจ์ ์œผ๋กœ ์ •์˜ํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ๋ฌธ์„œํ™”๋˜์ง€ ์•Š์€ ํŠธ๋ฆญ์„ ์›ํ•˜๋Š”๋Œ€๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ •์˜๋˜์ง€ ์•Š์•˜๊ฑฐ๋‚˜ ๋ณด์žฅ๋˜์ง€ ์•Š์€ ํ–‰๋™์— ์˜์กดํ•˜๋Š” ๊ฒƒ๋„ ๊ดœ์ฐฎ์ง€ ๋งŒ ๋Œ€๋‹ต์—์„œ ๊ทธ๊ฒƒ์„ ๋ถˆ๋Ÿฌ ์ฃผ๋ฉด ๊ฐ์‚ฌํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

์œ„์—์„œ ์„ค๋ช…ํ•œ ๋ฐ์ดํ„ฐ ์„ธํŠธ๋ฅผ ํšจ์œจ์ ์œผ๋กœ ์ƒ์„ฑํ•˜๋Š” ๋ช‡ ๊ฐ€์ง€ ๋ฐฉ๋ฒ•์€ ๋ฌด์—‡์ž…๋‹ˆ๊นŒ? Martin Smith ๋Š” CLR ์ €์žฅ ํ”„๋กœ ์‹œ์ €๊ฐ€ ๋„ˆ๋ฌด ๋งŽ์€ ํ–‰์„ ์ฒ˜๋ฆฌํ•˜๋Š” ์˜ค๋ฒ„ ํ—ค๋“œ๋กœ ์ธํ•ด ์ข‹์€ ์ ‘๊ทผ ๋ฐฉ์‹์ด ์•„๋‹ ์ˆ˜ ์žˆ๋‹ค๊ณ  ์ง€์ ํ–ˆ์Šต๋‹ˆ๋‹ค.



๋‹ต๋ณ€

์†”๋ฃจ์…˜์ด ๋žฉํ†ฑ ์—์„œ 35 ์ดˆ ๋™์•ˆ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค . ๋‹ค์Œ ์ฝ”๋“œ๋Š” 26 ์ดˆ๊ฐ€ ๊ฑธ๋ฆฝ๋‹ˆ๋‹ค (์ž„์‹œ ํ…Œ์ด๋ธ” ์ž‘์„ฑ ๋ฐ ์ฑ„์šฐ๊ธฐ ํฌํ•จ).

์ž„์‹œ ํ…Œ์ด๋ธ”

DROP TABLE IF EXISTS #T1, #T2, #T3, #T4;

CREATE TABLE #T1 (string varchar(6) NOT NULL PRIMARY KEY);
CREATE TABLE #T2 (string varchar(6) NOT NULL PRIMARY KEY);
CREATE TABLE #T3 (string varchar(6) NOT NULL PRIMARY KEY);
CREATE TABLE #T4 (string varchar(6) NOT NULL PRIMARY KEY);

INSERT #T1 (string)
VALUES
    ('A'), ('B'), ('C'), ('D'), ('E'), ('F'), ('G'),
    ('H'), ('I'), ('J'), ('K'), ('L'), ('M'), ('N'),
    ('O'), ('P'), ('Q'), ('R'), ('S'), ('T'), ('U'),
    ('V'), ('W'), ('X'), ('Y'), ('Z');

INSERT #T2 (string)
SELECT T1a.string + T1b.string
FROM #T1 AS T1a, #T1 AS T1b;

INSERT #T3 (string)
SELECT #T2.string + #T1.string
FROM #T2, #T1;

INSERT #T4 (string)
SELECT #T3.string + #T1.string
FROM #T3, #T1;

์ตœ๋Œ€ 4 ์ž์˜ ์ˆœ์„œ๋กœ ์กฐํ•ฉ ๋œ ํ•ญ๋ชฉ์„ ๋ฏธ๋ฆฌ ์ฑ„์šฐ๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค.

๋ฉ”์ธ ์ฝ”๋“œ

SELECT TOP (100000000)
    UA.string + UA.string2
FROM
(
    SELECT U.Size, U.string, string2 = '' FROM
    (
        SELECT Size = 1, string FROM #T1
        UNION ALL
        SELECT Size = 2, string FROM #T2
        UNION ALL
        SELECT Size = 3, string FROM #T3
        UNION ALL
        SELECT Size = 4, string FROM #T4
    ) AS U
    UNION ALL
    SELECT Size = 5, #T1.string, string2 = #T4.string
    FROM #T1, #T4
    UNION ALL
    SELECT Size = 6, #T2.string, #T4.string
    FROM #T2, #T4
) AS UA
ORDER BY
    UA.Size,
    UA.string,
    UA.string2
OPTION (NO_PERFORMANCE_SPOOL, MAXDOP 1);

์ด๋Š” ํ•„์š”์— ๋”ฐ๋ผ 5 ์ž ๋ฐ 6 ์ž ๋ฌธ์ž์—ด์ด ํŒŒ์ƒ ๋œ 4 ๊ฐœ์˜ ์‚ฌ์ „ ๊ณ„์‚ฐ ๋œ ํ…Œ์ด๋ธ”์˜ ๊ฐ„๋‹จํ•œ ์ˆœ์„œ ์œ ์ง€ ํ†ตํ•ฉ *์ž…๋‹ˆ๋‹ค. ์ ‘๋‘์‚ฌ์—์„œ ์ ‘๋‘์‚ฌ๋ฅผ ๋ถ„๋ฆฌํ•˜๋ฉด ์ •๋ ฌ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

์‹คํ–‰ ๊ณ„ํš


* ์œ„์˜ SQL์—๋Š” ์ฃผ๋ฌธ ๋ณด์กด ์—ฐํ•ฉ์„ ์ง์ ‘ ์ง€์ •ํ•˜๋Š” ๊ฒƒ์ด ์—†์Šต๋‹ˆ๋‹ค . ์˜ตํ‹ฐ๋งˆ์ด ์ €๋Š” ์ตœ์ƒ์œ„ ์ˆœ์„œ๋ฅผ ํฌํ•จํ•˜์—ฌ SQL ์ฟผ๋ฆฌ ์ŠคํŽ™๊ณผ ์ผ์น˜ํ•˜๋Š” ํŠน์„ฑ์„ ๊ฐ€์ง„ ์‹ค์ œ ์—ฐ์‚ฐ์ž๋ฅผ ์„ ํƒํ•ฉ๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์„œ๋Š” ์ •๋ ฌ์„ ํ”ผํ•˜๊ธฐ ์œ„ํ•ด merge join ๋ฌผ๋ฆฌ ์—ฐ์‚ฐ์ž์— ์˜ํ•ด ๊ตฌํ˜„ ๋œ ์—ฐ๊ฒฐ์„ ์„ ํƒํ•ฉ๋‹ˆ๋‹ค.

์‹คํ–‰ ๊ณ„ํš์€ ์‚ฌ์–‘์— ๋”ฐ๋ผ ์ฟผ๋ฆฌ ์‹œ๋งจํ‹ฑ ๋ฐ ์ตœ์ƒ์œ„ ์ˆœ์„œ๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. ๋ณ‘ํ•ฉ ์กฐ์ธ ์—ฐ๊ฒฐ์ด ์ˆœ์„œ๋ฅผ ์œ ์ง€ํ•œ๋‹ค๋Š” ๊ฒƒ์„ ์•Œ๋ฉด ์ฟผ๋ฆฌ ์ž‘์„ฑ๊ธฐ๋Š” ์‹คํ–‰ ๊ณ„ํš์„ ์˜ˆ์ƒ ํ•  ์ˆ˜ ์žˆ์ง€๋งŒ ์˜ตํ‹ฐ๋งˆ์ด ์ €๋Š” ๊ธฐ๋Œ€๊ฐ€ ์œ ํšจํ•œ ๊ฒฝ์šฐ์—๋งŒ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.


๋‹ต๋ณ€

์‹œ์ž‘ํ•˜๊ธฐ ์œ„ํ•ด ๋‹ต๋ณ€์„ ๊ฒŒ์‹œํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. ๋‚ด ์ฒซ ๋ฒˆ์งธ ์ƒ๊ฐ์€ ๊ฐ ๋ฌธ์ž์— ๋Œ€ํ•ด ํ•˜๋‚˜์˜ ํ–‰์ด์žˆ๋Š” ๋ช‡ ๊ฐœ์˜ ๋„์šฐ๋ฏธ ํ…Œ์ด๋ธ”๊ณผ ํ•จ๊ป˜ ์ค‘์ฒฉ ๋ฃจํ”„ ์กฐ์ธ์˜ ์ˆœ์„œ ์œ ์ง€ ํŠน์„ฑ์„ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ์–ด์•ผํ•œ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊นŒ๋‹ค๋กœ์šด ๋ถ€๋ถ„์€ ๊ฒฐ๊ณผ๋ฅผ ๊ธธ์ด๋ณ„๋กœ ์ •๋ ฌํ•˜๊ณ  ์ค‘๋ณต์„ ํ”ผํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ ๋ฐ˜๋ณต๋ฉ๋‹ˆ๋‹ค. โ€์™€ ํ•จ๊ป˜ ๋ชจ๋‘ 26 ๋Œ€๋ฌธ์ž๋ฅผ ํฌํ•จํ•˜๋Š” CTE์— ๊ฐ€์ž… ํ•  ๋•Œ ํฌ๋กœ์Šค ์˜ˆ๋ฅผ ๋“ค์–ด, ์ƒ์„ฑ์„ ๋๋‚ผ ์ˆ˜ 'A' + '' + 'A'์™€ '' + 'A' + 'A'๋ฌผ๋ก  ๊ฐ™์€ ๋ฌธ์ž์—ด์ด๋‹ค.

์ฒซ ๋ฒˆ์งธ ๊ฒฐ์ •์€ ๋„์šฐ๋ฏธ ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•  ์œ„์น˜์ž…๋‹ˆ๋‹ค. ์ž„์‹œ ํ…Œ์ด๋ธ”์„ ์‚ฌ์šฉํ•ด ๋ณด์•˜์ง€๋งŒ ๋ฐ์ดํ„ฐ๊ฐ€ ๋‹จ์ผ ํŽ˜์ด์ง€์— ์ ํ•ฉํ•˜๋”๋ผ๋„ ์„ฑ๋Šฅ์— ๋†€๋ผ ์šธ ์ •๋„๋กœ ๋ถ€์ •์ ์ธ ์˜ํ–ฅ์„ ๋ฏธ์ณค์Šต๋‹ˆ๋‹ค. ์ž„์‹œ ํ…Œ์ด๋ธ”์—๋Š” ๋‹ค์Œ ๋ฐ์ดํ„ฐ๊ฐ€ ํฌํ•จ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.

SELECT 'A'
UNION ALL SELECT 'B'
...
UNION ALL SELECT 'Y'
UNION ALL SELECT 'Z'

CTE๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์— ๋น„ํ•ด ์ฟผ๋ฆฌ๋Š” ํด๋Ÿฌ์Šคํ„ฐ ๋œ ํ…Œ์ด๋ธ”์˜ ๊ฒฝ์šฐ 3 ๋ฐฐ, ํž™์˜ ๊ฒฝ์šฐ 4 ๋ฐฐ ๋” ์˜ค๋ž˜ ๊ฑธ๋ ธ์Šต๋‹ˆ๋‹ค. ๋ฌธ์ œ๋Š” ๋ฐ์ดํ„ฐ๊ฐ€ ๋””์Šคํฌ์— ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋‹จ์ผ ํŽ˜์ด์ง€๋กœ ๋ฉ”๋ชจ๋ฆฌ์— ์ฝ๊ณ  ์ „์ฒด ๊ณ„ํš์— ๋Œ€ํ•ด ๋ฉ”๋ชจ๋ฆฌ์—์„œ ์ฒ˜๋ฆฌํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค. SQL Server๋Š” ์ผ๋ฐ˜์ ์ธ ํ–‰ ์ €์žฅ์†Œ ํŽ˜์ด์ง€์— ์ €์žฅ๋œ ๋ฐ์ดํ„ฐ๋ณด๋‹ค Constant Scan ์—ฐ์‚ฐ์ž์˜ ๋ฐ์ดํ„ฐ๋ฅผ ๋” ํšจ์œจ์ ์œผ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

ํฅ๋ฏธ๋กญ๊ฒŒ๋„ SQL Server๋Š” ์ •๋ ฌ ๋œ ๋ฐ์ดํ„ฐ๊ฐ€์žˆ๋Š” ๋‹จ์ผ ํŽ˜์ด์ง€ tempdb ํ…Œ์ด๋ธ”์˜ ์ •๋ ฌ ๋œ ๊ฒฐ๊ณผ๋ฅผ ํ…Œ์ด๋ธ” ์Šคํ’€์— ๋„ฃ๋„๋ก ์„ ํƒํ•ฉ๋‹ˆ๋‹ค.

SQL Server๋Š” ๊ต์ฐจ ์กฐ์ธ์˜ ๋‚ด๋ถ€ ํ…Œ์ด๋ธ”์— ๋Œ€ํ•œ ๊ฒฐ๊ณผ๋ฅผ ์˜๋ฏธ๊ฐ€์—†๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ๋ณด์ด๋”๋ผ๋„ ํ…Œ์ด๋ธ” ์Šคํ’€์— ๋„ฃ๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋งŽ์Šต๋‹ˆ๋‹ค. ์˜ตํ‹ฐ๋งˆ์ด ์ €๋Š”์ด ๋ถ„์•ผ์—์„œ ์•ฝ๊ฐ„์˜ ์ž‘์—…์ด ํ•„์š”ํ•˜๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. NO_PERFORMANCE_SPOOL์„ฑ๋Šฅ ์ €ํ•˜๋ฅผ ํ”ผํ•˜๊ธฐ ์œ„ํ•ด ์ฟผ๋ฆฌ๋ฅผ ์‹คํ–‰ํ–ˆ์Šต๋‹ˆ๋‹ค .

CTE๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํ—ฌํผ ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•˜๋Š” ๋ฐ์žˆ์–ด ํ•œ ๊ฐ€์ง€ ๋ฌธ์ œ์ ์€ ๋ฐ์ดํ„ฐ์˜ ์ˆœ์„œ๊ฐ€ ๋ณด์žฅ๋˜์ง€ ์•Š๋Š”๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์˜ตํ‹ฐ๋งˆ์ด ์ €๊ฐ€ ์™œ ์ฃผ๋ฌธํ•˜์ง€ ์•Š๊ธฐ๋กœ ๊ฒฐ์ •ํ–ˆ๋Š”์ง€๋Š” ์•Œ ์ˆ˜ ์—†์œผ๋ฉฐ ๋ชจ๋“  ํ…Œ์ŠคํŠธ์—์„œ CTE๋ฅผ ์ž‘์„ฑํ•œ ์ˆœ์„œ๋Œ€๋กœ ๋ฐ์ดํ„ฐ๊ฐ€ ์ฒ˜๋ฆฌ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

๊ทธ๋Ÿฌ๋‚˜ ํŠนํžˆ ์„ฑ๋Šฅ ์˜ค๋ฒ„ ํ—ค๋“œ๊ฐ€ ํฌ์ง€ ์•Š์€ ๊ฒฝ์šฐ์—๋Š” ์ˆ˜ํ–‰ ํ•  ์ˆ˜์žˆ๋Š” ๊ธฐํšŒ๊ฐ€์—†๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค. ๋ถˆํ•„์š”ํ•œ TOP์—ฐ์‚ฐ์ž ๋ฅผ ์ถ”๊ฐ€ํ•˜์—ฌ ํŒŒ์ƒ ํ…Œ์ด๋ธ”์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ์ •๋ ฌ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

(SELECT TOP (26) CHR FROM FIRST_CHAR ORDER BY CHR)

์ฟผ๋ฆฌ์— ์ถ”๊ฐ€ํ•˜๋ฉด ๊ฒฐ๊ณผ๊ฐ€ ์˜ฌ๋ฐ”๋ฅธ ์ˆœ์„œ๋กœ ๋ฐ˜ํ™˜๋ฉ๋‹ˆ๋‹ค. ๋ชจ๋“  ์ข…๋ฅ˜์˜ ์„ฑ๋Šฅ์— ๋ถ€์ •์ ์ธ ์˜ํ–ฅ์„ ๋ฏธ์น  ๊ฒƒ์œผ๋กœ ์˜ˆ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค. ์ฟผ๋ฆฌ ์ตœ์ ํ™” ํ”„๋กœ๊ทธ๋žจ์€ ์˜ˆ์ƒ ๋น„์šฉ์„ ๊ธฐ๋ฐ˜์œผ๋กœ์ด๋ฅผ ์˜ˆ์ธกํ–ˆ์Šต๋‹ˆ๋‹ค.

๋†€๋ž๊ฒŒ๋„, ๋ช…์‹œ ์  ์ˆœ์„œ์˜ ์œ ๋ฌด์— ๊ด€๊ณ„์—†์ด CPU ์‹œ๊ฐ„ ๋˜๋Š” ๋Ÿฐํƒ€์ž„์—์„œ ํ†ต๊ณ„์ ์œผ๋กœ ์œ ์˜ ํ•œ ์ฐจ์ด๋ฅผ ๊ด€์ฐฐ ํ•  ์ˆ˜ ์—†์—ˆ์Šต๋‹ˆ๋‹ค. ๋ฌด์—‡์ด๋“ , ์ฟผ๋ฆฌ๋Š” ORDER BY! ์ด ๋™์ž‘์— ๋Œ€ํ•œ ์„ค๋ช…์ด ์—†์Šต๋‹ˆ๋‹ค.

๋ฌธ์ œ์˜ ๊นŒ๋‹ค๋กœ์šด ๋ถ€๋ถ„์€ ์˜ฌ๋ฐ”๋ฅธ ์œ„์น˜์— ๊ณต๋ฐฑ ๋ฌธ์ž๋ฅผ ์‚ฝ์ž…ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์•Œ์•„๋‚ด๋Š” ๊ฒƒ์ด ์—ˆ์Šต๋‹ˆ๋‹ค. ์•ž์—์„œ ์–ธ๊ธ‰ํ–ˆ๋“ฏ์ด ๊ฐ„๋‹จํ•œ CROSS JOIN๋ฐ์ดํ„ฐ๋Š” ์ค‘๋ณต๋ฉ๋‹ˆ๋‹ค. ์šฐ๋ฆฌ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ด์œ ๋กœ 100000000 ๋ฒˆ์งธ ๋ฌธ์ž์—ด์˜ ๊ธธ์ด๊ฐ€ 6 ์ž๋ผ๋Š” ๊ฒƒ์„ ์•Œ๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

26 + 26 ^ 2 + 26 ^ 3 + 26 ^ 4 + 26 ^ 5 = 914654 <100000000

๊ทธ๋Ÿฌ๋‚˜

26 + 26 ^ 2 + 26 ^ 3 + 26 ^ 4 + 26 ^ 5 + 26 ^ 6 = 321272406> 100000000

๋”ฐ๋ผ์„œ CTE์— 6 ๋ฒˆ๋งŒ ๊ฐ€์ž…ํ•˜๋ฉด๋ฉ๋‹ˆ๋‹ค. CTE์— 6 ๋ฒˆ ๊ฐ€์ž…ํ•˜๊ณ  ๊ฐ CTE์—์„œ ํ•œ ๊ธ€์ž๋ฅผ ๊ฐ€์ ธ ์™€์„œ ๋ชจ๋‘ ์—ฐ๊ฒฐํ•œ๋‹ค๊ณ  ๊ฐ€์ •ํ•ฉ๋‹ˆ๋‹ค. ๊ฐ€์žฅ ์™ผ์ชฝ์˜ ๋ฌธ์ž๊ฐ€ ๊ณต๋ฐฑ์ด ์•„๋‹ˆ๋ผ๊ณ  ๊ฐ€์ •ํ•˜์‹ญ์‹œ์˜ค. ํ›„์† ๋ฌธ์ž๊ฐ€ ๋น„์–ด ์žˆ์œผ๋ฉด ๋ฌธ์ž์—ด์˜ ๊ธธ์ด๊ฐ€ 6 ์ž ๋ฏธ๋งŒ์ด๋ฏ€๋กœ ์ค‘๋ณต๋ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ๊ณต๋ฐฑ์ด ์•„๋‹Œ ์ฒซ ๋ฒˆ์งธ ๋ฌธ์ž๋ฅผ ์ฐพ์•„ ๊ณต๋ฐฑ์ด ์•„๋‹Œ ๋ชจ๋“  ๋ฌธ์ž๋ฅผ ์š”๊ตฌํ•˜์—ฌ ์ค‘๋ณต์„ ๋ฐฉ์ง€ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. FLAGCTE ์ค‘ ํ•˜๋‚˜์— ์—ด์„ ํ• ๋‹น ํ•˜๊ณ  WHERE์ ˆ์— ๊ฒ€์‚ฌ๋ฅผ ์ถ”๊ฐ€ํ•˜์—ฌ ์ด๋ฅผ ์ถ”์ ํ•˜๊ธฐ๋กœ ์„ ํƒํ–ˆ์Šต๋‹ˆ๋‹ค . ์ฟผ๋ฆฌ๋ฅผ ํ™•์ธํ•œ ํ›„์— ๋” ๋ช…ํ™•ํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค. ์ตœ์ข… ์ฟผ๋ฆฌ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

WITH FIRST_CHAR (CHR) AS
(
    SELECT 'A'
    UNION ALL SELECT 'B'
    UNION ALL SELECT 'C'
    UNION ALL SELECT 'D'
    UNION ALL SELECT 'E'
    UNION ALL SELECT 'F'
    UNION ALL SELECT 'G'
    UNION ALL SELECT 'H'
    UNION ALL SELECT 'I'
    UNION ALL SELECT 'J'
    UNION ALL SELECT 'K'
    UNION ALL SELECT 'L'
    UNION ALL SELECT 'M'
    UNION ALL SELECT 'N'
    UNION ALL SELECT 'O'
    UNION ALL SELECT 'P'
    UNION ALL SELECT 'Q'
    UNION ALL SELECT 'R'
    UNION ALL SELECT 'S'
    UNION ALL SELECT 'T'
    UNION ALL SELECT 'U'
    UNION ALL SELECT 'V'
    UNION ALL SELECT 'W'
    UNION ALL SELECT 'X'
    UNION ALL SELECT 'Y'
    UNION ALL SELECT 'Z'
)
, ALL_CHAR (CHR, FLAG) AS
(
    SELECT '', 0 CHR
    UNION ALL SELECT 'A', 1
    UNION ALL SELECT 'B', 1
    UNION ALL SELECT 'C', 1
    UNION ALL SELECT 'D', 1
    UNION ALL SELECT 'E', 1
    UNION ALL SELECT 'F', 1
    UNION ALL SELECT 'G', 1
    UNION ALL SELECT 'H', 1
    UNION ALL SELECT 'I', 1
    UNION ALL SELECT 'J', 1
    UNION ALL SELECT 'K', 1
    UNION ALL SELECT 'L', 1
    UNION ALL SELECT 'M', 1
    UNION ALL SELECT 'N', 1
    UNION ALL SELECT 'O', 1
    UNION ALL SELECT 'P', 1
    UNION ALL SELECT 'Q', 1
    UNION ALL SELECT 'R', 1
    UNION ALL SELECT 'S', 1
    UNION ALL SELECT 'T', 1
    UNION ALL SELECT 'U', 1
    UNION ALL SELECT 'V', 1
    UNION ALL SELECT 'W', 1
    UNION ALL SELECT 'X', 1
    UNION ALL SELECT 'Y', 1
    UNION ALL SELECT 'Z', 1
)
SELECT TOP (100000000)
d6.CHR + d5.CHR + d4.CHR + d3.CHR + d2.CHR + d1.CHR
FROM (SELECT TOP (27) FLAG, CHR FROM ALL_CHAR ORDER BY CHR) d6
CROSS JOIN (SELECT TOP (27) FLAG, CHR FROM ALL_CHAR ORDER BY CHR) d5
CROSS JOIN (SELECT TOP (27) FLAG, CHR FROM ALL_CHAR ORDER BY CHR) d4
CROSS JOIN (SELECT TOP (27) FLAG, CHR FROM ALL_CHAR ORDER BY CHR) d3
CROSS JOIN (SELECT TOP (27) FLAG, CHR FROM ALL_CHAR ORDER BY CHR) d2
CROSS JOIN (SELECT TOP (26) CHR FROM FIRST_CHAR ORDER BY CHR) d1
WHERE (d2.FLAG + d3.FLAG + d4.FLAG + d5.FLAG + d6.FLAG) =
    CASE
    WHEN d6.FLAG = 1 THEN 5
    WHEN d5.FLAG = 1 THEN 4
    WHEN d4.FLAG = 1 THEN 3
    WHEN d3.FLAG = 1 THEN 2
    WHEN d2.FLAG = 1 THEN 1
    ELSE 0 END
OPTION (MAXDOP 1, FORCE ORDER, LOOP JOIN, NO_PERFORMANCE_SPOOL);

CTE๋Š” ์ „์ˆ  ํ•œ ๋ฐ”์™€ ๊ฐ™๋‹ค. ALL_CHAR๋นˆ ๋ฌธ์ž์— ๋Œ€ํ•œ ํ–‰์ด ํฌํ•จ๋˜์–ด ์žˆ๊ธฐ ๋•Œ๋ฌธ์— 5 ๋ฒˆ ์—ฐ๊ฒฐ๋ฉ๋‹ˆ๋‹ค. ๋ฌธ์ž์—ด์˜ ๋งˆ์ง€๋ง‰ ๋ฌธ์ž๋Š” ๋น„์›Œ ๋‘˜ ์ˆ˜ ์—†์œผ๋ฏ€๋กœ ๋ณ„๋„์˜ CTE๊ฐ€ ์ •์˜๋ฉ๋‹ˆ๋‹ค FIRST_CHAR. ์ถ”๊ฐ€ ํ”Œ๋ž˜๊ทธ ์—ด ALL_CHAR์€ ์œ„์—์„œ ์„ค๋ช…ํ•œ๋Œ€๋กœ ์ค‘๋ณต์„ ๋ฐฉ์ง€ํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. ์ด ๊ฒ€์‚ฌ๋ฅผ ์ˆ˜ํ–‰ํ•˜๋Š” ๋ฐ ๋” ํšจ์œจ์ ์ธ ๋ฐฉ๋ฒ•์ด์žˆ์„ ์ˆ˜ ์žˆ์ง€๋งŒ ๋” ๋น„ํšจ์œจ์  ์ธ ๋ฐฉ๋ฒ•์ด ์žˆ์Šต๋‹ˆ๋‹ค. ํ•˜๋‚˜ ๊ฐœ ๋‚˜์— ์˜ํ•˜์—ฌ ์‹œ๋„ LEN()ํ•˜๊ณ  POWER()ํ˜„์žฌ ๋ฒ„์ „๋ณด๋‹ค ์—ฌ์„ฏ ๋ฐฐ ๋А๋ฆฐ ์ฟผ๋ฆฌ ์‹คํ–‰์„ํ–ˆ๋‹ค.

MAXDOP 1์™€ FORCE ORDERํžŒํŠธ๋Š” ํ™•์ธ ์ฃผ๋ฌธ์ด ์ฟผ๋ฆฌ์— ๋ณด์กด๋˜์–ด ์žˆ๋Š”์ง€ ํ™•์ธํ•˜๋Š” ๊ฒƒ์ด ํ•„์ˆ˜์ ์ด๋‹ค. ์ฃผ์„์ด ๋‹ฌ๋ฆฐ ์ถ”์ • ๊ณ„ํš์€ ์กฐ์ธ์ด ํ˜„์žฌ ์ˆœ์„œ ์ธ ์ด์œ ๋ฅผ ํ™•์ธํ•˜๋Š” ๋ฐ ๋„์›€์ด ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ฟผ๋ฆฌ ๊ณ„ํš์€ ์ข…์ข… ์˜ค๋ฅธ์ชฝ์—์„œ ์™ผ์ชฝ์œผ๋กœ ์ฝ์ง€ ๋งŒ ํ–‰ ์š”์ฒญ์€ ์™ผ์ชฝ์—์„œ ์˜ค๋ฅธ์ชฝ์œผ๋กœ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค. ์ด์ƒ์ ์œผ๋กœ SQL Server๋Š” d1์ƒ์ˆ˜ ์Šค์บ” ์—ฐ์‚ฐ์ž์—๊ฒŒ ์ •ํ™•ํžˆ 1 ์–ต ๊ฐœ์˜ ํ–‰์„ ์š”์ฒญํ•ฉ๋‹ˆ๋‹ค . ์™ผ์ชฝ์—์„œ ์˜ค๋ฅธ์ชฝ์œผ๋กœ ์ด๋™ํ•  ๋•Œ ๊ฐ ์—ฐ์‚ฐ์ž์—์„œ ๋” ์ ์€ ์ˆ˜์˜ ํ–‰์„ ์š”์ฒญํ•  ๊ฒƒ์œผ๋กœ ์˜ˆ์ƒํ•ฉ๋‹ˆ๋‹ค. ์šฐ๋ฆฌ๋Š” ์ด๊ฒƒ์„ ์‹ค์ œ ์‹คํ–‰ ๊ณ„ํš ์—์„œ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค . ๋˜ํ•œ ์•„๋ž˜๋Š” SQL Sentry Plan Explorer์˜ ์Šคํฌ๋ฆฐ ์ƒท์ž…๋‹ˆ๋‹ค.

์šฐ๋ฆฌ๋Š” d1์—์„œ ์ •ํ™•ํžˆ 1 ์–ต ๊ฐœ์˜ ํ–‰์„ ์–ป์—ˆ์Šต๋‹ˆ๋‹ค. d2์™€ d3 ์‚ฌ์ด์˜ ํ–‰ ๋น„์œจ์€ ๊ฑฐ์˜ ์ •ํ™•ํžˆ 27 : 1 (165336 * 27 = 4464072)์ด๋ฏ€๋กœ ํฌ๋กœ์Šค ์กฐ์ธ์˜ ์ž‘๋™ ๋ฐฉ์‹์— ๋Œ€ํ•ด ์ƒ๊ฐํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค. d1๊ณผ d2 ์‚ฌ์ด์˜ ํ–‰ ๋น„์œจ์€ 22.4์ด๋ฉฐ ์ผ๋ถ€ ๋‚ญ๋น„ ๋œ ์ž‘์—…์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค. ์—ฌ๋ถ„์˜ ํ–‰์€ ์ค‘๋ณต ๋œ ๊ฒƒ (๋ฌธ์ž์—ด ์ค‘๊ฐ„์˜ ๋นˆ ๋ฌธ์ž๋กœ ์ธํ•ด)์—์„œ ๋‚˜์˜จ ๊ฒƒ์œผ๋กœ ํ•„ํ„ฐ๋ง์„ ์ˆ˜ํ–‰ํ•˜๋Š” ์ค‘์ฒฉ ๋ฃจํ”„ ์กฐ์ธ ์—ฐ์‚ฐ์ž๋ฅผ ์ง€๋‚˜์น˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

LOOP JOIN๋•Œ๋ฌธ์— ํžŒํŠธ๋Š” ๊ธฐ์ˆ ์ ์œผ๋กœ ํ•„์š”ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค CROSS JOIN๋งŒ ๋ฃจํ”„๋กœ ๊ตฌํ˜„ ๋  ์ˆ˜๋Š” SQL ์„œ๋ฒ„์— ๊ฐ€์ž… ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋Š” NO_PERFORMANCE_SPOOL๋ถˆํ•„์š”ํ•œ ํ…Œ์ด๋ธ” ์Šคํ’€๋ง์„ ๋ฐฉ์ง€ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์Šคํ’€ ํžŒํŠธ๋ฅผ ์ƒ๋žตํ•˜๋ฉด ์ฟผ๋ฆฌ๊ฐ€ ์ปดํ“จํ„ฐ์—์„œ 3 ๋ฐฐ ๋” ์˜ค๋ž˜ ๊ฑธ๋ ธ์Šต๋‹ˆ๋‹ค.

์ตœ์ข… ์ฟผ๋ฆฌ์˜ CPU ์‹œ๊ฐ„์€ ์•ฝ 17 ์ดˆ์ด๊ณ  ์ด ๊ฒฝ๊ณผ ์‹œ๊ฐ„์€ 18 ์ดˆ์ž…๋‹ˆ๋‹ค. SSMS๋ฅผ ํ†ตํ•ด ์ฟผ๋ฆฌ๋ฅผ ์‹คํ–‰ํ•˜๊ณ  ๊ฒฐ๊ณผ ์ง‘ํ•ฉ์„ ๋ฒ„๋ฆด โ€‹โ€‹๋•Œ์˜€์Šต๋‹ˆ๋‹ค. ๋ฐ์ดํ„ฐ๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๋‹ค๋ฅธ ๋ฐฉ๋ฒ•์„ ๋ณด๋Š” ๋ฐ ๊ด€์‹ฌ์ด ์žˆ์Šต๋‹ˆ๋‹ค.


๋‹ต๋ณ€

์ตœ๋Œ€ 217,180,147,158 (8 ์ž)๊นŒ์ง€ ํŠน์ • ์ˆซ์ž์˜ ๋ฌธ์ž์—ด ์ฝ”๋“œ๋ฅผ ์–ป๋„๋ก ์ตœ์ ํ™” ๋œ ์†”๋ฃจ์…˜์ด ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ๋‚˜๋Š” ๋‹น์‹ ์˜ ์‹œ๊ฐ„์„ ์ด๊ธธ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค :

๋‚ด ์ปดํ“จํ„ฐ์—์„œ SQL Server 2014๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์ฟผ๋ฆฌ์— 18 ์ดˆ๊ฐ€ ๊ฑธ๋ฆฌ๊ณ  ๊ด‘์‚ฐ์—๋Š” 3m 46s๊ฐ€ ๊ฑธ๋ฆฝ๋‹ˆ๋‹ค. 2014๋Š” NO_PERFORMANCE_SPOOLํžŒํŠธ๋ฅผ ์ง€์›ํ•˜์ง€ ์•Š์œผ๋ฏ€๋กœ ๋‘ ์ฟผ๋ฆฌ ๋ชจ๋‘ ๋ฌธ์„œํ™”๋˜์ง€ ์•Š์€ ์ถ”์  ํ”Œ๋ž˜๊ทธ 8690์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค .

์ฝ”๋“œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

/* precompute offsets and powers to simplify final query */
CREATE TABLE #ExponentsLookup (
    offset          BIGINT NOT NULL,
    offset_end      BIGINT NOT NULL,
    position        INTEGER NOT NULL,
    divisor         BIGINT NOT NULL,
    shifts          BIGINT NOT NULL,
    chars           INTEGER NOT NULL,
    PRIMARY KEY(offset, offset_end, position)
);

WITH base_26_multiples AS (
    SELECT  number  AS exponent,
            CAST(POWER(26.0, number) AS BIGINT) AS multiple
    FROM    master.dbo.spt_values
    WHERE   [type] = 'P'
            AND number < 8
),
num_offsets AS (
    SELECT  *,
            -- The maximum posible value is 217180147159 - 1
            LEAD(offset, 1, 217180147159) OVER(
                ORDER BY exponent
            ) AS offset_end
    FROM    (
                SELECT  exponent,
                        SUM(multiple) OVER(
                            ORDER BY exponent
                        ) AS offset
                FROM    base_26_multiples
            ) x
)
INSERT INTO #ExponentsLookup(offset, offset_end, position, divisor, shifts, chars)
SELECT  ofst.offset, ofst.offset_end,
        dgt.number AS position,
        CAST(POWER(26.0, dgt.number) AS BIGINT)     AS divisor,
        CAST(POWER(256.0, dgt.number) AS BIGINT)    AS shifts,
        ofst.exponent + 1                           AS chars
FROM    num_offsets ofst
        LEFT JOIN master.dbo.spt_values dgt --> as many rows as resulting chars in string
            ON [type] = 'P'
            AND dgt.number <= ofst.exponent;

/*  Test the cases in table example */
SELECT  /*  1.- Get the base 26 digit and then shift it to align it to 8 bit boundaries
            2.- Sum the resulting values
            3.- Bias the value with a reference that represent the string 'AAAAAAAA'
            4.- Take the required chars */
        ref.[row_number],
        REVERSE(SUBSTRING(REVERSE(CAST(SUM((((ref.[row_number] - ofst.offset) / ofst.divisor) % 26) * ofst.shifts) +
            CAST(CAST('AAAAAAAA' AS BINARY(8)) AS BIGINT) AS BINARY(8))),
            1, MAX(ofst.chars))) AS string
FROM    (
            VALUES(1),(2),(25),(26),(27),(28),(51),(52),(53),(54),
            (18278),(18279),(475253),(475254),(475255),
            (100000000), (CAST(217180147158 AS BIGINT))
        ) ref([row_number])
        LEFT JOIN #ExponentsLookup ofst
            ON ofst.offset <= ref.[row_number]
            AND ofst.offset_end > ref.[row_number]
GROUP BY
        ref.[row_number]
ORDER BY
        ref.[row_number];

/*  Test with huge set  */
WITH numbers AS (
    SELECT  TOP(100000000)
            ROW_NUMBER() OVER(
                ORDER BY x1.number
            ) AS [row_number]
    FROM    master.dbo.spt_values x1
            CROSS JOIN (SELECT number FROM master.dbo.spt_values WHERE [type] = 'P' AND number < 676) x2
            CROSS JOIN (SELECT number FROM master.dbo.spt_values WHERE [type] = 'P' AND number < 676) x3
    WHERE   x1.number < 219
)
SELECT  /*  1.- Get the base 26 digit and then shift it to align it to 8 bit boundaries
            2.- Sum the resulting values
            3.- Bias the value with a reference that represent the string 'AAAAAAAA'
            4.- Take the required chars */
        ref.[row_number],
        REVERSE(SUBSTRING(REVERSE(CAST(SUM((((ref.[row_number] - ofst.offset) / ofst.divisor) % 26) * ofst.shifts) +
            CAST(CAST('AAAAAAAA' AS BINARY(8)) AS BIGINT) AS BINARY(8))),
            1, MAX(ofst.chars))) AS string
FROM    numbers ref
        LEFT JOIN #ExponentsLookup ofst
            ON ofst.offset <= ref.[row_number]
            AND ofst.offset_end > ref.[row_number]
GROUP BY
        ref.[row_number]
ORDER BY
        ref.[row_number]
OPTION (QUERYTRACEON 8690);

์—ฌ๊ธฐ์„œ ์†์ž„์ˆ˜๋Š” ๋‹ค๋ฅธ ์ˆœ์—ด์ด ์‹œ์ž‘๋˜๋Š” ์œ„์น˜๋ฅผ ๋ฏธ๋ฆฌ ๊ณ„์‚ฐํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

  1. ๋‹จ์ผ ๋ฌธ์ž๋ฅผ ์ถœ๋ ฅํ•ด์•ผ ํ•  ๊ฒฝ์šฐ 26 ^ 0์—์„œ ์‹œ์ž‘ํ•˜๋Š” 26 ^ 1 ์ˆœ์—ด์ด ์žˆ์Šต๋‹ˆ๋‹ค.
  2. 2 ๊ฐœ์˜ ๋ฌธ์ž๋ฅผ ์ถœ๋ ฅํ•ด์•ผ ํ•  ๊ฒฝ์šฐ 26 ^ 0 + 26 ^ 1์—์„œ ์‹œ์ž‘ํ•˜๋Š” 26 ^ 2 ์ˆœ์—ด์ด ์žˆ์Šต๋‹ˆ๋‹ค.
  3. 3 ๊ฐœ์˜ ๋ฌธ์ž๋ฅผ ์ถœ๋ ฅํ•ด์•ผ ํ•  ๋•Œ 26 ^ 0 + 26 ^ 1 + 26 ^ 2์—์„œ ์‹œ์ž‘ํ•˜๋Š” 26 ^ 3 ์ˆœ์—ด์ด ์žˆ์Šต๋‹ˆ๋‹ค.
  4. n ์ž ๋ฐ˜๋ณต

์‚ฌ์šฉ๋˜๋Š” ๋‹ค๋ฅธ ํŠธ๋ฆญ์€ ๋‹จ์ˆœํžˆ ์—ฐ๊ฒฐํ•˜๋Š” ๋Œ€์‹  sum์„ ์‚ฌ์šฉํ•˜์—ฌ ์˜ฌ๋ฐ”๋ฅธ ๊ฐ’์„ ์–ป๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ด๋ฅผ ๋‹ฌ์„ฑํ•˜๊ธฐ ์œ„ํ•ด ๊ฐ„๋‹จํžˆ ์ˆซ์ž 26์„ ๊ธฐ๋ณธ 256์œผ๋กœ ์˜คํ”„์…‹ํ•˜๊ณ  ๊ฐ ์ˆซ์ž์— ๋Œ€ํ•ด โ€˜Aโ€™์˜ ASCII ๊ฐ’์„ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ์ฐพ๊ณ ์žˆ๋Š” ๋ฌธ์ž์—ด์˜ ์ด์ง„ ํ‘œํ˜„์„ ์–ป์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ ๋‹ค์Œ ์ผ๋ถ€ ๋ฌธ์ž์—ด ์กฐ์ž‘์œผ๋กœ ํ”„๋กœ์„ธ์Šค๊ฐ€ ์™„๋ฃŒ๋ฉ๋‹ˆ๋‹ค.


๋‹ต๋ณ€

์ข‹์•„, ์—ฌ๊ธฐ ๋‚ด ์ตœ์‹  ์Šคํฌ๋ฆฝํŠธ๊ฐ€ ๊ฐ„๋‹ค.

๋ฃจํ”„ ์—†์Œ, ์žฌ๊ท€ ์—†์Œ.

6 ์ž๋งŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค

๊ฐ€์žฅ ํฐ ๋‹จ์ ์€ 1,00,00,000์— ์•ฝ 22 ๋ถ„์ด ๊ฑธ๋ฆฐ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค

์ด๋ฒˆ์—๋Š” ๋‚ด ์Šคํฌ๋ฆฝํŠธ๊ฐ€ ๋งค์šฐ ์งง์Šต๋‹ˆ๋‹ค.

SET NoCount on

declare @z int=26
declare @start int=@z+1
declare @MaxLimit int=10000000

SELECT TOP (@MaxLimit) IDENTITY(int,1,1) AS N
    INTO NumbersTest1
    FROM     master.dbo.spt_values x1
   CROSS JOIN (SELECT number FROM master.dbo.spt_values WHERE [type] = 'P' AND number < 500) x2
            CROSS JOIN (SELECT number FROM master.dbo.spt_values WHERE [type] = 'P' AND number < 500) x3
    WHERE   x1.number < 219
ALTER TABLE NumbersTest1 ADD CONSTRAINT PK_NumbersTest1 PRIMARY KEY CLUSTERED (N)


select N, strCol from NumbersTest1
cross apply
(
select
case when IntCol6>0 then  char((IntCol6%@z)+64) else '' end
+case when IntCol5=0 then 'Z' else isnull(char(IntCol5+64),'') end
+case when IntCol4=0 then 'Z' else isnull(char(IntCol4+64),'') end
+case when IntCol3=0 then 'Z' else isnull(char(IntCol3+64),'') end
+case when IntCol2=0 then 'Z' else isnull(char(IntCol2+64),'') end
+case when IntCol1=0 then 'Z' else isnull(char(IntCol1+64),'') end strCol
from
(
select  IntCol1,IntCol2,IntCol3,IntCol4
,case when IntCol5>0 then  IntCol5%@z else null end IntCol5

,case when IntCol5/@z>0 and  IntCol5%@z=0 then  IntCol5/@z-1
when IntCol5/@z>0 then IntCol5/@z
else null end IntCol6
from
(
select IntCol1,IntCol2,IntCol3
,case when IntCol4>0 then  IntCol4%@z else null end IntCol4

,case when IntCol4/@z>0 and  IntCol4%@z=0 then  IntCol4/@z-1
when IntCol4/@z>0 then IntCol4/@z
else null end IntCol5
from
(
select IntCol1,IntCol2
,case when IntCol3>0 then  IntCol3%@z else null end IntCol3
,case when IntCol3/@z>0 and  IntCol3%@z=0 then  IntCol3/@z-1
when IntCol3/@z>0 then IntCol3/@z
else null end IntCol4

from
(
select IntCol1
,case when IntCol2>0 then  IntCol2%@z else null end IntCol2
,case when IntCol2/@z>0 and  IntCol2%@z=0 then  IntCol2/@z-1
when IntCol2/@z>0 then IntCol2/@z
else null end IntCol3

from
(
select case when N>0 then N%@z else null end IntCol1
,case when N%@z=0 and  (N/@z)>1 then (N/@z)-1 else  (N/@z) end IntCol2

)Lv2
)Lv3
)Lv4
)Lv5
)LV6

)ca

DROP TABLE NumbersTest1

๋‹ต๋ณ€