hive存儲過程新建多個臨時表
⑴ hivewithas不同的作業相同的臨時表會有影響嗎
會。
在同一個會話不同作用域的時候(例如:大存儲過程內含小存儲過程的場景),使用同一個臨時表名,會引起錯亂。
只要把這個@operNum=#Tab.oper_num的欄位獲取的值注釋掉,就可以正常運行,不然運行的時候就一直'提示oper_num列無效',就很納悶,這個欄位是表中存在的,怎麼會無效呢。
反復查找原因,發現原來是那個功能使用的存儲過程裡面有一段執行更新這個表的代碼,而剛好在這個更新語句前面有個同樣名的#Tab臨時表,於是,在執行存儲過程事務進程的時候,觸發器在事務內就直接使用前面產生的臨時表進行賦值操作,而導致列名不匹配,無效。
⑵ Hive sql及窗口函數
hive函數:
1、根據指定條件返回結果:case when then else end as
2、基本類型轉換:CAST()
3、nvl:處理空欄位:三個str時,是否為空可以指定返回不同的值
4、sql通配符: https://www.w3school.com.cn/sql/sql_wildcards.asp
5、count(1)與COUNT(*):返回行數
如果表沒有主鍵,那麼count(1)比count(*)快;
如果有主鍵,那麼count(主鍵,聯合主鍵)比count(*)快;
count(1)跟count(主鍵)一樣,只掃描主鍵。count(*)跟count(非主鍵)一樣,掃描整個表。明顯前者更快一些。
性能問題:
1.任何情況下SELECT COUNT(*) FROM tablename是最優選擇,(指沒有where的情況);
2.盡量減少SELECT COUNT(*) FROM tablename WHERE COL = 『value』 這種查詢;
3.杜絕SELECT COUNT(COL) FROM tablename WHERE COL2 = 『value』 的出現。
count(expression):查詢 is_reply=0 的數量: SELECT COUNT(IF(is_reply=0,1,NULL)) count FROM t_iov_help_feedback;
6、distinct與group by
distinct去重所有distinct之後所有的欄位,如果有一個欄位值不一致就不作為一條
group by是根據某一欄位分組,然後查詢出該條數據的所需欄位,可以搭配 where max(time)或者Row_Number函數使用,求出最大的一條數據
7、使用with 臨時表名 as() 的形式,簡單的臨時表直接嵌套進枝段sql中,復雜的和需要復用的表寫到臨猛行譽時表中,關聯的時候先找到關聯欄位,過濾條件最好在臨時表中先過濾後關聯
處理json的函數:
split(json_array_string(schools), '\\|\\|') AS schools
get_json_object(school, '$.id') AS school_id,
字元串函數:
1、instr(』源字元串』 , 『目標字元串』 ,』開始位置』,』第幾次出現』)
instr(sourceString,destString,start,appearPosition)
1.sourceString代表源字元串; destString代表要從源字元串中查找的子串;
2.start代表查找的開始位置,這個參數可選的,默認為1;
3.appearPosition代表想從源字元中查找出第幾次出現的destString,這個參數也是可選的, 默認為1
4.如果start的值為負數,則代表從右往左進行查找,但是位置數據仍然從左向右計帶枯算。
5.返回值為:查找到的字元串的位置。如果沒有查找到,返回0。
最簡單例子: 在abcd中查找a的位置,從第一個字母開始查,查找第一次出現時的位置
select instr(『abcd』,』a』,1,1) from al; —1
應用於模糊查詢:instr(欄位名/列名, 『查找欄位』)
select code,name,dept,occupation from staff where instr(code, 『001』)> 0;
等同於 select code, name, dept, occupation from staff where code like 『%001%』 ;
應用於判斷包含關系:
select ccn,mas_loc from mas_loc where instr(『FH,FHH,FHM』,ccn)>0;
等同於 select ccn,mas_loc from mas_loc where ccn in (『FH』,』FHH』,』FHM』);
2、substr(string A,int start,int len)和 substring(string A,int start,int len),用法一樣
substr(time,1,8) 表示將time從第1位開始截取,截取的長度為8位
第一種用法:
substr(string A,int start)和 substring(string A,int start),用法一樣
功效:返回字元串A從下標start位置到結尾的字元串
第二種用法:
substr(string A,int start,int len)和 substring(string A,int start,int len),用法一樣
功效:返回字元串A從下標start位置開始,長度為len的字元串
3、get_json_object(form_data,'$.學生姓名') as student_name
json_tuple 函數的作用:用來解析json字元串中的多個欄位
4、split(full_name, '\\.') [5] AS zq; 取的是數組里的第六個
日期(時間)函數:
1、to_date(event_time) 返回日期部分
2、date_sub:返回當前日期的相對時間
當前日期:select curdate()
當前日期前一天:select date_sub(curdate(),interval 1 day)
當前日期後一天:select date_sub(curdate(),interval -1 day)
date_sub(from_unixtime(unix_timestamp(), 'yyyy-MM-dd HH:mm:ss'), 14) 將現在的時間總秒數轉為標准格式時間,返回14天之前的時間
時間戳>>>>日期:
from_unixtime(unix_timestamp(), 'yyyy-MM-dd HH:mm:ss') 將現在的時間總秒數轉為標准格式時間
from_unixtime(get_json_object(get_json_object(form_data,'$.挽單時間'),'$.$date')/1000) as retain_time
unix_timestamp('2019-08-15 16:40:00','yyyy-MM-dd HH:mm:ss') --1565858400
日期>>>>時間戳:unix_timestamp()
date_format:yyyy-MM-dd HH:mm:ss 時間轉格式化時間
select date_format('2019-10-07 13:24:20', 'yyyyMMdd000000')-- 20191007000000select date_format('2019-10-07', 'yyyyMMdd000000')-- 20191007000000
1.日期比較函數: datediff語法: datediff(string enddate,string startdate)
返回值: int
說明: 返回結束日期減去開始日期的天數。
舉例: hive> select datediff('2016-12-30','2016-12-29'); 1
2.日期增加函數: date_add語法: date_add(string startdate, intdays)
返回值: string
說明: 返回開始日期startdate增加days天後的日期。
舉例: hive>select date_add('2016-12-29',10); 2017-01-08
3.日期減少函數: date_sub語法: date_sub (string startdate,int days)
返回值: string
說明: 返回開始日期startdate減少days天後的日期。
舉例: hive>select date_sub('2016-12-29',10); 2016-12-19
4.查詢近30天的數據
select * from table where datediff(current_timestamp,create_time)<=30;
create_time 為table里的欄位,current_timestamp 返回當前時間 2018-06-01 11:00:00
3、trunc()函數的用法:當前日期的各種第一天,或者對數字進行不四捨五入的截取
日期:
1.select trunc(sysdate) from al --2011-3-18 今天的日期為2011-3-18
2.select trunc(sysdate, 'mm') from al --2011-3-1 返回當月第一天.
上月1號 trunc(add_months(current_date(),-1),'MM')
3.select trunc(sysdate,'yy') from al --2011-1-1 返回當年第一天
4.select trunc(sysdate,'dd') from al --2011-3-18 返回當前年月日
5.select trunc(sysdate,'yyyy') from al --2011-1-1 返回當年第一天
6.select trunc(sysdate,'d') from al --2011-3-13 (星期天)返回當前星期的第一天
7.select trunc(sysdate, 'hh') from al --2011-3-18 14:00:00 當前時間為14:41
8.select trunc(sysdate, 'mi') from al --2011-3-18 14:41:00 TRUNC()函數沒有秒的精確
數字:TRUNC(number,num_digits) Number 需要截尾取整的數字。Num_digits 的默認值為 0。TRUNC()函數截取時不進行四捨五入
11.select trunc(123.458,1) from al --123.4
12.select trunc(123.458,-1) from al --120
4、round():四捨五入:
select round(1.455, 2) #結果是:1.46,即四捨五入到十分位,也就是保留兩位小數
select round(1.5) #默認四捨五入到個位,結果是:2
select round(255, -1) #結果是:260,即四捨五入到十位,此時個位是5會進位
floor():地板數
ceil()天花板數
5、
6.日期轉年函數: year語法: year(string date)
返回值: int
說明: 返回日期中的年。
舉例:
hive> select year('2011-12-08 10:03:01') from al;
2011
hive> select year('2012-12-08') fromal;
2012
7.日期轉月函數: month語法: month (string date)
返回值: int
說明: 返回日期中的月份。
舉例:
hive> select month('2011-12-08 10:03:01') from al;
12
hive> select month('2011-08-08') fromal;
8
8.日期轉天函數: day語法: day (string date)
返回值: int
說明: 返回日期中的天。
舉例:
hive> select day('2011-12-08 10:03:01') from al;
8
hive> select day('2011-12-24') fromal;
24
9.日期轉小時函數: hour語法: hour (string date)
返回值: int
說明: 返回日期中的小時。
舉例:
hive> select hour('2011-12-08 10:03:01') from al;
10
10.日期轉分鍾函數: minute語法: minute (string date)
返回值: int
說明: 返回日期中的分鍾。
舉例:
hive> select minute('2011-12-08 10:03:01') from al;
3
11.日期轉秒函數: second語法: second (string date)
返回值: int
說明: 返回日期中的秒。
舉例:
hive> select second('2011-12-08 10:03:01') from al;
1
12.日期轉周函數: weekofyear語法: weekofyear (string date)
返回值: int
說明: 返回日期在當前的周數。
舉例:
hive> select weekofyear('2011-12-08 10:03:01') from al;
49
查看hive表在hdfs中的位置:show create table 表名;
在hive中hive2hive,hive2hdfs:
HDFS、本地、hive -----> Hive:使用 insert into | overwrite、loaddata local inpath "" into table student;
Hive ----> Hdfs、本地:使用:insert overwrite | local
網站訪問量統計:
uv:每用戶訪問次數
ip:每ip(可能很多人)訪問次數
PV:是指頁面的瀏覽次數
VV:是指你訪問網站的次數
sql:
基本函數:
count、max、min、sum、avg、like、rlike('2%'、'_2%'、%2%'、'[2]')(java正則)
and、or、not、in
where、group by、having、{ join on 、full join} 、order by(desc降序)
sort by需要與distribut by集合結合使用:
hive (default)> set maprece.job.reces=3; //先設置rece的數量
insert overwrite local directory '/opt/mole/datas/distribute-by'
row format delimited fields terminated by '\t'
先按照部門編號分區,再按照員工編號降序排序。
select * from emp distribute by deptno sort by empno desc;
外部表 create external table if not exists dept
分區表:create table dept_partition ( deptno int, dname string, loc string ) partitioned by ( month string )
load data local inpath '/opt/mole/datas/dept.txt' into table default.dept_partition partition(month='201809');
alter table dept_partition add/drop partition(month='201805') ,partition(month='201804');
多分區聯合查詢:union
select * from dept_partition2 where month='201809' and day='10';
show partitions dept_partition;
desc formatted dept_partition;
二級分區表:create table dept_partition2 ( deptno int, dname string, loc string ) partitioned by (month string, day string) row format delimited fields terminated by '\t';
分桶抽樣查詢:分區針對的是數據的存儲路徑;分桶針對的是數據文件
create table stu_buck(id int, name string) clustered by(id) into 4 bucketsrow format delimited fields terminated by '\t';
設置開啟分桶與rece為1:
set hive.enforce.bucketing=true;
set maprece.job.reces=-1;
分桶抽樣:select * from stu_bucktablesample(bucket x out of y on id);
抽取,桶數/y,x是從哪個桶開始抽取,y越大 抽樣數越少,y與抽樣數成反比,x必須小於y
給空欄位賦值:
如果員工的comm為NULL,則用-1代替或用其他欄位代替 :select nvl(comm,-1) from emp;
case when:如何符合記為1,用於統計、分組統計
select dept_id, sum(case sex when '男' then 1 else 0 end) man , sum(case sex when '女' then 1 else 0 end) woman from emp_sex group by dept_id;
用於組合歸類匯總(行轉列):UDAF:多轉一
concat:拼接查詢結果
collect_set(col):去重匯總,產生array類型欄位,類似於distinct
select t.base, concat_ws('|',collect_set(t.name)) from (select concat_ws(',',xingzuo,blood_type) base,name from person_info) t group by t.base;
解釋:先第一次查詢得到一張沒有按照(星座血型)分組的表,然後分組,使用collect_set將名字組合成數組,然後使用concat將數組變成字元串
用於拆分數據:(列轉行):UDTF:一轉多
explode(col):將hive一列中復雜的array或者map結構拆分成多行。
lateral view 側面顯示:用於和UDTF一對多函數搭配使用
用法:lateral view udtf(expression) tablealias as cate
cate:炸開之後的列別名
temptable :臨時表表名
解釋:用於和split, explode等UDTF一起使用,它能夠將一列數據拆成多行數據,在此基礎上可以對拆分後的數據進行聚合。
開窗函數:
Row_Number,Rank,Dense_Rank over:針對統計查詢使用
Row_Number:返回從1開始的序列
Rank:生成分組中的排名序號,會在名詞s中留下空位。3 3 5
dense_rank:生成分組中的排名序號,不會在名詞中留下空位。3 3 4
over:主要是分組排序,搭配窗口函數使用
結果:
SUM、AVG、MIN、MAX、count
preceding:往前
following:往後
current row:當前行
unbounded:unbounded preceding 從前面的起點, unbounded following:到後面的終點
sum:直接使用sum是總的求和,結合over使用可統計至每一行的結果、總的結果、當前行+之前多少行/之後多少行、當前行到往後所有行的求和。
over(rowsbetween 3/current ) 當前行到往後所有行的求和
ntile:分片,結合over使用,可以給數據分片,返回分片號
使用場景:統計出排名前百分之或n分之一的數據。
lead,lag,FIRST_VALUE,LAST_VALUE
lag與lead函數可以返回上下行的數據
lead(col,n,dafault) 用於統計窗口內往下第n行值
第一個參數為列名,第二個參數為往下第n行(可選,默認為1),第三個參數為默認值(當往下第n行為NULL時候,取默認值,如不指定,則為NULL)
LAG(col,n,DEFAULT) 用於統計窗口內往上第n行值
第一個參數為列名,第二個參數為往上第n行(可選,默認為1),第三個參數為默認值(當往上第n行為NULL時候,取默認值,如不指定,則為NULL)
使用場景:通常用於統計某用戶在某個網頁上的停留時間
FIRST_VALUE:取分組內排序後,截止到當前行,第一個值
LAST_VALUE:取分組內排序後,截止到當前行,最後一個值
范圍內求和: https://blog.csdn.net/happyrocking/article/details/105369558
cume_dist,percent_rank
–CUME_DIST :小於等於當前值的 行數 / 分組內總行數
–比如,統計小於等於當前薪水的人數,占總人數的比例
percent_rank:分組內當前行的RANK值-1/分組內總行數-1
總結:
在Spark中使用spark sql與hql一致,也可以直接使用sparkAPI實現。
HiveSql窗口函數主要應用於求TopN,分組排序TopN、TopN求和,前多少名前百分之幾。
與Flink窗口函數不同。
Flink中的窗口是用於將無線數據流切分為有限塊處理的手段。
window分類:
CountWindow:按照指定的數據條數生成一個 Window,與時間無關。
TimeWindow:按照時間生成 Window。
1. 滾動窗口(Tumbling Windows):時間對齊,窗口長度固定,不重疊::常用於時間段內的聚合計算
2.滑動窗口(Sliding Windows):時間對齊,窗口長度固定,可以有重疊::適用於一段時間內的統計(某介面最近 5min 的失敗率來報警)
3. 會話窗口(Session Windows)無時間對齊,無長度,不重疊::設置session間隔,超過時間間隔則窗口關閉。
⑶ hive存儲parquet表
parquet格式的表在生產環境中經常被使用到,具有列式存儲和壓縮等特點,我們怎麼在hive中存儲parquet格式的表呢。
這里使用oracle的emp表
載入本地數據到hive表
執行查詢
發現報錯
emp使用parquet格式存儲,其中imputFormat和outputFormat都是parquet的相關的,也前冊就是我的imputFormat是parquent的,但是你傳過來的是text,我不認識
我們看一下emp的相關信息,可以看到這里的都是parquet的format的,這是導致這次錯誤的原因。
這就導致了我們需要每次都先把text文件轉化為parquet的文件,然後parquent表進行載入才可以,下面介紹官方推薦的使用方法。
查看emp_tmp的表的信息,這里可以看到,默認的是TextImputFormat和TextOutputFormat的。
然後載入數據到emp_tmp,查看數據,是正常顯示的
然後現在把之前的emp裡面的數據給刪除
然後把emp_tmp表裡面的數據載入到emp
查詢一下,數據滑談正常顯示,這個方式使用起來還行,就是每次都需要對臨時表進行操作,還是比較麻煩的。
感覺這個問題是經常出現,為什麼會這樣呢。這個和hive的版本有一定的關系。
可以看出hive官方將inputformat和outputformat進行了整合,這樣使信悔碰用起來也是比較方便的。
但是可能有人想,那我修改inputformat不就行了,下面我介紹一下,看是否可以
創建emp2表,是parquet的存儲格式的
修改inputformat 和serde,這里inputFormat是TextInputFormat,SEDE使用的是LazySimpleSerDe,Outputformat任然是Parquet的,這里需要帶上。
查看emp2表的信息,如下圖表示修改成功
載入數據到emp2
查詢數據,執行成功
到這里,修改inputformat和serde的方法也介紹完成了,我們以為成功了,但是上hdfs上一看,文件還是txt格式的,所以通過修改inputformat和serde的方法不行。
肯定有人想使用這個方法
這個方法我也嘗試了,但是返回的值全都是null
在僅僅使用hive的時候,如果想把txt文件裡面的數據保存到parquet表裡面的話,可以使用建立臨時表的方法,這個方法也是比較好操作的。
但是其實如果使用spark,flink等分布式計算引擎的話,是可以直接的讀取txt數據保存到parquet表裡面的,框架幫我們做了轉化。這種方式也是我們在工作中經常使用的。
上面也介紹了修改inputformat和ser的方式,秀給inputformat是可以讓txt文件裡面的數據被讀進來的,如果同時還修改了serde為lazysimpleserde的話,這個是把數據保存為text格式的,已經完全和parquet沒有關系了,保存的文件還是txt格式的。僅修改inputformat,但是使用的serde是parquet的,但是數據進出不一致,也是有問題的。
⑷ hive查詢時間復雜度
1、使用Tez引擎
Apache Tez Engine是一個可擴展的框架,用於構建高性能批處理和互動式數據處理。它由YARN在Hadoop中 調度。Tez通過提高處理速度和保持MapRece擴展到數PB數據的能力來改進MapRece job。
通過設置hive.execution.engine 為tez:可以在環境中啟用Tez引擎:
set hive.execution.engine=tez;
2、使用向量化
向量化通過在單個操作中獲取 1024 行而不是 每次只獲取單行來改善 scans, aggregations, filters 和 join 這類操作的性能。
我們可以通過執行以下命令在環境中啟用向量化:
set hive.vectorized.execution.enabled=true;
set hive.vectorized.execution.rece.enabled=true;
3、使用ORCFile
Hive 支持 ORCfile,這是一種新的表存儲格式,在讀取,寫入和處理數據時,ORCFile格式優於Hive文件格式,它通過 predicate push-down, compression 等技術來提高查詢速度。
在 HIVE 表中使用 ORCFile,將有益於獲得 HIVE 快速響應的查詢。
ORCFile 格式通過對原始數據存儲量壓縮75%,提供了高效的存儲 Hive 數據的方法。
舉例,考慮兩個大表 A 和 B(存儲為 TextFIle,這里沒有指定一些列),使用一個簡單的查詢,如:
SELECT A.customerID,
A.name,
A.age,
A.address
JOIN B.role,
B.department,
B.salary ON A.customerID=B.customerID;
由於表 A 和表 B 都存儲為 TextFile,因此執行此查詢可能需要很長時間。
將這些表存儲格式轉換為 ORCFile 格式通常會明顯減少查詢時間:
CREATE TABLE A_ORC (
customerID int,
name string,
age int,
address string
) STORED AS ORC tblproperties (「orc.compress" = 「SNAPPY」)
;
INSERT INTO TABLE A_ORC
SELECT *
FROM A
;
CREATE TABLE B_ORC (
customerID int,
ROLE string,
salary float,
department string
) STORED AS ORC tblproperties (「orc.compress" = 「SNAPPY」)
;
INSERT INTO TABLE B_ORC
SELECT *
FROM B
;
SELECT A_ORC.customerID,
A_ORC.name,
A_ORC.age,
A_ORC.address
JOIN B_ORC.role,
B_ORC.department,
B_ORC.salary ON A_ORC.customerID=B_ORC.customerID
;
ORC 支持壓縮存儲(使用 ZLIB 或如上所示使用 SNAPPY),但也支持不壓縮存儲。
4、使用分區
通過分區,數據存儲在 HDFS 上的單獨單個文件夾中。Hive 將查詢分區數據集,而不是 掃描表的所有數據集。
創建臨時表並將數據載入到臨時表中
CREATE TABLE Employee_Temp(
EmloyeeID int,
EmployeeName Varchar(100),
Address Varchar(100),
STATE Varchar(100),
City Varchar(100),
Zipcode Varchar(100)
) ROW FORMAT DELIMITED FIELDS TERMINATED BY ',' STORED AS TEXTFILE;
LOAD DATA INPATH '/home/hadoop/hive' INTO TABLE Employee_Temp;
創建分區表
Create Table Employee_Part(
EmloyeeID int,
EmployeeName Varchar(100),
Address Varchar(100),
State Varchar(100),
Zipcode Varchar(100))
PARTITIONED BY (City Varchar(100))
ROW FORMAT DELIMITED
FIELDS TERMINATED BY ','
STORED AS TEXTFILE;
啟用動態分區的命令
SET hive.exec.dynamic.partition = true;
SET hive.exec.dynamic.partition.mode = nonstrict;
從臨時表導入數據到分區表
INSERT Overwrite TABLE Employee_Part Partition(City)
SELECT EmployeeID,
EmployeeName,
Address,
STATE,
City,
Zipcode
FROM Emloyee_Temp;
5、使用 分桶
桶表介紹:https://cwiki.apache.org/confluence/display/Hive/LanguageManual+DDL+BucketedTables
舉例:https://blog.csdn.net/m0_37534613/article/details/55258928
Hive 表被劃分為多個分區,稱為 Hive分區。Hive分區進一步細分為集群或桶,稱為 bucket 或 Cluster。
Create Table Employee_Part(
EmloyeeID int,
EmployeeName Varchar(100),
Address Varchar(100),
State Varchar(100),
Zipcode Varchar(100))
PARTITIONED BY (City Varchar(100))
Clustered By (EmployeeID) into 20 Buckets
ROW FORMAT DELIMITED
FIELDS TERMINATED BY ','
STORED AS TEXTFILE;
6、CBO 查詢優化器
Hive CBO 是使用 Apache calcite 來處理的。
早期的 Hive 版本中(Hive-0.14 之前),在提交最終執行之前,Hive 會優化每個查詢的邏輯和物理執行計劃。 這些優化不是基於查詢的成本優化(Cost-based Optimizer) 。
直到 Hive-0.14 時才添加了 Cost-based optimization ,這時已經根據查詢的成本進行優化(例如要執行的連接類型,如何排序連接,並行度等)。
要使用基於成本的優化,需要在查詢開頭設置以下參數
set hive.cbo.enable=true;
set hive.compute.query.using.stats=true;
set hive.stats.fetch.column.stats=true;
set hive.stats.fetch.partition.stats=true;
如果要收集表信息,請使用 Analyze 命令。
7、寫好的 SQL
SQL是一種強大的聲明性語言。 與其他聲明性語言一樣,編寫SQL語句的方法不止一種。
盡管每個語句的功能都相同,但它可能具有截然不同的性能特徵。
我們來看一個例子。 考慮點擊流事件表:
CREATE TABLE clicks (
timestamp date, sessionID string, url string, source_ip string
) STORED as ORC tblproperties (「orc.compress」 = 「SNAPPY」);
每條記錄代表一次點擊事件,我們希望找到每個sessionID的最新網址。
有人可能會考慮以下方法:
SELECT clicks.* FROM clicks inner join
(select sessionID, max(timestamp) as max_ts from clicks
group by sessionID) latest
ON clicks.sessionID = latest.sessionID and
clicks.timestamp = latest.max_ts;
在上面的查詢中,我們構建一個子查詢來收集每個會話中最新事件的時間戳,然後使用 內聯接 來過濾掉其餘的事件。
雖然查詢是一個合理的解決方案, 但是從功能的角度來看 ,有一種更好的方法來重寫這個查詢,如下所示:
SELECT * FROM
(SELECT *, RANK() over (partition by sessionID,
order by timestamp desc) as rank
FROM clicks) ranked_clicks
WHERE ranked_clicks.rank=1;
在這里,我們使用 Hive 的 OLAP 窗口功能(OVER 和 RANK)來實現相同的功能。
顯然,刪除不必要的連接幾乎總能帶來更好的性能,而且當使用大數據時,這比以往任何時候都更重要。
我發現很多情況下查詢不是最優的 - 所以仔細查看每個查詢並考慮重寫是否可以使它更好更快。
————————————————
版權聲明:本文為CSDN博主「highfei2011」的原創文章,遵循CC 4.0 BY-SA版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/high2011/article/details/96271903