ハロの外部記憶インターフェイス

そろそろ覚える努力が必要かも…

ファイルを分割する。

splitを利用し、大きいファイルを分割する。

split -b 2000m filename.zip filename.zip. 

-> 結果 filename.zip.ab, filename.zip.ac, ... 2GB単位で分割される。

分割されたファイルを結合する

cat filename.zip.* > filename.zip

tar圧縮したファイルをそのまま分割する。

tar cvf - *.* | split -b 200m - filename.tar_

-> 結果 filename.tar_ab, filenametar_ac, ... 200MB単位で分割される。

分割りしたファイルを結合と同時に解凍する。

cat filename.tar_* | tar -xvf -

SQL Server LocalDb利用する

LocalDbの作成

Visual Studioから「表示」-「SQL Server オブジェクトエキスプローラー」を表示する。 f:id:haronoid:20180216205232p:plain

ローカルDBのデータベースより、新しいデータベースを作成 f:id:haronoid:20180216205426p:plain

DB名とファイルの場所を指定して、作成する。

Visual Studioのプロジェクトに追加する。

一番簡単だったのはEntityFrameworkを利用する場合だった。 プロジェクトに新しい項目追加で「ADO.NET Entity Data Model」を追加する。 f:id:haronoid:20180216205841p:plain エータベースからEF Desiginerを選択し、対象のファイルを選択する。 f:id:haronoid:20180216205925p:plain

新しいファイルを選択する場合は「新しい接続」より、対象ファイルを選択する。 f:id:haronoid:20180216210043p:plain

プロジェクトにモデルデザイナが追加され、「App.config」に「connectionStrings」が追加されている事が確認できる。

<connectionStrings>
  <add name="App1DBEntities" connectionString="metadata=res://*/Model1.csdl|res://*/Model1.ssdl|res://*/Model1.msl;provider=System.Data.SqlClient;provider connection string=&quot;data source=(LocalDB)\MSSQLLocalDB;attachdbfilename=|DataDirectory|App1DB.mdf;integrated security=True;connect timeout=30;MultipleActiveResultSets=True;App=EntityFramework&quot;" providerName="System.Data.EntityClient" />
</connectionStrings>

自動でプロジェクトにmdfファイルがコピーされて入り、filepathがDataDirectoryになってしまう。

※ 特定フォルダーのファイルを参照したい場合は、|DataDirectory|をローカルパスに変更し、プロジェクト内のmdfファイルは削除する。

※ connectionStringsをLocalDBのプロパティの接続文字列を設定しても同じ動作になる。

<connectionStrings>
  <add name="App1DBEntities" connectionString="(LocalDB)\MSSQLLocalDB;AttachDbFilename=C:\LocalDB\App1DB.mdf;Integrated Security=True;Connect Timeout=30" providerName="System.Data.EntityClient" />
</connectionStrings>

ソース

App1DBEntities db = new App1DBEntities();
foreach (Users item in db.Users)
{
    Console.WriteLine(item.name);
}

DBの最新情報更新

DBの最新状態をソースに反映する方法、Entity Data Model画面上で「エータベースからモデルを更新」で最新化できる。 f:id:haronoid:20180216211146p:plain

参考: https://docs.microsoft.com/ja-jp/aspnet/core/tutorials/first-mvc-app/working-with-sql?tabs=aspnetcore2x

SQL Serverで外部ファイルをコマンドライン実行する

外部ファイルをコマンドラインから実行

サンプル db_nameに接続し、script.sqlを実行し、処理結果をscript.logファイルに出力する。

sqlcmd -U "sa" -P "password" -S "localhost" -d db_name -i script.sql -o script.log

サーバー認証の場合、-E

sqlcmd -S "localhost" -E -d db_name -i script.sql -o script.log

直接SQL文を実行する場合

sqlcmd -S "localhost" -E -d db_name  -Q "select getdate(); -o script.log
  • -qと-Qの違いQの場合、処理後、SQLCMDを終了する。

複数ファイルを実行する場合、カンマ具切りつなぐだけ

sqlcmd -S "localhost" -E -d db_name -i script1.sql,script2.sql,script3.sql -o script.log

ログ・ファイルを追記にする

sqlcmd -S "localhost" -E -d db_name  -Q "select getdate(); >> script.log

SQL ServerのManagement Studioでは早いがアプリケーションで実行すると遅くなる

Management Studioでのクエリ実行とPGの中での実行の違い

主に遅い原因は実行プランの違い、問題はなぜ違いが発生するかだが、原因としてManagement Studioでの実行とPGでの実行ではPGで頻繁に実行されるとSQLが再利用される。実行プランも再利用されるため、データによっては遅くなる場合がある。(らしい)

  • ARITHABORTがManagement StudioではデフォルトONだが、PG実行時はデフォルトOFFになっている。

PGのSQL実行時に意図的にONにしてあげると、早くなる場合あり。(効果なしの場合も多い)

SET ARITHABORT ON
-- 実行SQL 
SET ARITHABORT OFF

SQL文のエンコーディング問題

PGからSBサーバーへ送られるクエリのエンコーディングによっては以下の問題が発生しているみたい。varcharのほうが圧倒的多いはずだし、なんとかMSが頑張ってほしいな

  • SQL ServerではvarcharがSJIS、nvarcharがUnicode扱い
  • SQLがnvarcharとして実行されてた場合、varcharカラムに対して暗黙的にキャストが行われるらしい

インデックス断片化調査

SQL Serverびインデックス断片化の調査

