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 (20)
  • 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)
最新回應
  • 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
標籤
  • 夢想家
  • yh3IqUv4
  • ti
  • 978
  • 許蓋功問題
  • TCP
  • iis7
  • 驗證
  • pg21211211
  • FB0
  • Findindex
  • 死結
  • 4hew.com
  • 68
  • 1
  • 0
  • boeOMZUV
  • 編碼錯誤
  • -3679
  • SVG
  • gDcfE3Zp
  • line
  • bitmap
  • js UNION A
  • end
  • 黑貓
  • 3482121121
  • cA2yeXPF
  • 175
  • 1137
  • Su
  • 346
  • ltrbr4xk
  • NxFRfXz6
  • 效能
  • 548
  • 34
  • line ORDER
  • request.qu
  • Contains,
  • -1290
  • 0KeeTeam
  • -5672
  • 5151
  • Rf
  • win
  • 594
  • en
  • replace
  • ad
頁數 1 / 8 下一頁
搜尋 blog 結果:
postgreSql 大型 table 跑 Count 非常慢
可參考本文章:

https://dba.stackexchange.com/questions/245990/postgresql-extremely-slow-count-with-index-simple-query

vacuum analyze insider_event;
執行了 7 分鐘

ALTER TABLE insider_event SET (autovacuum_vacuum_scale_factor = 0, autovacuum_analyze_scale_factor = 0,  autovacuum_vacuum_threshold = 10000, autovacuum_analyze_threshold = 10000);

跑了 1.2 分鐘

修改 work_mem:
https://www.pgmustard.com/blog/work-mem

記憶體調整
https://www.enterprisedb.com/postgres-tutorials/how-tune-postgresql-memory
More...
Bike, 2024/2/5 上午 06:55:40
使用Parallel來平行處理迭代!!!
發現了一個很新奇的東西 Parallel
他可以做到平行處理迭代這件事
只要迴圈邏輯上不需要有先後順序的情況就可以使用來大幅度提高效能!


輸出值


需要特別注意如果於非同步中使用lock應使用SemaphoreSlim
如果要使用Dictionay應使用ConcurrentDictionary
More...
梨子, 2023/4/11 下午 12:49:47
使用SemaphoreSlim來對非同步情況下使用Lock
由於在使用Await時,系統的Thread並不保證會與該function使用同一個Thread。
因此使用lock將單一Thread鎖住會導致出現 'Cannot await in the body of a lock statement'的錯誤

將Lock物件改成使用SemaphoreSlim,於function起始與結束加入WaitAsync與Release即可達到Lock的效果。

SemaphoreSlim完整介紹 : 用 SemaphoreSlim 來做 async/await 的鎖定
使用如下圖↓

 
 
More...
梨子, 2023/3/23 下午 03:00:41
dotnet ef dbcontext scaffold
錯誤訊息:
dotnet : 因為找不到指定的命令或檔案,所以無法執行。
位於 線路:1 字元:1
+ dotnet ef dbcontext scaffold "Host=xxxxxxxxxxxxx;CommandTimeout=500 ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (因為找不到指定的命令或檔案,所以無法執行。:String) [], RemoteException
    + FullyQualifiedErrorId : NativeCommandError
 
可能的原因包括:
  * 內建 dotnet 命令拼寫錯誤。
  * 您預計要執行 .NET 程式,但不存在 dotnet-ef。
  * 您預計要執行全域工具,但在 PATH 上找不到此名稱且開頭為 dotnet 的可執行檔。
 
解決方法:
重新安裝套件,安裝指令:dotnet tool install --global dotnet-ef


 

參考:
dotnet ef 找不到指定的命令
 
More...
Reiko, 2023/2/13 下午 04:36:03
VS 2022 套件管理器主控台 亂碼
Console主控台的輸出,只要是非英文,都會是亂碼呈現



情況:
 
解決方法:
輸入:[Console]::OutputEncoding = [System.Text.Encoding]::UTF8



 
 
參考:
一次解決CONSOLE主控台輸出中文亂碼的編碼問題
【茶包射手日記】PowerShell 串接 EXE 輸出中文變亂碼
More...
Reiko, 2023/2/13 下午 04:25:51
Maui With SQLite
試了這兩個 Sample:

