UWInfo Blog
發表新文章
[Join] | [忘記密碼] | [Login]
搜尋

搜尋意見
文章分類-#Author#
[所有文章分類]
所有文章分類
  • ASP.NET (48)
  • ASP.NET2.0 (15)
  • ASP.NET4.0 (34)
  • JavaScript (49)
  • jQuery (26)
  • FireFox (4)
  • UW系統設定 (3)
  • SQL (39)
  • SQL 2008 (25)
  • mirror (4)
  • SVN (4)
  • IE (9)
  • IIS (21)
  • IIS6 (1)
  • 閒聊 (7)
  • W3C (6)
  • 作業系統 (9)
  • C# (24)
  • CSS (12)
  • FileServer (1)
  • HTML 5 (11)
  • CKEditor (3)
  • UW.dll (13)
  • Visual Studio (16)
  • Browser (8)
  • SEO (1)
  • Google Apps (3)
  • 網站輔助系統 (4)
  • DNS (5)
  • SMTP (4)
  • 網管 (11)
  • 社群API (3)
  • SSL (4)
  • App_Inventor (1)
  • URLRewrite (2)
  • 開發工具 (6)
  • JSON (1)
  • Excel2007 (1)
  • 試題 (3)
  • LINQ (1)
  • bootstrap (0)
  • Vue (3)
  • IIS7 (3)
  • foodpanda (2)
  • 編碼 (2)
  • 資安 (3)
  • Sourcetree (1)
  • MAUI (1)
  • CMD (1)
  • my sql (1)
  • API串接 (1)
最新回應
  • Newtonsoft.Json.JsonConvert.DeserializeObject 失敗的情況
    test...more
  • dotnet ef dbcontext scaffold
    ...more
  • [ASP.NET] 利用 aspnet_regiis 加密 web.config
    ...more
  • IIS ARR (reverse proxy) 服務安裝
    ...more
  • [錯誤訊息] 請加入 ScriptResourceMapping 命名的 jquery (區分大小寫)
    ...more
  • 用 Javascript 跨網頁讀取 cookie (Cookie cross page, path of cookie)
    ...more
  • 線上客服 - MSN
    本人信箱被盜用以致資料外洩,是否可以請貴平台予以協助刪除該信箱之使用謝謝囉...more
  • 插入文字到游標或選取處
    aaaaa...more
  • IIS 配合 AD (Active Directory) 認証, 使用 .Net 6.0
    太感謝你了~~~你救了我被windows 認證卡了好幾天QQ...more
  • PostgreSQL 的 monitor trigger
    FOR EACH ROW 可能要改為 FOR EACH STATEMENT ...more
標籤
  • 帳號
  • 866
  • 490
  • 654
  • Message
  • UNT
  • ltrbr4xk
  • maxAllowed
  • AD
  • 62
  • 98
  • -8136
  • max
  • Findindex
  • iis6
  • 存取被拒
  • Message212
  • 284
  • syslog
  • .animate
  • 4728-4728
  • 150
  • yyy
  • -8048 UNIO
  • 1402121121
  • -5846
  • LINE
  • IE
  • 134 ORDER
  • 192
  • sp_
  • ef ORDER B
  • [u2]
  • 1
  • https
  • BxpAZSkb
  • c
  • Line212112
  • OrderMain
  • vslerp
  • U2
  • workbench
  • postgre
  • 154
  • html212112
  • .
  • vb
  • 中文
  • aspx
  • join
頁數 3 / 9 上一頁 下一頁
搜尋 UNT 結果:
MySQL效能檢測與優化 (Workbench)
首先尋找出一支欲調效的Table或Query
 
再來我們可以先使用左上方工具列 'Query' 內的 Explain Current Statement
 便可以得到如以下的連結表
 
 
由圖中可以清楚的看見每一段Query後的資料量,並發現有數張表單是呈現紅色 'Full Table Scan'
,這代表該段Query對這張表單的每一行欄位都做了掃描。
再來我們在我們的Query前方加上 'EXPLAIN' 並執行
 
