都内で働くSEの技術的なひとりごと / Technical soliloquy of System Engineer working in Tokyo

都内でサラリーマンやってます。SQL Server を中心とした (2023年からは Azure も。) マイクロソフト系(たまに、OSS系などマイクロソフト以外の技術も...)の技術的なことについて書いています。日々の仕事の中で、気になったことを技術要素関係なく気まぐれに選んでいるので記事内容は開発言語、インフラ等ばらばらです。なお、当ブログで発信、発言は私個人のものであり、所属する組織、企業、団体等とは何のかかわりもございません。ブログの内容もきちんと検証して使用してください。英語の勉強のため、英語の

大量の IN 句の動作を見てみた

 お久しぶりです。最近は、激しい移動すなわち、「 #ダイヤモンド修行 」 が激しさを増しており、記事さえ中々書けない事態に陥っています。今回はそんなのやるなら初めからちゃんと JOIN したりするのを前提にクエリ設計したらいいやん!と批判を浴びそうな気がしますが、ちょっと気になったので簡単に検証してみます。

下記のような恐ろしい クエリ1 と クエリ2 を用意します。
※クエリ1

SELECT
    [SalesOrderID],
    [RevisionNumber],
    [OrderDate],
    [DueDate],
    [ShipDate],
    [Status],
    [OnlineOrderFlag],
    [SalesOrderNumber],
    [PurchaseOrderNumber],
    [AccountNumber],
    [CustomerID],
    [SalesPersonID],
    [TerritoryID],
    [BillToAddressID],
    [ShipToAddressID],
    [ShipMethodID],
    [CreditCardID],
    [CreditCardApprovalCode],
    [CurrencyRateID],
    [SubTotal],
    [TaxAmt],
    [Freight],
    [TotalDue],
    [Comment],
    [rowguid],
    [ModifiedDate]
FROM
    [AdventureWorks].[Sales].[SalesOrderHeader]
WHERE
    SalesOrderID IN('43659', '43660', '43661', '43662', '43663', '43664', '43665', '43666', '43667', '43668', '43669', '43670', '43671', '43672', '43673', '43674', '43675', '43676', '43677', '43678', '43679', '43680', '43681', '43682', '43683', '43684', '43685', '43686', '43687', '43688', '43689', '43690', '43691', '43692', '43693', '43694', '43695', '43696', '43697', '43698', '43699', '43700', '43701', '43702', '43703', '43704', '43705', '43706', '43707', '43708', '43709', '43710', '43711', '43712', '43713', '43714', '43715', '43716', '43717', '43718', '43719', '43720', '43721', '43722', '43723', '43724', '43725', '43726', '43727', '43728', '43729', '43730', '43731', '43732', '43733', '43734', '43735', '43736', '43737', '43738', '43739', '43740', '43741', '43742', '43743', '43744', '43745', '43746', '43747', '43748', '43749', '43750', '43751', '43752', '43753', '43754', '43755', '43756', '43757', '43758', '43759', '43760', '43761', '43762', '43763', '43764', '43765', '43766', '43767', '43768', '43769', '43770', '43771', '43772', '43773', '43774', '43775', '43776', '43777', '43778', '43779', '43780', '43781', '43782', '43783', '43784', '43785', '43786', '43787', '43788', '43789', '43790', '43791', '43792', '43793', '43794', '43795', '43796', '43797', '43798', '43799', '43800', '43801', '43802', '43803', '43804', '43805', '43806', '43807', '43808', '43809', '43810', '43811', '43812', '43813', '43814', '43815', '43816', '43817', '43818', '43819', '43820', '43821', '43822', '43823', '43824', '43825', '43826', '43827', '43828', '43829', '43830', '43831', '43832', '43833', '43834', '43835', '43836', '43837', '43838', '43839', '43840', '43841', '43842', '43843', '43844', '43845', '43846', '43847', '43848', '43849', '43850', '43851', '43852', '43853', '43854', '43855', '43856', '43857', '43858', '43859', '43860', '43861', '43862', '43863', '43864', '43865', '43866', '43867', '43868', '43869', '43870', '43871', '43872', '43873', '43874', '43875', '43876', '43877', '43878', '43879', '43880', '43881', '43882', '43883', '43884', '43885', '43886', '43887', '43888', '43889', '43890', '43891', '43892', '43893', '43894', '43895', '43896', '43897', '43898', '43899', '43900', '43901', '43902', '43903', '43904', '43905', '43906', '43907', '43908')

