MySQL 分页

MySQL 分页 一般MySQL最基本的分页方式: select * from content order by id desc limit 0, 10 在中小数据量的情况下,这样的SQL足够用了,唯一需要注意的问题就是确保使用了索引。随着数据量的增加,页数会越来越多,查看后几页的SQL就可能类似: select * from content order by id desc limit 10000, 10 一言以蔽之,就是越往后分页,LIMIT语句的偏移量就会越大,速度也会明显变慢。 此时,我们可以通过2种方式: 一,子查询的分页方式来提高分页效率,SQL语句如下: SELECT * FROM content WHERE id <= (SELECT id FROM content ORDER BY id desc LIMIT “.($page-1)*$pagesize.”, 1) ORDER BY id desc LIMIT $pagesize 为什么会这样呢?因为子查询是在索引上完成的,而普通的查询时在数据文件上完成的,通常来说,索引文件要比数据文件小得多,所以操作起来也会更有效率。 (via) 通过explain SQL语句发现: 子查询使用了索引! id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY content range PRIMARY PRIMARY 4 NULL 6264 Using where ...

Created 15156-11-15 · Updated 9096-10-09 · 1 min · 193 words · lcf

FOR XML PATH

FOR XML PATH http://www.cnblogs.com/doubleliang/archive/2011/07/06/2098775.html FOR XML PATH 有的人可能知道有的人可能不知道,其实它就是将查询结果集以XML形式展现,有了它我们可以简化我们的查询语句实现一些以前可能需要借助函数活存储过程来完成的工作。那么以一个实例为主. 一.FOR XML PATH 简单介绍 那么还是首先来介绍一下FOR XML PATH ,假设现在有一张兴趣爱好表 (hobby) 用来存放兴趣爱好,表结构如下: 接下来我们来看应用FOR XML PATH的查询结果语句如下: SELECT * FROM @hobby FOR XML PATH 结果: <row> <hobbyID>1</hobbyID> <hName>爬山</hName> </row> <row> <hobbyID>2</hobbyID> <hName>游泳</hName> </row> <row> <hobbyID>3</hobbyID> <hName>美食</hName> </row> 由此可见FOR XML PATH 可以将查询结果根据行输出成XML各式! 那么,如何改变XML行节点的名称呢?代码如下: SELECT * FROM @hobby FOR XML PATH('MyHobby') 结果一定也可想而知了吧?没错原来的行节点<row> 变成了我们在PATH后面括号()中,自定义的名称<MyHobby>,结果如下: <MyHobby> <hobbyID>1</hobbyID> <hName>爬山</hName> </MyHobby> <MyHobby> <hobbyID>2</hobbyID> <hName>游泳</hName> </MyHobby> <MyHobby> <hobbyID>3</hobbyID> <hName>美食</hName> </MyHobby> 这个时候细心的朋友一定又会问那么列节点如何改变呢?还记的给列起别名的关键字AS吗?对了就是用它!代码如下: SELECT hobbyID as 'MyCode',hName as 'MyName' FROM @hobby FOR XML PATH('MyHobby') 那么这个时候我们列的节点名称也会编程我们自定义的名称 <MyCode>与<MyName>结果如下: ...

Created 29296-07-29 · Updated 9096-10-09 · 2 min · 270 words · -

JDBC URL

