成人午夜视频全免费观看高清-秋霞福利视频一区二区三区-国产精品久久久久电影小说-亚洲不卡区三一区三区一区

postgresql測(cè)試的簡(jiǎn)單介紹

如何用 sysbench 并行裝載 PostgreSQL 測(cè)試數(shù)據(jù)

sysbench原來自帶的lua數(shù)據(jù)裝載腳本是使用以下方式串行裝載的,速度比較慢(比單條insert快,但是比COPY慢)。

我們提供的服務(wù)有:網(wǎng)站建設(shè)、網(wǎng)站制作、微信公眾號(hào)開發(fā)、網(wǎng)站優(yōu)化、網(wǎng)站認(rèn)證、鶴山ssl等。為上1000+企事業(yè)單位解決了網(wǎng)站和推廣的問題。提供周到的售前咨詢和貼心的售后服務(wù),是有科學(xué)管理、有技術(shù)的鶴山網(wǎng)站制作公司

insert into table1 values (),(),()....

insert into table2 values (),(),()....

...

insert into tablen values (),(),()....

使用prepare導(dǎo)入數(shù)據(jù)的用法舉例

./sysbench_pg --test=lua/oltp.lua --db-driver=pgsql --pgsql-host=127.0.0.1 --pgsql-port=1921 --pgsql-user=postgres --pgsql-password=postgres --pgsql-db=postgres --oltp-tables-count=64 --oltp-table-size=1000000 --num-threads=64 prepare

prepare 表示裝載數(shù)據(jù),但是它串行的。

sysbench0.5中可以在命令行中指定測(cè)試時(shí)啟動(dòng)的并行線程數(shù),這個(gè)測(cè)試過程是使用run命令,而且是多線程并發(fā)的,所以我們可以使用sysbench的run命令來造數(shù)據(jù),而不再使用其提供的prepare命令的方法來造數(shù)據(jù)。run命令會(huì)根據(jù)命令行參數(shù)--num-threads來指定并發(fā)線程數(shù)的多少。

在sysbench中自定義的lua腳本中要求實(shí)現(xiàn)以下幾個(gè)函數(shù):

function thread_init(thread_id): 此函數(shù)在線程創(chuàng)建后只被執(zhí)行一次

function event(thread_id): 每執(zhí)行一次就會(huì)被調(diào)用一次。

由上可以知道,本次造數(shù)據(jù)的腳本我們只需要實(shí)現(xiàn)thread_init()函數(shù)就可以了。

生成測(cè)試數(shù)據(jù)的腳本沿用老唐提供的代碼:

#include stdio.h

#include stdlib.h

#include time.h

#include stdint.h

#include sys/time.h

uint64_t my_rand(struct random_data * r1, struct random_data * r2)

{

uint64_t rand_max = 100000000000LL;

uint64_t result;

uint32_t u1, u2;

random_r(r1, u1);

random_r(r2, u2);

result = (int64_t)u1 * (int64_t)u2;

result = result % rand_max;

return result;

}

int main(int argc, char *argv[])

{

struct timeval tpstart;

struct random_data r1, r2;

int i;

int r;

int max_value;

char rand_state1[128];

char rand_state2[128];

if (argc !=2)

{

printf("Usage: %s rownums\n", argv[0]);

return 1;

}

max_value = atoi(argv[1]);

gettimeofday(tpstart,NULL);

initstate_r(tpstart.tv_usec,rand_state1,sizeof(rand_state1),r1);

srandom_r(tpstart.tv_usec, r1);

gettimeofday(tpstart,NULL);

initstate_r(tpstart.tv_usec,rand_state2,sizeof(rand_state1),r2);

srandom_r(tpstart.tv_usec, r2);

for (i=1; imax_value+1; i++)

{

r = my_rand(r1, r2) % max_value;

printf("%d,%d,%011llu-%011llu-%011llu-%011llu-%011llu-%011llu-%011llu-%011llu-%011llu-%011llu,%011llu-%011llu-%011llu-%011llu-%011llu\n",

i,

r,

my_rand(r1, r2),

my_rand(r1, r2),

my_rand(r1, r2),

my_rand(r1, r2),

my_rand(r1, r2),

my_rand(r1, r2),

my_rand(r1, r2),

my_rand(r1, r2),

my_rand(r1, r2),

my_rand(r1, r2),

my_rand(r1, r2),

my_rand(r1, r2),

my_rand(r1, r2),

my_rand(r1, r2),

my_rand(r1, r2)

);

}

return 0;

}