※クエリ2

SELECT
    [SalesOrderID],
    [RevisionNumber],
    [OrderDate],
    [DueDate],
    [ShipDate],
    [Status],
    [OnlineOrderFlag],
    [SalesOrderNumber],
    [PurchaseOrderNumber],
    [AccountNumber],
    [CustomerID],
    [SalesPersonID],
    [TerritoryID],
    [BillToAddressID],
    [ShipToAddressID],
    [ShipMethodID],
    [CreditCardID],
    [CreditCardApprovalCode],
    [CurrencyRateID],
    [SubTotal],
    [TaxAmt],
    [Freight],
    [TotalDue],
    [Comment],
    [rowguid],
    [ModifiedDate]
FROM
    [AdventureWorks].[Sales].[SalesOrderHeader]
WHERE
    SalesOrderID IN('43873', '43660', '43824', '43739', '43694', '43898', '43902', '43713', '43700', '43664', '43661', '43745', '43708', '43901', '43741', '43794', '43848', '43755', '43888', '43687', '43813', '43670', '43781', '43840', '43817', '43857', '43853', '43759', '43815', '43810', '43711', '43750', '43830', '43723', '43698', '43754', '43879', '43748', '43778', '43777', '43753', '43870', '43742', '43728', '43691', '43668', '43702', '43707', '43818', '43811', '43780', '43847', '43763', '43784', '43837', '43680', '43860', '43862', '43866', '43821', '43906', '43838', '43699', '43861', '43894', '43666', '43751', '43785', '43872', '43725', '43877', '43744', '43782', '43798', '43743', '43752', '43662', '43793', '43676', '43683', '43747', '43677', '43796', '43667', '43669', '43867', '43722', '43709', '43718', '43692', '43829', '43730', '43881', '43726', '43773', '43834', '43825', '43695', '43688', '43889', '43712', '43800', '43826', '43775', '43899', '43799', '43885', '43789', '43684', '43802', '43740', '43845', '43863', '43703', '43724', '43736', '43704', '43721', '43792', '43882', '43904', '43682', '43851', '43842', '43895', '43774', '43868', '43900', '43729', '43779', '43672', '43887', '43675', '43673', '43832', '43880', '43697', '43831', '43874', '43749', '43883', '43823', '43905', '43715', '43737', '43701', '43858', '43731', '43766', '43689', '43714', '43852', '43735', '43764', '43772', '43686', '43890', '43756', '43762', '43706', '43787', '43822', '43807', '43671', '43770', '43681', '43804', '43679', '43801', '43841', '43720', '43833', '43908', '43827', '43812', '43797', '43663', '43816', '43719', '43850', '43814', '43907', '43876', '43896', '43871', '43819', '43835', '43839', '43884', '43659', '43761', '43765', '43768', '43705', '43696', '43674', '43869', '43854', '43859', '43886', '43678', '43716', '43769', '43795', '43892', '43808', '43878', '43685', '43844', '43710', '43803', '43903', '43786', '43836', '43809', '43849', '43843', '43746', '43897', '43864', '43790', '43875', '43856', '43805', '43791', '43734', '43733', '43776', '43846', '43727', '43820', '43788', '43690', '43865', '43738', '43665', '43771', '43767', '43828', '43758', '43783', '43757', '43893', '43855', '43693', '43806', '43891', '43732', '43717', '43760')

 クエリ1 の IN 句の条件は、SalesOrderID が昇順で並び替えられています。クエリ2 の IN 句の条件はランダムに並び替えられています。それぞれ計測してみます。

  • 1回目f:id:koogucc11:20180305001430p:plain
  • 2回目f:id:koogucc11:20180305001435p:plain
  • 3回目f:id:koogucc11:20180305001440p:plain
  • 4回目f:id:koogucc11:20180305001445p:plain
  • 5回目f:id:koogucc11:20180305001449p:plain