https://learn.microsoft.com/en-us/training/modules/store-local-data/4-exercise-store-data-locally-with-sqlite

和 

https://blazorhelpwebsite.com/ViewBlogPost/61

結果專案在 Windows 環境下都可以正常執行,但切換到 Android Emulator 就無法存檔。

在查了很多資料後,發現需要裝額外的 Package,需安裝的 Package 如下:

    <ItemGroup>
     <PackageReference Include="sqlite-net-pcl" Version="1.8.116" />
     <PackageReference Include="SQLiteNetExtensions.Async" Version="2.1.0" />
     <PackageReference Include="SQLitePCLRaw.bundle_green" Version="2.1.4" />
     <PackageReference Include="SQLitePCLRaw.core" Version="2.1.4" />
     <PackageReference Include="SQLitePCLRaw.lib.e_sqlite3" Version="2.1.4" />
     <PackageReference Include="SQLitePCLRaw.provider.dynamic_cdecl" Version="2.1.4" />
     <PackageReference Include="System.Data.DataSetExtensions" Version="4.5.0" />
    </ItemGroup>



其它的發現為:
1. 雙點專案,就可以開啟 csproj 檔案。下方的 ItemGroup 就是已安裝的 package

2. 可以把 chrome 連接到 Android Emulator 的方法,在網址列輸入以下指令:
chrome://inspect/#devices
More...
Bike, 2023/2/12 下午 05:09:11
VS 建立虛擬目錄導致HttpHandler重複錯誤
 
於VS Web中建立虛擬目錄,導致Swagger Handler出現重複錯誤
主要原因是因為跟網站與子網站指向同一個資料夾,而父子網站的web.config有繼承關係導致。

解決方式:
1. 前往 根目錄 / .vs / 專案 / config / applicationhost.config

2. 將site中設定的子網站移除或變更虛擬目錄位置

 
3. 回到網頁重新整理就完成囉!

參考: 【茶包射手日記】怪異的web.config HttpHandler重複錯誤
More...
梨子, 2022/7/1 上午 11:57:02
使用Lucene.Net達成全文檢索!基礎解說(二)
上一集當中我們完成了Lucene基本操作中的Create與Read,這一集會將CRUD中的Update與Delete的操作方法告訴你,並且本集會著重於講解關於"Norms"與權重(Boost)在Lucene中的運作概念。

首先我們建立一個.Net 6的主控台應用程式
   

建立好後於右側專案右鍵選擇"管理Nuget套件",並選擇"瀏覽">於搜索列中搜尋"Lucene">安裝3.0.3最新穩定版 與 "System.Configuration.ConfigurationManager"

 
 安裝好後就可以於專案內使用Lucene套件囉!
再來依照上一篇的教學建立一套簡單的Lucene查詢

using Lucene.Net.Analysis.Standard;
using Lucene.Net.Documents;
using Lucene.Net.Index;
using Lucene.Net.QueryParsers;
using Lucene.Net.Search;
using Lucene.Net.Store;

var _dir = new DirectoryInfo("LuceneDocument");
if (!File.Exists(_dir.FullName))
{
    System.IO.Directory.CreateDirectory(_dir.FullName);
}
var analyzer = new StandardAnalyzer(Lucene.Net.Util.Version.LUCENE_CURRENT);
CreateIndex(GetProductsInformation(), _dir, analyzer);

while (true)
{
    Console.Write("請輸入欲查詢字串 :");
    var searchValue = Console.ReadLine();
    Search(searchValue, _dir, analyzer);
}

