欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

對于mysql的query_cache認識的誤區(qū)

 更新時間:2012年03月30日 00:44:14   作者:  
一直以來,對于mysql的query_cache,在網上就流行著這樣的說法,對于mysql的query_cache鍵值就是mysql的query,所以,如果在query中有任何的不同,包括多了個空格,都會導致mysql認為是不同的查詢
其實,這一種說法是不完全正確的。首先第一點,mysql的query_cache的鍵值并不是簡單的query,而是query加databasename加flag。這個從源碼中就可以看出。在這里不做重點描述,后續(xù)可以針對于這一點再具體分析。重要的是第二點,是不是加了空格,mysql就認為是不同的查詢呢?實際上這個是要分情況而言的,要看這個空格加在哪。 如果空格是加在query之前,比如是在query的起始處加了空格,這樣是絲毫不影響query cache的結果的,mysql認為這是一條query, 而如果空格是在query中,那會影響query cache的結果,mysql會認為是不同的query。

下面我們通過實驗及源碼具體分析。首先,我們先試驗一下:

首先,我們看一下mysql query_cache的狀態(tài):

image

首先,我們可以確認,mysql的query_cache功能是打開的。

其次,我們看一下狀態(tài):

image

因為這個db是新的db,所以hits,inset都為0,現在我們執(zhí)行一條select語句:

狀態(tài)變?yōu)椋?/P>

image

可以看到,執(zhí)行一條select后,現在的qcache狀態(tài)為,insert+1,這樣我們就可以推斷出,現在剛才那條select語句已經加入了qcache中。那我們現在再將剛才那條sql前面加上空格,看看會怎樣呢?

image

請注意,這條sql,比剛才那條sql前面多了一個空格。

按照網上的理論,這條sql應該會作為另一個鍵而插入另一個cache,不會復用先前的cache,但結果呢?

image

我們可以看到,hits變?yōu)榱?,而inserts根本沒變,這就說明了,這條在前面加了空格的query命中了沒有空格的query的結果集。從這,我們就可以得出結論,網上先前流傳的說法,是不嚴謹的。

那究竟是怎么回事呢?到底應該如何呢?為什么前面有空格的會命中了沒有空格的query的結果集。其實,這些我們可以通過源碼獲得答案。

翻看下mysql的源碼,我這翻看的是5.1的,在send_result_to_client(這個函數既是mysql調用query_cache的函數)這個函數里面有這樣一段,這段代碼,、

復制代碼 代碼如下:

/*
Test if the query is a SELECT
(pre-space is removed in dispatch_command).

First '/' looks like comment before command it is not
frequently appeared in real life, consequently we can
check all such queries, too.
*/
if ((my_toupper(system_charset_info, sql[i]) != 'S' ||
my_toupper(system_charset_info, sql[i + 1]) != 'E' ||
my_toupper(system_charset_info, sql[i + 2]) != 'L') &&
sql[i] != '/')
{
DBUG_PRINT("qcache", ("The statement is not a SELECT; Not cached"));
goto err;
}

是在檢驗語句是否為select語句,重點是上面那段注釋。特別是括弧中的,pre-space is removed in dispatch_command,也就是說,在語句開始之前的多余的空格已經被處理過了,在dispache_command這個函數中去掉了。

我們看下dispache_command這個方法,在這個方法里有這樣一段:

復制代碼 代碼如下:

if (alloc_query(thd, packet, packet_length))
break; // fatal error is set
char *packet_end= thd->query() + thd->query_length();
/* 'b' stands for 'buffer' parameter', special for 'my_snprintf' */
const char* end_of_stmt= NULL;

在這里,會調用alloc_query方法,我們看下這個方法的內容:
復制代碼 代碼如下:

bool alloc_query(THD *thd, const char *packet, uint packet_length)
{
char *query;
/* Remove garbage at start and end of query */
while (packet_length > 0 && my_isspace(thd->charset(), packet[0]))
{
packet++;
packet_length--;
}
const char *pos= packet + packet_length; // Point at end null
while (packet_length > 0 &&
(pos[-1] == ';' || my_isspace(thd->charset() ,pos[-1])))
{
pos--;
packet_length--;
}
/* We must allocate some extra memory for query cache
The query buffer layout is:
buffer :==
<statement> The input statement(s)
'\0' Terminating null char (1 byte)
<length> Length of following current database name (size_t)
<db_name> Name of current database
<flags> Flags struct
*/
if (! (query= (char*) thd->memdup_w_gap(packet,
packet_length,
1 + sizeof(size_t) + thd->db_length +
QUERY_CACHE_FLAGS_SIZE)))
return TRUE;
query[packet_length]= '\0';
/*
Space to hold the name of the current database is allocated. We
also store this length, in case current database is changed during
execution. We might need to reallocate the 'query' buffer
*/
char *len_pos = (query + packet_length + 1);
memcpy(len_pos, (char *) &thd->db_length, sizeof(size_t));
thd->set_query(query, packet_length);
/* Reclaim some memory */
thd->packet.shrink(thd->variables.net_buffer_length);
thd->convert_buffer.shrink(thd->variables.net_buffer_length);
return FALSE;
}

這個方法在一開始就會對query進行處理(代碼第4行),將開頭和末尾的garbage remove掉。
看到這里,我們基本已經明了了,mysql會對輸入的query進行預處理,將空格等東西給處理掉,所以不會開頭的空格不會影響到query_cache,因為對mysql來說,就是一條query。

相關文章

  • MySQL數據庫運維之數據恢復的方法

    MySQL數據庫運維之數據恢復的方法

    本篇文章主要介紹了MySQL數據庫運維之數據恢復的方法,此處總結一下恢復方案,并結合數據庫的二進制日志做下數據恢復的示范。小編覺得挺不錯的,現在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-06-06
  • MySQL中的驅動表與被驅動表及含義

    MySQL中的驅動表與被驅動表及含義

    使用join連接查詢時如果有where條件,則MySQL執(zhí)行器會根據查詢條件過濾后的結果自動選擇驅動表或被驅動表,這篇文章主要介紹了MySQL的驅動表與被驅動表,需要的朋友可以參考下
    2023-10-10
  • MySQL中創(chuàng)建表的三種方法匯總

    MySQL中創(chuàng)建表的三種方法匯總

    這篇文章主要介紹了MySQL中創(chuàng)建表的三種方法,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-02-02
  • Mysql邏輯架構詳解

    Mysql邏輯架構詳解

    今天小編就為大家分享一篇關于Mysql邏輯架構詳解,小編覺得內容挺不錯的,現在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧
    2019-01-01
  • Mysql大型SQL文件快速恢復方案分享

    Mysql大型SQL文件快速恢復方案分享

    這篇文章主要給大家介紹了關于Mysql大型SQL文件快速恢復方案的相關資料,文中通過示例代碼介紹的非常詳細,對大家學習或者使用Mysql具有一定的參考學習價值,需要的朋友們下面來一起學習學習吧
    2019-09-09
  • MySQL中insert語句的使用與優(yōu)化教程

    MySQL中insert語句的使用與優(yōu)化教程

    這篇文章主要介紹了MySQL中insert語句的使用與優(yōu)化教程,使用insert語句插入數據是MySQL入門學習中的基礎知識,需要的朋友可以參考下
    2016-03-03
  • C#列出局域網中可用SQL Server服務器

    C#列出局域網中可用SQL Server服務器

    SQLDMO(SQL Distributed Management Objects,SQL分布式管理對象)封裝了Microsoft SQL Server數據庫中的對象。SQLDMO是Microsoft SQL Server中企業(yè)管理器所使用的應用程序接口,所以它可以執(zhí)行很多功能,其中當然也包括對數據庫的備份和恢復。
    2008-04-04
  • windows下MySQL 5.7.3.0安裝配置圖解教程(安裝版)

    windows下MySQL 5.7.3.0安裝配置圖解教程(安裝版)

    這篇文章主要介紹了windows下MySQL 5.7.3.0安裝配置圖解教程(安裝版),需要的朋友可以參考下
    2016-04-04
  • 美團網技術團隊分享的MySQL索引及慢查詢優(yōu)化教程

    美團網技術團隊分享的MySQL索引及慢查詢優(yōu)化教程

    這篇文章主要介紹了美團網技術團隊分享的MySQL索引及慢查詢優(yōu)化教程,結合了實際的磁盤IO情況對一些優(yōu)化方案作出了分析,十分推薦!需要的朋友可以參考下
    2015-11-11
  • 如何通過SQL找出2個表里值不同的列的方法

    如何通過SQL找出2個表里值不同的列的方法

    本篇文章對如何通過SQL找出2個表里值不同的列的方法進行了詳細的分析介紹,需要的朋友參考下
    2013-05-05

最新評論