便得到了該段Query所關聯的表單與其詳細資訊

其中針對EXPLAIN的欄位說明如下:
table:關連到的資料表(Table)會顯示在此。
type:顯示使用了何種類型。從最優至最差的類型為const、eq_reg、ref、range、indexhe、ALL。
possible_keys:顯示可能使用到的索引。此為從WHERE語法中選擇一個適合的欄位名稱。
key:實際使用到的索引。如果為NULL,則是沒有使用索引。
key_len:使用索引的長度。長度越短 準確性越高。
ref:顯示那一列的索引被使用。一般是一個常數(const)。
rows:MySQL用來返回資料的筆數。
Extra:MySQL用來解析額外的查詢訊息。如果此欄位的值為:Using temporary和Using filesort,表示MySQL無法使用索引。
Extra為MySQL用來解析額外的查詢訊息,其中欄位值所代表的意義如下:
Distinct:當MySQL找到相關連的資料時,就不再搜尋。
Not exists:MySQL優化 LEFT JOIN,一旦找到符合的LEFT JOIN資料後,就不再搜尋。
Range checked for each Record(index map:#):無法找到理想的索引。此為最慢的使用索引。
Using filesort:當出現這個值時,表示此SELECT語法需要優化。因為MySQL必須進行額外的步驟來進行查詢。
Using index:返回的資料是從索引中資料,而不是從實際的資料中返回,當返回的資料都出現在索引中的資料時就會發生此情況。
Using temporary:同Using filesort,表示此SELECT語法需要進行優化。此為MySQL必須建立一個暫時的資料表(Table)來儲存結果,此情況會發生在針對不同的資料進行ORDER BY,而不是GROUP BY。
Using where:使用WHERE語法中的欄位來返回結果。
System:system資料表,此為const連接類型的特殊情況。
Const:資料表中的一個記錄的最大值能夠符合這個查詢。因為只有一行,這個值就是常數,因為MySQL會先讀這個值然後把它當做常數。
eq_ref:MySQL在連接查詢時,會從最前面的資料表,對每一個記錄的聯合,從資料表中讀取一個記錄,在查詢時會使用索引為主鍵或唯一鍵的全部。
ref:只有在查詢使用了非唯一鍵或主鍵時才會發生。
range:使用索引返回一個範圍的結果。例如:使用大於>或小於<查詢時發生。
index:此為針對索引中的資料進行查詢。
ALL:針對每一筆記錄進行完全掃描,此為最壞的情況,應該盡量避免。

 
 
 
我們可以注意到 `browse_history` 這個表單在Query中並沒有使用索引,
可以從上方的QueryString中發現該段Query的Left Join是查詢`product_id`這個欄位,前往這個Table並幫其建立Index來增加檢索效率。
  
步驟三的時候可以選擇複數欄位來建立Index,但是要注意的是在使用索引欄位作為條件時,如果該索引是複合索引,那麼必須使用到該索引中的第一個欄位作為條件時才能保證系統使用該索引,否則該索引將不會被使用,並且應儘可能的讓欄位順序與索引順序相一致。

再來是在Query語句中應該注意以下事項
1.避免在索引列上進行運算, 這將導致引擎放棄使用索引而進行全表掃描。
2.不使用NOT IN和<>操作, NOT IN和<>操作都不會使用索引將進行全表掃描。NOT IN可以NOT EXISTS代替,id<>9則可使用id>9 or id<9來代替。
3.檢查where條件與order by 欄位,避免全表掃描。
4.應儘量避免在 where 子句中對欄位進行 null 值判斷,否則將導致引擎放棄使用索引而進行全表掃描,如: 可以在num上設定預設值0,確保表中num列沒有null值,然後這樣查詢: select id from t where num = 0
5.應儘量避免在 where 子句中使用 or 來連線條件,如果一個欄位有索引,一個欄位沒有索引,將導致引擎放棄使用索引而進行全表掃描。可以拆分條件,進行子句的union all查詢,如: select id from t where num=10 or name = 'admin'  拆分 select id from t where num = 10 union all select id from t where name = 'admin'
6.in 和 not in 也要慎用,否則會導致全表掃描,如: select id from t where num in(1,2,3) 對於連續的數值,能用 between 就不要用 in 了: select id from t where num between 1 and 3,
用 exists 代替 in 是一個好的選擇: select num from a where num in(select num from b) 換成 select num from a where exists(select 1 from b where num=a.num)
7.like語句的%不要前置, 否則索引失效 將導致全表掃描。
8.如果在 where 子句中使用引數,也會導致全表掃描。 因為SQL只有在執行時才會解析區域性變數,但優化程式不能將訪問計劃的選擇推遲到執行時;它必須在編譯時進行選擇。然 而,如果在編譯時建立訪問計劃,變數的值還是未知的,因而無法作為索引選擇的輸入項。
9.應儘量避免在where子句中對欄位進行函式操作,這將導致引擎放棄使用索引而進行全表掃描。
10.不要在 where 子句中的“=”左邊進行函式、算術運算或其他表示式運算,否則系統將可能無法正確使用索引。
11.在使用索引欄位作為條件時,如果該索引是複合索引,那麼必須使用到該索引中的第一個欄位作為條件時才能保證系統使用該索引,否則該索引將不會被使用,並且應儘可能的讓欄位順序與索引順序相一致。
12.Update 語句,如果只更改1、2個欄位,不要Update全部欄位,否則頻繁呼叫會引起明顯的效能消耗,同時帶來大量日誌。
對於多張大資料量(這裡幾百條就算大了)的表JOIN,要先分頁再JOIN,否則邏輯讀會很高,效能很差。
13.select count(*) from table;這樣不帶任何條件的count會引起全表掃描,並且沒有任何業務意義,是一定要杜絕的。
14.任何地方都不要使用 select * from t ,用具體的欄位列表代替“*”,不要返回用不到的任何欄位。
15.避免頻繁建立和刪除臨時表,以減少系統表資源的消耗。臨時表並不是不可使用,適當地使用它們可以使某些例程更有效,例如,當需要重複引用大型表或常用表中的某個資料集時。但是,對於一次性事件, 最好使用匯出表。
16.在新建臨時表時,如果一次性插入資料量很大,那麼可以使用 select into 代替 create table,避免造成大量 log ,以提高速度;如果資料量不大,為了緩和系統表的資源,應先create table,然後insert。
17.儘量拆分大的 DELETE 或INSERT 語句,批量提交SQL語句。
18.儘量避免使用遊標,因為遊標的效率較差,如果遊標操作的資料超過1萬行,那麼就應該考慮改寫。

參考來源:
1. http://blog.twbryce.com/mysql-explain/
2. https://www.gushiciku.cn/pl/gkis/zh-tw
3. https://www.itread01.com/content/1548581229.html
More...
梨子, 2022/3/28 下午 09:00:29
Framework未安裝, 但實際上已經安裝

下載Runtime版本打開後出現, 【這部電腦已經安裝 .NET Framework 4.6.2 (含) 以上版本的更新】

後來下載Developer Pack版本安裝完畢後就可以了
https://dotnet.microsoft.com/download/dotnet-framework/net462​​​​​​​

 
More...
choco, 2021/8/23 下午 02:28:48
HTTP 錯誤 413.1 - Request Entity Too Large
 


httpRuntime 加 maxRequestLength 沒作用, 請到 system.webServer 設定 maxAllowedContentLength
<system.webServer>
...
<security>
<requestFiltering>
    <!--1073741824 ==> 1GB-->
    <requestLimits maxAllowedContentLength="1073741824" />
</requestFiltering>
</security>
...
</system.webServer>

 
More...
Reiko, 2021/3/25 下午 02:36:36
ORM 的新範列
一些範列如下:

        //直接使用 Operator
        var products = ORM.Product.Select()
            .Where(CN.Product.Name == "ABC")
            .And(CN.Product.Name != "DEF")
            .And(CN.Product.Name % "ABC%") //這是 Like
            .And(CN.Product.Name | "apple, orange".SqlListStr()) // 這是 in
            .And(CN.Product.Is_Available)
            .And(!CN.Product.Is_Deleted)
            .And(CN.Product.OriginalPrice > 5)
            .And(CN.Product.OriginalPrice <= 500)
            .And(CN.Product.CreateDate < DateTime.Now.AddMonths(-1))
            .GetList<ORM.Product>();

//產出 SQL: Select * From [Product] (NoLock) Where ( ([Name] <> N'DEF') ) And ( ([Name] like N'ABC%') ) And ( ([Name] in ('apple',' orange')) ) And ([Is_Available] = 'Y') And ( ([Is_Deleted] = 'N') ) And ( ([OriginalPrice] > 5) ) And ( ([OriginalPrice] <= 500) ) And ( ([CreateDate] < '2020-11-26T10:17:15.553') )


        //用 Id 取出物件並修改
        var product = ORM.Product.Get(3);
        U2.WU.DebugWriteLine(product.Name);
        product.Name = "平格藍均抱枕套45*45 ABC";
        product.Modify();

        //新增一筆資料
        var newId = new ORM.Product()
        {
            Name = "New Product",
            OriginalPrice = 100,
            Is_Hot = "Y"
        }.Add();

        //用 Id 修改資料
        var updateCount = new ORM.Product(3)
        {
            Name = "New Product",
            OriginalPrice = 100,
            Is_Hot = "Y"
        }.Modify();

More...
Bike, 2020/12/26 下午 12:04:26
試題
試說明以下程式碼的功用, 以及可改進的部份.


        string EndDate = Request["EndDate"];

        DataTable qtyControls = U2.SQL.DTFromSQL("Select YA00, PD00 from QtyControl Where EndDate > '" + EndDate + "' and SoldQty >= InitQty");

        var values = qtyControls.AsEnumerable().Select(r => "('" + r.Field<string>("YA00") + "','" + r.Field<string>("PD00") + "')").ToList();

        var sqls = new List<string>();
        sqls.Add("Delete StopSaleYAP;");

        int start = 0;        
        while(start < values.Count)
        {
            var end = start + 999;
            if(end > values.Count - 1)
            {
                end = values.Count;
            }

            sqls.Add("insert into StopSaleYAP(YA00, PD00) Values" + string.Join(",", values.GetRange(start, end)) + ";");

            start = end + 1;
        }

        U2.SQL.ExecuteSQL(string.Join("\r\n", sqls));


        public static bool IsErrorOrder(Order.Input.CheckValidOrder dto)
        {
            if (dto.OrderNos == null || dto.OrderNos.Count == 0)
            {
                return false;
            }

            var orderCount = dto.OrderNos.Count();
            var orders = NpreoOrderMain.GetList(dto.OrderNos);
            if (orders.Count != orderCount || !dto.OrderNos.Any(x => orders.Select(o => o.Order_No).Contains(x)))
            {
                return true;
            }
            return false;
        }


        var fu = Request.Files[0];
        fu.SaveAs(Server.MapPath("UploadFiles/") + fu.FileName);


--

基本題:

1. 對 Linq 熟嗎.

2. 對 ASP.Net 的 Cache  熟悉嗎.

3. 用過什麼 ORM, 試說明優缺點.

4. 試說明 MVC 的架構.

資安相關問題:

1. 試說明 SQL Injection

2. 試說明 Cross Site Injection.

3. 上傳檔案要注意的事項.

4. 試說明 cookie 的安全設定 ? same site, secure, http only.


前端相關加分題:

1. jQuery 或 Vue 熟悉嗎 ?

2. 試說明 RWD

3. 試說明 bootstrap

進階問題:

1. 試說明 Reflection

2. 試說明 Dependency Injection

3.  試說明 singleton vs static

4. 試單有兩個欄位 Id, Status (付款待確認: 1.1;  已付款: 2,  訂單已出貨: 3; 訂單取消中: 5; )
狀態 1.1 和 狀態 2 的訂單可取消,取消後改為狀態 5

客人要取消訂單,訂單編號為 123, 試說明程式執行的過程。
More...
Bike, 2020/10/24 上午 10:24:51
在 CentOS 上面啟動多個 .Net Core 的網站
1. 參考這裡設定第一個網站:
https://blog.johnwu.cc/article/centos-asp-net-core-neginx.html
注意, 文章中有一個錯誤:
/etc/nginx/conf.d/my-website.conf 的第 27 行, 應該是 include /etc/nginx/conf.d/default_proxy_settings;

2.  因為要避開 5000 port, 所以修改第二個網站的 appsettings.json, 讓第二個網站開在 5002 port, 如下.
{
"Logging": {
    "LogLevel": {
     "Default": "Information",
     "Microsoft": "Warning",
     "Microsoft.Hosting.Lifetime": "Information"
    }
},
"Kestrel": {
        "EndPoints": {
                "Http": {
                        "Url": "http://localhost:5002"
                }
        }
},
"AllowedHosts": "*"
}


3. 新增 /etc/nginx/conf.d/my-website2.conf, 要注意
    A. portal2
    B. server localhost:5002
    C. server_name coretest2.bike.idv.tw
    當然 SSL 憑証的檔名也要記得改.

upstream portal2 {
    # localhost:5000 改成 ASP.NET Core 所監聽的 Port
    server localhost:5002;
}

server {
    # 只要是透過這些 Domain 連 HTTP 80 Port,都會轉送封包到 ASP.NET Core
    listen 80;
    # 可透過空白區分,綁定多個 Domain
    server_name coretest2.bike.idv.tw;
    location / {
        proxy_pass http://portal2/;
        include /etc/nginx/conf.d/default_proxy_settings;
    }
}

# 用 HTTPS 必須要有 SSL 憑證,如果沒有要綁定 SSL 可以把下面整段移除
server {
    # 只要是透過這些 Domain 連 HTTPS 443 Port,都會轉送封包到 ASP.NET Core
    listen 443 ssl;
    server_name coretest2.bike.idv.tw;
    ssl_certificate /etc/nginx/ssl/coretest2.bike.idv.tw.crt;
    ssl_certificate_key /etc/nginx/ssl/coretest2.bike.idv.tw.key;

    location / {
        proxy_pass http://portal2/;
        include /etc/nginx/conf.d/default_proxy_settings;
    }
}


改完後就可以用了.

以下是 https://blog.johnwu.cc/article/centos-asp-net-core-neginx.html 抄過來的一些檔案, 作為備份:

setup-aspnet-core.sh
#!/bin/bash

main() {
    sudo yum -y install epel-release
    sudo yum -y update

    install_nginx
    install_dotnet

    sudo firewall-cmd --add-service=http --permanent
    sudo firewall-cmd --add-service=https --permanent
    sudo firewall-cmd --reload
}

install_nginx() {
    echo "###################################"
    echo "########## Install Nginx ##########"
    echo "###################################"
    sudo yum -y install httpd-tools nginx
    sudo setsebool -P httpd_can_network_connect on
    sudo sed -i 's/^SELINUX=.*/SELINUX=disabled/' /etc/selinux/config
    sudo setenforce 0
    sudo systemctl enable nginx
    sudo systemctl restart nginx
}

install_dotnet() {
    echo "###########################################"
    echo "########## Install .NET Core 2.2 ##########"
    echo "###########################################"
    sudo rpm -Uvh https://packages.microsoft.com/config/rhel/7/packages-microsoft-prod.rpm
    sudo yum -y install aspnetcore-runtime-2.2
}

main "$@"


用以下指令執行:
sudo sh setup-aspnet-core.sh



/etc/systemd/system/my-website.service, (/bin/dotnet 有可能是 /usr/bin/dotnet)
[Unit]
# Description=<此服務的摘要說明>
Description=MyWebsite

[Service]
# WorkingDirectory=<ASP.NET Core 專案目錄>
WorkingDirectory=/usr/share/my-website

# ExecStart=/bin/dotnet <ASP.NET Core 起始 dll>
ExecStart=/bin/dotnet MyWebsite.dll

# 啟動若失敗,就重啟到成功為止
Restart=always
# 重啟的間隔秒數
RestartSec=10

# 設定環境變數,注入給 ASP.NET Core 用
Environment=ASPNETCORE_ENVIRONMENT=Production
Environment=DOTNET_PRINT_TELEMETRY_MESSAGE=false

[Install]
WantedBy=multi-user.target


服務相關指令:
# 開啟,開機自動啟動服務
systemctl enable my-website.service

# 關閉,開機自動啟動服務
systemctl disable my-website.service

# 啟動服務
systemctl start my-website.service

# 重啟服務
systemctl restart my-website.service

# 停止服務
systemctl stop my-website.service

# 查看服務狀態
systemctl status my-website.service


/etc/nginx/conf.d/default_proxy_settings
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $http_connection;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Host $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_cache_bypass $http_upgrade;


/etc/nginx/conf.d/my-website.conf
upstream portal {
    # localhost:5000 改成 ASP.NET Core 所監聽的 Port
    server localhost:5000;
}

server {
    # 只要是透過這些 Domain 連 HTTP 80 Port,都會轉送封包到 ASP.NET Core
    listen 80;
    # 可透過空白區分,綁定多個 Domain
    server_name demo.johnwu.cc example.johnwu.cc;
    location / {
        proxy_pass http://portal/;
        include /etc/nginx/conf.d/default_proxy_settings;
    }
}

# 用 HTTPS 必須要有 SSL 憑證,如果沒有要綁定 SSL 可以把下面整段移除
server {
    # 只要是透過這些 Domain 連 HTTPS 443 Port,都會轉送封包到 ASP.NET Core
    listen 443 ssl;
    server_name demo.johnwu.cc;
    ssl_certificate /etc/nginx/ssl/demo.johnwu.cc_bundle.crt;
    ssl_certificate_key /etc/nginx/ssl/demo.johnwu.cc.key;

    location / {
        proxy_pass http://portal/;
        include /etc/nginx/conf.d/default_proxy_settings;
    }
}


Nginx 重新啟動:
# 檢查 Nginx 的設定是否有誤
nginx -t

# 若沒有錯誤,即可套用
nginx -s reload
More...
Bike, 2020/7/7 上午 08:01:43
在 MySQL 建立 Cache 用的 Trigger
use clinic;

INSERT INTO change_notification(`table_name`) VALUES('sys_config');

drop trigger if exists au_sys_config;
drop trigger if exists ai_sys_config;
drop trigger if exists ad_sys_config;

delimiter |

CREATE TRIGGER au_sys_config after UPDATE ON `sys_config`
FOR EACH ROW
BEGIN
DECLARE v_row_count int DEFAULT row_count();
IF v_row_count!=1 THEN
update change_notification set change_count = change_count + 1, update_date = now() where table_name = 'sys_config';
END IF;
END;
|

CREATE TRIGGER ai_sys_config after INSERT ON `sys_config`
FOR EACH ROW
BEGIN
DECLARE v_row_count int DEFAULT row_count();
IF v_row_count!=1 THEN
update change_notification set change_count = change_count + 1, update_date = now() where table_name = 'sys_config';
END IF;
END;
|

CREATE TRIGGER ad_sys_config after Delete ON `sys_config`
FOR EACH ROW
BEGIN
DECLARE v_row_count int DEFAULT row_count();
IF v_row_count!=1 THEN
update change_notification set change_count = change_count + 1, update_date = now() where table_name = 'sys_config';
END IF;
END;
|

delimiter ;
More...
Bike, 2019/11/6 下午 07:17:50
IIS 7.0 ClientIP() 會抓到 IPv6 而非 IPv4
IIS 7.0 之後 
用 HttpContext.Current.Request.UserHostAddress 抓的IP會是 
類似 fe80::b148:cddc:81cd:fd10%2 
這樣的IPv6 位址
如果要抓 IPv4 要特別改寫

參考
https://dotblogs.com.tw/hunterpo/2011/03/21/21991


HttpContext.Current.Request.UserHostAddress


暫時的替代方法
public static string GetClientIPv4() { string ipv4 = String.Empty; foreach (IPAddress ip in Dns.GetHostAddresses(GetClientIP())) { if (ip.AddressFamily.ToString() == "InterNetwork") { ipv4 = ip.ToString(); break; } } if (ipv4 != String.Empty) { return ipv4; } // 原作使用 Dns.GetHostName 方法取回的是 Server 端資訊,非 Client 端。 // 改寫為利用 Dns.GetHostEntry 方法,由獲取的 IPv6 位址反查 DNS 紀錄, // 再逐一判斷何者屬 IPv4 協定,即可轉為 IPv4 位址。 foreach (IPAddress ip in Dns.GetHostEntry(GetClientIP()).AddressList) //foreach (IPAddress ip in Dns.GetHostAddresses(Dns.GetHostName())) { if (ip.AddressFamily.ToString() == "InterNetwork") { ipv4 = ip.ToString(); break; } } return ipv4; } /// <summary> /// 取得客戶端主機位址 /// </summary> public static string GetClientIP() { if (null == HttpContext.Current.Request.ServerVariables["HTTP_VIA"]) { return HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"]; } else { return HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"]; } }
More...
sean, 2019/6/27 下午 06:47:31
SQL需要定期索引重建或重組
今天發生一個SQL奇怪的現象,記錄一下
就是訂單列表(使用分頁的SQL 找出 top 20)跑很久才出來,大約10多秒 
SQL指令條件僅有訂單日期(預設是1年內訂單,訂單總數有130萬筆),而訂單日期也有做index
之前都大約1~2秒就出來,這一兩天卻要10秒才跑出來

用執行計畫評估功能查也看不出哪裡有問題,把一些子查詢拿掉也沒有改善
所以就改一下搜尋條件,改搜尋半年內訂單,大約 5秒
改搜尋兩年內訂單,1秒!!! 真是神奇,把條件區間拉大反而很快???????
直覺上覺得索引table是不是太大太亂了,剛好看到CreateDate索引有個重建按鈕
就勇敢把他按下去,想說會不會跑很久,結果重建只要不到1秒就好了
然後神奇的事發生了,訂單列表不須一秒就顯示出來啦!

SQL 指令大概長這樣
Select * from (
Select Top 20 * from (
select Top 20 a.*
--, CompelteOrderId= (select top 1 K.Id from packing_list_main k With(NoLock) join Order_Main p With(NoLock) on k.Order_Id=p.Id where k.En_Packing_List_Status=300 and P.MEmber_Id=a.Member_Id )
--, [MemoCount_前台問題] = (Select COUNT(*) from Order_Memo With(NoLock) where Order_Memo.Order_Id = a.Id and Memo_Type = 1)
--, [MemoCount_業務備註] = (Select COUNT(*) from Order_Memo With(NoLock) where Order_Memo.Order_Id = a.Id and Memo_Type = 3)
--, [MemoCount_系統檢查] = (Select COUNT(*) from Order_Memo With(NoLock) where Order_Memo.Order_Id = a.Id and Memo_Type = 4)
--, QnACount = (select count(*) from Order_QnA With(NoLock) where Order_Id = a.Id)
from V_Order_Main_For_Admin_List a With(NoLock) left join Member b with(NoLock) on a.Member_Id=b.Id where (1=1) and En_Order_Status <> -300 and a.Create_Date >='2018-06-20' order by Id Desc
) AS T1 order by Id
) AS T2 order by Id Desc


參考 will will web 的舊文章,原來定期把索引整理整理,也是要記得做的。
不過週期上我想 1季或半年跑一次應該就可以了
-------------------------------------------------------------------
後記: 2020/6/22 -  一年後又發生一樣的狀況,真是神奇
這次 OrderMain CreateDate 沒有很分散。只有 2.X %
想說其他 index 是不是該重建,但是都沒有效果
最後只好重建 CreateDate --> 結果居然解決了

看 2021年會在發生嗎?

 
More...
darren, 2019/6/21 上午 12:05:00
複製 SQL 帳號權限的語法
如下, 要記得修改 database_name, userOLD, userNEW 三個參數

CREATE TABLE #Command
    (
    Id int NOT NULL IDENTITY (1, 1),
    command nvarchar(MAX) NOT NULL
    )  ON [PRIMARY]
     TEXTIMAGE_ON [PRIMARY]
GO

USE database_name  -- Use the database from which you want to extract the permissions
GO

SET NOCOUNT ON

DECLARE @OldUser sysname, @NewUser sysname

SET @OldUser = 'userOLD' --The user or role from which to copy the permissions from
SET @NewUser = 'userNEW' --The user or role to which to copy the permissions to

insert into #Command(command)
Select convert(nvarchar(max), '--Database Context')

insert into #Command(command)
SELECT 'USE' + SPACE(1) + QUOTENAME(DB_NAME())

insert into #Command(command)
SELECT '--Cloning permissions from' + SPACE(1) + QUOTENAME(@OldUser) + SPACE(1) + 'to' + SPACE(1) + QUOTENAME(@NewUser)

insert into #Command(command)
SELECT 'EXEC sp_addrolemember @rolename ='
    + SPACE(1) + QUOTENAME(USER_NAME(rm.role_principal_id), '''') + ', @membername =' + SPACE(1) + QUOTENAME(@NewUser, '''') AS '--Role Memberships'
FROM    sys.database_role_members AS rm
WHERE USER_NAME(rm.member_principal_id) = @OldUser
ORDER BY rm.role_principal_id ASC

insert into #Command(command)
SELECT CASE WHEN perm.state <> 'W' THEN perm.state_desc ELSE 'GRANT' END
    + SPACE(1) + perm.permission_name + SPACE(1) + 'ON ' + QUOTENAME(USER_NAME(obj.schema_id)) + '.' + QUOTENAME(obj.name)
    + CASE WHEN cl.column_id IS NULL THEN SPACE(0) ELSE '(' + QUOTENAME(cl.name) + ')' END
    + SPACE(1) + 'TO' + SPACE(1) + QUOTENAME(@NewUser) COLLATE database_default
    + CASE WHEN perm.state <> 'W' THEN SPACE(0) ELSE SPACE(1) + 'WITH GRANT OPTION' END AS '--Object Level Permissions'
FROM    sys.database_permissions AS perm
    INNER JOIN
    sys.objects AS obj
    ON perm.major_id = obj.[object_id]
    INNER JOIN
    sys.database_principals AS usr
    ON perm.grantee_principal_id = usr.principal_id
    LEFT JOIN
    sys.columns AS cl
    ON cl.column_id = perm.minor_id AND cl.[object_id] = perm.major_id
WHERE usr.name = @OldUser
ORDER BY perm.permission_name ASC, perm.state_desc ASC

insert into #Command(command)
SELECT CASE WHEN perm.state <> 'W' THEN perm.state_desc ELSE 'GRANT' END
    + SPACE(1) + perm.permission_name + SPACE(1)
    + SPACE(1) + 'TO' + SPACE(1) + QUOTENAME(@NewUser) COLLATE database_default
    + CASE WHEN perm.state <> 'W' THEN SPACE(0) ELSE SPACE(1) + 'WITH GRANT OPTION' END AS '--Database Level Permissions'
FROM    sys.database_permissions AS perm
    INNER JOIN
    sys.database_principals AS usr
    ON perm.grantee_principal_id = usr.principal_id
WHERE usr.name = @OldUser
AND perm.major_id = 0
ORDER BY perm.permission_name ASC, perm.state_desc ASC

Select command from #Command order by Id
drop table #Command
More...
Bike, 2019/6/5 下午 08:42:56
|< 123456789 >|
頁數 3 / 9 上一頁 下一頁
~ Uwinfo ~