インデックスの並び順で IN 句指定されたほうが明らかに高速ですね。もう少し詳しくみてみましょう。SET STATISTICS PROFILE ON を付加します。
f:id:koogucc11:20180305002230p:plain

指定した IN 句の条件がきちんと並び替えられていますね。レスポンス差は内部的にこのソートの負荷が生じた結果なのでしょうか。

VALUES:(((43659)),((43660)),((43661)),((43662)),((43663)),((43664)),((43665)),((43666)),((43667)),((43668)),((43669)),((43670)),((43671)),((43672)),((43673)),((43674)),((43675)),((43676)),((43677)),((43678)),((43679)),((43680)),((43681)),((43682)),((43683)),((43684)),((43685)),((43686)),((43687)),((43688)),((43689)),((43690)),((43691)),((43692)),((43693)),((43694)),((43695)),((43696)),((43697)),((43698)),((43699)),((43700)),((43701)),((43702)),((43703)),((43704)),((43705)),((43706)),((43707)),((43708)),((43709)),((43710)),((43711)),((43712)),((43713)),((43714)),((43715)),((43716)),((43717)),((43718)),((43719)),((43720)),((43721)),((43722)),((43723)),((43724)),((43725)),((43726)),((43727)),((43728)),((43729)),((43730)),((43731)),((43732)),((43733)),((43734)),((43735)),((43736)),((43737)),((43738)),((43739)),((43740)),((43741)),((43742)),((43743)),((43744)),((43745)),((43746)),((43747)),((43748)),((43749)),((43750)),((43751)),((43752)),((43753)),((43754)),((43755)),((43756)),((43757)),((43758)),((43759)),((43760)),((43761)),((43762)),((43763)),((43764)),((43765)),((43766)),((43767)),((43768)),((43769)),((43770)),((43771)),((43772)),((43773)),((43774)),((43775)),((43776)),((43777)),((43778)),((43779)),((43780)),((43781)),((43782)),((43783)),((43784)),((43785)),((43786)),((43787)),((43788)),((43789)),((43790)),((43791)),((43792)),((43793)),((43794)),((43795)),((43796)),((43797)),((43798)),((43799)),((43800)),((43801)),((43802)),((43803)),((43804)),((43805)),((43806)),((43807)),((43808)),((43809)),((43810)),((43811)),((43812)),((43813)),((43814)),((43815)),((43816)),((43817)),((43818)),((43819)),((43820)),((43821)),((43822)),((43823)),((43824)),((43825)),((43826)),((43827)),((43828)),((43829)),((43830)),((43831)),((43832)),((43833)),((43834)),((43835)),((43836)),((43837)),((43838)),((43839)),((43840)),((43841)),((43842)),((43843)),((43844)),((43845)),((43846)),((43847)),((43848)),((43849)),((43850)),((43851)),((43852)),((43853)),((43854)),((43855)),((43856)),((43857)),((43858)),((43859)),((43860)),((43861)),((43862)),((43863)),((43864)),((43865)),((43866)),((43867)),((43868)),((43869)),((43870)),((43871)),((43872)),((43873)),((43874)),((43875)),((43876)),((43877)),((43878)),((43879)),((43880)),((43881)),((43882)),((43883)),((43884)),((43885)),((43886)),((43887)),((43888)),((43889)),((43890)),((43891)),((43892)),((43893)),((43894)),((43895)),((43896)),((43897)),((43898)),((43899)),((43900)),((43901)),((43902)),((43903)),((43904)),((43905)),((43906)),((43907)),((43908)))

時間あったら、読んでみたい。

SQL Server 2017 Administrator's Guide

SQL Server 2017 Administrator's Guide