压缩Sqlite数据文件大小,解决数据删除后占用空间不变的问题

估计有人在使用sqlite数据库时,会有这种情况,删除数据库里面的一些数据后,却发现Sqlite数据库文件占用空间的大小一点没有少,这是为什么呢?

原因:

当你从Sqlite删除数据后,未使用的磁盘空间被添加到一个内在的”空闲列表”中用于存储你下次插入的数据。磁盘空间并没有丢失。但是也不向操作系统返回磁盘空间。

解决方法:

1.手动执行VACUUM命令

 

 

 

 

 

 

 

 

 

 

 

 

 

 

2.自动VACUUM

 

下面是VACUUM命令的详细说明

 

SQLite Vacuum

VACUUM 命令通过复制主数据库中的内容到一个临时数据库文件,然后清空主数据库,并从副本中重新载入原始的数据库文件。这消除了空闲页,把表中的数据排列为连续的,另外会清理数据库文件结构。

如果表中没有明确的整型主键(INTEGER PRIMARY KEY),VACUUM 命令可能会改变表中条目的行 ID(ROWID)。VACUUM 命令只适用于主数据库,附加的数据库文件是不可能使用 VACUUM 命令。

如果有一个活动的事务,VACUUM 命令就会失败。VACUUM 命令是一个用于内存数据库的任何操作。由于 VACUUM 命令从头开始重新创建数据库文件,所以 VACUUM 也可以用于修改许多数据库特定的配置参数。

手动 VACUUM

下面是在命令提示符中对整个数据库发出 VACUUM 命令的语法:

$sqlite3 database_name "VACUUM;"

您也可以在 SQLite 提示符中运行 VACUUM,如下所示:

sqlite> VACUUM;

您也可以在特定的表上运行 VACUUM,如下所示:

sqlite> VACUUM table_name;

自动 VACCUM(Auto-VACUUM)

SQLite 的 Auto-VACUUM 与 VACUUM 不大一样,它只是把空闲页移到数据库末尾,从而减小数据库大小。通过这样做,它可以明显地把数据库碎片化,而 VACUUM 则是反碎片化。所以 Auto-VACUUM 只会让数据库更小。

在 SQLite 提示符中,您可以通过下面的编译运行,启用/禁用 SQLite 的 Auto-VACUUM:

sqlite> PRAGMA auto_vacuum = NONE;  -- 0 means disable auto vacuum
sqlite> PRAGMA auto_vacuum = INCREMENTAL;  -- 1 means enable incremental vacuum
sqlite> PRAGMA auto_vacuum = FULL;  -- 2 means enable full auto vacuum

您可以从命令提示符中运行下面的命令来检查 auto-vacuum 设置:

$sqlite3 database_name "PRAGMA auto_vacuum;"

PHP中字符串和数字比较(很容易出的问题)

PHP中的比较运算符有点诡异,很容易出错,现列出比较规则:

1).当两个字符进行比较时,比较这两个字符的ASCII码

2).当两个字符串进行比较时,从第一个字符开始挨个比较对应的ASCII码,知道某一位置两个字符ASCII码不一致时给出结果,如’ba’>’az’,’10′<‘a’

3).当一个数字与一个字符/字符串比较时,首先将字符/字符串转化为数字,再与数字进行比较,如12<’21as’, ‘dsa’=0,同理 ‘a’+10=10;

4).当两个数字字符串进行比较时,首先将两个字符串当做数字,并且用科学计数法存储这两个字符串,科学计数法保留小数点后16位,再进行比较。

由此就会产生一个bug

如:$str1 = “123456789012345678”;

$str2 = “123456789012345679”;

(最后一位不一样)

在比较时会先将两个字符串用科学计数法进行储存,因为保留16位小数,所以结果为

$str1=1.2345678901234567E+17;

$str2=1.2345678901234567E+17。

结果再比较就会产生$str1 等于 $str2 这样的结果;

解决办法为使用 === 或者strcmp等字符串比较函数进行强类型判断

另外,长度不同、在字符串中加非数字字符等等都会引起两个字符串的不等。

例如:$str1 = “a123456789012345678”;

$str2 = “a123456789012345679”;

此时$str1 和 $str2就不相等,因为存在a 这个非数字字符,所以系统不会讲两个字符串当成数字字符串进行比较,而是使用 2)中两个字符串比较方法。

下面是示例代码:

 var_dump('1000000'<'a');    //result: boolean true
 var_dump('a'<1);            //result: boolean true
 var_dump(1<'1000000');      //result: boolean true
 var_dump(1=='1adde');     //result: boolean true

 

java和php在继承中构造函数得简单对比

今天简单对比一下java和php的构造函数在继承中的不同。

