SQL Server 2016 的交易記錄傳送可能需要手動安裝 .NET Framework 3.5

交易記錄傳送實際上是透過各SQL Server執行個體上的作業呼叫「sqllogship.exe」應用程式,需要小心的是在安裝SQL Server 2016時並未要求一定需要.NET Framework 3.5,而sqllogship.exe工具程式需要.NET Framework 3.5,導致執行失敗卻未將失敗原因寫入作業記錄。

透過命令提示列呼叫sqllogship.exe才會出現缺少.NET Framework 3.5的錯誤訊息。

今日推出的 SQL Server Data Tools 16.3,對 Tabular Model 的 Explorer 終於讓人可以一目了然

image

定義 AD Domain 是單一字母的,不能在 Windows Server 2012 R2 Server 建 iSCSI target

天啊,我自己在家裡的 AD Domain 叫 i,竟然導致奇怪的 Bug,會有如下的錯誤訊息:

Unable to create iSCSI virtual disk

要修 bug 都還不一定裝得上 hotfix…

https://support.microsoft.com/en-us/kb/2953557

最後是建立一台不加入 Domain 的 Windows Server 2012 R2 當作 iSCSI target…

指定應用程式只用某幾顆 CPU

今天 SharePoint 莫名掛掉,然後發現是更新時多 CPU 彼此造成更新錯誤,照以下的說明

https://blogs.msdn.microsoft.com/spses/2015/05/12/sharepoint-2010-2013-an-exception-of-type-microsoft-sharepoint-administration-spupdatedconcurrencyexception-was-thrown-while-installing-an-update/

透過 PowerShell 語法解掉

