并行查询执行
SmartESQL 为通过 SQL 引擎中的线程池实现的序列的并行处理提供支持,这能够优化多处理器环境中序列操作的性能。线程池允许序列函数将序列均等地分配到各个线程中,并在各线程上并行执行计算,从而减少总的执行时间。
线程池大小
线程池的大小可以通过环境变量 MCO_CPU_NUMBER 进行调节。如果未设置 MCO_CPU_NUMBER 环境变量,则系统中 CPU 核心的总数将作为池的大小。如果硬件支持超线程(HT)——大多数现代 CPU 都支持——池中的线程数等于 HT 核心的数量(通常每个物理核心有两个)。因此,如果机器有 4 个实际核心,线程数就是 8。实际上,这有时可能会损害性能。
启用并行处理
xSQL 配置文件选项 sql_use_connection_pool 可以禁用线程池的使用。请注意,此参数的默认值为 true(表示在启动时创建线程池)。
在运行时,可以使用 SQL 函数 seq_parallelism() 来限制用于运行查询的线程数量。该函数接受要使用的线程数作为参数,并返回线程池中的线程总数。例如:
XSQL>select seq_parallelism(4);
#1
------------------------------------------------------------------------------
4
Selected records: 1
请注意,函数 seq_parallelism() 影响整个服务器,而不仅仅是单个客户端会话。因此,不应从同时运行的不同客户端执行 seq_parallelism()。另外请注意,如果 seq_parallelism() 请求的并行线程数超过了环境变量 MCO_CPU_NUMBER 中指定的池大小(默认值为可用核心数),SQL 引擎将使用 MCO_CPU_NUMBER 中指定的数值。
Windows 系统中的线程池管理
在 Windows 系统中,线程池的管理方式可能会给开发人员带来一些挑战。为了支持序列的并行处理,我们使用了 ThreadPool 类,并实例化了一个全局变量 ThreadPool。当应用程序从 main() 函数退出时,ThreadPool 的析构函数会自动调用,释放与线程池相关的所有资源,如内存、同步原语和任务。
然而,在 Windows C++ 运行时环境中,存在一个潜在的问题:当应用程序退出时,C++ 运行时会先停止除主线程之外的所有线程,然后再调用全局对象的析构函数。这意味着,当 ThreadPool 的任务已经被停止时,再调用其析构函数就为时已晚了。
为了解决这个问题,我们在 Windows 系统上采取了一种临时方案,即不调用 ThreadPool 的析构函数。虽然这可以避免部分问题,但在某些情况下,仍可能导致资源泄漏。例如,如果数据库是在 xSQL 服务器(或 .NET Framework 或 JNI 服务器应用程序)上下文中创建的,并且该服务器在运行时动态加载数据库 DLL(如 mcoxsql.dll 或 mcoxsql_debug.dll),而数据库又使用了序列,那么每次重新加载 DLL 都可能引发资源泄漏。
我们正在努力开发更可靠的解决方案,并将在未来的版本中推出。在此期间,Windows 开发人员请注意这一潜在问题,以确保系统的稳定性和性能。