編譯此C語言程序的方法如下:

gcc gendata.c -o gendata

新建一個(gè)copy.lua的腳本,內(nèi)容如下

調(diào)用 common.lua中的 set_vars() 繼承來自 common.lua 的全局變量。

函數(shù) copydata(table_id) : 創(chuàng)建表,創(chuàng)建管道,將管道數(shù)據(jù)傳輸?shù)絧sql -c "copy ..."客戶端的方式導(dǎo)入數(shù)據(jù)。

函數(shù) create_index(table_id) : 創(chuàng)建索引,調(diào)整SEQUENCE next val。

注意咯, oltp_tables_count 必須是 num_threads 的倍數(shù),在 thread_init 中, 以num_threads 為步調(diào),以thread_id+1為起始值,設(shè)置i的值,并調(diào)用copydata(table_id)和create_index(table_id)。

$ vi lua/copy.lua

pathtest = string.match(test, "(.*/)") or ""

dofile(pathtest .. "common.lua")

function copydata(table_id)

local query

query = [[

CREATE UNLOGGED TABLE sbtest]] .. table_id .. [[ (

id SERIAL NOT NULL,

k INTEGER,

c CHAR(120) DEFAULT '' NOT NULL,

pad CHAR(60) DEFAULT '' NOT NULL,

PRIMARY KEY (id)

) ]]

db_query(query)

os.execute ('export PGPASSWORD=' .. pgsql_password)

os.execute ('rm -f sbtest' .. table_id .. '.dat')

os.execute ('mknod sbtest' .. table_id .. '.dat p')

os.execute ('./gendata ' .. oltp_table_size .. ' sbtest'..table_id ..'.dat ')

os.execute ('cat sbtest' .. table_id .. '.dat | psql -h ' .. pgsql_host .. ' -p ' .. pgsql_port .. ' -U ' .. pgsql_user .. ' -d ' .. pgsql_db .. ' -c "copy sbtest' .. table_id .. ' from stdin with csv"')

os.execute ('rm -f sbtest' .. table_id .. '.dat')

end

function create_index(table_id)

db_query("select setval('sbtest" .. table_id .. "_id_seq', " .. (oltp_table_size+1) .. ")" )

db_query("CREATE INDEX k_" .. table_id .. " on sbtest" .. table_id .. "(k)")

end

function thread_init(thread_id)

set_vars()

print("thread prepare"..thread_id)

for i=thread_id+1, oltp_tables_count, num_threads do

copydata(i)

create_index(i)

end

end

function event(thread_id)

os.exit()

end

用法,必須把psql放到路徑中,因?yàn)閘ua中需要用到psql命令

export PATH=/home/digoal/pgsql9.5/bin:$PATH

生成數(shù)據(jù),速度比以前快多了

./sysbench_pg --test=lua/copy.lua \

--db-driver=pgsql \

--pgsql-host=127.0.0.1 \

--pgsql-port=1921 \

--pgsql-user=postgres \

--pgsql-password=postgres \

--pgsql-db=postgres \

--oltp-tables-count=64 \

--oltp-table-size=1000000 \

--num-threads=64 \

run

清除數(shù)據(jù), drop table

./sysbench_pg --test=lua/copy.lua \

--db-driver=pgsql \

--pgsql-host=127.0.0.1 \

--pgsql-port=1921 \

--pgsql-user=postgres \

--pgsql-password=postgres \

--pgsql-db=postgres \

--oltp-tables-count=64 \

--oltp-table-size=1000000 \

--num-threads=64 \

cleanup

lua全局變量代碼:

sysbench/scripting/lua/src/lua.h:#define lua_register(L,n,f) (lua_pushcfunction(L, (f)), lua_setglobal(L, (n)))

sysbench/scripting/lua/src/lua.h:#define lua_setglobal(L,s) lua_setfield(L, LUA_GLOBALSINDEX, (s))

sysbench/scripting/lua/src/lbaselib.c: lua_setglobal(L, "_G");

sysbench/scripting/lua/src/lbaselib.c: lua_setglobal(L, "_VERSION"); /* set global _VERSION */