$cmd="start "+""""" /affinity 1 "+"""C:\Program Files\Common Files\microsoft shared\Web Server Extensions\15\BIN\Psconfig.exe""" + " -cmd" +  " upgrade" + " -inplace" + " b2b" + " -wait"
cmd.exe /c $cmd

但意外發現 start 可以指定 cpu affinity,這比先前的問題還有趣,可以參照以下的 blog

https://blogs.msdn.microsoft.com/santhoshonline/2011/11/24/how-to-launch-a-process-with-cpu-affinity-set/

image

可以透過 Process Explorer

image

看到 CPU Affinity 真的是 2^0 + 2^4 = 11 (16進位)

image

先用 SSMS 2016 英文版為 SQL Server 2016 中文版設定 AG

到目前為止 SSMS 2016(2016 年 7 或 8 月號,網路 download 寫的是 7 月號,但安裝完程式 show 的是 8 月號)中文版建置 AG 的精靈有 Bug,但可以用英文版 SSMS 幫中文版 SQL Server 建置與設定。

查詢某個服務聽的 Port

get-process | where name -like msmd* | select name,id |ft –AutoSize

netstat -ao -p tcp | where {$_ -like ‘*上述的 id*’}

當過濾欄位是 char/varchar 時,透過 SqlCommand 搭配 SqlParameter 時,大量存取會有效能考量

最近幫朋友壓測時,發現的問題。

依據 SQL Server 的 Data Type Precedence https://msdn.microsoft.com/en-us/library/ms190309.aspx

  1. user-defined data types (highest)

  2. sql_varian t

  3. xml

  4. datetimeoffset

  5. datetime2

  6. datetime

  7. smalldatetime

  8. date

  9. time

  10. float

  11. real

  12. decimal

  13. money

  14. smallmoney

  15. bigint

  16. int

  17. smallint

  18. tinyint

  19. bit

  20. ntext

  21. text

  22. image

  23. timestamp

  24. uniqueidentifier

  25. nvarchar (including nvarchar(max) )

  26. nchar

  27. varchar (including varchar(max) )

  28. char

  29. varbinary (including varbinary(max) )

  30. binary (lowest)

代表輸入的條件參數若是 unicode,而目標欄位是 char/varchr/text,將會是欄位內所有的紀錄值先轉型成 unicode,再跟輸入條件比較。

範例程式碼:

use tempdb

drop table if exists t1

create table t1(c1 int identity primary key,c2 char(6),c3 char(10),c4 varchar(50),c5 datetime2(7) default(sysdatetime()),
c6 uniqueidentifier default(newsequentialid()),c7 bigint default(0))

set nocount on

declare @i int=0
while @i<100000
begin
    insert t1(c2,c3,c4) values(right(‘000000’+convert(varchar(6),@i),6),
    right(‘0000000000’+convert(varchar(6),@i),10),rand())
    set @i+=1
end

select * from t1

create index idx on t1(c2,c3,c4)
go
create proc sp @c2 char(6),@c3 char(10),@c4 varchar(50)
as
    select c1 from t1 where c2=@c2 and c3=@c3 and c4=@c4
go

簡單利用 console 程式測試

using System;
using System.Data.SqlClient;

namespace ConsoleApplication4
{
    class Program
    {
        static void Main(string[] args)
        {
            using (SqlConnection cnn = new SqlConnection("Data Source=.;Initial Catalog=tempdb;integrated security=sspi"))
            {
                SqlCommand cmd = new SqlCommand("select c1 from t1 where c2=@c2 and c3=@c3 and c4=@c4");
                cmd.Parameters.Add(new SqlParameter("c2", "000000"));
                cmd.Parameters.Add(new SqlParameter("c3", "0000000000"));
                cmd.Parameters.Add(new SqlParameter("c4", "0.0558658"));
                cmd.Connection = cnn;

                SqlCommand cmd2 = new SqlCommand("select c1 from t1 where c2=@c2 and c3=@c3 and c4=@c4");
                cmd2.Parameters.Add(new SqlParameter("c2", System.Data.SqlDbType.Char,6));
                cmd2.Parameters.Add(new SqlParameter("c3", System.Data.SqlDbType.Char, 10));
                cmd2.Parameters.Add(new SqlParameter("c4", System.Data.SqlDbType.VarChar, 50));
                cmd2.Parameters[0].Value = "000000";
                cmd2.Parameters[1].Value = "0000000000";
                cmd2.Parameters[2].Value = "0.0558658";
                cmd2.Connection = cnn;

                SqlCommand cmd3 = new SqlCommand("sp");
                cmd3.CommandType = System.Data.CommandType.StoredProcedure;
                cmd3.Parameters.Add(new SqlParameter("c2", "000000"));
                cmd3.Parameters.Add(new SqlParameter("c3", "0000000000"));
                cmd3.Parameters.Add(new SqlParameter("c4", "0.0558658"));
                cmd3.Connection = cnn;

                cnn.Open();
                long l = DateTime.Now.Ticks;
                int times = 100000;
                for(int i=0;i<times;i++)
                {
                    //exec sp_executesql N’select c1 from t1 where c2=@c2 and c3=@c3 and c4=@c4′,N’@c2 nvarchar(6),@c3 nvarchar(10),@c4 nvarchar(9)’,@c2=N’000000′,@c3=N’0000000000′,@c4=N’0.0558658′
                    SqlDataReader dr = cmd.ExecuteReader();
                    dr.Close();
                }
                Console.WriteLine((DateTime.Now.Ticks – l).ToString());

                System.Threading.Thread.Sleep(3000);

                l = DateTime.Now.Ticks;
                for (int i = 0; i <times; i++)
                {
                    //exec sp_executesql N’select c1 from t1 where c2=@c2 and c3=@c3 and c4=@c4′,N’@c2 char(6),@c3 char(10),@c4 varchar(50)’,@c2=’000000′,@c3=’0000000000′,@c4=’0.0558658′
                    SqlDataReader dr = cmd2.ExecuteReader();
                    dr.Close();
                }
                Console.WriteLine((DateTime.Now.Ticks – l).ToString());
                System.Threading.Thread.Sleep(3000);

                l = DateTime.Now.Ticks;
                for (int i = 0; i < times; i++)
                {
                    //exec sp @c2=N’000000′,@c3=N’0000000000′,@c4=N’0.0558658′
                    SqlDataReader dr = cmd3.ExecuteReader();
                    dr.Close();
                }
                Console.WriteLine((DateTime.Now.Ticks – l).ToString());
            }
        }
    }
}

 

若 .NET 未指定 type,會自動賦予 nvarchar,導致欄位為 char 的要轉成 nvarchar 再行比較,以此例而言,也就是每次比較就需要轉 10 萬筆,3 欄位的紀錄值:

image

就單次查詢時,SQL Server 的執行計畫判讀不覺得有效能差,所以彼此占比相同。

但重複執行 10 萬次後,時間上,可以看得出來,因為指定正確的欄位型態,或是 Stored Procedure 只需要輸入參數時轉對參數型態,實際語法比較時,不需逐筆轉換,所以效率較佳。

image

就總 CPU 耗用而言,因為無法平行運算,轉資料型態導致 CPU 要跑得比較久,但只會操死一顆 CPU

image

Tabular 授權

試了一會兒 AS/Tabular/DAX 授權

=tbPromotion[Id]=var UserIDs=LOOKUPVALUE(tbUser[ID],[UserName],CUSTOMDATA()) return CALCULATE(VALUES( tbUserPromotion[PromotionID]), SUMMARIZE(‘tbUserPromotion’, tbUserPromotion[PromotionID]),

tbUserPromotion[UserID]=UserIDs)

執行結果似乎是我要的,雖然自己高度存疑,但傳回的資料紀錄又好像都對

一直處在拼積木的過程,搞不清自己在寫什麼,試著放函數到另一個函數的參數位置,一次次地拼著…

似乎現在流行的資料語言不流行語言本身的可讀性

移轉 Table 到不同 FileGroup

回答朋友的問題:利用 drop_existing 選項,在新 FileGroup 重建叢集索引

https://social.msdn.microsoft.com/Forums/sqlserver/en-US/025825ee-ecbc-4d7c-94ff-0595afc48347/how-to-move-a-table-from-a-file-groupprimary-to-another?forum=transactsql

CREATE unique clustered INDEX pk_testmember ON DBO.資料表

(

欄位 ASC

)

WITH (DROP_EXISTING=ON, ONLINE=ON)

ON 新的 FileGroup

Unicode、Big5或其他的文字編碼?Windows 輸入的是 Unicode,要如何解釋是你告訴 SQL Server

剛朋友問的問題,簡單的邏輯如下:

select ‘a中文煊’ collate SQL_Latin1_General_CP1_CI_AS,Convert(varbinary(10),’a中文煊’  collate SQL_Latin1_General_CP1_CI_AS),
‘a中文煊’ collate Chinese_Taiwan_Stroke_CI_AS,Convert(varbinary(10),’a中文煊’  collate Chinese_Taiwan_Stroke_CI_AS),
N’a中文煊’ collate Chinese_Taiwan_Stroke_CI_AS,Convert(varbinary(10),N’a中文煊’  collate Chinese_Taiwan_Stroke_CI_AS)

image

輸入時,Windows 收到的是 Unicode,且包含延伸字集,如同我現在的選字:

image

當檔案用 Unicode 存時,你都可以看得到,因為是文字編輯器在呈現這些文字圖形與 Unicode 的對應。

但要跟 SQL Server 溝通或存入時,你會告知目標的字集為何,因此上述三個範例,分別要用 Latin、Big5 和 Unicode 呈現,而 Unicode 是 superset,其他的字集較小,SQL Server 只能轉換兩個字集間能轉的部分,其餘都是問號了

關注

有新文章發表時,會立即傳送至你的收信匣。

加入其他 33 位關注者