处理上百万条的数据库如何提高处理查询速度

1.对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引。
2.应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索引而进行全表扫描,如:
select id from t where num is null
可以在num上设置默认值0,确保表中num列没有null值,然后这样查询:
select id from t where num=0
3.应尽量避免在 where 子句中使用!=或<>操作符,否则将引擎放弃使用索引而进行全表扫描。
4.应尽量避免在 where 子句中使用 or 来连接条件,否则将导致引擎放弃使用索引而进行全表扫描,如:
select id from t where num=10 or num=20
可以这样查询:
select id from t where num=10
union all
select id from t where num=20
5.in 和 not in 也要慎用,否则会导致全表扫描,如:
select id from t where num in(1,2,3)
对于连续的数值,能用 between 就不要用 in 了:
select id from t where num between 1 and 3
6.下面的查询也将导致全表扫描:
select id from t where name like ‘%abc%’
若要提高效率,可以考虑全文检索。
7.如果在 where 子句中使用参数,也会导致全表扫描。因为SQL只有在运行时才会解析局部变量,但优化程序不能将访问计划的选择推迟到运行时;它必须在编译时进行选择。然而,如果在编译时建立访问计划,变量的值还是未知的,因而无法作为索引选择的输入项。如下面语句将进行全表扫描:
select id from t where
可以改为强制查询使用索引:
select id from t with(index(索引名)) where
8.应尽量避免在 where 子句中对字段进行表达式操作,这将导致引擎放弃使用索引而进行全表扫描。如:
select id from t where num/2=100
应改为:
select id from t where num=100*2
9.应尽量避免在where子句中对字段进行函数操作,这将导致引擎放弃使用索引而进行全表扫描。如:
select id from t where substring(name,1,3)=’abc’–name以abc开头的id
select id from t where datediff(day,createdate,’2005-11-30′)=0–‘2005-11-30’生成的id
应改为:
select id from t where name like ‘abc%’
select id from t where createdate>=’2005-11-30′ and createdate<‘2005-12-1’
10.不要在 where 子句中的“=”左边进行函数、算术运算或其他表达式运算,否则系统将可能无法正确使用索引。
11.在使用索引字段作为条件时,如果该索引是复合索引,那么必须使用到该索引中的第一个字段作为条件时才能保证系统使用该索引,否则该索引将不会被使用,并且应尽可能的让字段顺序与索引顺序相一致。
12.不要写一些没有意义的查询,如需要生成一个空表结构:
select col1,col2 into #t from t where 1=0
这类代码不会返回任何结果集,但是会消耗系统资源的,应改成这样:
create table #t(…)
13.很多时候用 exists 代替 in 是一个好的选择:
select num from a where num in(select num from b)
用下面的语句替换:
select num from a where exists(select 1 from b where num=a.num)
14.并不是所有索引对查询都有效,SQL是根据表中数据来进行查询优化的,当索引列有大量数据重复时,SQL查询可能不会去利用索引,如一表中有字段sex,male、female几乎各一半,那么即使在sex上建了索引也对查询效率起不了作用。
15.索引并不是越多越好,索引固然可以提高相应的 select 的效率,但同时也降低了 insert 及 update 的效率,因为 insert 或 update 时有可能会重建索引,所以怎样建索引需要慎重考虑,视具体情况而定。一个表的索引数最好不要超过6个,若太多则应考虑一些不常使用到的列上建的索引是否有必要。
16.应尽可能的避免更新 clustered 索引数据列,因为 clustered 索引数据列的顺序就是表记录的物理存储顺序,一旦该列值改变将导致整个表记录的顺序的调整,会耗费相当大的资源。若应用系统需要频繁更新 clustered 索引数据列,那么需要考虑是否应将该索引建为 clustered 索引。
17.尽量使用数字型字段,若只含数值信息的字段尽量不要设计为字符型,这会降低查询和连接的性能,并会增加存储开销。这是因为引擎在处理查询和连接时会逐个比较字符串中每一个字符,而对于数字型而言只需要比较一次就够了。
18.尽可能的使用 varchar/nvarchar 代替 char/nchar ,因为首先变长字段存储空间小,可以节省存储空间,其次对于查询来说,在一个相对较小的字段内搜索效率显然要高些。
19.任何地方都不要使用 select * from t ,用具体的字段列表代替“*”,不要返回用不到的任何字段。
20.尽量使用表变量来代替临时表。如果表变量包含大量数据,请注意索引非常有限(只有主键索引)。
21.避免频繁创建和删除临时表,以减少系统表资源的消耗。
22.临时表并不是不可使用,适当地使用它们可以使某些例程更有效,例如,当需要重复引用大型表或常用表中的某个数据集时。但是,对于一次性事件,最好使用导出表。
23.在新建临时表时,如果一次性插入数据量很大,那么可以使用 select into 代替 create table,避免造成大量 log ,以提高速度;如果数据量不大,为了缓和系统表的资源,应先create table,然后insert。
24.如果使用到了临时表,在存储过程的最后务必将所有的临时表显式删除,先 truncate table ,然后 drop table ,这样可以避免系统表的较长时间锁定。
25.尽量避免使用游标,因为游标的效率较差,如果游标操作的数据超过1万行,那么就应该考虑改写。
26.使用基于游标的方法或临时表方法之前,应先寻找基于集的解决方案来解决问题,基于集的方法通常更有效。
27.与临时表一样,游标并不是不可使用。对小型数据集使用 FAST_FORWARD 游标通常要优于其他逐行处理方法,尤其是在必须引用几个表才能获得所需的数据时。在结果集中包括“合计”的例程通常要比使用游标执行的速度快。如果开发时间允许,基于游标的方法和基于集的方法都可以尝试一下,看哪一种方法的效果更好。
28.在所有的存储过程和触发器的开始处设置 SET NOCOUNT ON ,在结束时设置 SET NOCOUNT OFF 。无需在执行存储过程和触发器的每个语句后向客户端发送 DONE_IN_PROC 消息。
29.尽量避免大事务操作,提高系统并发能力。
30.尽量避免向客户端返回大数据量,若数据量过大,应该考虑相应需求是否合理。

