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

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

SQL Server Management Studio の知っておいたほうが良い機能について挙げてみる - その13 - ( オブジェクトエクスプローラーの詳細って? )

 お久しぶりです。もう半年ほど記事投稿していませんでした。そして、二カ月ほど SQL Server を扱っていませんでした。時間もあったんですが、仕事で使わないものは中々使う気にならないですし、記事にしようという気力が湧かないものです。今日久しぶりに Windows Update をしようかと思い、Parallels から Windows を起動してみました。そして、ついでに SQL Server Management Studio を 17.9.1 へアップデートしてみました。
 

f:id:koogucc11:20190416002014p:plain
懐かしの SSMS 笑

 メニューを触っていると、表示→オブジェクトエクスプローラーの詳細というメニューを見つけました。クリックしたこともなかったので、クリックしてみます。ふむ、選択したオブジェクトの詳細が参照できるわけですね。

f:id:koogucc11:20190416002707p:plain
オブジェクトエクスプローラーの詳細でデータベースを選択

 さらにクリックして行くと、テーブルのプロパティも参照できます。

f:id:koogucc11:20190416003014p:plain
オブジェクトエクスプローラーの詳細でテーブルを選択

 列を右クリックすると、一覧に表示する列をカスタマイズできます。

f:id:koogucc11:20190416003219p:plain
オブジェクトエクスプローラーの詳細の列で右クリック

 うーん。dmv 使ってクエリ書くかな笑。久しぶりの投稿内容が薄っぺらくて申し訳ありませんでした。

 少し前に第三世代の iPad Pro 買ったから、Apple Pencil 2 も欲しいなぁ。

Apple Pencil(第2世代)

Apple Pencil(第2世代)

 Apple Watch 4 のベルトを新調。純正は高いので、お安いものを購入。

やはりダークテーマはいいなぁと思って SSMS ver. 18 Preview 4 を扱っていたら、Azure Data Studio とか見えたのでお試してみた

 SQL Server Management Studio 18 preview 4 がリリースされました。
cloudblogs.microsoft.com

 やっぱりダークテーマはいいですね。可能であれば、オブジェクトエクスプローラーも Visual Studio と同じくダークなテーマになるとより見やすくなるかなと思います。(おそらく正式リリースでは対応されるんでしょう。)
f:id:koogucc11:20181007225018p:plain

 明るい箇所があると目に優しくないですね。
f:id:koogucc11:20181007225428p:plain

 mac も速攻ダークに変えました。たまに対応していないツールがあったりすると、目が疲れますが....

 ちょっとメニューを触っていたら、見慣れない ( というか自分が情弱なだけ? ) 項目が目に入ってきました。Azure Data Studio。
f:id:koogucc11:20181007225609p:plain

 インストールしてみました。あれ、SQL Operations Studio じゃない?名前が変更されたんですかね?
f:id:koogucc11:20181007230751p:plain

 色々リリースされていますね。もうまったくついていけていません。SQL Server については情弱の一途をたどっています...

 これくらいのバッテリーがほしくなってきました。キャンプ兼災害時用。色々あって迷ってしまいます。やはり信頼性の高い Anker ですかね?

 ソーラーパネルもあると対策としては完璧かもしれませんね。

実行プランの読み方をまとめてみる - その11 ( Where 句の条件の型が列の型と異なる場合の実行プランを読んでみる ) -

 実行プランの読み方は情報も少ないので、内容の理解に苦しんでいる方も多いかもしれません。過去にはいくつか投稿しているので、そちらも参考にしてください。
ryuchan.hatenablog.com
ryuchan.hatenablog.com
ryuchan.hatenablog.com
ryuchan.hatenablog.com
ryuchan.hatenablog.com
ryuchan.hatenablog.com
ryuchan.hatenablog.com
ryuchan.hatenablog.com
ryuchan.hatenablog.com
ryuchan.hatenablog.com

 さて、過去の投稿を参考にしつつ、今回投稿する記事も参考にして、実行プランをスラスラ読めるようにしましょう。早速下記のクエリを実行して見ましょう。
※データベースは、ここからダウンロードしてください。
※クエリはわざと不適切な状態にしています。

-- OrderDate 型は datetime なので型が間違っている。
DECLARE @min_date datetime2
DECLARE @max_date datetime2