sysbench/scripting/lua/src/lbaselib.c: lua_setglobal(L, "newproxy"); /* set global `newproxy' */

sysbench/scripting/script_lua.c: lua_setglobal(state, opt-name);

sysbench/scripting/script_lua.c: lua_setglobal(state, "sb_rand");

sysbench/scripting/script_lua.c: lua_setglobal(state, "sb_rand_uniq");

sysbench/scripting/script_lua.c: lua_setglobal(state, "sb_rnd");

sysbench/scripting/script_lua.c: lua_setglobal(state, "sb_rand_str");

sysbench/scripting/script_lua.c: lua_setglobal(state, "sb_rand_uniform");

sysbench/scripting/script_lua.c: lua_setglobal(state, "sb_rand_gaussian");

sysbench/scripting/script_lua.c: lua_setglobal(state, "sb_rand_special");

sysbench/scripting/script_lua.c: lua_setglobal(state, "db_connect");

sysbench/scripting/script_lua.c: lua_setglobal(state, "db_disconnect");

sysbench/scripting/script_lua.c: lua_setglobal(state, "db_query");

sysbench/scripting/script_lua.c: lua_setglobal(state, "db_bulk_insert_init");

sysbench/scripting/script_lua.c: lua_setglobal(state, "db_bulk_insert_next");

sysbench/scripting/script_lua.c: lua_setglobal(state, "db_bulk_insert_done");

sysbench/scripting/script_lua.c: lua_setglobal(state, "db_prepare");

sysbench/scripting/script_lua.c: lua_setglobal(state, "db_bind_param");

sysbench/scripting/script_lua.c: lua_setglobal(state, "db_bind_result");

sysbench/scripting/script_lua.c: lua_setglobal(state, "db_execute");

sysbench/scripting/script_lua.c: lua_setglobal(state, "db_close");

sysbench/scripting/script_lua.c: lua_setglobal(state, "db_store_results");

sysbench/scripting/script_lua.c: lua_setglobal(state, "db_free_results");

sysbench/scripting/script_lua.c: lua_setglobal(state, "DB_ERROR_NONE");

sysbench/scripting/script_lua.c: lua_setglobal(state, "DB_ERROR_DEADLOCK");

sysbench/scripting/script_lua.c: lua_setglobal(state, "DB_ERROR_FAILED");

sysbench/scripting/script_lua.c: lua_setglobal(L, "db_driver");

傳入?yún)?shù),可以把sysbench_pg的參數(shù)-替換成_在lua腳本中使用這些變量,例子

--pgsql-host=127.0.0.1 - 對(duì)應(yīng)lua中的變量名 pgsql_host

--pgsql-port=1921 - 對(duì)應(yīng)lua中的變量名 pgsql_port

--pgsql-user=postgres - 對(duì)應(yīng)lua中的變量名 pgsql_user

--pgsql-password=postgres - 對(duì)應(yīng)lua中的變量名 pgsql_password

--pgsql-db=postgres - 對(duì)應(yīng)lua中的變量名 pgsql_db

--oltp-tables-count=64 - 對(duì)應(yīng)lua中的變量名 oltp_tables_count

--oltp-table-size=1000000 - 對(duì)應(yīng)lua中的變量名 oltp_table_size

--num-threads=64 - 對(duì)應(yīng)lua中的變量名 num_threads

postgresql 建立索引

一、索引的類型:

PostgreSQL提供了多種索引類型:B-Tree、Hash、GiST和GIN,由于它們使用了不同的算法,因此每種索引類型都有其適合的查詢類型,缺省時(shí),CREATE INDEX命令將創(chuàng)建B-Tree索引。

1. B-Tree:

CREATE TABLE test1 (

id integer,

content varchar

);

CREATE INDEX test1_id_index ON test1 (id);

B-Tree索引主要用于等于和范圍查詢,特別是當(dāng)索引列包含操作符" 、=和"作為查詢條件時(shí),PostgreSQL的查詢規(guī)劃器都會(huì)考慮使用B-Tree索引。在使用BETWEEN、IN、IS NULL和IS NOT NULL的查詢中,PostgreSQL也可以使用B-Tree索引。然而對(duì)于基于模式匹配操作符的查詢,如LIKE、ILIKE、~和 ~*,僅當(dāng)模式存在一個(gè)常量,且該常量位于模式字符串的開頭時(shí),如col LIKE 'foo%'或col ~ '^foo',索引才會(huì)生效,否則將會(huì)執(zhí)行全表掃描,如:col LIKE '%bar'。