j j j

tomcat6调优参数

service.xml配置
<Connector port=”8080″
redirectPort=”8443″
maxHttpHeaderSize=”8192″
useBodyEncodingForURI=”true”
minProcessors=”100″
maxProcessors=”5000″
maxThreads=”5000″
minSpareThreads=”1000″
maxSpareThreads=”4000″
enableLookups=”false”
acceptCount=”3500″
compression=”on”
compressionMinSize=”2048″
compressableMimeType=”text/html,text/xml,text/javascript,text/css,text/plain”
connectionTimeout=”20000″
disableUploadTimeout=”true”
debug=”0″
URIEncoding=”UTF-8″ />

j j j

CentOS上安装Memcached[转]

1.安装Memcached前需要先安装Libevent:# curl -O http://www.monkey.org/~provos/libevent-1.4.9-stable.tar.gz
# tar zxf libevent-1.4.9-stable.tar.gz
# cd libevent-1.4.9-stable
# ./configure
# make
# make install

 

2.接着安装Memcached:
# curl -O http://www.danga.com/memcached/dist/memcached-1.2.7.tar.gz
# tar zxf memcached-1.2.7.tar.gz
# cd memcached-1.2.7
# ./configure
# make
# make install

 

3.接着在当前用户的.bash_profile中添加

LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/lib
export LD_LIBRARY_PATH


4.运行

# memcached -m 512 -u nobody -vv

测试时候发现会出现以下错误信息:

“/usr/local/memcached/bin/memcached: error while loading shared libraries: libevent-1.4.so.2: cannot open shared object file: No such file or directory”

错误的原因是未在系统中注册Libevent. 解决方法如下:

# vi /etc/ld.so.conf.d/libevent-i386.conf

在VI中输入以下一行内容:

/usr/local/lib/

最后不要忘了
# ldconfig

 

5.运行

# memcached -m 512 -u nobody -vv

……….

<6 server listening
<7 server listening
<8 send buffer was 109568, now 268435456
<8 server listening (udp)
<9 send buffer was 109568, now 268435456
<9 server listening (udp)

Memcached运行正常。

原文:http://www.cnblogs.com/inrie/archive/2009/04/12/1434018.html

j j j

nginx上传限制

利用nginx做了play的前端服务器,应用一切正常,但是管理后台上传文件时,受到了限制,原来是nginx的一个参数惹的祸! client_max_body_size这个参数限制了上传文件的大小,默认是1M,此参数是在代理设置文件中配置的, 下面是我的proxy.conf 配置信息。
location / {
proxy_pass        http://fabo;
proxy_redirect          off;
proxy_set_header   Host             $host:80;
proxy_set_header   X-Real-IP        $remote_addr;
proxy_set_header   X-Forwarded-For  $proxy_add_x_forwarded_for;
client_max_body_size    1000m;
}