JDBC URL disable tls JDK8版本过高引起MySQL连接失败:javax.net.ssl.SSLHandshakeException: No appropriate protocol >[https://juejin.cn/post/6969142310718144520](https://juejin.cn/post/6969142310718144520) jdbc:mysql://127.0.0.1/database0?useunicode=true&characterencoding=utf8&tinyInt1isBit=false&useSSL=false MySQL MySQL Connector/J Driver 驱动程序包: http://mvnrepository.com/artifact/MySQL/MySQL-connector-java 驱动程序类名: com.MySQL.jdbc.Driver JDBC URL Format The general format for a JDBC URL for connecting to a MySQL server is as follows, with items in square brackets ([ ]) being optional: jdbc:MySQL://[host1][:port1][,[host2][:port2]]…[/[database]] [?propertyName1=propertyValue1[&propertyName2=propertyValue2]...] Here is a simple example for a connection URL: jdbc:MySQL://localhost:3306/sakila?profileSQL=true JDBC URL: jdbc:MySQL://<host>:<port>/<database_name> 默认端口3306,如果服务器使用默认端口则port可以省略 MySQL Connector/J Driver 允许在URL中添加额外的连接属性jdbc:MySQL://<host>:<port>/<database_name>?property1=value1&property2=value2 常用的有两个,一个是gjt (Giant Java Tree) 组织提供的MySQL驱动,其JDBC Driver名称 (JAVA类名) 为: org.gjt.mm.MySQL.Driver ...

Created 5056-03-05 · Updated 9096-10-09 · 2 min · 350 words · -

MemCache

MemCache http://blog.csdn.net/hjm4702192/article/details/7894080 Memcach什么是Memcache Memcache集群环境下缓存解决方案 Memcache是一个高性能的分布式的内存对象缓存系统,通过在内存里维护一个统一的巨大的hash表,它能够用来存储各种格式的数据,包括图像、视频、文件以及数据库检索的结果等。简单的说就是将数据调用到内存中,然后从内存中读取,从而大大提高读取速度。 Memcache是danga的一个项目,最早是LiveJournal 服务的,最初为了加速 LiveJournal 访问速度而开发的,后来被很多大型的网站采用。 Memcached是以守护程序方式运行于一个或多个服务器中,随时会接收客户端的连接和操作 为什么会有Memcache和memcached两种名称 其实Memcache是这个项目的名称,而memcached是它服务器端的主程序文件名,知道我的意思了吧。一个是项目名称,一个是主程序文件名,在网上看到了很多人不明白,于是混用了。 Memcached是高性能的,分布式的内存对象缓存系统,用于在动态应用中减少数据库负载,提升访问速度。Memcached由Danga Interactive开发,用于提升LiveJournal.com访问速度的。LJ每秒动态页面访问量几千次,用户700万。Memcached将数据库负载大幅度降低,更好的分配资源,更快速访问。 上网baidu了很多东西,几乎都差不多,而且基于java的说的很少,所有只有在研究了各个其他语言类的应用后再来尝试在java上进行简单的操作应用。先从memcached上进行说明,memcached的最新版是采用c语言进行开发和设计的,据说旧版的是采用perl语言开发的,而且它是一个应用软件来的,是作为缓存服务器的服务器端运行在服务器上的,需要使用特定的语言编写客户端与其进行通信来进行数据的缓存和获取。通常我们是把memcached安装运行在web服务器上,然后通过对需要的数据进行缓存,据我目前所知,所有数据的缓存设置和存取操作,以及数据的更新后替换操作全部需要程序来进行,而不是自动进行的 (自动不知道能不能成功,呵呵) 。下面从一个实际的例子来应用memcached。 如何要下载的话,到http://danga.com/memcached/下载memcached。 Ubuntu下安装Memcached 编译前,请先确认gcc、make、patch等编译工具是否已安装,并可正常使用。 安装Libevent Libevent是一个异步事件处理软件函式库,以BSD许可证释出。Memcached依赖Libevent,因此必须先编译安装Libevent。 检测libevent 安装是否成功,输入: # ls -al /usr/lib | grep libevent 会出现如下结果 (不同的机器可能有不同的输出) : yangfei@yangfei-laptop:~$ ls -al /usr/lib |grep libevent lrwxrwxrwx 1 root root 21 2009-07-19 08:45 libevent-1.4.so.2 -> libevent-1.4.so.2.1.3 -rwxr-xr-x 1 root root 301588 2009-07-19 08:45 libevent-1.4.so.2.1.3 -rw-r-r- 1 root root 386638 2009-07-19 08:45 libevent.a lrwxrwxrwx 1 root root 26 2009-07-19 08:45 libevent_core-1.4.so.2 -> libevent_core-1.4.so.2.1.3 ...

Created 28286-06-28 · Updated 9096-10-09 · 11 min · 2211 words · -

kafka consumer

kafka consumer 按照 Kafka 默认的消费逻辑设定,一个分区只能被同一个消费组(ConsumerGroup)内的一个消费者消费。 即同一个partition内的消息只能被同一个组中的一个consumer消费。当消费者数量多于partition的数量时,多余的消费者空闲 assignment, 分配策略 Kafka提供了消费者客户端参数partition.assignment.strategy用来设置消费者与订阅主题之间的分区分配策略。 默认情况下,此参数的值为:org.apache.kafka.clients.consumer.RangeAssignor,即采用RangeAssignor分配策略。除此之外,Kafka中还提供了另外两种分配策略: RoundRobinAssignor和StickyAssignor。消费者客户端参数partition.asssignment.strategy可以配置多个分配策略,彼此之间以逗号分隔。 RangeAssignor RangeAssignor 策略的原理是按照消费者总数和分区总数进行整除运算来获得一个跨度,然后将分区按照跨度进行平均分配,以保证分区尽可能均匀地分配给所有的消费者。对于每一个topic,RangeAssignor策略会将消费组内所有订阅这个topic的消费者按照名称的字典序排序,然后为每个消费者划分固定的分区范围,如果不够平均分配,那么字典序靠前的消费者会被多分配一个分区。 range assignor 在某些情况下会分配不均匀, 有可能会出现部分消费者过载的情况. RoundRobinAssignor 把 topic 和 consumer 排序, 依次给 topic 分配 consumer, 同一个 topic 中的不同 partition 分被均匀分配给不同的 consumer. RoundRobinAssignor 策略的原理是将消费组内所有消费者以及消费者所订阅的所有topic的partition按照字典序排序,然后通过轮询消费者方式逐个将分区分配给每个消费者。RoundRobinAssignor策略对应的partition.assignment.strategy参数值为:org.apache.kafka.clients.consumer.RoundRobinAssignor。 如果同一个消费组内所有的消费者的订阅信息都是相同的,那么RoundRobinAssignor策略的分区分配会是均匀的。 如果同一个消费组内的消费者所订阅的Topic 是不相同的,那么在执行分区分配的时候就不是完全的轮询分配,有可能会导致分区分配的不均匀。如果某个消费者没有订阅消费组内的某个topic,那么在分配分区的时候此消费者将分配不到这个topic的任何分区。 StickyAssignor “sticky”这个单词可以翻译为“粘性的”,Kafka从0.11.x版本开始引入这种分配策略,它主要有两个目的: ① 分区的分配要尽可能的均匀; ② 分区的分配尽可能的与上次分配的保持相同。 当两者发生冲突时,第一个目标优先于第二个目标。鉴于这两个目标,StickyAssignor策略的具体实现要比RangeAssignor和RoundRobinAssignor这两种分配策略要复杂很多。 从结果上看StickyAssignor策略比另外两者分配策略而言显得更加的优异,这个策略的代码实现也是异常复杂,如果大家在一个 group 里面,不同的 Consumer 订阅不同的 topic, 那么设置Sticky 分配策略还是很有必要的。 properties.put("enable.auto.commit", "true"); properties.put("auto.commit.interval.ms", "1000"); properties.put("auto.offset.reset", "latest"); properties.put("session.timeout.ms", "30000"); properties.put("key.deserializer", "org.apache.kafka.common.serialization.StringDeserializer"); properties.put("value.deserializer", "org.apache.kafka.common.serialization.ByteArrayDeserializer"); Consumer Group 主要用于实现高伸缩性,高容错性的 Consumer 机制。因此,消息的接收是基于 Consumer Group 的。组内多个 Consumer 实例可以同时读取 Kafka 消息,同一时刻一条消息只能被一个消费者消费,而且一旦某一个 consumer “挂了”, Consumer Group 会立即将已经崩溃的 Consumer 负责的分区转交给其他 Consumer 来负责。从而保证 Consumer Group 能够正常工作。 ...

Created 21216-05-21 · Updated 9096-10-09 · 3 min · 573 words · -

Redis3 集群数据迁移

Redis3 集群 数据迁移 一、概述 要让集群正常工作至少需要3个主节点,在这里我们要创建6个redis节点,其中三个为主节点,三个为从节点,对应的redis节点的ip和端口对应关系如下 127.0.0.1:7000 127.0.0.1:7001 127.0.0.1:7002 127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005 二、准备环境 安装ruby 集群环境需要ruby,所以需要安装下 yum install ruby yum install ruby-rdoc ruby setup.rb 安装完毕后启动依然报错 需要安装redis库 gem install redis 问题解决 下载最新redis版本 3.06 并进行构建 创建用户 useradd redis passwd redis 切换用户 su – redis 上传redis包到home目录 tar -zxvf redis-3.0.6.tar.gz mv redis-3.0.6 redis3.0 cd redis3.0 make 本环境为伪集群环境,所以在一台机器,多机情况相同 mkdir /home/redis/ cluster-test cd /home/redis/ cluster-test mkdir 7000 mkdir 7001 mkdir 7002 mkdir 7003 mkdir 7004 mkdir 7005 三、修改配置 ...

Created 6066-08-06 · Updated 9096-10-09 · 5 min · 874 words · -

Redis Replication, sentinel

“Redis Replication, sentinel” Redis 主从 Replication 的配置 beanlam 发布于 2015-04-20 本专栏与Redis相关的文章 Redis Sentinel机制与用法 (一) Redis Sentinel机制与用法 (二) Jedis的JedisSentinelPool源代码分析 Jedis的Sharded源代码分析 Redis 主从 Replication 的配置 详解Redis SORT命令 JedisCommand接口说明 本文参考翻译自《Redis Replication documentation》 概述 Redis的replication机制允许slave从master那里通过网络传输拷贝到完整的数据备份。具有以下特点: 异步复制。从2.8版本开始,slave能不时地从master那里获取到数据。 允许单个master配置多个slave slave允许其它slave连接到自己。一个slave除了可以连接master外,它还可以连接其它的slave。形成一个图状的架构。 master在进行replication时是非阻塞的,这意味着在replication期间,master依然能够处理客户端的请求。 slave在replication期间也是非阻塞的,也可以接受来自客户端的请求,但是它用的是之前的旧数据。可以通过配置来决定slave是否在进行replication时用旧数据响应客户端的请求,如果配置为否,那么slave将会返回一个错误消息给客户端。不过当新的数据接收完全后,必须将新数据与旧数据替换,即删除旧数据,在替换数据的这个时间窗口内,slave将会拒绝客户端的请求和连接。 一般使用replication来可以实现扩展性,例如说,可以将多个slave配置为“只读”,或者是纯粹的数据冗余备份。 能够通过replication来避免master每次持久化时都将整个数据集持久化到硬盘中。只需把master配置为不进行save操作(把配置文件中save相关的配置项注释掉即可),然后连接上一个slave,这个slave则被配置为不时地进行save操作的。不过需要注意的是,在这个用例中,必须确保master不会自动启动。更多详情请继续往下读。 Master持久化功能关闭时Replication的安全性 当有需要使用到replication机制时,一般都会强烈建议把master的持久化开关打开。即使为了避免持久化带来的延迟影响,不把持久化开关打开,那么也应该把master配置为不会自动启动的。 为了更好地理解当一个不进行持久化的master如果允许自动启动所带来的危险性。可以看看下面这种失败情形: 假设我们有一个redis节点A,设置为master,并且关闭持久化功能,另外两个节点B和C是它的slave,并从A复制数据。 如果A节点崩溃了导致所有的数据都丢失了,它会有重启系统来重启进程。但是由于持久化功能被关闭了,所以即使它重启了,它的数据集是空的。 而B和C依然会通过replication机制从A复制数据,所以B和C会从A那里复制到一份空的数据集,并用这份空的数据集将自己本身的非空的数据集替换掉。于是就相当于丢失了所有的数据。 即使使用一些HA工具,比如说sentinel来监控master-slaves集群,也会发生上述的情形,因为master可能崩溃后迅速恢复。速度太快而导致sentinel无法察觉到一个failure的发生。 当数据的安全很重要、持久化开关被关闭并且有replication发生的时候,那么应该禁止实例的自启动。 replication工作原理 如果你为master配置了一个slave,不管这个slave是否是第一次连接上Master,它都会发送一个SYNC命令给master请求复制数据。 master收到SYNC命令后,会在后台进行数据持久化,持久化期间,master会继续接收客户端的请求,它会把这些可能修改数据集的请求缓存在内存中。当持久化进行完毕以后,master会把这份数据集发送给slave,slave会把接收到的数据进行持久化,然后再加载到内存中。然后,master再将之前缓存在内存中的命令发送给slave。 当master与slave之间的连接由于某些原因而断开时,slave能够自动重连Master,如果master收到了多个slave并发连接请求,它只会进行一次持久化,而不是一个连接一次,然后再把这一份持久化的数据发送给多个并发连接的slave。 当master和slave断开重连后,一般都会对整份数据进行复制。但从redis2.8版本开始,支持部分复制。 数据部分复制 从2.8版本开始,slave与master能够在网络连接断开重连后只进行部分数据复制。 master会在其内存中创建一个复制流的等待队列,master和它所有的slave都维护了复制的数据下标和master的进程id,因此,当网络连接断开后,slave会请求master继续进行未完成的复制,从所记录的数据下标开始。如果进程id变化了,或者数据下标不可用,那么将会进行一次全部数据的复制。 支持部分数据复制的命令是PSYNC 不需硬盘参与的Replication 一般情况下,一次复制需要将内存的数据写到硬盘中,再将数据从硬盘读进内存,再发送给slave。 对于速度比较慢的硬盘,这个操作会给master带来性能上的损失。Redis2.8版本开始,实验性地加上了无硬盘复制的功能。这个功能能将数据从内存中直接发送到slave,而不用经过硬盘的存储。 不过这个功能目前处于实验阶段,还未正式发布。 相关配置 与replication相关的配置比较简单,只需要把下面一行加到slave的配置文件中: slaveof 192.168.1.1 6379 你只需要把ip地址和端口号改一下。当然,你也可以通过客户端发送SLAVEOF命令给slave。 部分数据复制有一些可调的配置参数,请参考redis.conf文件。 无硬盘复制功能可以通过repl-diskless-sync来配置,另外一个配置项repl-diskless-sync-delay用来配置当收到第一个请求时,等待多个slave一起来请求之间的间隔时间。 只读的slave 从redis2.6版本开始,slave支持只读模式,而且是默认的。可以通过配置项slave-read-only来进行配置,并且支持客户端使用CONFIG SET命令来动态修改配置。 ...

Created 18186-06-18 · Updated 9096-10-09 · 1 min · 133 words · -

redis ziplist

“redis list” linkedlist 每个node包含了三个部分,指向前一个节点和后一个节点的指针,以及一个数据值。而一个list包含了指向首尾的指针、整个list的长度,以及三个函数指针,用来复制节点的值、释放节点的值,以及比较节点内容。 ziplist 压缩列表 ziplist是一种特殊编码的节省内存空间的双链表,能以O(1)的时间复杂度在两端push和pop数据 ziplist是redis中实现的一个地址连续的链表。 每次操作都需要重新分配内存 先看下官方对ziplist的整体描述 /* The ziplist is a specially encoded dually linked list that is designed to be very memory efficient. It stores both strings and integer values, where integers are encoded as actual integers instead of a series of characters. It allows push and pop operations on either side of the list * in O(1) time. However, because every operation requires a reallocation of the memory used by the ziplist, the actual complexity is related to the ...

Created 4046-07-04 · Updated 9096-10-09 · 3 min · 428 words · -

redis scan

“redis scan” redis用scan代替keys 众所周知,当redis中key数量越大,keys 命令执行越慢,而且最重要的会阻塞服务器,对单线程的redis来说,简直是灾难,且在生产环境,keys命令一般是被禁止的。scan可用来替换keys请求。 所以说官方的建议是: 生产环境屏蔽掉 keys 命令。 在对键进行增量式迭代的过程中, 键可能会被修改, 所以增量式迭代命令只能对被返回的元素提供有限的保证 。 scan用法 SCAN cursor [MATCH pattern] [COUNT count] scan 0 match *news* count 3 scan是一个增量迭代式的命令,这意味着每次调用这个命令都会返回一个游标cursor,该游标用于下次查询。查询开始时,cursor值为0;当查询结束时,cursor的值也回归到0。 举个例子: 开始查询,scan cursor为0,返回的cursor为17 redis 127.0.0.1:6379> scan 0 “17” “key:12” “key:8” “key:4” “key:14” “key:16” “key:17” “key:15” “key:10” “key:3” “key:7” “key:1” 下一次查询,以上一次查询返回的cursor为起始位置 redis 127.0.0.1:6379> scan 17 查询返回cursor为0,标志查询结束 “0” “key:5” “key:18” “key:0” “key:2” “key:19” “key:13” “key:6” “key:9” “key:11” count count可理解为迭代过程中的步长,指每次调用scan时应执行的工作量,该值默认为10。每次调用count的值可以随意指定,只要下一次传递cursor是上一次调用返回的cursor就行。 match 需要注意的是,match操作时在元素被检出后执行的。假设redis中只有少量元素符合pattern条件,那么很可能在多次调用中scan返回的数据为空,例如: 查找key中包含11的键,因为这里没有指定count,所以默认为10 redis 127.0.0.1:6379> scan 0 MATCH 11 ...

Created 21216-07-21 · Updated 9096-10-09 · 2 min · 333 words · -

Redis 主从模式 VS 哨兵 sentinel 模式 VS Redis cluster 模式

“主从模式 VS 哨兵sentinel模式 VS Redis cluster模式” 主从模式 (redis2.8版本之前的模式) 、 哨兵 sentinel模式 (redis2.8及之后的模式) 、 redis cluster模式 (redis3.0版本之后) 主从模式原理 同MySQL主从复制的原因一样,Redis虽然读取写入的速度都特别快,但是也会产生读压力特别大的情况。为了分担读压力,Redis支持主从复制,Redis的主从结构可以采用一主多从或者级联结构,Redis主从复制可以根据是否是全量分为全量同步和增量同步。下图为级联结构。 优点: 解决数据备份问题 做到读写分离,提高服务器性能 缺点: 每个客户端连接redis实例的时候都是指定了ip和端口号的,如果所连接的redis实例因为故障下线了,而主从模式也没有提供一定的手段通知客户端另外可连接的客户端地址,因而需要手动更改客户端配置重新连接 主从模式下,如果主节点由于故障下线了,那么从节点因为没有主节点而同步中断,因而需要人工进行故障转移工作 无法实现动态扩容 sentinel 哨兵模式 Sentinel (哨兵) 是 Redis 的高可用性解决方案: 由一个或多个 Sentinel实例组成的Sentinel系统可以监视任意多个主服务器, 以及这些主服务器属下的所有从服务器,并在被监视的主服务器进入下线状态时,自动将下线主服务器属下的某个从服务器升级为新的主服务器。 优点 Master 状态监测 如果 Master 异常,则会进行 Master-slave 转换,将其中一个 Slave 作为 Master,将之前的 Master 作为 Slave Master-Slave 切换后,master_redis.conf、slave_redis.conf 和 sentinel.conf 的内容都会发生改变,即 master_redis.conf 中会多一行 slaveof 的配置,sentinel.conf 的监控目标会随之调换 缺点: 如果是从节点下线了,sentinel 是不会对其进行故障转移的,连接从节点的客户端也无法获取到新地可用从节点 无法实现动态扩容 cluster 模式 在这个图中,每一个蓝色的圈都代表着一个redis的服务器节点。它们任何两个节点之间都是相互连通的。客户端可以与任何一个节点相连接,然后就可以访问集群中的任何一个节点。对其进行存取和其他操作。 一般集群建议搭建三主三从架构,三主提供服务,三从提供备份功能。每一个节点都存有这个集群所有主节点以及从节点的信息。 它们之间通过互相的ping-pong判断是否节点可以连接上。如果有一半以上的节点去ping一个节点的时候没有回应,集群就认为这个节点宕机了,然后去连接它的备用节点。如果某个节点和所有从节点全部挂掉,我们集群就进入faill状态。还有就是如果有一半以上的主节点宕机,那么我们集群同样进入发力了状态。这就是我们的redis的投票机制,具体原理如下图所示: (1)投票过程是集群中所有master参与,如果半数以上master节点与master节点通信超时(cluster-node-timeout),认为当前master节点挂掉. (2):什么时候整个集群不可用(cluster_state:fail)? ...

Created 9096-10-09 · Updated 9096-10-09 · 4 min · 693 words · -

SQLite

SQLite version: 3.44.0 SQLite 通过文件来保存数据库,一个文件就是一个数据库 commands # archlinux install sqlite sudo pacman -S sqlite # ubuntu sudo apt install sqlite3 # 打开一个已经存在的数据库 sqlite3 /var/lib/enx-api/enx.db # 启动 sqlite sqlite3 # 列出数据库文件和名字 .databases # query schema, 列出所有的表 .table # 查看表结构, 注意, 表名后面没有分号 .schema table0 # 创建数据库 sqlite3 /data/rssx/rssx.db # insert data insert into table_0 (name) values ('foo'); CREATE TABLE if not exists table_1 (name varchar(50) collate nocase PRIMARY KEY, create_time timestamp DEFAULT NULL); insert into table_1 (name) values ('foo'); insert into table_1 (name) values ('Foo'); -- Runtime error: UNIQUE constraint failed: table_1.name (19) # help .help # show tables .tables # insert # alter table, rename alter table feed rename to feeds; COLLATE NOCASE 列定义里的 COLLATE NOCASE 表示该列上的字符串比较不区分大小写(主要覆盖 ASCII 的 A–Z / a–z)。 ...

Created 5056-01-05 · Updated 28286-08-28 · 5 min · 874 words · -

DuckDB: 嵌入式 OLAP 数据库

DuckDB DuckDB 是一个进程内(in-process)的分析型数据库,常被称作「分析界的 SQLite」:不需要单独的服务进程,一个库文件就是一个数据库,直接嵌入到应用里运行。区别在于它面向 OLAP——列式存储、向量化执行,为聚合与扫描大量数据做优化。 官网:https://duckdb.org/ 单文件数据库,零依赖,零配置 可直接查询 CSV / Parquet / JSON 文件,不必先导入 与 Python / R / Pandas / Arrow 深度集成 安装 # archlinux sudo pacman -S duckdb # macOS brew install duckdb # Python pip install duckdb CLI 常用命令 -- 打开或新建一个数据库文件 duckdb my.duckdb -- 纯内存模式(进程退出即丢失) duckdb .tables -- 列出所有表 .schema table0 -- 查看表结构 .mode box -- 结果以表格形式输出 .timer on -- 显示查询耗时 .help .quit 直接查询文件 DuckDB 最实用的能力:把文件当表用,不用建表和导入。 ...

Created 28286-08-28 · Updated 28286-08-28 · 2 min · 290 words · -

关系型数据库与 NoSQL 对比

关系型数据库与 NoSQL 对比 一、关系型数据库? 1.概念 关系型数据库是指采用了关系模型来组织数据的数据库。简单来说,关系模式就是二维表格模型。 主要代表:SQL Server,Oracle,Mysql,PostgreSQL。 2.优点 (1).容易理解,二维表的结构非常贴近现实世界,二维表格,容易理解。 (2)使用方便,通用的sql语句使得操作关系型数据库非常方便。 (3)易于维护,数据库的ACID属性,大大降低了数据冗余和数据不一致的概率。 3.瓶颈 (1 )海量数据的读写效率。 对于网站的并发量高,往往达到每秒上万次的请求,对于传统关系型数据库来说,硬盘I/o是一个很大的挑战。 (2) 高扩展性和可用性。 在基于web的结构中,数据库是最难以横向拓展的,当一个应用系统的用户量和访问量与日俱增的时候,数据库没有办法像web Server那样简单的通过添加更多的硬件和服务节点来拓展性能和负载能力。 传统数据库操作涉及事物机制,每次写入操作需要进行undo、redo操作,然后将redo操作记录到日志文件,有事物开销,不适合写多读少的场景. 二、从关系型到非关系型 关系型数据库的最大优点就是事务的一致性,这个特性,使得关系型数据库中可以适用于一切要求一致性比较高的系统中。比如:银行系统。 但是在网页应用中,对这种一致性的要求不是那么的严格,允许有一定的时间间隔,所以关系型数据库这个特点不是那么的重要了。相反,关系型数据库为了维护一致性所付出的巨大代价就是读写性能比较差。而像微博、facebook这类应用,对于并发读写能力要求极高,关系型数据库已经无法应付。所以必须用一种新的数据结构存储来替代关系型数据库。所以非关系型数据库应用而生。 三、非关系型 1.概念 NoSQL非关系型数据库,主要指那些非关系型的、分布式的,且一般不保证ACID的数据存储系统,主要代表MongoDB,Redis、CouchDB。 NoSQL提出了另一种理念,以键值来存储,且结构不稳定,每一个元组都可以有不一样的字段,这种就不会局限于固定的结构,可以减少一些时间和空间的开销。使用这种方式,为了获取用户的不同信息,不需要像关系型数据库中,需要进行多表查询。仅仅需要根据key来取出对应的value值即可。 2.NoSQL 命名的含义 NoSQL 并不是「完全不用 SQL」,而是不以关系模型为核心。NoSQL 的字面含义经过了演变: 早期理解为 “No SQL”,意指不使用 SQL 后来业界更倾向解读为 “Not Only SQL”,即「不只是 SQL」,强调对关系型数据库的补充而非替代 区分一个数据库是不是 NoSQL,关键看数据模型(是否以关系/表来组织数据),而不是查询语言的语法。事实上很多 NoSQL 数据库都提供了类 SQL 的接口,例如: Cassandra 有 CQL(Cassandra Query Language),语法与 SQL 非常接近 MongoDB 持续增强聚合查询能力 ClickHouse 支持 SQL 语法,但底层是列式存储,不基于关系模型 3.分类 (1)面向高性能并发读写的key-value数据库 主要特点是具有极高的并发读写性能,例如Redis、Tokyo Cabint等。 (2)面向海量数据访问的面向文档数据库 ...

Created 21216-02-21 · Updated 8086-06-08 · 1 min · 115 words · -

PostgreSQL

PostgreSQL commands \l 或 \list meta-command 列出所有数据库 sudo -u postgres psql -c "\l" 用 \c + 数据库名 来进入数据库: \dt 列出所有数据库表: # 查看表结构, 索引 \d table0 # 比上面多几个字段 Storage | Stats target | Description \d+ table0 # Turn off printing of column names and result row count footers, etc. This is equivalent to \t or \pset tuples_only. \t tuples only on/off, tuples only on 的时候 select 语句的输出不带 header \h \? \du 列出所有的用户 # 创建用户 CREATE USER user_0 WITH PASSWORD 'password_0'; # create database, 所有者 user_0 create database database_0 OWNER user_0; psql -h 192.168.1.100 -p 5432 -U user_0 -d database_0 PGPASSWORD=password_0 psql -h 192.168.1.100 -p 5432 -U user_0 -d database_0 --command 'select version();' #当表没有其他关系时 TRUNCATE TABLE tablename; #当表中有外键时,要用级联方式删所有关联的数据 TRUNCATE TABLE tablename CASCADE; # 查看 表大小 select pg_size_pretty(pg_relation_size('table0')); # 查看配置文件路径, 切换到 postgres 用户执行 psql -c "show config_file" # 查看版本 select version(); pacman -S postgresql psql -h 127.0.0.1 -p 5432 -d database0 -U user0 # create table create table test(id int, c1 int); create table table0(field0 json); # delete table DROP TABLE table0; # 查看字段类型 select column_name, data_type from information_schema.columns where table_name='table0'; select * length( "abc"::TEXT) insert into test select generate_series(1,10000), random()*10; # 复制表结构到另外一个数据库 pg_dump -U postgres --schema-only source_db | psql -U postgres target_db 导入/导出 export, 导出, 备份 # https://www.postgresql.org/download/linux/ubuntu/ # install pg_dump sudo apt install -y postgresql-common # This script will enable the PostgreSQL APT repository on apt.postgresql.org sudo /usr/share/postgresql-common/pgdg/apt.postgresql.org.sh # ubuntu install pg_dump sudo apt-get install postgresql-client-17 # -h, host 127.0.0.1 # -p, port 5432 # -t, table: table0, 不加 -t 参数时会导出所有表结构 # -s, 不导出数据 # database: database0 # -F : 指定输出文件的格式,它可以是以下格式之一: c: 自定义格式 d: 目录格式存档 t: tar 文件包 p: SQL 脚本文件 # -W 命令执行时提示输入用户密码(不会直接在命令中写密码)。 pg_dump -h 127.0.0.1 -U username -W -F t db_name > foo.tar # 导入 # -c --clean 创建数据库对象前先清理(删除)它们。 pg_restore -h 127.0.0.1 -U username -W -d db_name -c foo.tar pg_dump -h 127.0.0.1 -p 5432 -t table_0 -U postgres database0 > foo.sql pg_dump -h 127.0.0.1 -p 5432 -s -t table_0 -U postgres database0 > foo.sql # 导出并压缩 pg_dump -d db_name | gzip > db.gz pg_dump -a -t table_0 "host=127.0.0.1 hostaddr=127.0.0.1 port=5432 user=user_0 password=password_0 dbname=db_0" # export insert sql pg_dump -a -t table_0 "host=127.0.0.1 hostaddr=127.0.0.1 port=5432 user=user_0 password=password_0 dbname=db_0" --inserts 导入 # sql psql -h 127.0.0.1 -p 5432 -t table0 -U postgres -d database0 -f foo.sql # csv, https://stackoverflow.com/questions/26701735/extra-data-after-last-expected-column-while-trying-to-import-a-csv-file-into-p \COPY agency (agency_name, agency_url, agency_timezone) FROM 'myFile.txt' CSV HEADER DELIMITER ','; 导出指定的行 https://stackoverflow.com/questions/12815496/export-specific-rows-from-a-postgresql-table-as-insert-sql-script ...

Created 14146-04-14 · Updated 3036-06-03 · 18 min · 3639 words · -

MySQL 宽表写入性能问题:为什么会慢,何时该考虑时序库

背景 在业务增长阶段,很多系统都会遇到类似问题:写入路径以 insert 为主,单条记录字段很多,写入频率持续升高,最终出现写入延迟抬升、队列积压、应用侧内存压力变大。 这类问题通常被称为“宽表高频写入瓶颈”。这里把它拆开讲清楚:为什么会慢、先做什么优化、以及什么时候该考虑从关系型数据库迁移到时序数据库。 一个真实案例可参考:物联网平台协议解析服务生产环境 OOM:MySQL 迁移 InfluxDB。 为什么宽表高频写入容易慢 宽表写入慢,通常不是单点问题,而是多个开销叠加: 单行体积大:每次写入涉及更多页修改和日志写入。 索引维护成本高:索引越多,单次 insert 需要更新的 B+Tree 越多。 随机写放大:页分裂、二级索引回表结构维护,会放大 I/O。 事务与刷盘约束:redo/binlog/fsync 的组合决定了吞吐上限。 后台线程竞争:flush、checkpoint、purge 跟前台写入争抢资源。 这里的“更多页”并不是指“每一行一定跨很多页”,而是指一次写入会牵动更多数据页:InnoDB 以页(默认常见为 16 KB)为最小读写单位。行越宽,单页可容纳的记录数越少,同样数据量需要更多页;插入时更容易触发页满和页分裂。同时,写入不只改数据页,还会改聚簇索引页、二级索引页以及对应日志;如果包含较大 TEXT/BLOB 字段,还可能涉及溢出页。结果是单次写入的页修改与日志写入成本一起上升。 在高并发下,这些开销叠加后,常见表现是:写入 RT 上升,连接占用时间变长,线程池阻塞,进而把上游消费链路拖慢。 先做 MySQL 侧排查和优化 在决定换库前,建议先把 MySQL 侧可优化项跑一遍: 表结构:拆分冷热字段,把大字段从核心写入表拆出去。 索引策略:只保留必要索引,避免“为查而建”过多索引拖慢写入。 主键设计:优先使用短且有序的主键,降低页分裂概率。 批量写入:小批次 batch insert,减少事务提交次数。 连接池与并发:避免连接池过大导致数据库抖动,结合压测设上限。 存储参数:检查 innodb_buffer_pool_size、innodb_flush_log_at_trx_commit、sync_binlog 等配置是否与场景匹配。 观测指标:重点盯写入 RT、TPS、磁盘写 IOPS、redo 生成速率、checkpoint age、锁等待。 如果这些动作做完后仍然无法满足目标吞吐,再考虑架构级改造更稳妥。 什么时候考虑时序数据库 当业务数据明显符合以下特征时,时序数据库通常更有优势: 写多读少,且主要是追加写。 读请求以时间范围查询为主。 业务天然带时间戳主维度。 接受按保留策略做冷热分层与过期清理。 这类场景下,时序引擎在写路径和压缩存储上的结构性优势,往往比继续堆关系库参数更有效。 迁移建议 从 MySQL 到时序库,建议用“双写 + 渐进切读”: 先双写,确保新旧链路数据可对账。 下游按服务分批切读,避免一次性切换。 保留回退开关,出现异常可快速切回旧链路。 观察一段稳定窗口后,再下线旧写入逻辑。 InfluxDB 相关基础可参考:InfluxDB。 ...

Created 3036-06-03 · Updated 3036-06-03 · 1 min · 84 words · -

MySQL 大表优化

MySQL 大表优化 这篇是我基于一篇早期讨论内容整理的实践笔记,重点放在“遇到大表性能问题时,按什么顺序处理更稳妥”。 原讨论链接: https://www.zhihu.com/question/19719997/answer/81930332 处理顺序(先低成本,再高成本) 大多数系统都适合按以下顺序推进,避免一上来就分库分表: 先优化 SQL 和索引。 再加缓存(如 Redis),减少数据库读压力。 再做读写分离(主从)或副本扩展。 再评估分区表(前提是查询条件能命中分区键)。 再做垂直拆分(按业务域拆库)。 最后才是水平拆分(分库分表 + 路由)。 核心原因是:越往后改造成本越高,业务侵入越强,回退也越困难。 SQL 与索引是第一优先级 很多慢库问题并不是“数据库不行”,而是这三件事没有做透: SQL 写法没有针对索引设计。 索引数量过多或选择不对,拖慢写入。 优化单条 SQL 时忽略了全局负载,出现“局部变快、整体变慢”。 建议先做这套最小闭环: 用慢查询日志找 Top N SQL。 用 EXPLAIN 验证执行计划。 在压测环境对比“改前/改后”整体 RT、QPS、CPU、IO。 分区、垂直拆分、水平拆分怎么选 分区表 适合“时间范围明显、查询常带分区键”的表。优点是对业务代码相对透明;缺点是分区命中差时容易扫全分区。 垂直拆分 适合按业务域解耦,把不同模块压力拆到不同库。它能降低单实例总压力,但不能解决单表本身太大的问题。 水平拆分 适合单表已达到容量或吞吐瓶颈。收益大,但代价也最大: 需要稳定的分片键设计。 SQL 路由、聚合查询、跨分片事务复杂度明显上升。 常常需要改表结构、做冗余字段、改应用代码。 关于 InnoDB 与 MyISAM 的取舍 在当前线上系统里,绝大多数场景优先 InnoDB: 支持事务与行级锁。 并发写能力更稳。 故障恢复能力更好。 MyISAM 在某些纯读场景可能有优势,但在写多或读写混合场景里,通常不是优先选项。 实战建议 如果你正在处理“大表 + 写入变慢”,建议按下面清单落地: 先确认瓶颈在 SQL、锁、IO、还是连接池。 明确读写模型(读多写少、写多读少、时间范围查询比例)。 先完成 SQL/索引/缓存优化,再决定是否拆分。 如果进入拆分阶段,先做垂直拆分,再做水平拆分。 延伸阅读 MySQL 宽表写入性能问题:为什么会慢,何时该考虑时序库 数据库水平拆分垂直拆分 MySQL INNODB

Created 22226-12-22 · Updated 3036-06-03 · 1 min · 77 words · -

LevelDB

简介 LevelDB 是由 Google 工程师 Jeff Dean 和 Sanjay Ghemawat 开发的开源 KV 存储引擎,两人同时也是 Bigtable 和 MapReduce 的主要设计者。LevelDB 可以理解为单机版的 Bigtable Tablet Server,能够处理十亿级别规模的 Key-Value 数据持久性存储。 主要特性: 数据按 Key 有序存储,支持自定义比较函数 提供 Put / Get / Delete 以及原子批量操作接口 支持 Snapshot 快照读,读操作不受并发写影响 支持 Snappy 数据压缩 写性能极高:随机写约 40 万条/秒,随机读约 6~10 万条/秒(4核机器) 写速度远大于读速度;顺序读写远快于随机读写 LevelDB 是单进程嵌入式库,不提供网络服务,适合作为其他系统的本地存储引擎。Chrome 浏览器用它存储 IndexedDB 数据,比特币/以太坊节点用它存储区块链状态。 LSM-Tree LevelDB 的核心数据结构是 LSM-Tree(Log-Structured Merge-Tree),一种针对写入密集型场景优化的存储结构。 核心思想: 将随机写转化为顺序写,以牺牲部分读性能换取极高的写入吞吐量。 写入流程 写入请求 ↓ WAL(预写日志,顺序写磁盘) ↓ MemTable(内存,有序跳表 SkipList) ↓ 满了之后 Immutable MemTable(只读,等待 flush) ↓ flush(minor compaction) L0(SSTable 文件,磁盘) ↓ compaction(major compaction) L1 → L2 → ... Ln 三大放大问题 问题 说明 写放大 数据会被反复 compaction,实际写磁盘量远大于原始数据量,通常 10x~30x 读放大 读时需要依次查 MemTable → Immutable MemTable → L0 → L1 → … 空间放大 同一 key 可能存在多个版本,直到 compaction 才合并清理 为什么写快 所有写入都是顺序 I/O(追加 WAL、批量 flush) 没有 B-Tree 那样的随机写和页分裂开销 一次写入只涉及一次磁盘顺序追加写 + 一次内存 SkipList 插入 使用 LSM-Tree 的系统 LevelDB / RocksDB — 经典实现(RocksDB 是 LevelDB 的增强版) Cassandra、HBase — 分布式存储 ClickHouse MergeTree — 列式存储引擎 静态结构 LevelDB 的数据存储在内存和磁盘两部分,主要由六个组件构成: ...

Created 28286-04-28 · Updated 28286-04-28 · 3 min · 524 words · -

sql basic

between and BETWEEN 用以查询确定范围的值,这些值可以是数字,文本或日期 。 BETWEEN 运算符是闭区间的:包括开始 和 结束值 。 not between 则是不包含前后边界的 select select * from table0 where column0!=''; !=’’ 会过滤掉值为 null 的数据. The reason is simple: nulls are neither equal, nor not equal, to anything. This makes sense when you consider that null means “unknown”, and the truth of a comparison to an unknown value is also unknown. The corollary is that: null = null is not true null = some_value is not true null != some_value is not true The two special comparisons IS NULL and IS NOT NULL exist to deal with testing if a column is, or is not, null. No other comparisons to null can be true. ...

Created 18186-04-18 · Updated 18186-04-18 · 2 min · 358 words · -

kafka basic, command

kafka basic, command kafka_2.13-3.4.0.tgz scala 版本 2.13 kafka 版本 3.4.0 TLS kafka todo commands # list topic bin/kafka-topics.sh --list --bootstrap-server 127.0.0.1:9092 # create topic bin/kafka-topics.sh --create --partitions 1 --replication-factor 1 --topic topic_0 --bootstrap-server 127.0.0.1:9092 # consumer bin/kafka-console-consumer.sh --topic topic_0 --bootstrap-server 127.0.0.1:9092 # producer bin/kafka-console-producer.sh --bootstrap-server 127.0.0.1:9092 --topic topic_0 # list group name bin/kafka-consumer-groups.sh --bootstrap-server 127.0.0.1:9092 --list # 查看 consumer group offset bin/kafka-consumer-groups.sh --bootstrap-server 127.0.0.1:9092 --describe --group group0 # tls ./kafka-topics.sh --list --bootstrap-server 127.0.0.1:9093 --command-config /tmp/kafka.conf content of kafka.conf ...

Created 19196-11-19 · Updated 19196-11-19 · 10 min · 1993 words · -

redis pipeline

“redis pipeline” why pipeline ? Redis 客户端与 server 的请求/响应模型 前面的文章 Redis 底层协议RESP详解 ,介绍到 redis 客户端与 redis-server 交互通信,采用的 TCP 请求/响应模型; 我们通过 Redis 客户端执行命令,如set key value,客户端遵循RESP协议,将命令的协议串发送给redis-server执行,redis-server执行完成后再同步返回结果。 手写Redis客户端-实现自己的Jedis 对这一过程进行了重点分析,并遵循RESP实现了自己简易版的Redis客户端。 Redis客户端与server通信,使用的是客户端-服务器 (CS) 模式;每次交互,都是完整的请求/响应模式。 这意味着通常情况下一个请求会遵循以下步骤: 客户端连接服务端,基于特定的端口,发送一个命令,并监听Socket返回,通常是以阻塞模式,等待服务端响应。 服务端处理命令,并将结果返回给客户端。 很显然,我们使用jedis或lettuce执行Redis命令,每次都是建立socket连接,并等待返回。 每个命令底层建立TCP连接的时间是省不掉的,即使我们都是在内网使用Redis,内网快但请求/响应的往返时间是不会减少的。 当需要对一组kv进行批量操作时,这组命令的耗时=sum(N*(建立连接时间+发送命令、返回结果的往返时间RTT)),随批量操作的key越多,时间累加呈线性增长。 顺理成章的,就出现了像数据库连接池等池化思想的衍生,redis连接也进行“池化”,如JedisPool。 JedisPool就足够了? 池化connection后,每次执行命令都从池子里“借”,用完之后再将connection“还”到池子。只是节省了创建TCP连接的时间; 当需要对一组kv进行批量操作时,JedisPool池子里的connection连接、极端情况都被用完了,怎么办? ——需要等待JedisPool池里有可复用的connection才能继续执行; redis.clients.jedis.exceptions.JedisConnectionException: Could not get a resource from the pool … Caused by: java.util.NoSuchElementException: Timeout waiting for idle object at org.apache.commons.pool2.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:449) 如果在指定的等待时间内没有等到idle空闲连接,就报异常了。 尽管使用了池化、将connection进行复用,但不可避免的带来其他问题: https://jjlu521016.github.io/2018/12/09/JedisPool常见问题.html 除了池化的connection会被瞬间用完,Redis官网还给出了另外一个性能损耗的原因: It’s not just a matter of RTT https://redis.io/topics/pipelining 虽然池化的connection,节省了建立连接的时间,但多条命令(发送命令到sever、server返回结果)分别执行多次socket网络IO,涉及到read()和write() syscall系统调用,这意味着从用户态到内核态。上下文切换是巨大的速度损失。 ...

Created 24246-07-24 · Updated 24246-07-24 · 1 min · 184 words · -