与性能相关:SQL Server如何处理来自单个.NET桌面应用程序的多个连接的并发查询?

时间:2009-05-21 20:57:49

标签: sql-server performance concurrency database-connection

单线程版本说明:

  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
    内存:4GB

6 个答案:

答案 0 :(得分:3)

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

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

此外,我假设您的查询具有相似的权重。也就是说,你没有一个持续15秒和5个100毫秒的线程。

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

BTW你应该考虑使用Asynchronous Processing = true并依赖于像BeginExecuteReader这样的异步方法,在没有客户端线程开销的情况下并行执行命令。

答案 1 :(得分:0)

您可以在进程运行时查看任务管理器。如果它显示100%的CPU使用率,那么它的CPU绑定。否则它的IO绑定。

对于超线程,50%的CPU使用率大致相当于100%的使用率!

哇我没想到这个帖子多大了。我想将其他人的回应留给他人总是好的。

答案 2 :(得分:0)

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

也许你的数据库是I / O绑定的?

答案 3 :(得分:0)

我的第一个倾向是你试图解决线程的IO问题,这几乎不可行。 IO是IO,更多线程不会增加管道。您最好一次性下载所有问题及其答案,并使用多个线程在本地处理批处理。

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

关于SQL服务器处理,我理解SQL Server将尝试尽可能多地同时处理多个连接(每个连接一次一个语句),直到配置允许的最大连接数。你遇到的问题几乎从来都不是线程问题,几乎总是锁定或IO问题。

答案 4 :(得分:0)

线程是否可能共享连接?你运行时是否验证了多个SPID(sp_who)?

答案 5 :(得分: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)