SET @min_date = '2011-05-31 00:00:00.000'
SET @max_date = '2011-07-31 00:00:00.000'

SET STATISTICS PROFILE ON

SELECT 
    SalesOrderID,
    RevisionNumber,
    OrderDate
FROM 
    -- OrderDate のインデックスを作成した。
    Sales.SalesOrderHeader WITH (INDEX(IX_SalesOrderHeader_OrderDate))
WHERE 
    OrderDate > @min_date
AND OrderDate < @max_date

SET STATISTICS PROFILE OFF

 実行プランは下図の通りです。
f:id:koogucc11:20180819234905p:plain

 Computer Scalar、Concatenation, Merge Interval オペレータって何しているかはっきりわかりませんよね?それぞれのオペレーターのプロパティを見ても、定義済みの値が [Expr1008] = (Expr1003, Expr1006), [Expr1009] = (Expr1004, Expr1007), [Expr1010] = (Expr1002, Expr1005) とか、出力一覧がExpr1003, Expr1004, Expr1002とか意味不明ですね。expr といえば、整数計算とか式評価を思い浮かべますが....

  • Compute Scalar
    f:id:koogucc11:20180819235900p:plain

  • Concatenation
    f:id:koogucc11:20180819235903p:plain

  • Merge Interval
    f:id:koogucc11:20180819235906p:plain

 さて、今回のような実行プランを見ていくにはグラフィカルな実行プランでは詳細はわかりません。各オペレーターの詳細情報を参照するには、実行プランの XML を参照するか、SET STATISTICS PROFILE ON の結果を参照する必要があります。今回は、SET STATISTICS PROFILE ON の結果を見ていくことにしましょう。今回実行したクエリには、SET STATISTICS PROFILE ON を付加してあるので、下図の赤枠の情報も出力されているかと思います。赤枠部分の情報を詳しく見ていきましょう。
f:id:koogucc11:20180820001109p:plain

 まず、Compute Scalar オペレーターの内容から参照してみましょう。GetRangeWithMismatchedTypes という関数が発生しています。文字通り型指定が間違っているけど、範囲を取得するみたいな関数(あっているかはわかりません。)ですね。下記のパターンでは、Expr1003 = @min_date, Expr1004 = NULL がそれぞれ割り当てられます。
※(6)が何に使用されるのかイマイチ推測できない…

([Expr1003],[Expr1004],[Expr1002])=GetRangeWithMismatchedTypes([@min_date],NULL,(6))

 下記のパターンでは、Expr1006 = NULL , Expr1007 = @max_date がそれぞれ割り当てられます。

([Expr1006],[Expr1007],[Expr1005])=GetRangeWithMismatchedTypes(NULL,[@max_date],(10))

 上記の結果をクエリに当てはめると下記のようになります。

SELECT
    SalesOrderID,
    RevisionNumber,
    OrderDate
FROM
    Sales.SalesOrderHeader WITH(INDEX(IX_SalesOrderHeader_OrderDate))
WHERE
    (
        OrderDate > Expr1003
    AND OrderDate < Expr1004
    )
AND (
        OrderDate < Expr1007
    AND OrderDate > Expr1006
    )

 次に、Concatenation オペレーターをみていきましょう。 OrderDate > Expr1003 と OrderDate > Expr1006、OrderDate < Expr1004 と OrderDate < Expr1007 が結合されます。

[Expr1008] = ([Expr1003], [Expr1006]), [Expr1009] = ([Expr1004], [Expr1007]), [Expr1010] = ([Expr1002], [Expr1005])

 次に、Merge Interval オペレーターでダブった範囲が消去されます。OrderDate > Expr1003 と OrderDate > Expr1006 から、Expr1008 = @min_date となります。OrderDate < Expr1004 と OrderDate < Expr1007 から、Expr1009 = @max_date となります。
 
 最後に Expr1008 と Expr1009 でシークを行ないます。

OBJECT:([AdventureWorks].[Sales].[SalesOrderHeader].[IX_SalesOrderHeader_OrderDate]), SEEK:([AdventureWorks].[Sales].[SalesOrderHeader].[OrderDate] > [Expr1008] AND [AdventureWorks].[Sales].[SalesOrderHeader].[OrderDate] < [Expr1009]) ORDERED FORWARD, FORCEDINDEX

 これは一例ですが、型の指定が間違っているだけで、SQL Server はこのような複雑な処理を行ないます。少しでも負荷を減らすためにも型を正しく指定しましょう。下記の型が正しいクエリを発行してみましょう。

