说实话,以前用mysql的Between and 都是这样的用法:where id between 123 and 456。
偶尔居然看到了原来可以where 123 between start_date and end_date
这个用法有点妖异。记录一下。以后实际应用的时候看看效果如何
Submitted by gouki on 2012, November 21, 6:53 PM
说实话,以前用mysql的Between and 都是这样的用法:where id between 123 and 456。
偶尔居然看到了原来可以where 123 between start_date and end_date
这个用法有点妖异。记录一下。以后实际应用的时候看看效果如何
Submitted by gouki on 2012, October 30, 11:00 PM
改了点东西,因为想着要把项目优化,但是每条数据如果都存到单一数据库中,会造成以后的数据越来越大,怎么办?于是我想到了,可以考虑将单类数据存储到sqlite中,既可以备份,又可以用作缓存和其他作用。
所以就想到了sqlite的一些特性,当然,花了大量的时间测试代码,即,一份代码自动生成不同的数据库,可以自由控制读取哪个库哪个表。基于YII而已。写的有点挫,但现在这样的好处是可以不改动原有任何一行代码。
OK,接着转sqlite的字段类型。
一、存储种类和数据类型:
SQLite将数据值的存储划分为以下几种存储类型:
NULL: 表示该值为NULL值。
INTEGER: 无符号整型值。
REAL: 浮点值。
TEXT: 文本字符串,存储使用的编码方式为UTF-8、UTF-16BE、UTF-16LE。
BLOB: 存储Blob数据,该类型数据和输入数据完全相同。
由于SQLite采用的是动态数据类型,而其他传统的关系型数据库使用的是静态数据类型,即字段可以存储的数据类型是在表声明时即以确定的,因此它们之间 在数据存储方面还是存在着很大的差异。在SQLite中,存储分类和数据类型也有一定的差别,如INTEGER存储类别可以包含6种不同长度的 Integer数据类型,然而这些INTEGER数据一旦被读入到内存后,SQLite会将其全部视为占用8个字节无符号整型。因此对于SQLite而 言,即使在表声明中明确了字段类型,我们仍然可以在该字段中存储其它类型的数据。然而需要特别说明的是,尽管SQLite为我们提供了这种方便,但是一旦 考虑到数据库平台的可移植性问题,我们在实际的开发中还是应该尽可能的保证数据类型的存储和声明的一致性。除非你有极为充分的理由,同时又不再考虑数据库 平台的移植问题,在此种情况下确实可以使用SQLite提供的此种特征。
1. 布尔数据类型:
SQLite并没有提供专门的布尔存储类型,取而代之的是存储整型1表示true,0表示false。
2. 日期和时间数据类型:
和布尔类型一样,SQLite也同样没有提供专门的日期时间存储类型,而是以TEXT、REAL和INTEGER类型分别不同的格式表示该类型,如:
TEXT: "YYYY-MM-DD HH:MM:SS.SSS"
REAL: 以Julian日期格式存储
INTEGER: 以Unix时间形式保存数据值,即从1970-01-01 00:00:00到当前时间所流经的秒数。
二、类型亲缘性:
为了最大化SQLite和其它数据库引擎之间的数据类型兼容性,SQLite提出了"类型亲缘性(Type Affinity)"的概念。我们可以这样理解"类型亲缘性 ",在表字段被声明之后,SQLite都会根据该字段声明时的类型为其选择一种亲缘类型,当数据插入时,该字段的数据将会优先采用亲缘类型作为该值的存储 方式,除非亲缘类型不匹配或无法转换当前数据到该亲缘类型,这样SQLite才会考虑其它更适合该值的类型存储该值。SQLite目前的版本支持以下五种 亲缘类型:
亲缘类型 | 描述 |
TEXT | 数值型数据在被插入之前,需要先被转换为文本格式,之后再插入到目标字段中。 |
NUMERIC | 当文本数据被插入到亲缘性为NUMERIC的 字段中时,如果转换操作不会导致数据信息丢失以及完全可逆,那么SQLite就会将该文本数据转换为INTEGER或REAL类型的数据,如果转换失 败,SQLite仍会以TEXT方式存储该数据。对于NULL或BLOB类型的新数据,SQLite将不做任何转换,直接以NULL或BLOB的方式存储 该数据。需要额外说明的是,对于浮点格式的常量文本,如"30000.0",如果该值可以转换为INTEGER同时又不会丢失数值信息,那么SQLite 就会将其转换为INTEGER的存储方式。 |
INTEGER | 对于亲缘类型为INTEGER的字段,其规则等同于NUMERIC,唯一差别是在执行CAST表达式时。 |
REAL | 其规则基本等同于NUMERIC,唯一的差别是不会将"30000.0"这样的文本数据转换为INTEGER存储方式。 |
NONE | 不做任何的转换,直接以该数据所属的数据类型进行存储。 |
1. 决定字段亲缘性的规则:
字段的亲缘性是根据该字段在声明时被定义的类型来决定的,具体的规则可以参照以下列表。需要注意的是以下列表的顺序,即如果某一字段类型同时符合两种亲缘性,那么排在前面的规则将先产生作用。
1). 如果类型字符串中包含"INT",那么该字段的亲缘类型是INTEGER。
2). 如果类型字符串中包含"CHAR"、"CLOB"或"TEXT",那么该字段的亲缘类型是TEXT,如VARCHAR。
3). 如果类型字符串中包含"BLOB",那么该字段的亲缘类型是NONE。
4). 如果类型字符串中包含"REAL"、"FLOA"或"DOUB",那么该字段的亲缘类型是REAL。
5). 其余情况下,字段的亲缘类型为NUMERIC。
2. 具体示例:
声明类型 | 亲缘类型 | 应用规则 |
INT INTEGER TINYINT SMALLINT MEDIUMINT BIGINT UNSIGNED BIG INT INT2 INT8 |
INTEGER | 1 |
CHARACTER(20) VARCHAR(255) VARYING CHARACTER(255) NCHAR(55) NATIVE CHARACTER(70) NVARCHAR(100) TEXT CLOB |
TEXT | 2 |
BLOB | NONE | 3 |
REAL DOUBLE DOUBLE PRECISION FLOAT |
REAL | 4 |
NUMERIC DECIMAL(10,5) BOOLEAN DATE DATETIME |
NUMERIC | 5 |
注:在SQLite中,类型VARCHAR(255)的长度信息255没有任何实际意义,仅仅是为了保证与其它数据库的声明一致性。
三、比较表达式:
在SQLite3中支持的比较表达式有:"=", "==", "<", "<=", ">", ">=", "!=", "<>", "IN", "NOT IN", "BETWEEN", "IS" and "IS NOT"。
数据的比较结果主要依赖于操作数的存储方式,其规则为:
1). 存储方式为NULL的数值小于其它存储类型的值。
2). 存储方式为INTEGER和REAL的数值小于TEXT或BLOB类型的值,如果同为INTEGER或REAL,则基于数值规则进行比较。
3). 存储方式为TEXT的数值小于BLOB类型的值,如果同为TEXT,则基于文本规则(ASCII值)进行比较。
4). 如果是两个BLOB类型的数值进行比较,其结果为C运行时函数memcmp()的结果。
四、操作符:
所有的数学操作符(+, -, *, /, %, <<, >>, &, and |)在执行之前都会先将操作数转换为NUMERIC存储类型,即使在转换过程中可能会造成数据信息的丢失。此外,如果其中一个操作数为NULL,那么它们 的结果亦为NULL。在数学操作符中,如果其中一个操作数看上去并不像数值类型,那么它们结果为0或0.0。
-------
上面的这一小段来自:http://www.cnblogs.com/stephen-liu74/archive/2012/02/22/2325258.html,其实这里也有一份,不过这一份嘛 ,就整理的不太好了。所以我扔到code框里。。其实以前有一份pdf的,但一下子找不到了。而且。。。mac下看chm和pdf都不太爽。。
Submitted by gouki on 2012, October 15, 9:00 AM
归到数据库分类实在让我有点汗颜,毕竟这只是一个聚会性质的交流。并非真的就是与数据库相关,但内容因为还是涉及到了数据库,所以。。。归到这里吧。
这次大会去的比较晚了,因为小朋友的屁股上发了点东西(俗语:风疹块),所以本来是考虑不去的,但因为三件事,我还是去了:1、小朋友的屁股上用了以前的药,好了很多,几乎没了;2、票子送不掉,很多人一听是早上8点到场,都大义懔然的放弃了;3、锅巴引诱我,说是给我准备了特别的礼物
意外:意外在这里看到了前前同事,余老板,原来,她还在篱笆网,她笑称自己是钉子户,其实我是真的挺佩服她,能在国内一家互联网公司做超过5年,并不是一件容易的事情。
废话说了那么多,现在就让我们开始吧。
因为去的晚,所以对数据库与SSD的存储没有听到多少,但说白了,听了对我也没多大用处,小公司吧,用不上这些,大公司吧,可挑选的余地又太大,如果求稳,就研究不了新技术 ,如果求新技术 ,却又不能保证一定稳定,象网易,在云阅读上就用了SSD的硬件,我想他在备份上面的代价会是多少呢?小公司真的烧不起这个钱啊,虽然说混合应用的SSD+SATA的盘1T也才1000左右,但我们没那么多机房来折腾,也不会有dell公司的人来帮忙维护和技术支持,我们不是VIP用户啊,亲
第二个演讲的又是让我很郁闷的,虽然我在事前其实也很想知道这一块的东西,legenddb,类似于mysql proxy或者说mysqlcluster的工具,他们确实走在了我们的前面,但对应用型 的公司来说,没人敢用就是一个很大的问题。你没有完整的技术支持,不能保证后续的服务,出了BUG,你不能在很快响应。国内很多公司选择了mysql,有很大一部分原因在于,mysql社区版是开源的,所以可以有针对性的对它进行修改。如果你legend开源了,你还能走多久?legenddb,老谭也在台上说了,目前在某些join查询上效率还不是很高。而legenddb最大的功能其实就是用来做分布式数据库,并且通过timeline来做数据同步等(为了一致,每台服务器还必须得精准校验时间,否则可能会出问题,即数据出错),有兴趣的朋友可以上他们的网站上看看:http://www.mysqlab.net/,我感兴趣的原因是,它们说他们的软件是基于go开发的,黑黑
第三位演讲的是支付宝的朋友。讲了一个数据库的架构方面的设计,即又要保证ACID,还得让CAP这个标准也能够相对较好的应用。什么时候选择ACP,什么时候选择APC,都是一个讲究,在这上面,他用了一个简单的例子,即:用户付钱给商家。看起来很简单,但因为支付宝是担保交易,所以,简单的看起来就是:
1、用户支付时:用户update余额,中间帐户update状态
2、物流进行时:中间帐户维护状态
3、用户确认时:商家update余额,中间帐户update状态
只是在第一步的时候,特别是在聚划算的时候,传说每秒就是几千单,如果从传统意义上来说,没有一台服务器能够达到这样的效果,于是就采用了类似分片的效果,将中间帐户切分成N份(也就可以用N台机器来处理),然后再通过事务合并(这一段是我猜想。。。)
有时候说起来简单,做起来很复杂啊。比如他说,当搞活动的时候就加几台机器,活动结束后就减几台机器。对于程序来说,加减法并不是数学上的加减法,每加一台服务器,带来的成本和风险就会大几分,怎么把握也是一个难题。当然对于我这样的应用型人来说,暂时遇不到,很幸福啊。
好象我对第三位演讲的内容也介绍的比较水,但由于他的内容集中在CAP把握的度上,所以我也不太好介绍,毕竟我对这方面的掌握也不是特别的深
第四位是神仙,(http://xiezhenye.com/),介绍了mongodb的auto sharding。好吧,小公司又是不太会用的一个项目,在小项目中,mysql的查询效率并不会太低于mongodb。所以我就稍稍看了一下,主要也是因为auto sharding是自动切分的,我就不多介绍了。
不过,技术人员的通病就是,自己会用,但不会说。或者是在QQ里在聊天群里非常能说,但现场三棍子打不出个闷屁来,这都是一个问题。下一步我就是要建议thinkinlamp经常搞搞小型聚会,先内部交流,逼着大家上台讲。讲完了再下来沉淀,然后所有人讲完后,再接着讲一遍。只有这样,以后才能真正的走出来,不然,永远只是幕后,没有人认识你啊。
第五位是新浪微博的朋友。他先是很自我宣传了一下,然后介绍了他们在项目中用redis处理计数的功能。表面上很简单的几个数字,来的却并不方便,这其中最大的问题就是用户基数。用他们的话来说,就算是做cache,也不是那么简单的。注册用户3.x亿,每天发贴有1亿+,峰值达到了300W+/秒(这个数据记不清了,希望没错,据说是在春节那天),1亿的数据,相应的人员的微博数要加1,相关人员的未读数要+1,这些存储所花的代价是多少?好吧,我们先用100,000,000折腾一下,1M是多少字节?1G是多少字节?光这些+1所占的空间是多少?如果再加上要绑定的key呢?即用户ID,但又不是直接就用户ID+1,而是uid+comment,uid+post这类组合的key,这样一算的话,它的key得是多长?占了多少空间???说说都是很恐怖的事情,不要说是在做了,所以新浪在不停的为key减少空间。毕竟value只是一个整型,占的空间并不大,相反,key却真正的成了最大的存储空间占用的罪人。这一块的水比较深,我不多介绍。
其实中间还有一位厂商,DSG,但是我没有好好听,毕竟,oracle对我们来说太大了。。我还是初级用户。我很蛋定,谢谢。。。
中间,为了拿到锅巴准备的礼物,上去做一个“oppa 江南 style”的鸟叔POSE。。。。
Submitted by gouki on 2012, September 14, 1:47 PM
Redis 在运行一段时间后,发现有部分的数据确实没有缓存的必要,这时,切换数据库当然是一个办法。还有办法,flush掉所有的数据。
flush太危险了。所以。。还是删除key吧,比较安全一点。比如我删除keys "abc:*"的key
在cli里不能直接操作,但是可以
./redis-cli -n 0 keys "abc:*"|xargs ./redis-cli -n 0 del
这样就可以了。
不过因为我的正则不好,所以。。本来想长度为32的key都清掉的。。。(32位,你懂的)
还好某个库我不用了。。
Submitted by gouki on 2012, September 14, 1:42 PM
之前在“ Yii的又一个BUG?”提过我将数据导入到数据库时,进直接用ActiveRecord导入的,所以字段的类型都是String,后来发现问题,指定字段 为int值
这两天为了做一个查询,看了一下程序又遇到了问题:
同样的参数,同样的内容,一个查询能够有值,一个查询一点数据都没有。。。这是怎么回事?
一步步的测试下来,最后怀疑是字段类型,从$_GET回来的参数应该是字符串型而不是int,于是做了一个强制转换,数据果然就有了。我晕啊。。。大哥,你绕了我吧?
看来以后对于这类的数据,只要涉及mongo的,还是要多做一次额外的处理,否则连问题都没法发现。当然这也是因为不细心导致的。
慎记