2. Hash:

CREATE INDEX name ON table USING hash (column);

散列(Hash)索引只能處理簡(jiǎn)單的等于比較。當(dāng)索引列使用等于操作符進(jìn)行比較時(shí),查詢規(guī)劃器會(huì)考慮使用散列索引。

這里需要額外說明的是,PostgreSQL散列索引的性能不比B-Tree索引強(qiáng),但是散列索引的尺寸和構(gòu)造時(shí)間則更差。另外,由于散列索引操作目前沒有記錄WAL日志,因此一旦發(fā)生了數(shù)據(jù)庫崩潰,我們將不得不用REINDEX重建散列索引。

3. GiST:

GiST索引不是一種單獨(dú)的索引類型,而是一種架構(gòu),可以在該架構(gòu)上實(shí)現(xiàn)很多不同的索引策略。從而可以使GiST索引根據(jù)不同的索引策略,而使用特定的操作符類型。

4. GIN:

GIN索引是反轉(zhuǎn)索引,它可以處理包含多個(gè)鍵的值(比如數(shù)組)。與GiST類似,GIN同樣支持用戶定義的索引策略,從而可以使GIN索引根據(jù)不同的索引策略,而使用特定的操作符類型。作為示例,PostgreSQL的標(biāo)準(zhǔn)發(fā)布中包含了用于一維數(shù)組的GIN操作符類型,如:、=、等。

二、復(fù)合索引:

PostgreSQL中的索引可以定義在數(shù)據(jù)表的多個(gè)字段上,如:

CREATE TABLE test2 (

major int,

minor int,

name varchar

}

CREATE INDEX test2_mm_idx ON test2 (major, minor);

1. B-Tree類型的復(fù)合索引:

在B-Tree類型的復(fù)合索引中,該索引字段的任意子集均可用于查詢條件,不過,只有當(dāng)復(fù)合索引中的第一個(gè)索引字段(最左邊)被包含其中時(shí),才可以獲得最高效率。

2. GiST類型的復(fù)合索引:

在GiST類型的復(fù)合索引中,只有當(dāng)?shù)谝粋€(gè)索引字段被包含在查詢條件中時(shí),才能決定該查詢會(huì)掃描多少索引數(shù)據(jù),而其他索引字段上的條件只是會(huì)限制索引返回的條目。假如第一個(gè)索引字段上的大多數(shù)數(shù)據(jù)都有相同的鍵值,那么此時(shí)應(yīng)用GiST索引就會(huì)比較低效。

3. GIN類型的復(fù)合索引:

與B-Tree和GiST索引不同的是,GIN復(fù)合索引不會(huì)受到查詢條件中使用了哪些索引字段子集的影響,無論是哪種組合,都會(huì)得到相同的效率。

使用復(fù)合索引應(yīng)該謹(jǐn)慎。在大多數(shù)情況下,單一字段上的索引就已經(jīng)足夠了,并且還節(jié)約時(shí)間和空間。除非表的使用模式非常固定,否則超過三個(gè)字段的索引幾乎沒什么用處。

三、組合多個(gè)索引:

PostgreSQL可以在查詢時(shí)組合多個(gè)索引(包括同一索引的多次使用),來處理單個(gè)索引掃描不能實(shí)現(xiàn)的場(chǎng)合。與此同時(shí),系統(tǒng)還可以在多個(gè)索引掃描之間組成AND和OR的條件。比如,一個(gè)類似WHERE x = 42 OR x = 47 OR x = 53 OR x = 99的查詢,可以被分解成四個(gè)獨(dú)立的基于x字段索引的掃描,每個(gè)掃描使用一個(gè)查詢子句,之后再將這些掃描結(jié)果OR在一起并生成最終的結(jié)果。另外一個(gè)例子是,如果我們?cè)趚和y上分別存在獨(dú)立的索引,那么一個(gè)類似WHERE x = 5 AND y = 6的查詢,就會(huì)分別基于這兩個(gè)字段的索引進(jìn)行掃描,之后再將各自掃描的結(jié)果進(jìn)行AND操作并生成最終的結(jié)果行。

