3

单线程版本说明:

  1. 程序收集问题列表。
  2. 对于每个问题,获取模型答案,并通过评分模块运行每个问题。

  • 评分模块进行许多(只读)数据库查询。
  • 串行处理,单数据库连接。

我决定通过将问题列表分成块并为每个块创建一个线程来对上述程序进行多线程处理。

每个线程打开它自己的数据库连接并处理它自己的问题列表(6 个线程中的每个线程大约有 95 个问题)。应用程序等待所有线程完成,然后聚合结果以供显示。

令我惊讶的是,多线程版本的运行时间几乎相同,大约需要 16 秒而不是 17 秒。

问题:

为什么我没有看到在具有单独连接的单独线程上同时执行查询所期望的性能提升?机器有 8 个处理器。

当查询来自单个应用程序时,SQL Server 是否会同时处理查询,或者它(或 .net 本身)是否会序列化它们?

可能有一些错误配置,这会使它运行得更快,或者我可能只是将 SQL Server 推到了它的计算极限?

当前配置:

Microsoft SQL Server Developer Edition 9.0.1406 RTM
操作系统:Windows Server 2003 标准
处理器:8
RAM:4GB

4

6 回答 6

3

这只是在黑暗中的一个镜头,但我敢打赌你没有看到性能提升,因为它们由于共享资源(记录)的锁定而在数据库中序列化自己。现在是小字。

我假设您的 C# 代码实际上是正确的,并且您实际上确实启动了单独的线程并并行发出每个查询。无意冒犯,但我看到很多人提出这种说法,并且由于各种原因,代码实际上在客户端中是串行的。您应该通过监视服务器来验证这一点(通过 Profiler,或使用 sys.dm_exec_requests 和 sys.dm_exec_sessions)。

我还假设您的查询具有相似的权重。即,您没有一个持续 15 秒的线程和 5 个持续 100 毫秒的线程。

您所描述的症状缺乏更多详细信息,表明您在每个线程的开头都有一个写操作,该操作对某些资源进行了 X 锁定。第一个线程启动并锁定资源,其他 5 个等待。第一个线程完成,释放资源,然后下一个线程抓取它,其他 4 个等待。所以最后一个线程必须等待所有其他 5 个线程的执行。通过查看sys.dm_exec_requests并监控阻塞请求的内容,这将非常容易解决。

顺便说一句,您应该考虑使用 Asynchronous Processing=true 并依靠 BeginExecuteReader 之类的异步方法来并行执行命令,而不会产生客户端线程的开销。

于 2009-05-21T22:14:03.333 回答
1

You can simply check the task manager when the process is running. If it's showing 100% CPU usage then its CPU bound. Otherwise its IO Bound.

For hyperthreading 50% CPU usage is roughly equal to 100% usage!

Wow I didn't realize how old the thread was. I guess its always good to leave the response for others looking.

于 2009-11-13T22:02:25.957 回答
0

is it possible that the the threads share a connection? did you verify that multiple SPIDs are created when this runs (sp_who)?

于 2009-05-21T21:10:23.103 回答
0

你的数据库有多大?您的 HDD / Raid / 其他存储的速度有多快

也许您的数据库受 I/O 限制?

于 2009-05-21T21:00:21.360 回答
0

我的第一个倾向是您正在尝试使用线程解决 IO 问题,这几乎永远不会奏效。IO就是IO,多线程不增加管道。您最好一次性下载所有问题及其答案,并使用多个线程在本地处理该批次。

话虽如此,您可能正在经历一些导致缓慢的数据库锁定。由于您在谈论只读查询,请尝试在查询中使用 with (nolock) 提示,看看是否有帮助。

关于 SQL Server 处理,据我了解,SQL Server 将尝试同时处理尽可能多的连接(每个连接一次一条语句),直至配置允许的最大连接数。您看到的那种 if 问题几乎从来都不是线程问题,而且几乎总是锁定或 IO 问题。

于 2009-05-21T21:04:10.683 回答
0

我在 task_address 上跨 sys.dm_os_workers、sys.dm_os_tasks 和 sys.dm_exec_requests 运行了一个连接查询,结果如下(排除了一些无趣/零值字段,其他前缀为 ex 或 os 以解决歧义):

-COL_NAME-  -Thread_1-  -Thread_2-  -Thread_3-  -Thread_4-