とりあえず30%以上だったら、最高値を検討しよう

SELECT a.index_id, name, avg_fragmentation_in_percent  
FROM sys.dm_db_index_physical_stats (DB_ID(N'DbName'), NULL, NULL, NULL, NULL) AS a  
    JOIN sys.indexes AS b 
      ON a.object_id = b.object_id AND a.index_id = b.index_id
WHERE avg_fragmentation_in_percent > 30
GO  

インデックス再構成

断片化が30%未満の場合、再編成でも大丈夫らしい

ALTER INDEX IDX_INDEX1 
  ON DbName.TableName
REORGANIZE ;   

テーブルの全インデックス再構成

ALTER INDEX ALL ON DbName.TableName
REORGANIZE ;  

インデックス再構築

断片化が30%以上の場合、再構築が有効

ALTER INDEX IDX_INDEX1 
  ON DbName.TableName
REBUILD ;   

テーブルの全インデックス再構築

ALTER INDEX ALL ON DbName.TableName
REBUILD WITH (FILLFACTOR = 80, SORT_IN_TEMPDB = ON,
              STATISTICS_NORECOMPUTE = ON);

REBUILD WITH (ONLINE = ON) ;

インデックスの再構成と再構築の違い

再構築がひとつのトランザクションでインデックスを完全に再作成するのに対して、再構成は処理単位ごと (処理単位はページ) にトランザクションが分割されていて、リーフページ間でインデックス行を移動させることで行を前に詰めて断片化を解消しているという点

  • 再構成(REORGANIZE)
  • 再構築(REBUILD)
    • 現在のインデックスはそのままで新しいインデックスを作成する。(DBのデータファイルが新しいインデックス分容量が増える)
    • 完了までがトランザクションになるため、途中で止めた場合、全てロールバックになる。
    • 完了まではインデックスが2つ存在する状態

参考: https://blogs.msdn.microsoft.com/jpsql/2013/02/28/977/ https://docs.microsoft.com/ja-jp/sql/relational-databases/indexes/reorganize-and-rebuild-indexes

SQL ServerにOracleにリンクサーバーを設定する。

SQL ServerORACLEへのリンクサーバ設定

ORACLE用リンクサーバーを作成する。

以下のスクリプトより、リンクサーバーを作成する。

USE [master]
GO
EXEC master.dbo.sp_addlinkedserver 
 @server = N'ORA_LINK',              -- リンクサーバー名
 @srvproduct=N'Oracle',              -- プロダクト名 特に意味はなさそう
 @provider='OraOLEDB.Oracle',  -- 固定
 @datasrc='ORCL'                        -- tnsnames.oraに設定したSIDを設定する。
GO
EXEC master.dbo.sp_serveroption @server=N'ORA_LINK', @optname=N'collation compatible', @optvalue=N'false'
GO
EXEC master.dbo.sp_serveroption @server=N'ORA_LINK', @optname=N'data access', @optvalue=N'true'
GO
EXEC master.dbo.sp_serveroption @server=N'ORA_LINK', @optname=N'dist', @optvalue=N'false'
GO
EXEC master.dbo.sp_serveroption @server=N'ORA_LINK', @optname=N'pub', @optvalue=N'false'
GO
EXEC master.dbo.sp_serveroption @server=N'ORA_LINK', @optname=N'rpc', @optvalue=N'false'
GO
EXEC master.dbo.sp_serveroption @server=N'ORA_LINK', @optname=N'rpc out', @optvalue=N'false'
GO
EXEC master.dbo.sp_serveroption @server=N'ORA_LINK', @optname=N'sub', @optvalue=N'false'
GO
EXEC master.dbo.sp_serveroption @server=N'ORA_LINK', @optname=N'connect timeout', @optvalue=N'0'
GO
EXEC master.dbo.sp_serveroption @server=N'ORA_LINK', @optname=N'collation name', @optvalue=null
GO
EXEC master.dbo.sp_serveroption @server=N'ORA_LINK', @optname=N'lazy schema validation', @optvalue=N'false'
GO
EXEC master.dbo.sp_serveroption @server=N'ORA_LINK', @optname=N'query timeout', @optvalue=N'0'
GO
EXEC master.dbo.sp_serveroption @server=N'ORA_LINK', @optname=N'use remote collation', @optvalue=N'true'
GO
EXEC master.dbo.sp_serveroption @server=N'ORA_LINK', @optname=N'remote proc transaction promotion', @optvalue=N'true'
GO
USE [master]
GO
EXEC master.dbo.sp_addlinkedsrvlogin 
  @rmtsrvname = N'ORA_LINK', 
  @locallogin = NULL , 
  @useself = N'False', 
  @rmtuser = N'scott',      -- ORACLEのログインユーザID
  @rmtpassword = N'tiger'  -- ログインパスワード
GO

接続確認処理

以下のSQLの結果として1が表示されれば成功

SELECT * FROM OPENQUERY(ORA_LINK,'SELECT 1 D FROM DUAL')

トラブルシューティング

サードパーティOracle プロバイダを使用していて、その Oracle プロバイダを SQL Server プロセス外部で実行できない場合、プロバイダ オプションを変更してインプロセスで実行できるようにします。 * ManagementStudioから「サーバーオブジェクト\リンクサーバー\プロバイダ」からOraOLEDB.Oracleをダブルクリックし、InProcess許可をチェックいれる。

参考: https://support.microsoft.com/ja-jp/help/280106/how-to-set-up-and-troubleshoot-a-linked-server-to-an-oracle-database-i