void CreateIndex(List<Product> information, DirectoryInfo dir, StandardAnalyzer analyzer)
{
    using (var directory = FSDirectory.Open(dir))
    {
        using (var indexWriter = new IndexWriter(directory, analyzer, true, IndexWriter.MaxFieldLength.LIMITED))
        {
            foreach (var index in information)
            {
                var document = new Document();
                document.Add(new Field("Id", index.Id.ToString(), Field.Store.YES, Field.Index.NO));
                document.Add(new Field("Name", index.Name, Field.Store.YES, Field.Index.ANALYZED));
                document.Add(new Field("Description", index.Description, Field.Store.YES, Field.Index.ANALYZED));
                indexWriter.AddDocument(document);
            }
            indexWriter.Optimize();
            indexWriter.Commit();
        }
    }
}
void Search(string searchValue, DirectoryInfo dir, StandardAnalyzer analyzer)
{
    using (var directory = FSDirectory.Open(_dir))
    {
        var parser = new QueryParser(Lucene.Net.Util.Version.LUCENE_CURRENT, "Description", analyzer).Parse(searchValue);
        using (var indexSearcher = new IndexSearcher(directory))
        {
            var queryLimit = 20;
            var hits = indexSearcher.Search(parser, queryLimit);
            if (!hits.ScoreDocs.Any())
            {
                Console.WriteLine("查無相關結果。");
                return;
            }
            Document doc;
            foreach (var hit in hits.ScoreDocs)
            {
                doc = indexSearcher.Doc(hit.Doc);
                Console.WriteLine("Score :" + hit.Score + ", Id :" + doc.Get("Id") + ", Name :" + doc.Get("Name") + ", Description :" + doc.Get("Description"));
            }
        }
    }
}

List<Product> GetProductsInformation()
{
    return new List<Product> {
            new Product{ Id = 1, Name = "蘋果", Description = "一天一蘋果,醫生遠離我。"},
            new Product{ Id = 2, Name = "橘子", Description = "醫生給娜美最珍貴的寶藏。"},
            new Product{ Id = 3, Name = "梨子", Description = "我是梨子,比蘋果好吃多囉!"},
            new Product{ Id = 4, Name = "葡萄", Description = "吃葡萄不吐葡萄皮,不吃葡萄倒吐葡萄皮"},
            new Product{ Id = 5, Name = "榴槤", Description = "水果界的珍寶!好吃一直吃。"}
        };
}
class Product
{
    public long Id { get; set; }
    public string Name { get; set; } = null!;
    public string Description { get; set; } = null!;
}


好囉! 接下來我們要如何更新索引呢?
更新其實就是將存在的索引刪除並重新建立Document,不存在的則直接新增。
首先準備一組資料準備更新

List<Product> GetUpdateProductsInformation()
{
    return new List<Product>
    {
        new Product{ Id = 6, Name = "香蕉", Description = "運動完後吃根香蕉補充養分。"},
        new Product{ Id = 2, Name = "橘子", Description = "橘子跟柳丁你分得出來嗎?"}
    };
}


*欲更新的Document必須與創建所引時使用的Document欄位相同*

void Update(string key, List<Product> information, DirectoryInfo dir, StandardAnalyzer analyzer)
{
    using( var directory = FSDirectory.Open(dir))
    {
        using(var indexWriter = new IndexWriter(directory, analyzer, false, IndexWriter.MaxFieldLength.LIMITED))
        {
            foreach (var index in information)
            {
                var document = new Document();
                document.Add(new Field("Id", index.Id.ToString(), Field.Store.YES, Field.Index.NO));
                document.Add(new Field("Name", index.Name, Field.Store.YES, Field.Index.ANALYZED));
                document.Add(new Field("Description", index.Description, Field.Store.YES, Field.Index.ANALYZED));
                indexWriter.UpdateDocument(new Term("Name", key) ,document);
            }
        }
    }
}


來測試看看
   
可以看見 Name = 橘子 的索引已經改為我們新準備的資料囉。
再來是刪除!
與更新非常相似,只需要使用deleteDocument()就可以了。

void Delete(string key, DirectoryInfo dir, StandardAnalyzer analyzer)
{
    using (var directory = FSDirectory.Open(dir))
    {
        using (var indexWriter = new IndexWriter(directory, analyzer, false, IndexWriter.MaxFieldLength.LIMITED))
        {
            indexWriter.DeleteDocuments(new Term("Name", key));
            indexWriter.Optimize();
            indexWriter.Commit();
        }
    }
}


再來看看輸出結果
 可以發現 Score :0.7554128, Id :2, Name :橘子, Description :醫生給娜美最珍貴的寶藏。這筆索引已經被移除囉!
  
