Vous trouverez ci-dessous une solution T-SQL qui écrit le premier million de nombres dans une table temporaire. Cela prend environ 84 ms sur ma machine. Les goulots d'étranglement clés attendent sur le verrou NESTING_TRANSACTION_FULL et CXPACKET
, tous deux que je ne sais pas comment résoudre, à part changer MAXDOP
. Je voulais un plan de requête qui puisse tirer parti des boucles imbriquées parallèles et du parallélisme basé sur la demande, ce que j'ai réussi à obtenir:
Le code est un peu long. En bref, je réunis deux tables dérivées de 246 lignes et 271 lignes pour un total de 66666 lignes. Ces lignes sont jointes à une table dérivée de 15 lignes qui tire parti du fait que le modèle FIZZBUZZ est répété pour toutes les 15 lignes. Les dix dernières lignes sont ajoutées avec un UNION ALL
.
DROP TABLE IF EXISTS #t;
SELECT res.fizzbuzz INTO #t
FROM
(
VALUES
(0),
(15),
(30),
(45),
(60),
(75),
(90),
(105),
(120),
(135),
(150),
(165),
(180),
(195),
(210),
(225),
(240),
(255),
(270),
(285),
(300),
(315),
(330),
(345),
(360),
(375),
(390),
(405),
(420),
(435),
(450),
(465),
(480),
(495),
(510),
(525),
(540),
(555),
(570),
(585),
(600),
(615),
(630),
(645),
(660),
(675),
(690),
(705),
(720),
(735),
(750),
(765),
(780),
(795),
(810),
(825),
(840),
(855),
(870),
(885),
(900),
(915),
(930),
(945),
(960),
(975),
(990),
(1005),
(1020),
(1035),
(1050),
(1065),
(1080),
(1095),
(1110),
(1125),
(1140),
(1155),
(1170),
(1185),
(1200),
(1215),
(1230),
(1245),
(1260),
(1275),
(1290),
(1305),
(1320),
(1335),
(1350),
(1365),
(1380),
(1395),
(1410),
(1425),
(1440),
(1455),
(1470),
(1485),
(1500),
(1515),
(1530),
(1545),
(1560),
(1575),
(1590),
(1605),
(1620),
(1635),
(1650),
(1665),
(1680),
(1695),
(1710),
(1725),
(1740),
(1755),
(1770),
(1785),
(1800),
(1815),
(1830),
(1845),
(1860),
(1875),
(1890),
(1905),
(1920),
(1935),
(1950),
(1965),
(1980),
(1995),
(2010),
(2025),
(2040),
(2055),
(2070),
(2085),
(2100),
(2115),
(2130),
(2145),
(2160),
(2175),
(2190),
(2205),
(2220),
(2235),
(2250),
(2265),
(2280),
(2295),
(2310),
(2325),
(2340),
(2355),
(2370),
(2385),
(2400),
(2415),
(2430),
(2445),
(2460),
(2475),
(2490),
(2505),
(2520),
(2535),
(2550),
(2565),
(2580),
(2595),
(2610),
(2625),
(2640),
(2655),
(2670),
(2685),
(2700),
(2715),
(2730),
(2745),
(2760),
(2775),
(2790),
(2805),
(2820),
(2835),
(2850),
(2865),
(2880),
(2895),
(2910),
(2925),
(2940),
(2955),
(2970),
(2985),
(3000),
(3015),
(3030),
(3045),
(3060),
(3075),
(3090),
(3105),
(3120),
(3135),
(3150),
(3165),
(3180),
(3195),
(3210),
(3225),
(3240),
(3255),
(3270),
(3285),
(3300),
(3315),
(3330),
(3345),
(3360),
(3375),
(3390),
(3405),
(3420),
(3435),
(3450),
(3465),
(3480),
(3495),
(3510),
(3525),
(3540),
(3555),
(3570),
(3585),
(3600),
(3615),
(3630),
(3645),
(3660),
(3675)
) v246 (n)
CROSS JOIN
(
VALUES
(0),
(15),
(30),
(45),
(60),
(75),
(90),
(105),
(120),
(135),
(150),
(165),
(180),
(195),
(210),
(225),
(240),
(255),
(270),
(285),
(300),
(315),
(330),
(345),
(360),
(375),
(390),
(405),
(420),
(435),
(450),
(465),
(480),
(495),
(510),
(525),
(540),
(555),
(570),
(585),
(600),
(615),
(630),
(645),
(660),
(675),
(690),
(705),
(720),
(735),
(750),
(765),
(780),
(795),
(810),
(825),
(840),
(855),
(870),
(885),
(900),
(915),
(930),
(945),
(960),
(975),
(990),
(1005),
(1020),
(1035),
(1050),
(1065),
(1080),
(1095),
(1110),
(1125),
(1140),
(1155),
(1170),
(1185),
(1200),
(1215),
(1230),
(1245),
(1260),
(1275),
(1290),
(1305),
(1320),
(1335),
(1350),
(1365),
(1380),
(1395),
(1410),
(1425),
(1440),
(1455),
(1470),
(1485),
(1500),
(1515),
(1530),
(1545),
(1560),
(1575),
(1590),
(1605),
(1620),
(1635),
(1650),
(1665),
(1680),
(1695),
(1710),
(1725),
(1740),
(1755),
(1770),
(1785),
(1800),
(1815),
(1830),
(1845),
(1860),
(1875),
(1890),
(1905),
(1920),
(1935),
(1950),
(1965),
(1980),
(1995),
(2010),
(2025),
(2040),
(2055),
(2070),
(2085),
(2100),
(2115),
(2130),
(2145),
(2160),
(2175),
(2190),
(2205),
(2220),
(2235),
(2250),
(2265),
(2280),
(2295),
(2310),
(2325),
(2340),
(2355),
(2370),
(2385),
(2400),
(2415),
(2430),
(2445),
(2460),
(2475),
(2490),
(2505),
(2520),
(2535),
(2550),
(2565),
(2580),
(2595),
(2610),
(2625),
(2640),
(2655),
(2670),
(2685),
(2700),
(2715),
(2730),
(2745),
(2760),
(2775),
(2790),
(2805),
(2820),
(2835),
(2850),
(2865),
(2880),
(2895),
(2910),
(2925),
(2940),
(2955),
(2970),
(2985),
(3000),
(3015),
(3030),
(3045),
(3060),
(3075),
(3090),
(3105),
(3120),
(3135),
(3150),
(3165),
(3180),
(3195),
(3210),
(3225),
(3240),
(3255),
(3270),
(3285),
(3300),
(3315),
(3330),
(3345),
(3360),
(3375),
(3390),
(3405),
(3420),
(3435),
(3450),
(3465),
(3480),
(3495),
(3510),
(3525),
(3540),
(3555),
(3570),
(3585),
(3600),
(3615),
(3630),
(3645),
(3660),
(3675),
(3690),
(3705),
(3720),
(3735),
(3750),
(3765),
(3780),
(3795),
(3810),
(3825),
(3840),
(3855),
(3870),
(3885),
(3900),
(3915),
(3930),
(3945),
(3960),
(3975),
(3990),
(4005),
(4020),
(4035),
(4050)
) v271 (n)
CROSS APPLY
(
VALUES
(CAST(v246.n * 271 + v271.n + 1 AS CHAR(8))),
(CAST(v246.n * 271 + v271.n + 2 AS CHAR(8))),
(CAST('FIZZ' AS CHAR(8))),
(CAST(v246.n * 271 + v271.n + 4 AS CHAR(8))),
(CAST('BUZZ' AS CHAR(8))),
(CAST('FIZZ' AS CHAR(8))),
(CAST(v246.n * 271 + v271.n + 7 AS CHAR(8))),
(CAST(v246.n * 271 + v271.n + 8 AS CHAR(8))),
(CAST('FIZZ' AS CHAR(8))),
(CAST('BUZZ' AS CHAR(8))),
(CAST(v246.n * 271 + v271.n + 11 AS CHAR(8))),
(CAST('FIZZ' AS CHAR(8))),
(CAST(v246.n * 271 + v271.n + 13 AS CHAR(8))),
(CAST(v246.n * 271 + v271.n + 14 AS CHAR(8))),
(CAST('FIZZBUZZ' AS CHAR(8)))
) res (fizzbuzz)
UNION ALL
SELECT v.fizzbuzz
FROM (
VALUES
('999991'),
('999992'),
('FIZZ'),
('999994'),
('BUZZ'),
('FIZZ'),
('999997'),
('999998'),
('FIZZ'),
('BUZZ')
) v (fizzbuzz)
OPTION (MAXDOP 6, NO_PERFORMANCE_SPOOL);
Utilisation d'une table optimisée en mémoire pour SQL Server 2014 et d'une procédure compilée en mode natif:
Procédure native:
Tester:
Résultats typiques:
Cela écrit la sortie de la procédure dans une variable de table en mémoire, car sinon nous testons simplement la vitesse d'affichage des résultats dans SSMS.
Un million de lignes
La procédure native ci-dessus prend environ 12 secondes pour s'exécuter sur 1 000 000 de numéros. Il existe toutes sortes de moyens plus rapides de faire la même chose dans T-SQL. Un que j'ai écrit avant suit. Il s'exécute en environ 500 ms sur mon ordinateur portable sur un million de lignes lorsque le plan parallèle prévu est atteint:
la source
Celui-ci fonctionne de la même manière sur ma machine que la première (0 ms). Je ne sais pas si elle évoluerait plus rapidement ou non.
la source
La meilleure version que j'ai trouvée fonctionne en 30 ms sur ma machine:
la source
Selon sqlfiddle.com, cela prend 7 ms:
N'utilise aucune table, proc stocké ou CTE.
la source
J'ai obtenu une version raisonnable du proc stocké compilé en mode natif fonctionnant pour 1 million de lignes en ~ 500-800 ms. C'est une conversion T-SQL que j'ai faite de l'algorithme au niveau du bit d' ici avec un peu d'aide du blog d'Adam Machanic sur les opérations au niveau du bit ici .
J'espère (je l'espère) suivre les mêmes règles que le proc de 500ms / 1 million de lignes de @ PaulWhite, c'est-à-dire générer les résultats mais ne pas les afficher / ne pas les faire circuler dans le cadre du timing. Il doit s'agir d'index de hachage sur les tables en mémoire pour des tailles de vitesse et de godet de 4194304 ou 8388608, ce qui m'a semblé être le point idéal, bien que cela donne évidemment un nombre élevé de compartiments vides.
la source
J'ai trouvé et joué avec ce seul sous-sélecteur sans CTE. max_elapsed_time dans les statistiques de requête affiche 1036
la source
Je ne prends aucun crédit pour le code écrit, je voulais juste voir combien de temps cela prendrait
UN MILLIARD DE RANGS!
La réponse est: environ 10 minutes.
la source
PostgreSQL
PostgreSQL fournit
generate_series
une fonction Table-Value (Set-Returning Function) qui rend cela beaucoup plus simple. Je suppose que vous ne voulez rien que ce soit lorsque le nombre ni 3, ni 5 n'y entre.la source