Java中:

情况1:父类如果有无参数的构造函数,子类无论写没写构造函数,则会自动隐式调用父类构造

class Human{
    Human(){
        System.out.println("父类构造函数");
    }
}
class Man extends Human{
    Man(){
        System.out.println("子类构造函数");
    }
    public static void main(String[] args) {
        Man m=new Man();
    }
}

情况2:如果父类构造是有参数的,你则必须手动使用super关键字来调用,否则编译不通过

php中:

情况1:如果父类有构造函数,子类没有构造函数,子类则会自动调用父类构造。

情况2:如果父类有构造函数,子类也有构造函数,这个时候子类的构造函数则会覆盖父类构造,你必须使用parent关键字手动调用父类构造

<?php 
class Human{
    public function __construct(){
        echo '父类构造函数';
    }
   
}
class Man extends Human{
    public function __construct(){
        parent::__construct();
        echo '子类构造函数';
    }

}

$stu=new Man();

[laravel]laravel配置多数据库和操作多数据库

首先声明连接

<?php return array( 'default' => 'mysql',



'connections' => array(



    # Our primary database connection

    'mysql' => array(

        'driver'    => 'mysql',

        'host'      => 'host1',

        'database'  => 'database1',

        'username'  => 'user1',

        'password'  => 'pass1'

        'charset'   => 'utf8',

        'collation' => 'utf8_unicode_ci',

        'prefix'    => '',

    ),



    # Our secondary database connection

    'mysql2' => array(

        'driver'    => 'mysql',

        'host'      => 'host2',

        'database'  => 'database2',

        'username'  => 'user2',

        'password'  => 'pass2'

        'charset'   => 'utf8',

        'collation' => 'utf8_unicode_ci',

        'prefix'    => '',

    ),

),

);

在查询的时候,指明你前面声明的连接名称

$users = DB::connection('mysql2')->select(...);

或者在eloquent的model里面指明你要使用的连接

<?php 
class SomeModel extends Eloquent {

protected $connection = 'mysql2';

}

MySQL数据类型:使用unsigned得注意事项

unsigned说明

unsigned属性就是将数字类型无符号化,例如INT的类型范围是-2 147 483 648 ~ 2 147 483 647, INT UNSIGNED的范围类型就是0 ~ 4 294 967 295。可以增加字段长度。

在MYSQL中整型范围:

类型                      大小        范围(有符号)                               范围(无符号) 用途

TINYINT            1 字节    (-128,127)                                       (0,255) 小整数值

SMALLINT         2 字节    (-32 768,32 767)                             (0,65 535) 大整数值

MEDIUMINT     3 字节    (-8 388 608,8 388 607)                    (0,16 777 215) 大整数值

INT或INTEGER  4 字节    (-2 147 483 648,2 147 483 647)       (0,4 294 967 295) 大整数值

猛得看起来这是一个不错的属性选项,特别是对于主键是自增长的类型,因为一般来说,用户都希望主键是非负数。然而在实际使用中,UNSIGNED可能会带来一些负面的影响,让我们一起来看看:

先建一张测试表:

DROP TABLE IF EXISTS `test`;
CREATE TABLE `test` (
 `a` int(255) unsigned NOT NULL,
 `b` int(255) unsigned NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

创建了一个表test,存储引擎为InnoDB。表上有两个UNSIGNED的INT类型,接着我们来运行下面一句sql:

select a-b from test

这时结果会是什么呢?会是-1吗?答案是不确定的,可以是-1,也可以是一个很大的正值,还可能会报错.

在windows中会报如下错误:

[Err] 1690 – BIGINT UNSIGNED value is out of range in ‘(`test1`.`test`.`a` – `test1`.`test`.`b`)’

在linux中会得出:

a – b: 4294967295

哎,纳闷了,怎么没有得出我们心中的结果呢?

这个问题的核心是,在MySQL数据库中,对于UNSIGNED数的操作,其返回值都是UNSIGNED的。而正负数这个问题在《MySQL技术内幕:InnoDB存储引擎》中有更深入的分析,有兴趣的可以进一步研究。

那么,怎么获得-1这个值呢?这并不是一件难事,只要对SQL_MODE这个参数进行设置即可,

SET sql_mode='NO_UNSIGNED_SUBTRACTION';

Query OK, 0 rows affected (0.00 sec)

mysql> SELECT a-b FROM t\G;

个人的看法是不要随便使用UNSIGNED,看情况而定,因为可能会带来一些意想不到的效果。另外,对于INT类型可能存放不了的数据,INT UNSIGNED同样可能存放不了,与其如此,还不如在数据库设计阶段将INT类型提升为BIGINT类型。