可以發現筆者於更新或刪除時都是輸入單一字來做異動,除了表達可以對索引做複合更動外,
是因為更新與刪除索引同樣會使用到分詞器(analyzer),
*所輸入的索引值非ID等數值時必須要配合分詞器的分詞能力*才能取得所想異動的索引喔!


Boost是什麼呢?
Boost 分為 :
1. Index Time Boost : 在建立索引時就計算好的值。例如上一篇中提到的(NORMS)
2. Query Time Boost : 查詢時賦與搜尋條件不同的值以影響結果。
我們先來測試Index Time Boost的部分
void CreateIndexWithBoost(List<Product> information, DirectoryInfo dir, StandardAnalyzer analyzer)
{
    using (var directory = FSDirectory.Open(dir))
    {
        using (var indexWriter = new IndexWriter(directory, analyzer, true, IndexWriter.MaxFieldLength.LIMITED))
        {
            foreach (var index in information)
            {
                var document = new Document();
                document.Add(new Field("Id", index.Id.ToString(), Field.Store.YES, Field.Index.NO));
                document.Add(new Field("Name", index.Name, Field.Store.YES, Field.Index.ANALYZED));
                document.Add(new Field("Description", index.Description, Field.Store.YES, Field.Index.ANALYZED));
                document.GetField("Name").Boost = 1.5F;
                document.GetField("Description").Boost = 0.5F;

                indexWriter.AddDocument(document);
            }
            indexWriter.Optimize();
            indexWriter.Commit();
        }
    }
}


並記得重新CreateIndex才能刷新欄位的權重值喔。


很明顯的搜尋出來的Score分數變動了! 但是有沒有發現明明Name欄位的Boost改成了1.5,蘋果的數值卻仍然只有一半呢?
這是因為我們的Search中所參照的欄位為Description,所以在計算Score的時候其實是完全沒有參與的喔!
另外要記得,使用Index Time Boost的時候,欲給予銓重分配的欄位Field.Index不能使用NO_NORMS,不然這個欄位並不會紀錄權重的資料。

再來我們試試看Query Time Boost
void SearchWithBoost(string searchValue, DirectoryInfo dir, StandardAnalyzer analyzer)
{
    using (var directory = FSDirectory.Open(_dir))
    {
        using (var indexSearcher = new IndexSearcher(directory))
        {
            var query = new QueryParser(Lucene.Net.Util.Version.LUCENE_CURRENT, "Name", analyzer).Parse(searchValue);
            var query2 = new QueryParser(Lucene.Net.Util.Version.LUCENE_CURRENT, "Description", analyzer).Parse(searchValue);

            query.Boost = 2.0F;
            query2.Boost = 0.5F;

            BooleanQuery booleanQuery = new BooleanQuery();
            booleanQuery.Add(query, Occur.SHOULD);
            booleanQuery.Add(query2, Occur.SHOULD);

            var hits = indexSearcher.Search(booleanQuery, 20);
            if (!hits.ScoreDocs.Any())
            {
                Console.WriteLine("查無相關結果。");
                return;
            }
            Document doc;
            foreach (var hit in hits.ScoreDocs)
            {
                doc = indexSearcher.Doc(hit.Doc);
                Console.WriteLine("Score :" + hit.Score + ", Id :" + doc.Get("Id") + ", Name :" + doc.Get("Name") + ", Description :" + doc.Get("Description"));
            }
        }
    }
}


這次我們搜尋兩個欄位"Name"與"Description",並使用 BooleanQuery來將其組合。
BooleanQuery中的 Occur有三種參數 : "MUST","MUST_NOT","SHOULD",功能與字面上的意思一樣為"必須要有","必須沒有"與"有無都包含"。

 
查詢出來的分數就不一樣囉!

以上就是這一次的分享,Lucene是一款容易入門但是要實際上戰場卻又十分複雜的功能,想要達成真正高效能的全文檢索,在前期的文件規畫配置與資料的權重配比都是一個巨大的挑戰。未來會繼續分享關於Lucene的其他有趣功能,還請繼續期待呦!
另外也可以到GitHub下載我的範例來參考呦!
GitHub: https://github.com/g13579112000/Lucene

