简体   繁体   English

查询关闭事件 1074 时,使用 Get-WinEvent / Get-EventLog 查询事件日志非常慢

[英]Event Log query with Get-WinEvent / Get-EventLog is very slow when querying shutdown event 1074

I'm writing a PowerShell script that needs to be able to get the query the System Event Log and find events with the Event ID 1074 which indicates a shutdown.我正在编写一个 PowerShell 脚本,该脚本需要能够查询System事件日志并查找事件 ID 为 1074 的事件,该事件指示关闭。

To do this, I was using the following code, however, I've taken notice that when running the code on servers with larger System Event Logs, the command takes many seconds to complete.为此,我使用了以下代码,但是,我注意到在具有较大System事件日志的服务器上运行代码时,该命令需要很多秒才能完成。

Get-WinEvent -LogName 'System' | Where-Object { $_.Id -eq 1074 }

Is there a way to improve the performance of this code?有没有办法提高这段代码的性能?

Get-WinEvent vs Get-EventLog Get-WinEvent 与 Get-EventLog

The first performance boost you can get is using Get-WinEvent over Get-EventLog .您可以获得的第一个性能提升是使用Get-WinEvent不是Get-EventLog That is because Get-WinEvent is replacing Get-EventLog and is supposed to perform better .那是因为Get-WinEvent正在取代Get-EventLog并且应该表现得更好

Correctly filtering the query正确过滤查询

I found a fantastic article by Ed Wilson which goes into great detail how you can improve the performance of a query such as the one I've posted above.我找到了Ed Wilson 的一篇很棒的文章,其中详细介绍了如何提高查询的性能,例如我在上面发布的查询。 I will highlight the performance tweaks I made to greatly improve the performance of my script.我将重点介绍我为大大提高脚本性能所做的性能调整。

  1. Don't use the -LogName parameter, but rather, use the appropriate -ProviderName of the provider that generates the event you're looking for (Ed's blog post goes into detail of how to find this).不要使用-LogName参数,而是使用适当的-ProviderName生成你正在寻找的事件提供者(Ed的博客文章进入的是如何找到这个细节)。 In my case, I needed to use the User32 provider since that's the provider that generates the 1074 event I'm interested in.就我而言,我需要使用User32提供程序,因为这是生成我感兴趣的1074事件的提供程序。
  2. Avoid full traversals of data if at all possible.尽可能避免完全遍历数据。 You'll notice my script had a Where-Object clause.您会注意到我的脚本有一个Where-Object子句。 This clause would iterate over ever event piped into it looking for only the ones that have the 1074 Id.该子句将遍历通过管道输入它的所有事件,仅查找具有1074 Id 的事件。 To avoid this, Get-WinEvent has a -FilterHashtable parameter which can be used to filter your query results within the Get-WinEvent cmdlet, improving efficiency.为了避免这种情况,Get-WinEvent 有一个-FilterHashtable参数,可用于过滤Get-WinEvent cmdlet 中的查询结果,从而提高效率。 As quoted in the Microsoft documentation: "When you work with large event logs, it's not efficient to send objects down the pipeline to a Where-Object command."正如 Microsoft 文档中引用的那样: “当您使用大型事件日志时,将对象沿管道发送到 Where-Object 命令是效率不高的。”

The code编码

I've implemented the aforementioned concepts and timed the improvements for each to show the difference in performance using the Measure-Command cmdlet with the -Expression parameter.我已经实现了上述概念,并对每个改进进行了计时,以使用带有-Expression参数的Measure-Command cmdlet 来显示性能差异。 Note that the machine that I'm testing on has 23,581 events in the System log.请注意,我正在测试的机器的System日志中有 23,581 个事件。

Baseline基线

Measure-Command -Expression {
    Get-WinEvent -LogName 'System' | Where-Object { $_.Id -eq 1074 }
}

# TotalSeconds      : 7.600536

Using ProviderName vs LogName使用ProviderNameLogName

Measure-Command -Expression {
    Get-WinEvent -ProviderName 'User32' | Where-Object { $_.Id -eq 1074 }
}

# TotalSeconds      : 0.1929325

Using FilterHashtable使用FilterHashtable

Measure-Command -Expression {
    Get-WinEvent -FilterHashtable @{ProviderName = "User32"; Id = 1074} 
}

# TotalSeconds      : 0.1578928

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM