sqlite3连接查询和多次select的对比

作者:dawncold 发布时间:May 14, 2012 分类:技术

通过todo_meta把todo和user联系起来,要查出userid为0~6的所有todo。随机了10W条todo数据进去。

左外连接查询比两次select快10~20%左右。


#! /usr/bin/env python
# coding: utf-8

import sqlite3
import os
import time
import random

def connect():
	return sqlite3.connect('./test.db')


def insertProgress(conn, user_id):
	cur = conn.execute('INSERT INTO todo(title, date) VALUES(?,?)', ['just test!!!', time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())])
	conn.execute('INSERT INTO todo_meta(todo_id, user_id) VALUES(?,?)', [cur.lastrowid, user_id])


def insertManyData(conn):
	#reset database
	os.system('sqlite3 test.db < schema.sql')
	
	conn.cursor()
	counts = [0,0,0,0,0,0]
	for i in xrange(100000):
		userid = random.choice([0, 1, 2, 3, 4, 5])
		counts[userid] += 1
		insertProgress(conn, userid)
	conn.commit()
	conn.close()
	print counts

def selectUsingLeftOuterJoin(conn, user_id):
	conn.cursor()
	cur = conn.execute('SELECT t.title, t.date \
											FROM todo t LEFT OUTER JOIN todo_meta tm \
											ON tm.todo_id = t.id\
											WHERE tm.user_id = ?', [user_id])

def selectTwoTimes(conn, user_id):
	conn.cursor()
	cur = conn.execute('SELECT todo_id FROM todo_meta WHERE user_id = ?', [user_id])
	for tid in [row[0] for row in cur.fetchall()]:
		cur = conn.execute('SELECT title, date FROM todo WHERE id = ?', [tid])

if __name__ == "__main__":
	uids = [0, 1, 2, 3, 4, 5]
	insert_time_start = time.time()
	insertManyData(connect())
	print "Insert Time: %f" % (time.time() - insert_time_start)
	select_ULOJ_start = time.time()
	for uid in uids:
		selectUsingLeftOuterJoin(connect(), uid)
	print "Select Using Left Outer Join time: %f" % (time.time() - select_ULOJ_start)
	select_two_times = time.time()
	for uid in uids:
			selectTwoTimes(connect(), uid)
	print "Select Two Times time: %f" % (time.time() - select_two_times)

schema:


drop table if exists todo;
drop table if exists user;
drop table if exists todo_meta;
create table todo (
	id integer primary key autoincrement,
	title string not null,
	date datetime not null
);
create table user (
	id integer primary key autoincrement,
	email string not null,
	password string not null,
	nickname string not null,
	salt string not null
);
create table todo_meta (
	todo_id integer,
	user_id integer,
	foreign key(todo_id) references todo(id),
	foreign key(user_id) references user(id)
);

启动脚本就会创建数据库并开始测试。

sqlite3的rowcount

作者:dawncold 发布时间:May 14, 2012 分类:技术

最近写了一个todo的webapp,在用户登陆的时候是select数据库中的内容进行对比判断,当然如果select的内容是0那就表示用户登陆失败了,可能账号或者密码写错了,数据库用的sqlite3,在python的api中发现有cursor.rowcount可用,于是就这么判断一下是不是有数据被select出来了,没想到这样判断是错误的。

select的rowcount永远为-1,哎,这里着实坑了我一番啊~

只好cursor.fetchone()先,然后判断得到的内容是不是None。

这里得到的答案。

逆序对的求解

作者:dawncold 发布时间:May 7, 2012 分类:技术

今天看到算法导论上关于求解一个序列的逆序对的问题,以前自己在这个地方写着解答方法,不过今天怎么看都不懂了,从网上找了找,大都说得很模糊,不过自己突然有种领悟了的感觉,找了个简单的例子,实验了一下,自己的结论是正确的:)

例子是(2,3,8,6,1)这个序列,找出所有的5个逆序对。最好的方法是nlogn复杂度的利用归并排序的副产品——merge部分统计,统计比较左右列表时,左侧大于右侧时“左侧”列表中剩余数目。

归并的划分应该是这样的,(2,3,8)为左侧,(6,1)为右侧,继续划分为(2,3)和8,右边是6和1。下面就开始合并了,(2,3)和8这边还是(2,3,8),右侧出现一个逆序对,在合并6,1的时候因为作为“左侧”的6要大于1,所以这里有1个逆序对,这里的1就是此时“左侧”序列中的元素个数。

在往下走,要合并(2,3,8)和(1,6),马上就出现了2>1这样的情况,此时会出现(2,1)、(3,1)、(8,1)这几个逆序对,后面还会出现(8,6)这个逆序对,一共就这么5个。

因为原始序列是(2,3,8,6,1),我们需要用到这个原始序列的顺序来判断顺序排在前面的值却大于后面的,这样的机会在每次merge的时候是非常合适的。

这是修改后输出逆序对的归并排序算法,有点可惜哈,这么长的排序算法只让副产品在台前显露了一把!


#! /usr/bin/env python
# coding: utf-8

def merge(arraylist, first, middle, last):
    temp = []
    i = first
    j = middle + 1
    while i <= middle and j <= last:
        if arraylist[i] <= arraylist[j]:
            temp.append(arraylist[i])
            i += 1
        else:
            for x in arraylist[i:middle + 1]:
                print "(%d,%d)" % (x, arraylist[j])
            temp.append(arraylist[j])
            j += 1
    while i <= middle:
        temp.append(arraylist[i])
        i += 1
    while j <= last:
        temp.append(arraylist[j])
        j += 1
    for i in range(0, last - first + 1):
        arraylist[first + i] = temp[i]

def merge_sort(arraylist, first, last):
    if first < last:
        middle = (first + last) / 2
        merge_sort(arraylist, first, middle)
        merge_sort(arraylist, middle + 1, last)
        merge(arraylist, first, middle, last)

if __name__ == "__main__":
	lst = [2,3,8,6,1]
	merge_sort(lst, 0, len(lst) - 1)

运行结果:


(6,1)
(2,1)
(3,1)
(8,1)
(8,6)

(我的代码缩进似乎出了点问题,本身这段归并排序也是从网上找来的,所以混合了不少tab和whitespace,弄了好久都是error indent,最后我无奈用whitespace来做缩进,好歹调试通过了!)

web.py真不好用

作者:dawncold 发布时间:May 6, 2012 分类:技术

本来做了个一个todo的app感觉python写web app真得好快啊,于是想加入一个user的功能,这样注册的用户就可以写自己的todo了,不过这么一加才感觉到web.py真不好用了,特别是session,还有templates也不怎么好用,官方的文档不知道为何也不给个完整版的,api只是写出来了,但基本都不说是什么作用,想清楚知道运行机制那就得看源代码了,还好不“那么”长!

哎,暂时就放一下web.py吧!到头来过度依赖框架绝对不是什么好事,嗯,不是什么好兆头现在的我!

网站都挂掉了

作者:dawncold 发布时间:May 2, 2012 分类:技术

突然发现mysql无法用localhost连接进去,而用127.0.0.1可以。

linux下是这样的,如果用localhost连接是走的socket路线,用127.0.0.1走的是tcp路线。

修改了php.ini中的mysql.default_socket,值为mysql.sock的文件路径,重启php就好了,不过phpmyadmin的问题依然没有解决,我只是把连接主机换成了127.0.0.1暂时用着。