為了組合多個(gè)索引,系統(tǒng)掃描每個(gè)需要的索引,然后在內(nèi)存里組織一個(gè)BITMAP,它將給出索引掃描出的數(shù)據(jù)在數(shù)據(jù)表中的物理位置。然后,再根據(jù)查詢的需要,把這些位圖進(jìn)行AND或者OR的操作并得出最終的BITMAP。最后,檢索數(shù)據(jù)表并返回?cái)?shù)據(jù)行。表的數(shù)據(jù)行是按照物理順序進(jìn)行訪問的,因?yàn)檫@是位圖的布局,這就意味著任何原來的索引的排序都將消失。如果查詢中有ORDER BY子句,那么還將會(huì)有一個(gè)額外的排序步驟。因?yàn)檫@個(gè)原因,以及每個(gè)額外的索引掃描都會(huì)增加額外的時(shí)間,這樣規(guī)劃器有時(shí)候就會(huì)選擇使用簡(jiǎn)單的索引掃描,即使有多個(gè)索引可用也會(huì)如此。

四、唯一索引:

CREATE UNIQUE INDEX name ON table (column [, ...]);

五、表達(dá)式索引:

表達(dá)式索引主要用于在查詢條件中存在基于某個(gè)字段的函數(shù)或表達(dá)式的結(jié)果與其他值進(jìn)行比較的情況,如:

SELECT * FROM test1 WHERE lower(col1) = 'value';

此時(shí),如果我們僅僅是在col1字段上建立索引,那么該查詢?cè)趫?zhí)行時(shí)一定不會(huì)使用該索引,而是直接進(jìn)行全表掃描。如果該表的數(shù)據(jù)量較大,那么執(zhí)行該查詢也將會(huì)需要很長(zhǎng)時(shí)間。解決該問題的辦法非常簡(jiǎn)單,在test1表上建立基于col1字段的表達(dá)式索引,如:

CREATE INDEX test1_lower_col1_idx ON test1 (lower(col1));

SELECT * FROM people WHERE (first_name || ' ' || last_name) = 'John Smith';

和上面的例子一樣,盡管我們可能會(huì)為first_name和last_name分別創(chuàng)建獨(dú)立索引,或者是基于這兩個(gè)字段的復(fù)合索引,在執(zhí)行該查詢語句時(shí),這些索引均不會(huì)被使用,該查詢能夠使用的索引只有我們下面創(chuàng)建的表達(dá)式索引。

CREATE INDEX people_names ON people ((first_name || ' ' || last_name));

CREATE INDEX命令的語法通常要求在索引表達(dá)式周圍書寫圓括弧,就像我們?cè)诘诙€(gè)例子里顯示的那樣。如果表達(dá)式只是一個(gè)函數(shù)調(diào)用,那么可以省略,就像我們?cè)诘谝粋€(gè)例子里顯示的那樣。

從索引維護(hù)的角度來看,索引表達(dá)式要相對(duì)低效一些,因?yàn)樵诓迦霐?shù)據(jù)或者更新數(shù)據(jù)的時(shí)候,都必須為該行計(jì)算表達(dá)式的結(jié)果,并將該結(jié)果直接存儲(chǔ)到索引里。然而在查詢時(shí),PostgreSQL就會(huì)把它們看做WHERE idxcol = 'constant',因此搜索的速度等效于基于簡(jiǎn)單索引的查詢。通常而言,我們只是應(yīng)該在檢索速度比插入和更新速度更重要的場(chǎng)景下使用表達(dá)式索引。

六、部分索引:

部分索引(partial index)是建立在一個(gè)表的子集上的索引,而該子集是由一個(gè)條件表達(dá)式定義的(叫做部分索引的謂詞)。該索引只包含表中那些滿足這個(gè)謂詞的行。

由于不是在所有的情況下都需要更新索引,因此部分索引會(huì)提高數(shù)據(jù)插入和數(shù)據(jù)更新的效率。然而又因?yàn)椴糠炙饕绕胀ㄋ饕?,因此可以更好的提高確實(shí)需要索引部分的查詢效率。見以下三個(gè)示例:

1. 索引字段和謂詞條件字段一致:

CREATE INDEX access_log_client_ip_ix ON access_log(client_ip)

WHERE NOT (client_ip inet '192.168.100.0' AND client_ip inet '192.168.100.255');

下面的查詢將會(huì)用到該部分索引:

SELECT * FROM access_log WHERE url = '/index.html' AND client_ip = inet '212.78.10.32';

下面的查詢將不會(huì)用該部分索引:

一個(gè)不能使用這個(gè)索引的查詢可以是

SELECT * FROM access_log WHERE client_ip = inet '192.168.100.23';

2. 索引字段和謂詞條件字段不一致:

PostgreSQL支持帶任意謂詞的部分索引,唯一的約束是謂詞的字段也要來自于同樣的數(shù)據(jù)表。注意,如果你希望你的查詢語句能夠用到部分索引,那么就要求該查詢語句的條件部分必須和部分索引的謂詞完全匹配。 準(zhǔn)確說,只有在PostgreSQL能夠識(shí)別出該查詢的WHERE條件在數(shù)學(xué)上涵蓋了該索引的謂詞時(shí),這個(gè)部分索引才能被用于該查詢。

CREATE INDEX orders_unbilled_index ON orders(order_nr) WHERE billed is not true;

下面的查詢一定會(huì)用到該部分索引:

SELECT * FROM orders WHERE billed is not true AND order_nr 10000;

那么對(duì)于如下查詢呢?

SELECT * FROM orders WHERE billed is not true AND amount 5000.00;

這個(gè)查詢將不像上面那個(gè)查詢這么高效,畢竟查詢的條件語句中沒有用到索引字段,然而查詢條件"billed is not true"卻和部分索引的謂詞完全匹配,因此PostgreSQL將掃描整個(gè)索引。這樣只有在索引數(shù)據(jù)相對(duì)較少的情況下,該查詢才能更有效一些。

下面的查詢將不會(huì)用到部分索引。

SELECT * FROM orders WHERE order_nr = 3501;

3. 數(shù)據(jù)表子集的唯一性約束:

CREATE TABLE tests (

subject text,

target text,

success boolean,

...

);

CREATE UNIQUE INDEX tests_success_constraint ON tests(subject, target) WHERE success;

該部分索引將只會(huì)對(duì)success字段值為true的數(shù)據(jù)進(jìn)行唯一性約束。在實(shí)際的應(yīng)用中,如果成功的數(shù)據(jù)較少,而不成功的數(shù)據(jù)較多時(shí),該實(shí)現(xiàn)方法將會(huì)非常高效。

七、檢查索引的使用:

見以下四條建議:

1. 總是先運(yùn)行ANALYZE。

該命令將會(huì)收集表中數(shù)值分布狀況的統(tǒng)計(jì)。在估算一個(gè)查詢返回的行數(shù)時(shí)需要這個(gè)信息,而規(guī)劃器則需要這個(gè)行數(shù)以便給每個(gè)可能的查詢規(guī)劃賦予真實(shí)的開銷值。如果缺乏任何真實(shí)的統(tǒng)計(jì)信息,那么就會(huì)使用一些缺省數(shù)值,這樣肯定是不準(zhǔn)確的。因此,如果還沒有運(yùn)行ANALYZE就檢查一個(gè)索引的使用狀況,那將會(huì)是一次失敗的檢查。

2. 使用真實(shí)的數(shù)據(jù)做實(shí)驗(yàn)。

用測(cè)試數(shù)據(jù)填充數(shù)據(jù)表,那么該表的索引將只會(huì)基于測(cè)試數(shù)據(jù)來評(píng)估該如何使用索引,而不是對(duì)所有的數(shù)據(jù)都如此使用。比如從100000行中選1000行,規(guī)劃器可能會(huì)考慮使用索引,那么如果從100行中選1行就很難說也會(huì)使用索引了。因?yàn)?00行的數(shù)據(jù)很可能是存儲(chǔ)在一個(gè)磁盤頁面中,然而沒有任何查詢規(guī)劃能比通過順序訪問一個(gè)磁盤頁面更加高效了。與此同時(shí),在模擬測(cè)試數(shù)據(jù)時(shí)也要注意,如果這些數(shù)據(jù)是非常相似的數(shù)據(jù)、完全隨機(jī)的數(shù)據(jù),或按照排序順序插入的數(shù)據(jù),都會(huì)令統(tǒng)計(jì)信息偏離實(shí)際數(shù)據(jù)應(yīng)該具有的特征。