-- datetime2 ではなく、datetime を指定する。
DECLARE @min_date datetime
DECLARE @max_date datetime

SET @min_date = '2011-05-31 00:00:00.000'
SET @max_date = '2011-07-31 00:00:00.000'

SET STATISTICS PROFILE ON

SELECT 
    SalesOrderID,
    RevisionNumber,
    OrderDate
FROM 
    Sales.SalesOrderHeader WITH (INDEX(IX_SalesOrderHeader_OrderDate))
WHERE 
    OrderDate > @min_date
AND OrderDate < @max_date

SET STATISTICS PROFILE OFF

 
 実行プランを参照すると、Computer Scalar、Concatenation, Merge Interval オペレーターが全て無くなっています。かなりスッキリしましたね。
f:id:koogucc11:20180820021533p:plain

 実行プランが単純化されることで、クエリの解析は高速化されますし、キャッシュプランのサイズも小さくなります。その結果、データベースサーバーへの負荷が軽減されます。条件に指定する型は正確に指定するように意識しましょう。

 SQL Server 2017 でのパフォーマンスチューニングはどう変わるんだろう。2012 で止まってる自分は未知の世界。

SQL Server 2017 Query Performance Tuning: Troubleshoot and Optimize Query Performance

SQL Server 2017 Query Performance Tuning: Troubleshoot and Optimize Query Performance

SQL Server Management Studio を触っていて、GO コマンドをみてふと Go のことを思い出したので、ちょっと勉強をしてみる

 今年のお盆休みは初の10連休でした。これだけ休みが長いとふと何かを勉強したくなるもんですね。最近はデータベースばかりでプログラミングに触れていませんでした。SQL Server を触っていて、GO コマンドを見たとき下記の記事を思いだしました。
codezine.jp

 求人数的には、RubyPython には及びませんが、年収では堂々一位です。今後人気が出そうですね。ミーハーなこともあり、早速 GO のお勉強を開始したいと思います(笑) ちょっとググってみるとわかりやすい記事がいくつも見つかります。下記のサイトが一番わかりやすそうです。
なぜGo言語 (golang) はよい言語なのか・Goでプログラムを書くべき理由

 悪い点がいくつか挙げられていました。

Generics (template) がない
継承がない
例外がない。まるで1970年代に設計されたかのようである。
非知的なプログラマのためにデザインされている。

 ここで、「非知的なプログラマのためにデザインされている。」という項目がありましたが、大規模プロジェクトになると様々なレベルの開発者が関わるため、この点は非常に重要だと感じます。知識のない開発者に継承や Generics などを下手に扱わせて、メンテナンス性などを落とすくらいなら、ある程度制限がある方がソースのレベルも一定に保てていいように思います。※ただ、やっぱり継承欲しいです。

 try catch finally などの例外処理がないとありますが、とりあえず手法は存在するようです。try に対応する defer を使って panic() 関数でコールした内容を catch にあたる recover() 関数で処理するようです。また、この defer,panic, recover は内部処理的なものに使うのが指針のようで、API レベルのものには error オブジェクトを使用するのが本流のようです。
blog.amedama.jp

 それ以外には、繰り返し処理には do や while は存在せず、for 分のみです。switch 文では case に条件を複数指定することができます。※ case 1,2,3,4 みたいに。

 たまに、言語を勉強するなら C++ を学べばどんな言語でもできるようになるという方もいらっしゃいますが、C++ が挫折する人も多く、開発言語を習得するにはハードルが高いように思えます。Go であれば習得も速く、言語習得するには最適なような気がします。(個人的意見です。)

 とりあえず Go の開発環境をインストールして見た。面白そうなので、しばらく触ってみよう。
f:id:koogucc11:20180819131934p:plain

みんなのGo言語【現場で使える実践テクニック】

みんなのGo言語【現場で使える実践テクニック】

SQL Server のチューニングについてまとめてみる - その 25 - ( パーティションを有効に使ってみる )

 久しぶりの投稿です。梅雨前にもかかわらず関東はいい天気に恵まれ、来週の月曜日までこの天気が続くようです。