测试一下配置文件/usr/local/nginx/sbin/nginx -t
重启nginx:kill -HUP `cat /usr/local/nginx/logs/nginx.pid`
这里我的设置是1000M的上限,通过修改client_max_body_size 设置的大小,重启nginx服务,解决了文件上传问题!

j j j

CentOS 5.5 中 Python 升级到 2.6.5

Python升级的过程(CentOS 5.5 中实验成功,其他发行版本Linux可作参考)。

1、下载

wget http://www.python.org/ftp/python/2.6.5/Python-2.6.5.tar.bz22、解压tar jxvf Python-2.6.5.tar.bz23、编译安装cd Python-2.6.5./configuremake && make installPython 默认安装目录在/usr/local/lib/python2.6查看一下刚才安装的版本 /usr/local/lib/python2.6 -V,看到了2.6.5吧4、更改系统默认版本之前查看版本使用 /usr/local/lib/python2.6 -V,现在来把系统默认的Python指向刚才安装的Python2.6。(如果有人问为什么不把2.4.3卸载呢?呃,貌似网上有讲yum是基于2.4.3,所以我也就没那样折腾)mv /usr/bin/python /usr/bin/python.bakln -s /usr/local/bin/python2.6 /usr/bin/python敲入 python -V 查看是否成功。5、修复不能正常工作的yum在完成了上面4步之后,如果有使用yum的话会发现出错,这是因为yum 依赖2.4.3而现在默认的 Python 版本是2.6.5。vim /usr/bin/yum将首行显示的 !#/usr/bin/python 修改为 !#/usr/bin/python2.4保存搞定。

Python 安装Mysqldb问题
yum install MySQL-python

j j j

nginx搭建支持flv mp4 seek 实现拖拽

wget http://sourceforge.net/projects/pcre/files/pcre/8.12/pcre-8.12.zip/download

wget http://h264.code-shop.com/download/nginx_mod_h264_streaming-2.2.7.tar.gz

wget http://nginx.org/download/nginx-1.0.0.tar.gz
wget http://sourceforge.net/projects/yamdi/files/yamdi/1.8/yamdi-1.8.tar.gz/download

tar zxvf  yamdi-1.8.tar.gz
cd yamdi-1.8
gcc yamdi.c -o yamdi -O2 -Wall

mv yamdi /usr/bin/
注意我们编译的 yamdi 它起着重要的作用,因为一个FLV视频要能够拖拽播放,这个FLV在其 metadata中有关键桢的信息,但大部分FLV 是没有的。所以,我们要甬道开源的yamdi来为视频添加关键帧信息
命令为
yamdi -i input.flv -o out.flv

yamdi的参数:
-i 指定FLV源文件.
-o 指定输出文件,如果文件名为-,则输出到标准输出设备上,如果不指定也是
-x 插入的metadata信息XML文件。如果输出文件省略了,则只生成metadata信息.
-c 一个写入creator标签的字符串.
-l 添加 onLastSecond 行为.
-h 显示帮助信息.

安装nginx

安装nginx之前必须先安装pcre

pcre编译安装需要gcc gcc-c++

yum install gcc gcc-c++ openssl-devel zlib-devel

unzip pcre-8.12.zip

cd pcre-8.12

./configure

make && make install