3. 如果索引沒有得到使用,那么在測(cè)試中強(qiáng)制它的使用也許會(huì)有些價(jià)值。有一些運(yùn)行時(shí)參數(shù)可以關(guān)閉各種各樣的查詢規(guī)劃。

4. 強(qiáng)制使用索引用法將會(huì)導(dǎo)致兩種可能:一是系統(tǒng)選擇是正確的,使用索引實(shí)際上并不合適,二是查詢計(jì)劃的開銷計(jì)算并不能反映現(xiàn)實(shí)情況。這樣你就應(yīng)該對(duì)使用和不使用索引的查詢進(jìn)行計(jì)時(shí),這個(gè)時(shí)候EXPLAIN ANALYZE命令就很有用了。

測(cè)試MySQL和Postgresql數(shù)據(jù)庫查詢性能怎么做到單線程和多線程查詢

可以用多進(jìn)程模擬。如果用批處理腳本的話。

看你怎么測(cè)。

如果使用jdbc程序段,多線程確實(shí)可以模擬。一個(gè)線程一個(gè)連接。

設(shè)計(jì)好標(biāo)準(zhǔn)的數(shù)據(jù)集。網(wǎng)上或許有下載的。記錄好測(cè)試環(huán)境和測(cè)試各個(gè)階段所花時(shí)間。

如何測(cè)試很多個(gè)用戶同時(shí)查詢postgresql數(shù)據(jù)庫時(shí)的效率

一、使用EXPLAIN:

PostgreSQL為每個(gè)查詢都生成一個(gè)查詢規(guī)劃,因?yàn)檫x擇正確的查詢路徑對(duì)性能的影響是極為關(guān)鍵的。PostgreSQL本身已經(jīng)包含了一個(gè)規(guī)劃器用于尋找最優(yōu)規(guī)劃,我們可以通過使用EXPLAIN命令來查看規(guī)劃器為每個(gè)查詢生成的查詢規(guī)劃。

PostgreSQL中生成的查詢規(guī)劃是由1到n個(gè)規(guī)劃節(jié)點(diǎn)構(gòu)成的規(guī)劃樹,其中最底層的節(jié)點(diǎn)為表掃描節(jié)點(diǎn),用于從數(shù)據(jù)表中返回檢索出的數(shù)據(jù)行。然而,不同

的掃描節(jié)點(diǎn)類型代表著不同的表訪問模式,如:順序掃描、索引掃描,以及位圖索引掃描等。如果查詢?nèi)匀恍枰B接、聚集、排序,或者是對(duì)原始行的其它操作,那

么就會(huì)在掃描節(jié)點(diǎn)"之上"有其它額外的節(jié)點(diǎn)。并且這些操作通常都有多種方法,因此在這些位置也有可能出現(xiàn)不同的節(jié)點(diǎn)類型。EXPLAIN將為規(guī)劃樹中的每

個(gè)節(jié)點(diǎn)都輸出一行信息,顯示基本的節(jié)點(diǎn)類型和規(guī)劃器為執(zhí)行這個(gè)規(guī)劃節(jié)點(diǎn)計(jì)算出的預(yù)計(jì)開銷值。第一行(最上層的節(jié)點(diǎn))是對(duì)該規(guī)劃的總執(zhí)行開銷的預(yù)計(jì),這個(gè)數(shù)

值就是規(guī)劃器試圖最小化的數(shù)值。

這里有一個(gè)簡(jiǎn)單的例子,如下:

復(fù)制代碼 代碼如下:

EXPLAIN SELECT * FROM tenk1;

QUERY PLAN

-------------------------------------------------------------

Seq Scan on tenk1 (cost=0.00..458.00 rows=10000 width=244)

EXPLAIN引用的數(shù)據(jù)是:

1). 預(yù)計(jì)的啟動(dòng)開銷(在輸出掃描開始之前消耗的時(shí)間,比如在一個(gè)排序節(jié)點(diǎn)里做排續(xù)的時(shí)間)。

2). 預(yù)計(jì)的總開銷。