f:id:koogucc11:20180602164823j:plain


 長らくチューニングに関する投稿をしていませんでした。前回 ( その24 ) は7か月前ですね。
ryuchan.hatenablog.com

 MSDN では、パーティションについて以下のように記載されています。

パーティション テーブルとパーティション インデックスのデータは、データベース内の複数のファイル グループに分散できるように、行方向に複数の単位に分割されています。パーティション分割により、大きいテーブルとインデックスの管理可能性と拡張性が向上します。パーティション テーブルとパーティション インデックスは、SQL Server の Enterprise Edition、Developer Edition、および Evaluation Edition でのみ使用できます。

 管理と拡張性だけではなく、WHERE 句の条件として指定することによりパフォーマンスが飛躍的に向上します。それでは早速実験してみましょう。パーティション分割されたテーブル(パーティションID 1から20 まで存在するテーブル)にクエリを投げてみます。パーティションが 20 存在し、アクセスしたパーティションが 1..20 ですべてのパーティションにアクセスしたと判断できます。
f:id:koogucc11:20180602173656p:plain

 WHERE 句の条件に、$PARTITION.パーティション関数 ( パーティション列 ) を付加します。今回のケースで 1 から 20 のパーティションの中から、13 から 14 のみにアクセスしたい場合は、

$PARTITION.パーティション関数 ( パーティション列 ) BETWEEN 13 AND 14

と指定します。パーティション条件を指定した状態でクエリを実行すると、パーティションID の 13 から 14 のみにアクセスしていることが判断できます。CPU の推定コストも減少していますね。
f:id:koogucc11:20180602190121p:plain

 チューニングの記事もコツコツ投稿していないといけないですね。気力が続く限り、がんばります。

 iPad 2018 の付属品も色々買いました。

クラスタ化インデックスと非クラスタ化インデックスでこんなことやったらどうなんだろうと思ったことを実験してみる

 搭乗回数が若干減っています。#ダイヤモンド修行 がなかなか思い通りに進みません。それはさておき、最近、ふと思ったことがあり、記事を書く回数も昨年にも増して少なくなっているため、若干記事にする意味あるかなと思いながらも…記事にしてみます。

 AdventureWorks の SalesOrderDetail テーブルに対して、クラスタ化インデックス、非クラスタ化インデックスを3種類作成してみます。

CREATE CLUSTERED INDEX ClusteredIndex ON Sales.SalesOrderDetail_
(
    ModifiedDate ASC
)

CREATE NONCLUSTERED INDEX NonClusteredIndex-1 ON Sales.SalesOrderDetail_
(
    ProductID ASC,
    CarrierTrackingNumber ASC
)

CREATE NONCLUSTERED INDEX NonClusteredIndex-2 ON Sales.SalesOrderDetail_
(
    ProductID ASC,
    CarrierTrackingNumber ASC,
    ModifiedDate ASC
)

 下記のクエリを SQL Server Management Studio で実行してみます。

SELECT
    ProductID
FROM
    Sales.SalesOrderDetail_ WITH(INDEX([NonClusteredIndex-1]))
WHERE
    ProductID = 750
AND CarrierTrackingNumber = 'E46D-4692-AC'
AND ModifiedDate BETWEEN '2011-07-07 00:00:00.000' AND '2011-12-07 00:00:00.000'
SELECT
    ProductID
FROM
    Sales.SalesOrderDetail_ WITH(INDEX([NonClusteredIndex-2]))
WHERE
    ProductID = 750
AND CarrierTrackingNumber = 'E46D-4692-AC'
AND ModifiedDate BETWEEN '2011-07-07 00:00:00.000' AND '2011-12-07 00:00:00.000'
SELECT
    ProductID
FROM
    Sales.SalesOrderDetail_
WHERE
    ProductID = 750
AND CarrierTrackingNumber = 'E46D-4692-AC'
AND ModifiedDate BETWEEN '2011-07-07 00:00:00.000' AND '2011-12-07 00:00:00.000'

 実行プランの結果は下図のとおりです。
f:id:koogucc11:20180429093812p:plain

 少しでも差が出るかと思ったんですが、コスト上変わらないですね。もう少し実験してみるか。

 iPad 9.7
www.apple.com

 Apple Pencil
www.apple.com

 Logicool Keys-to-Go Ultra Slim Keyboard with iPhone Stand
www.apple.com

 ケース

 フィルム