tar zxvf  nginx_mod_h264_streaming-2.2.7.tar.gz
tar zxvf nginx-1.0.0.tar.gz
cd nginx-1.0.0
./configure  –user=www –group=www –with-http_sub_module –with-http_flv_module  –add-module=../nginx_mod_h264_streaming-2.2.7 –with-http_dav_module –with-http_stub_status_module –with-http_addition_module
make时会有报错如下:
make[1]: *** [objs/addon/src/ngx_http_h264_streaming_module.o] Error 1
make[1]: Leaving directory `/home/mock/BUILD_ROOT/BUILD/nginx-0.8.38′
make: *** [build] Error 2
解决办法:Vim nginx_mod_h264_streaming-2.2.7/src/ngx_http_streaming_module.c  将如下几行注释
/* TODO: Win32 */
if (r->zero_in_uri)
{
return NGX_DECLINED;
}
make && make install
nginx配置文件
#nginx.conf
worker_processes 1;
events {
use epoll;
worker_connections  65535;

}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
server {
listen 80;
server_name localhost;
location / {
root html;
index index.html index.htm;
}

location ~ \.mp4$ {
mp4;
}
location ~ \.flv$ {
flv;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
}
命令测试:
curl -v http://xx.xx.com/resbase/2010/06/baihezhengdan.flv?start=10240000 -o /dev/null
找个支持seek(拖拽)的播放器JWplayer
http://www.longtailvideo.com/support/jw-player-setup-wizard

j j j

解決圖層被Flash擋住的終極方法

如果網頁上有 Flash 的話,往往 Flash 會把彈出的圖層或是使用jQuery dialog彈出的視窗給擋住,(FF除外,IE6,7,8均出現被擋情況)

解決辦法就是給Flash設置透明的參數:wmode=”transparent”。

並在 embed 標籤中設置 wmode=”transparent”

如果還是有問題,可以嘗試給 Flash 外面增加一個 DIV 標籤,並給他設置 z-index:0; 的樣式即可。

針對flowplayer,需要修改代碼爲

$f(“fms”, {src:”/public/javascripts/flow/flowplayer-3.2.7.swf”,wmode: ‘transparent’}, {

…其他代碼

j j j

nginx无法正常显示图片和css的一个原因

前几天在服务器上面配置nginx,发现加入的一个网站无法正常显示图片和css样式表,百思不得其解。后来查看日志,发现

2011/07/19 18:33:06 [crit] 13321#0: *115 open() “/usr/local/nginx/proxy_temp/9/00/0000000009” failed (13: Permission denied) while reading upstream, client: 221.223.78.59,

这么一段,到网上一搜,才知道,原来是proxy_temp这个目录权限不够,因为nginx是用apache用户运行的,而这个目录是www权限,这就是修改了ngxin默认运行用户的后遗症。目录改完权限之后,问题解决。又学了一招。

j j j

Play framework+nginx反向代理无法获得remoteAddress解决办法

今天碰到一个问题,要在play里面判断客户端ip,从而判断用户来源,用nginx做反向代理,结果无论如何得到的都是127.0.0.1的地址

后来查了一些资料,记录如下:

1、play的application.conf的配置文件要加入一行:XForwardedSupport=127.0.0.1,10.0.0.25

When using an HTTP frontal server, request addresses are seen as coming from the HTTP server. In a usual set-up, where you both have the Play app and the proxy running on the same machine, the Play app will see the requests coming from 127.0.0.1.

Proxy servers can add a specific header to the request to tell the proxied application where the request came from. Most web servers will add an X-Forwarded-For header with the remote client IP address as first argument. If you enable the forward support in your Play app configuration:

XForwardedSupport=127.0.0.1,10.0.0.25
官方说法就是前端服务器会加入X-Forwarded-For这个参数,play就可以从前端服务器获取客户端ip地址了

不过光这些还不行

2、nginx配置文件还要在location里面加入

location / {
index  index.html index.htm index.jsp index.jspx index.do;
proxy_set_header        Host            $host;
proxy_set_header        X-Real-IP       $remote_addr;
proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass       http://127.0.0.1:9000;
client_max_body_size    1000m;  //上传文件设置最大可以上传1g档案
}

ok,问题解决,收工~~~

j j j

linux scp

假设本地主机linux100,远程主机linux200
一,在linux100主机里的用户
运行
#ssh-keygen -t rsa
结果如下
QUOTE:
Generating public/private rsa key pair.
Enter file in which to save the key (/home/.username/ssh/id_rsa):#回车
Enter passphrase (empty for no passphrase):#回车
Enter same passphrase again:#回车
Your identification has been saved in /home/.username /.ssh/id_rsa.
Your public key has been saved in /home/.username /.ssh/id_rsa.pub.
The key fingerprint is:
38:25:c1:4d:5d:d3:8946:67:bf:52:af:c3:17:0c username@localhost
Generating RSA keys:
Key generation complete.

会在用户目录~/.ssh/产生两个文件,id_rsa,id_rsa.pub
二,把linux100主机上的id_rsa.pub文件拷贝到linux200主机的root用户主目录下的.ssh目录下,并且改名为 authorized_keys
即:
/root/.ssh/authorized_keys
这样在linux100主机上使用scp命令复制文件到linux200上将不提示输入密码了,直接复制了。

反之亦然!

多主机认证,需要将id_rsa.pub先改名,在使用cat authorized_keys1.pub >> authorized_keys 追加即可

j j j