3). 預(yù)計(jì)的該規(guī)劃節(jié)點(diǎn)輸出的行數(shù)。

4). 預(yù)計(jì)的該規(guī)劃節(jié)點(diǎn)的行平均寬度(單位:字節(jié))。

這里開銷(cost)的計(jì)算單位是磁盤頁面的存取數(shù)量,如1.0將表示一次順序的磁盤頁面讀取。其中上層節(jié)點(diǎn)的開銷將包括其所有子節(jié)點(diǎn)的開銷。這里的輸出

行數(shù)(rows)并不是規(guī)劃節(jié)點(diǎn)處理/掃描的行數(shù),通常會(huì)更少一些。一般而言,頂層的行預(yù)計(jì)數(shù)量會(huì)更接近于查詢實(shí)際返回的行數(shù)。

現(xiàn)在我們執(zhí)行下面基于系統(tǒng)表的查詢:

復(fù)制代碼 代碼如下:

SELECT relpages, reltuples FROM pg_class WHERE relname = 'tenk1';

從查詢結(jié)果中可以看出tenk1表占有358個(gè)磁盤頁面和10000條記錄,然而為了計(jì)算cost的值,我們?nèi)匀恍枰懒硗庖粋€(gè)系統(tǒng)參數(shù)值。

復(fù)制代碼 代碼如下:

postgres=# show cpu_tuple_cost;

cpu_tuple_cost

----------------

0.01

(1 row)

cost = 358(磁盤頁面數(shù)) + 10000(行數(shù)) * 0.01(cpu_tuple_cost系統(tǒng)參數(shù)值)

下面我們?cè)賮砜匆粋€(gè)帶有WHERE條件的查詢規(guī)劃。

復(fù)制代碼 代碼如下:

EXPLAIN SELECT * FROM tenk1 WHERE unique1 7000;

QUERY PLAN

------------------------------------------------------------

Seq Scan on tenk1 (cost=0.00..483.00 rows=7033 width=244)

Filter: (unique1 7000)

EXPLAIN的輸出顯示,WHERE子句被當(dāng)作一個(gè)"filter"應(yīng)用,這表示該規(guī)劃節(jié)點(diǎn)將掃描表中的每一行數(shù)據(jù),之后再判定它們是否符合過濾的條

件,最后僅輸出通過過濾條件的行數(shù)。這里由于WHERE子句的存在,預(yù)計(jì)的輸出行數(shù)減少了。即便如此,掃描仍將訪問所有10000行數(shù)據(jù),因此開銷并沒有

真正降低,實(shí)際上它還增加了一些因數(shù)據(jù)過濾而產(chǎn)生的額外CPU開銷。

上面的數(shù)據(jù)只是一個(gè)預(yù)計(jì)數(shù)字,即使是在每次執(zhí)行ANALYZE命令之后也會(huì)隨之改變,因?yàn)锳NALYZE生成的統(tǒng)計(jì)數(shù)據(jù)是通過從該表中隨機(jī)抽取的樣本計(jì)算的。

如果我們將上面查詢的條件設(shè)置的更為嚴(yán)格一些的話,將會(huì)得到不同的查詢規(guī)劃,如:

復(fù)制代碼 代碼如下:

EXPLAIN SELECT * FROM tenk1 WHERE unique1 100;

QUERY PLAN

分享文章:postgresql測(cè)試的簡(jiǎn)單介紹
地址分享:http://jinyejixie.com/article38/dsdgpsp.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供搜索引擎優(yōu)化、靜態(tài)網(wǎng)站品牌網(wǎng)站建設(shè)、網(wǎng)站排名網(wǎng)站收錄、軟件開發(fā)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)

成都網(wǎng)站建設(shè)公司
游戏| 德昌县| 昌江| 社会| 抚松县| 耿马| 柳江县| 西畴县| 祁东县| 勃利县| 长海县| 广东省| 西盟| 铜鼓县| 乌恰县| 临海市| 尼玛县| 崇文区| 三明市| 汝城县| 肇庆市| 且末县| 微博| 正定县| 海兴县| 依兰县| 磴口县| 江都市| 盘山县| 滦南县| 丽江市| 濮阳县| 台州市| 体育| 敦煌市| 双柏县| 新安县| 胶州市| 嘉义市| 佛山市| 黑山县|