task_state  SUSPENDED   SUSPENDED   SUSPENDED   SUSPENDED
context_switches_count  2   2   2   2
worker_address  0x3F87A0E8  0x5993E0E8  0x496C00E8  0x366FA0E8
is_in_polling_io_completion_routine 0   0   0   0
pending_io_count    0   0   0   0
pending_io_byte_count   0   0   0   0
pending_io_byte_average 0   0   0   0
wait_started_ms_ticks   1926478171  1926478187  1926478171  1926478187
wait_resumed_ms_ticks   1926478171  1926478187  1926478171  1926478187
task_bound_ms_ticks 1926478171  1926478171  1926478156  1926478171
worker_created_ms_ticks 1926137937  1923739218  1921736640  1926137890
locale  1033    1033    1033    1033
affinity    1   4   8   32
state   SUSPENDED   SUSPENDED   SUSPENDED   SUSPENDED
start_quantum   3074730327955210    3074730349757920    3074730321989030    3074730355017750
end_quantum 3074730334339210    3074730356141920    3074730328373030    3074730361401750
quantum_used    6725    11177   11336   6284
max_quantum 4   15  5   20
boost_count 999 999 999 999
tasks_processed_count   765 1939    1424    314
os.task_address 0x006E8A78  0x00AF12E8  0x00B84C58  0x00D2CB68
memory_object_address   0x3F87A040  0x5993E040  0x496C0040  0x366FA040
thread_address  0x7FF08E38  0x7FF8CE38  0x7FF0FE38  0x7FF92E38
signal_worker_address   0x4D7DC0E8  0x571360E8  0x2F8560E8  0x4A9B40E8
scheduler_address   0x006EC040  0x00AF4040  0x00B88040  0x00E40040
os.request_id   0   0   0   0
start_time  2009-05-26 19:39    39:43.2 39:43.2 39:43.2
ex.status   suspended   suspended   suspended   suspended
command SELECT  SELECT  SELECT  SELECT
sql_handle  0x020000009355F1004BDC90A51664F9174D245A966E276C61  0x020000009355F1004D8095D234D39F77117E1BBBF8108B26  0x020000009355F100FC902C84A97133874FBE4CA6614C80E5  0x020000009355F100FC902C84A97133874FBE4CA6614C80E5
statement_start_offset  94  94  94  94
statement_end_offset    -1  -1  -1  -1
plan_handle 0x060007009355F100B821C414000000000000000000000000  0x060007009355F100B8811331000000000000000000000000  0x060007009355F100B801B259000000000000000000000000  0x060007009355F100B801B259000000000000000000000000
database_id 7   7   7   7
user_id 1   1   1   1
connection_id   BABF5455-409B-4F4C-9BA5-B53B35B11062    A2BBCACF-D227-466A-AB08-6EBB56F34FF2    D330EDFE-D49B-4148-B7C5-8D26FE276D30    649F0EC5-CB97-4B37-8D4E-85761847B403
blocking_session_id 0   0   0   0
wait_type   CXPACKET    CXPACKET    CXPACKET    CXPACKET
wait_time   46  31  46  31
ex.last_wait_type   CXPACKET    CXPACKET    CXPACKET    CXPACKET
wait_resource               
open_transaction_count  0   0   0   0
open_resultset_count    1   1   1   1
transaction_id  3052202 3052211 3052196 3052216
context_info    0x  0x  0x  0x
percent_complete    0   0   0   0
estimated_completion_time   0   0   0   0
cpu_time    0   0   0   0
total_elapsed_time  54  41  65  39
reads   0   0   0   0
writes  0   0   0   0
logical_reads   78745   123090  78672   111966
text_size   2147483647  2147483647  2147483647  2147483647
arithabort  0   0   0   0
transaction_isolation_level 2   2   2   2
lock_timeout    -1  -1  -1  -1
deadlock_priority   0   0   0   0
row_count   6   0   1   1
prev_error  0   0   0   0
nest_level  2   2   2   2
granted_query_memory    512 512 512 512

所有查询的查询计划预测器显示几个节点,0% 用于选择,100% 用于聚集索引查找。

编辑:我遗漏的字段和值(对于所有 4 个线程都相同,除了 context_switch_count):exec_context_id(0), host_address(0x00000000), status(0), is_preemptive(0), is_fiber(0), is_sick(0), is_in_cc_exception(0), is_fatal_exception(0), is_inside_catch(0), context_switch_count(3-89078), exception_num(0), exception_Severity(0), exception_address(0x00000000), return_code(0), fiber_address(NULL), language(us_english), date_format(mdy), date_first(7), quoted_identifier(1), ansi_defaults(0), ansi_warnings(1), ansi_padding(1), ansi_nulls(1), concat_null_yields_null(1), executing_managed_code(0)

于 2009-05-27T12:26:37.393 回答