參考文件:
1. 黑暗大大的全文檢索筆記 : https://blog.darkthread.net/blog/lucene-net-notes-1/
2. Makble : http://makble.com/lucene-field-boost-example
3. CSDN Jack2013tong 文章 : https://blog.csdn.net/huwei2003/article/details/53408388
More...
梨子, 2022/4/20 下午 09:34:03
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
IIS 配合 AD (Active Directory) 認証, 使用 .Net 6.0
環境說明:

AD Server: dc1 (192.168.101.109)
PC: pc110 (192.168.101.110)
PC: pc111 (192.168.101.111)

第一步,把 PC 加入 AD, 這個算是基本操作,網路上說明很多, 就不再截圖了。不過在這裡還是遇到了第一個問題,解決過程請參考另一份文件: https://blog.uwinfo.com.tw/Article.aspx?Id=486

第二步,在 Visual Studio 的測試環境中測試:
一開始是使用 .Net 6.0 來實作,沒想到找到的文件都是 .Net Core 3.1 的,所以先用 .Net Core 3.1 實做了一次,後來改用 .Net 6.0 實作才成功。使用 .Net 6.0 實作的過程如下:

1. 建立一個 MVC 的標準專案: 
 
為了避免憑証問題,所以拿掉了 HTTPS 的設定


2. 改寫 launchSettings.json:
iisSettings 中的 windowsAuthentication 改為 True, anonymousAuthentication 改為 false。如下圖:
 
3. 修改 Program.cs, 加入以下四行指令:
builder.Services.AddAuthentication(IISDefaults.AuthenticationScheme);
builder.Services.AddAuthorization();
app.UseAuthentication();
app.UseAuthorization();
(注意: UseAuthentication 要加在 UseAuthentication 之後, VS 2022 應該會提示要新增 using Microsoft.AspNetCore.Server.IISIntegration;)
 
4. 在 HomeController 增加一個 Action, 以讀取驗証資料:

        [Route("GetAuthenticatedUser")]
        [HttpGet("[action]")]
        public IdentityUser GetUser()
        {
            return new IdentityUser()
            {
                Username = User.Identity?.Name,
                IsAuthenticated = User.Identity != null ? User.Identity.IsAuthenticated : false,
                AuthenticationType = User.Identity?.AuthenticationType
            };
        }

        public class IdentityUser
        {
            public string Username { get; set; }
            public bool IsAuthenticated { get; set; }
            public string AuthenticationType { get; set; }
        }
 
5. 啟動時記得要改用 IIS Express (感覺早上花了兩三個小時在為了這個問題打轉):


6. 執行結果:

第三步,在 IIS 中安裝網站:
1. 在安裝 IIS 時,記得要勾選 windows 驗證


2. 安裝 .Net 6.0 的 Hosting Bundle
https://dotnet.microsoft.com/en-us/download/dotnet/6.0
 
3. 新增網站:
主機名稱留空白 (AD 驗証在網域內好像不會使用指定的主機名稱,這個有待後續再做確認)


如果沒有刪除預設網站,會遇到警告,直接確認即可.


要把 Default Web Site 關閉,再啟動測試站
 
要啟動 windows 驗証: 
在 web.config 中增加 
      <security>
        <authentication>
          <anonymousAuthentication enabled="false" />
          <windowsAuthentication enabled="true" />
        </authentication>
      </security>



修改 applicationHost.config:

檔案位置: %windir%\system32\inetsrv\config\applicationHost.config
這兩地方的 Deny 改為 Allow
<section name="anonymousAuthentication" overrideModeDefault="Deny" />
<section name="windowsAuthentication" overrideModeDefault="Deny" />

 
參考文件: https://docs.microsoft.com/zh-tw/iis/get-started/planning-for-security/how-to-use-locking-in-iis-configuration

3. 可以取得登入資訊如下:

4. 從 Domain 中另一台主機來存取,不用登入,自動取得目前登入者的資訊。
 
5. 從非網域主機連線: 會要求認証
 

目前遇到問題: 在網域中的電腦只能用主機名稱登入,非網域的電腦,才能夠使用網址登入。

測試專案下載: https://github.com/bikehsu/AD60
 
More...
Bike, 2022/3/19 下午 09:10:08
|< 12345678 >|
頁數 1 / 8 下一頁
~ Uwinfo ~