精华内容
下载资源
问答
  • 假设单线程查询SQL耗时1S,那么开启两个线程查询SQL理想情况下也是1S多点才对,机器是4核,但是目前结果近乎2倍显然有异;暂且不考虑从线程池获取连接,任务线程核心代码如下:@Overridepublic void run() {long s =...

    假设单线程查询SQL耗时1S,那么开启两个线程查询SQL理想情况下也是1S多点才对,机器是4核,但是目前结果近乎2倍显然有异;

    暂且不考虑从线程池获取连接,任务线程核心代码如下:

    @Override

    public void run() {

    long s = System.currentTimeMillis();

    System.out.println(Thread.currentThread().getName() + "准备执行");

    try (Connection connection = DBUtils.openConnection();

    PreparedStatement preparedStatement = connection.prepareStatement(querySql);

    ResultSet resultSet = preparedStatement.executeQuery()) {

    long e = System.currentTimeMillis();

    System.out.println(Thread.currentThread().getName() + "执行耗时:" + (e - s));

    } catch (Exception e) {

    e.printStackTrace();

    } finally {

    latch.countDown();

    }

    }

    目的是分表查询采用多线程,使用CountDownLatch,结果汇总,提交任务代码如下:

    CountDownLatch countDownLatch = new CountDownLatch(TABLE_SIZE);

    ExecutorService executor = Executors.newFixedThreadPool(TABLE_SIZE);

    List names = new LinkedList<>();

    long s = System.currentTimeMillis();

    System.out.println("获取数据库连接成功,准备执行SQL...");

    try {

    for (int i = 0; i < TABLE_SIZE; i++) {

    Task task = new Task(countDownLatch, names, PRE_SQL + i);

    executor.execute(task);

    }

    countDownLatch.await();

    executor.shutdownNow();

    } catch (InterruptedException e) {

    e.printStackTrace();

    }

    long e = System.currentTimeMillis();

    System.out.println("总耗时:" + (e - s) + "ms");

    当指定1个任务时,控制台输出:

    获取数据库连接成功,准备执行SQL...

    pool-1-thread-1准备执行

    pool-1-thread-1执行耗时:708

    总耗时:708ms

    当指定2个任务时,控制台输出:

    获取数据库连接成功,准备执行SQL...

    pool-1-thread-1准备执行

    pool-1-thread-2准备执行

    pool-1-thread-2执行耗时:2054

    pool-1-thread-1执行耗时:2055

    总耗时:2057ms

    当指定4个任务时,控制台输出:

    获取数据库连接成功,准备执行SQL...

    pool-1-thread-2准备执行

    pool-1-thread-3准备执行

    pool-1-thread-1准备执行

    pool-1-thread-4准备执行

    pool-1-thread-3执行耗时:3189

    pool-1-thread-1执行耗时:3203

    pool-1-thread-2执行耗时:3241

    pool-1-thread-4执行耗时:3245

    总耗时:3248ms

    在程序运行期间查看mysql,show processlist;

    | 136 | root | localhost:50225 | test | Query | 1 | Sending data | SELECT SQL_NO_CACHE `id`, `name` FROM test_3 |

    | 135 | root | localhost:50224 | test | Query | 1 | Sending data | SELECT SQL_NO_CACHE `id`, `name` FROM test_1 |

    | 138 | root | localhost:50227 | test | Query | 1 | Sending data | SELECT SQL_NO_CACHE `id`, `name` FROM test_0 |

    | 137 | root | localhost:50226 | test | Query | 1 | Sending data | SELECT SQL_NO_CACHE `id`, `name` FROM test_2 |

    然后SQL状态就变成了Writing to net,不知道是否正常,对Mysql不是很懂。

    我也试过单线程for循环6次,耗时出入不大。

    单条SQL执行差不多在1S左右,现在4条SQL同时执行,并没有在1S多就返回结果,而是在3S多同时结束,那么这里的问题到底是什么原因导致的呢?

    展开全文
  • 当数据量过大时,一个程序的执行时间就会主要花费在等待次查询返回结果,在这个过程中cpu无疑是处于等待io的空闲状态的,这样既浪费了cpu资源,又花费了大量时间(当然这里主要说多线程,批量查询不在考虑范围,...

    当数据量过大时,一个程序的执行时间就会主要花费在等待单次查询返回结果,在这个过程中cpu无疑是处于等待io的空闲状态的,这样既浪费了cpu资源,又花费了大量时间(当然这里主要说多线程,批量查询不在考虑范围,总会存在不能批量查询的情况),在这种非密集型运算(及大量占用cpu资源)的情况下在python中无疑运用多线程是一个非常棒的选择。

    二.知识点:

    数据库连接池的运用及优势,python中多线程的运用,队列的运用

    数据库连接池:限制了数据库的连接最大个数,每次连接都是可以重复使用的,当然也可以限制每个连接的重复使用次数(这个在这里是没必要的),需要注意的是设置的数据库的最大连接个数最好要大于我们自己开的最大线程个数,一般逻辑是每个线程占用一个数据库连接可以使程序达到最大速度,如果小于则可能存在同时连接个数大于数据库允许的最大连接个数的风险。使用数据库连接池的优势在于,python多线程并发操作数据库,会存在链接数据库超时、数据库连接丢失、数据库操作超时等问题,而数据库连接池提供线程间可共享的数据库连接,并自动管理连接。

    python多线程:在程序等待io的时间里调用多线程去数据库执行查询操作。

    队列:这个就是数据结构里面的知识了,一般队列的常用模式先进先出队列。(这里主要用的是队列取一个数就少一个数的原理,其实用列表也可以实现,他的先进先出主要强调的是一个顺序关系,这一点到没用上,就当是练练手了)

    三.两段代码作比较:

    数据库的截图:

    第一段代码:正常循环查询并打印出执行时间

    #!/usr/bin/python

    # -*- coding=utf-8 -*-

    import time

    import threading

    import MySQLdb

    import Queue

    from MySQLdb.cursors import DictCursor

    from DBUtils.PooledDB import PooledDB

    def mysql_connection():

    host = 'localhost'

    user = 'root'

    port = 3306

    password = '123456'

    db = 'test'

    charset = 'utf8'

    limit_count = 3 # 最低预启动数据库连接数量

    pool = PooledDB(MySQLdb, limit_count, maxconnections=15, host=host, user=user, port=port, passwd=password, db=db, charset=charset,

    use_unicode=True, cursorclass=DictCursor)

    return pool

    start = time.time()

    pool = mysql_connection()

    for id in range(50):

    con = pool.connection()

    cur = con.cursor()

    sql = '''select id,name,age,weight from test where id = %s '''%id

    cur.execute(sql)

    time.sleep(0.5)

    result = cur.fetchall()

    if result:

    print('this is tread %s (%s,%s,%s,%s)'%(id,result[0]['id'],result[0]['name'],result[0]['age'],result[0]['weight']))

    else:

    print('this tread %s result is none'%id)

    end = time.time() - start

    print(end)

    执行结果:

    第二段代码:限制数据库连接池最大15个连接,用队列限制最大线程个数为10个

    #!/usr/bin/python

    # -*- coding=utf-8 -*-

    import time

    import threading

    import MySQLdb

    import Queue

    from MySQLdb.cursors import DictCursor

    from DBUtils.PooledDB import PooledDB

    def mysql_connection():

    host = 'localhost'

    user = 'root'

    port = 3306

    password = '123456'

    db = 'test'

    charset = 'utf8'

    limit_count = 3 # 最低预启动数据库连接数量

    pool = PooledDB(MySQLdb, limit_count, maxconnections=15, host=host, user=user, port=port, passwd=password, db=db, charset=charset,

    use_unicode=True, cursorclass=DictCursor)

    return pool

    def tread_connection_db(id):

    con = pool.connection()

    cur = con.cursor()

    sql = '''select id,name,age,weight from test where id = %s '''%id

    cur.execute(sql)

    time.sleep(0.5)

    result = cur.fetchall()

    if result:

    print('this is tread %s (%s,%s,%s,%s)'%(id,result[0]['id'],result[0]['name'],result[0]['age'],result[0]['weight']))

    else:

    print('this tread %s result is none'%id)

    con.close()

    if __name__=='__main__':

    start = time.time()

    #创建线程连接池,最大限制15个连接

    pool = mysql_connection()

    #创建队列,队列的最大个数及限制线程个数

    q=Queue.Queue(maxsize=10)

    #测试数据,多线程查询数据库

    for id in range(50):

    #创建线程并放入队列中

    t = threading.Thread(target=tread_connection_db, args=(id,))

    q.put(t)

    #队列队满

    if q.qsize()==10:

    #用于记录线程,便于终止线程

    join_thread = []

    #从对列取出线程并开始线程,直到队列为空

    while q.empty()!=True:

    t = q.get()

    join_thread.append(t)

    t.start()

    #终止上一次队满时里面的所有线程

    for t in join_thread:

    t.join()

    end = time.time() - start

    print(end)

    程序备注应该还算比较清晰的哈,程序执行结果:

    四.结论:

    看结果说话

    到此这篇关于python使用多线程查询数据库的实现示例的文章就介绍到这了,更多相关python 多线程查询数据库内容请搜索以前的文章或继续浏览下面的相关文章希望大家以后多多支持!

    展开全文
  • SpringBoot多线程异步查询步骤 1、创建线程池 import java.util.concurrent.ThreadPoolExecutor; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation....

    Spring boot 多线程异步查询步骤

    1、创建线程池

    import java.util.concurrent.ThreadPoolExecutor;
    
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
    
    @Configuration
    public class ThreadPoolConfig {
    	
    	/** 核心线程数(默认线程数) */
        private static final int corePoolSize = 5;
        /** 最大线程数 */
        private static final int maxPoolSize = 8;
        /** 允许线程空闲时间(单位:默认为秒) */
        private static final int keepAliveTime = 60;
        /** 缓冲队列大小 */
        private static final int queueCapacity = 100;
        /** 线程池名前缀 */
        private static final String threadNamePrefix = "DirectSearchEsService-";
    
        @Bean("taskExecutor") // bean的名称,默认为首字母小写的方法名
        public ThreadPoolTaskExecutor taskExecutor(){
            ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
            executor.setCorePoolSize(corePoolSize);
            executor.setMaxPoolSize(maxPoolSize);
            executor.setQueueCapacity(queueCapacity);
            executor.setKeepAliveSeconds(keepAliveTime);
            executor.setThreadNamePrefix(threadNamePrefix);
    
            // 线程池对拒绝任务的处理策略
            // CallerRunsPolicy:由调用线程(提交任务的线程)处理该任务
            executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
            // 初始化
            executor.initialize();
            return executor;
        }
    }
    

    2、SpringBoot启动类开启异步

    @SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
    @EnableSwagger2Doc
    @EnableAsync
    public class BootstrapApplication {
    	public static void main(String[] args) {
    		SpringApplication.run(BootstrapApplication.class, args);
        }
    }
    

    3、编写异步方法

    @Service
    public class DirectSearchEsService {
    	//线程池bean名称,可不填。
    	@Async("taskExecutor")
    	public Future<JsonObject> queryApiDirectIndex(String sysCode, String modelCode){
    		JsonObject result= new JsonObject();
    		//查询等业务逻辑,返回值必须为 Future类型
    		return new AsyncResult<JsonObject>(result);
    	}
    }
    

    4、调用异步方法

    //按天查询数据方法
    private JsonObject queryApiDirect(String sysCode, String modelCode) {
    	//只保留了有用代码,直接复制会报错
    	BlockingQueue<Future<JsonObject>> queue = new LinkedBlockingQueue();
    	Future<JsonObject> future;
    	//循环调用查询 queryApiDirectIndex
    	for (int i = 0; i <= between; i++) {
    		if(i==0) {//第一天
    			//本方法和异步方法尽量不要放在同一个类,否则有不生效问题,需要特殊处理。
    			future = directSearchEsService.queryApiDirectIndex(sysCode,modelCodeTime);
    		}else if(i == between) {//最后一天
    			future = directSearchEsService.queryApiDirectIndex(sysCode,modelCodeTime);
    		}else {//中间
    			future = directSearchEsService.queryApiDirectIndex(sysCode,modelCodeTime);
    		}
    		queue.add(future);
    	}
    	int queueSize = queue.size();
    	JsonArray dataArray = new JsonArray();
           LOG.info("queue size:" + queueSize);
           //拼装结果
           for (int i = 0; i < queueSize; i++) {
    		JsonObject data = queue.take().get();
           	JsonArray queryArray = data.getAsJsonArray("data");
           	dataArray.addAll(data.getAsJsonArray("data"));
           	total+=queryArray.size();
           }
           result.add("data", dataArray);
           result.addProperty("total", total);
    	return result;
    }
    
    展开全文
  • 通过适当的体系结构,多线程可以帮助将查询的负载抵消到CPU上,而不是进行慢速磁盘读/操作.在某些情况下,使用CPU周期计算值更快,而不是创建计算列(之前已保存到磁盘)并从磁盘读取此列.在某些RDBMS中,有一个临时DB...

    这是我的意见:

    通常,DB系统的瓶颈(或最慢的部分)是磁盘. CPU仅在算术运算,处理或CPU执行的任何其他任务期间出现峰值.通过适当的体系结构,多线程可以帮助将查询的负载抵消到CPU上,而不是进行慢速磁盘读/写操作.在某些情况下,使用CPU周期计算值更快,而不是创建计算列(之前已保存到磁盘)并从磁盘读取此列.

    在某些RDBMS中,有一个临时DB(tempdb),该实例上的所有DB都使用它来进行排序,散列,临时变量等…多线程和拆分此tempdb文件可用于提高tempdb的吞吐量从而提高整体服务器性能.

    使用多线程(并行),可以将查询的结果集拆分为在服务器的不同核心上进行处理,而不是单独使用一个核心.此功能并不总能提高性能,但有时会出现这种情况,因此可以使用该功能.

    DB可用的线程用于多种用途:读取/写入磁盘,用户连接,后台作业,锁定/锁存,网络IO等等…根据操作系统体系结构,线程被抢先送入CPU并且使用等待和队列进行管理.如果CPU可以很快地处理这些线程,那么等待时间将会很短.多线程数据库将比单线程数据库更快,因为在单线程数据库中,只会回收一个线程而不是让其他部分可用.

    可伸缩性也成为一个问题,因为管理和执行扩展的DB系统需要更多的线程.

    展开全文
  • 多线程数据查询统计

    2021-01-28 03:13:16
    最近在做一个需求,就是根据选定的对账查询该对账下的所有交易明细,但是由于交易明细表过大——几百万——且没有做分表等操作,数据库用的是...鉴于此,考虑使用多线程来解决该问题,因为交易明细表中存在交...
  • 表中有50W笔数据,表结构很简单,主键id(32位随机码),外加一个name字段,都是varchar2类型,想取出全部数据并封装到JavaBean中,但是一次查询耗时太长,想使用多线程的方法取出这些数据,但是用下面的多线程代码...
  • 文章目录进程和线程理论知识二者区别单线程多线程 进程和线程 由于理论概念难以理解,我在资料的过程中经常能看到这样一个形象的比喻: 除此之外,也可以看一下阮一峰大神的一篇博客:进程与线程的一个简单解释...
  • 线程技术已经不是什么新鲜事物了,但普通用户可能与双核心技术区分不开。例如开启了超线程技术的Pentium4530与PentiumD530在操作系统中都同样被识别为两颗处理器,它们究竟是不是一样的呢?这个问题确实具有迷惑性...
  • 多线程处理多表同时查询 知识点 通过ThreadPoolExecutor创建多线程 场景 场景说明:一个业务流程需要去查询数据库四次(分别是查询不同的表) 业务处理时间:(4O) 使用多线程处理 处理说明:通过创建线程池,分别...
  • 近乎所有与Java相关的面试都会问到缓存的问题,基础一点的会...一般常用的缓存服务器有Redis、Memcached等,就redis单线程,这篇文章做一个简单介绍Redis采用的是基于内存的采用的是单进程单线程模型的KV 数据库,由...
  • 下面从单线程多线程两个方面实现定时器的功能。1、单线程(schedule)首先我们需要一个单独的定时任务类,继承TimerTask,用来表示具体的定时任务,单独提出来封装成一个类,方便管理和实现:import java.util.Timer...
  • 数据库有自己的连接锁机制,如果是针对同一台机器使用同一个接口进行插入的话多线程单线程是一样的。除非你有好几台数据库服务器,这样再使用多线程来进行上面的工作的话效率才会明显提高。易语言查询数据库时出现...
  • 考虑调用三方接口本来就比较耗时,加上多个时间段单线程比较慢,改用多线程进行查询。前端又是同步调用,等待返回结果,所以采用CompletionService来处理。1.定义线程池package com.hzddyx.supervise.common.thread;...
  • 什么是进程?当一个程序开始运行时,它就是一个进程,进程包括运行中的程序和程序所使用到的...多线程是指程序中包含多个执行流,即在一个程序中可以同时运行多个不同的线程来执行不同的任务,也就是说允许单个程...
  • 因为数组不能全部放进内存,所以把它放进数据库中,我的数据库是这样设计的,把四维数组拆成二维数组,每次读或一个二维数组。 我使用了40个线程跑算法,数据库中在collection中每个键对应的值是一个二维数组,...
  • 今天就来讨论一下使用【优化sql】和【多线程】方式提升全表查询效率 ⚠️注意,这只是简单测试,用于讲解思路,真实情况会更加的复杂,效率可能会相对受到影响,而且也会受硬件配置的影响,所以不是绝对的 前置准备...
  • 具体到这个程序,确实有大量的batch操作,并且开了29个处理线程,并且hbase集群加了一批机器后,达到了近400台的规模,那极端情况下,将有1万线程,还不包括其他处理线程。而当时又有个进程被同时调度到这台...
  • 一、单线程(单条循环)插入50000条记录:每执行一次就要访问一次数据库import java.sql.Connection;import java.sql.DriverManager;import java.sql.ResultSet;import java.sql.SQLException;import java.sql....
  • packageserverAndClient;importjava.io.BufferedReader;importjava.io.IOException;importjava.io.InputStreamReader;importjava.io.PrintWriter;importjava.net.InetAddress;importjava.net.Socket;...
  • 问题发现最近在复习多线程相关知识,结果一动手就出现了问题,问题是这样的,在单元测试中使用多线程测试,发现只要子线程在睡眠一段时间,程序就退出了,毫无征兆!!!!看看我的代码(请不要拘泥这段代码带来的...
  • 先看看总结的结论:A. 由此可见,要想保证线程安全的话,可以有这4...SQLite使用多线程模式,每个线程创建自己的数据库连接。SQLite使用串行模式,所有线程共用全局的数据库连接。B. 关于数据库连接和数据库事务,以...
  • sqlite之多线程总结

    2021-02-26 11:04:04
    12.android 多线程数据库读写分析与优化11.多线程操作Sqlite?====最新需要给软件做数据库读写方面的优化,之前无论读写,都是用一个 SQLiteOpenHelper.getWriteableDataBase() 来操作数据库,现在需要多线程并发读写...
  • Spring Boot 多线程使用

    2021-01-05 19:09:58
    Spring Boot 提供了非常优雅使用多线程执行任务的方式,本文说明 Spring Boot 项目如何利用 ThreadPoolTaskExecutor 来使用多线程。 创建 Spring Boot 项目 使用 IntelliJ Idea 创建向导创建一个 Spring Boot 项目,...
  • 一、高并发系统接受实现多用户多请求的高并发时,通过多线程来实现。二、线程后台处理大任务一个程序是线性执行的。如果程序执行到要花大量时间处理的任务时,那主程序就得等待其执行完才能继续执行下面的。那用户就...
  • 2.3 Redis的IO多路复用3 多线程IO多路复用3.1 产生背景3.2 Redis多线程实现思路3.3 Redis多线程具体实现 1 Redis为什么是单线程的 1.1 官方解释 Redis官网–>Documentation–>Tutorials & FAQ–>F
  • 我需要找到一种可以在这里使用多线程的方法,这样我就可以运行这个过程的多个实例来加快速度.我知道我可以使用* DBMS_SCHEDULER *并且可能使用* DBMS_ALERT *但是我无法弄清楚如何在循环中使用它们. 有人能引导我朝...
  • 使用场景是QPS并不大,单每个查询由于需要访问较数据,对大量数据做处理,执行时间较长(通常秒级以上)。分析可以将一个大查询分成个子...但由于MySQL一个查询只能在单线程中执行,导致即使将一个大查询拆分成...
  • Android 单线程模型详解及实例我们今天将会在这篇文章中为大家详细介绍有关Android单线程模型的相关内容。希望初学者们可以通过本文介绍的内容对这一概念有一个充分的认识,并从中对这一系统有一个深刻的认识。当第...
  • java多线程-锁

    2021-03-14 10:57:53
    因此,如果线程不断竞争访问相同的 synchronized 同步块,就存在一种风险,其中一个或线程永远也得不到访问权 —— 也就是说访问权总是分配给了其它线程。这种情况被称作线程饥饿。为了避免这种问题,锁需要...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 345,685
精华内容 138,274
关键字:

多线程查单线程写