MySQL中普通sql與預編譯sql 區別
MySQL中的預編譯提到的不多,oracle上一次編譯多次執行,是有很大的效能提升的,這裡看下mysql為什麼沒有那麼大的提升,以及跟普通sql相比有哪些區別。
執行緒在初始化建立的時候,會使用init_sql_alloc分配main_mem_root部分,main_mem_root也是mem_root, 在sql執行時候使用。
執行普通的sql,在轉發sql後,回進行記憶體的分配,分配到mem_root中,會先在free列表中查詢是否有足夠的空間,沒有就分配,有就返回分配的地址。呼叫堆疊如下:
mysqld!alloc_root (/Users/xiaoyu.bai/Downloads/mysql-5.7.29/mysys/my_alloc.c:274) mysqld!Query_arena::alloc(unsigned long) (/Users/xiaoyu.bai/Downloads/mysql-5.7.29/sql/sql_class.h:783) mysqld!alloc_query(THD*, char const*, unsigned long) (/Users/xiaoyu.bai/Downloads/mysql-5.7.29/sql/sql_parse.cc:2158) mysqld!dispatch_command(THD*, COM_DATA const*, enum_server_command) (/Users/xiaoyu.bai/Downloads/mysql-5.7.29/sql/sql_parse.cc:1467) mysqld!do_command(THD*) (/Users/xiaoyu.bai/Downloads/mysql-5.7.29/sql/sql_parse.cc:1032) mysqld!::handle_connection(void *) (/Users/xiaoyu.bai/Downloads/mysql-5.7.29/sql/conn_handler/connection_handler_per_thread.cc:313) mysqld!::pfs_spawn_thread(void *) (/Users/xiaoyu.bai/Downloads/mysql-5.7.29/storage/perfschema/pfs.cc:2197) libsystem_pthread.dylib!_pthread_start (未知源:0) libsystem_pthread.dylib!thread_start (未知源:0)
在普通sql執行完成後,會呼叫free_root 進行mem_root記憶體的釋放
mysqld!free_root (/Users/xiaoyu.bai/Downloads/mysql-5.7.29/mysys/my_alloc.c:487) mysqld!dispatch_command(THD*, COM_DATA const*, enum_server_command) (/Users/xiaoyu.bai/Downloads/mysql-5.7.29/sql/sql_parse.cc:1947) mysqld!do_command(THD*) (/Users/xiaoyu.bai/Downloads/mysql-5.7.29/sql/sql_parse.cc:1032) mysqld!::handle_connection(void *) (/Users/xiaoyu.bai/Downloads/mysql-5.7.29/sql/conn_handler/connection_handler_per_thread.cc:313) mysqld!::pfs_spawn_thread(void *) (/Users/xiaoyu.bai/Downloads/mysql-5.7.29/storage/perfschema/pfs.cc:2197) libsystem_pthread.dylib!_pthread_start (未知源:0) libsystem_pthread.dylib!thread_start (未知源:0)
預編譯sql執行
1 SET @s = 'SELECT * from products where code=?'; 2 PREPARE stmt2 FROM @s; 3 SET @a = 200; 4 EXECUTE stmt2 USING @a;
執行1的時候是跟普通sql一樣的使用mem_root,釋放mem_root
在執行第二步的時候也會線上程上使用記憶體,進行語法解析,驗證語句,執行緒中儲存了stmt_map物件,這個字典用來存放預編譯的語句
mysqld!alloc_query(THD*, char const*, unsigned long) (/Users/xiaoyu.bai/Downloads/mysql-5.7.29/sql/sql_parse.cc:2158) mysqld!Prepared_statement::prepare(char const*, unsigned long) (/Users/xiaoyu.bai/Downloads/mysql-5.7.29/sql/sql_prepare.cc:3247) mysqld!mysql_sql_stmt_prepare(THD*) (/Users/xiaoyu.bai/Downloads/mysql-5.7.29/sql/sql_prepare.cc:2323) mysqld!mysql_execute_command(THD*, bool) (/Users/xiaoyu.bai/Downloads/mysql-5.7.29/sql/sql_parse.cc:2837) mysqld!mysql_parse(THD*, Parser_state*) (/Users/xiaoyu.bai/Downloads/mysql-5.7.29/sql/sql_parse.cc:5584) mysqld!dispatch_command(THD*, COM_DATA const*, enum_server_command) (/Users/xiaoyu.bai/Downloads/mysql-5.7.29/sql/sql_parse.cc:1491) mysqld!do_command(THD*) (/Users/xiaoyu.bai/Downloads/mysql-5.7.29/sql/sql_parse.cc:1032) mysqld!::handle_connection(void *) (/Users/xiaoyu.bai/Downloads/mysql-5.7.29/sql/conn_handler/connection_handler_per_thread.cc:313) mysqld!::pfs_spawn_thread(void *) (/Users/xiaoyu.bai/Downloads/mysql-5.7.29/storage/perfschema/pfs.cc:2197) libsystem_pthread.dylib!_pthread_start (未知源:0) libsystem_pthread.dylib!thread_start (未知源:0)
在這裡呼叫lex_start進行了一次解析。
所以如果預編譯語句有很多的話,這個map會比較大,引數max_prepared_stmt_count是限制的全域性的數量
if (thd->stmt_map.insert(thd, stmt))
執行第四步的時候,是真正的執行,堆疊
mysqld!mysql_sql_stmt_execute(THD*) (/Users/xiaoyu.bai/Downloads/mysql-5.7.29/sql/sql_prepare.cc:2640) mysqld!mysql_execute_command(THD*, bool) (/Users/xiaoyu.bai/Downloads/mysql-5.7.29/sql/sql_parse.cc:2842) mysqld!mysql_parse(THD*, Parser_state*) (/Users/xiaoyu.bai/Downloads/mysql-5.7.29/sql/sql_parse.cc:5584) mysqld!dispatch_command(THD*, COM_DATA const*, enum_server_command) (/Users/xiaoyu.bai/Downloads/mysql-5.7.29/sql/sql_parse.cc:1491) mysqld!do_command(THD*) (/Users/xiaoyu.bai/Downloads/mysql-5.7.29/sql/sql_parse.cc:1032) mysqld!::handle_connection(void *) (/Users/xiaoyu.bai/Downloads/mysql-5.7.29/sql/conn_handler/connection_handler_per_thread.cc:313) mysqld!::pfs_spawn_thread(void *) (/Users/xiaoyu.bai/Downloads/mysql-5.7.29/storage/perfschema/pfs.cc:2197) libsystem_pthread.dylib!_pthread_start (未知源:0) libsystem_pthread.dylib!thread_start (未知源:0)
執行完後,也會呼叫 free_root進行釋放。
所以預編譯跟普通sql執行,多了儲存預編譯語句的map物件,預編譯多了一次賦值的解析與執行。
問題1: 一次編譯,多次執行,編譯的結果放到哪裡了?
mysql的跟oracle不太一樣,mysql的是每次輸入引數,會給sql設定下對應的值,然後走一遍普通的mysql_execute_command的流程。stmt_map針對效能提升這沒有什麼用途,就是用來儲存語句的。
所以這裡來看,mysql 使用預編譯語句對效能的影響不如oracle那麼大,只是在防止注入的安全上有用。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/25719946/viewspace-2947595/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- SQL join中on與where區別SQL
- PL/SQL中command window與SQL window的區別SQL
- MYSQL和SQL的區別MySql
- SQL JOIN 中 on 與 where 有何區別SQL
- SQL中Having與Where的區別SQL
- MS SQL Server和MySQL區別ServerMySql
- 預編譯SQL為什麼能夠防止SQL隱碼攻擊編譯SQL
- SQL truncate 、delete與drop區別SQLdelete
- sql server agent與sql server有什麼區別 ?SQLServer
- SQL中where和on的區別SQL
- sql server中的一個坑-len與datalength區別SQLServer
- order by在SQL Server與Oracle中的一個區別SQLServerOracle
- SQL中on條件與where條件的區別[轉]SQL
- 【SQL】UNION ALL 與UNION 的區別SQL
- SQL中IN和EXISTS用法的區別SQL
- 編譯程式與解釋程式區別?編譯
- SQL Server中臨時表與表變數的區別SQLServer變數
- [精選] SQL中的IN與NOT IN、EXISTS與NOT EXISTS的區別及效能分析SQL
- sql中UNION和UNION ALL的區別SQL
- SQL 中having 和where的區別SQL
- 使用edit編輯緩衝區中的sqlSQL
- Sql server char,nchar,varchar與Nvarchar的區別SQLServer
- MySQL5.7中的sql_mode預設值MySql
- SQL Server中count(*)和Count(1)的區別SQLServer
- Oracle9i中v$sql、v$sqlarea、v$sqltext、v$sql_plan的聯絡與區別OracleSQL
- 對線面試官:SQL中的IN與NOT IN、EXISTS與NOT EXISTS的區別及效能分析面試SQL
- Mysql學習總結(50)——Oracle,mysql和SQL Server的區別MySqlOracleServer
- MYSQL中的普通索引,主健,唯一,全文索引區別MySql索引
- 你知道「編譯」與「解釋」的區別嗎?編譯
- MySQL語法中=與:=的區別MySql
- apache動態編譯/靜態編譯區別Apache編譯
- PL/SQL DEVELOPER工具與toad工具的區別SQLDeveloper
- Hive SQL 編譯過程詳解HiveSQL編譯
- 在Pandas中 SQL操作:SQLAlchemy和PyMySQL的區別MySql
- 【SQL】Oracle SQL join on語句and和where使用區別SQLOracle
- V$sql_text v$sqlarea v$sql 的區別SQL
- 工控機與普通電腦的區別
- 粵語與普通話的區別1