电脑知识|欧美黑人一区二区三区|软件|欧美黑人一级爽快片淫片高清|系统|欧美黑人狂野猛交老妇|数据库|服务器|编程开发|网络运营|知识问答|技术教程文章 - 好吧啦网

您的位置:首頁技術文章
文章詳情頁

mysql查詢語句優化

瀏覽:9日期:2023-10-17 11:07:29

這篇說下mysql查詢語句優化

是否請求了不需要的數據

典型案例:查詢不需要的記錄,多表關聯時返回全部列,總是取出全部列,重復查詢相同的數據。

是否在掃描額外的記錄

最簡單的衡量查詢開銷的指標。

響應數據掃描的行數返回的行數 訪問類型

在評估查詢開銷時,需要考慮下從表中找到某一行數據的成本,mysql有好多種方式可以查找并返回一行結果。有些訪問方式可能需要掃描很多行才能返回一行結果,也有些方式可能無須掃描就能返回結果。

在EXPLAIN語句中type列反應了訪問類型。訪問類型有很多種,從全表掃描到索引掃描,范圍掃描,唯一索引查詢,常數引用等。這里列的這些,速度是從慢到快,掃描的行數也是從小到大。

因此,要盡力避免讓每一條sql做全表掃描。

如果查詢沒辦法找到合適的訪問類型,那么解決的最好方式通常就是增加一個合適的索引,這個上一篇里說到過。索引讓mysql以最高效,掃描行數最少的方式找到需要的記錄。

一般mysql有三種方式應用where條件。從好到壞依次為

在索引中使用where條件過濾不匹配的記錄,這是在存儲引擎層中完成。使用索引覆蓋掃描(在extra列中出現using index)來返回記錄,直接從索引中過濾不需要的記錄并返回命中的結果。這是在mysql服務層完成的,但不用再回表查詢記錄。從表中返回數據,然后過濾不滿足條件的記錄(在extra列中出現where),這是在mysql服務層完成的,mysql需要先從數據表中讀取記錄然后過濾。

如果發現查詢中掃描大量的數據卻只返回少量的行。可以嘗試下面方法優化。

使用索引覆蓋掃描,把所有需要用到的列都放到索引中,這樣存儲引擎不用回表獲取對應行就可以返回結果了。改變表的結構,例如使用單獨的匯總表重寫這個復雜的查詢,讓mysql優化器以更優化的方式執行這個查詢重構查詢方式

一個復雜查詢還是多個簡單查詢?

在傳統實現中,總是強調數據庫層完成盡可能多的工作,這樣做的邏輯在于以前總是認為網絡通信,查詢解析,優化是一件代價很高的事。

但是這樣的想法對于mysql并不適用,mysql從設計上讓連接和斷開連接都很輕量,在返回一個小的查詢結果方面很高效。另外,現在的網絡速度比以前快的多,無論是寬帶還是延遲。在某些版本的mysql上,即便在一個通用的服務器上,也能運行每秒超過10萬的查詢。即使是一個千兆網卡也能輕松滿足每秒超過2000次的查詢。

切分查詢

即所謂的分而治之,將大查詢切分成小查詢,每個查詢功能完全一樣,每次只返回一小部分結果。

刪除舊的數據就是個很好的例子,定期的清理大量數據時,如果用一個大語句一次性完成的話,則可能一次鎖住很多數據,占滿整個事務日志,耗盡系統資源,阻塞很多小的但很重要的查詢。

因此可以

分解關聯查詢

簡單說,就是對每個表進行一次單表查詢,然后將結果在應用程序中進行關聯。例如

可以將其分解成下面查詢來替代

乍一看,這樣做沒有好處。事實上,有下面這些優勢

讓緩存效率更高。許多應用程序可以方便的緩存單表查詢對應的結果對象。將查詢分解后,執行單個查詢可以減少鎖的競爭。在應用層做關聯,可以更容易對數據庫進行拆分,更容易做到高性能,可擴展。查詢本身效率也會有所提升。在這個例子中,使用in代替關聯查詢,可以讓mysql按照id順序進行查詢,這可能比隨機的關聯更高效。可以減少冗余記錄的查詢。做關聯查詢時,可能需要重復訪問一部分數據。從這點看,這樣的重構還可能減少網絡和內存的消耗。實現了哈希關聯,而不是使用mysql的嵌套循環關聯。某些場景,哈希關聯的效率要高很多。 mysql如何執行關聯查詢

mysql中“關聯”一詞所包含的意義比一般理解上要更廣泛。總的來說,mysql認為任何一個查詢都是一次“關聯”,并不僅僅是一個查詢需要到兩個表匹配才叫關聯。所以,在mysql中,每個查詢,每個片段(包括子查詢,甚至基于單表的select)都可能是關聯。

下面看下mysql如何執行關聯查詢。

先看union查詢。mysql先將一系列的單個查詢結果放到一個臨時表中,然后再重新讀取臨時表數據完成union查詢。在mysql概念中,每個查詢都是一次關聯,所以讀取結果臨時表也是一次關聯。

mysql對任何關聯都執行嵌套循環關聯策略,即mysql先在一個表中循環取出單條數據,然后再嵌套循環到下一個表中尋找匹配的行,依次下去,直到所有表中匹配的行為止。然后根據各個表匹配的行,返回查詢中所需要的各個列。

可以看到查詢是從actor表開始的,這是mysql關聯查詢優化器自動做的選擇。現在用STRAIGHT_JOIN關鍵字,不讓mysql自動優化關聯。

這次的關聯順序倒轉過來,可以看到,倒轉后第一個關聯表只需要掃描很少的行數。而且第二個,第三個關聯表都是根據索引查詢,速度都很快。

最后,確保任何的group by,order by中的表達式只涉及到一個表中的列,這樣mysql才有可能使用索引優化這個過程。

排序優化

無論如何排序都是一個成本很高的操作。所以從性能角度考慮,應盡可能避免排序或避免對大量數據進行排序。

上一篇說到了如何通過索引排序。當不能使用索引生成排序結果時,mysql需要自己進行排序,如果數據量小,就在內存中進行,數據量大,則需要使用磁盤。mysql統一將這一過程稱為文件排序(filesort)。

在關聯查詢時如果需要排序,mysql會分兩種情況處理文件排序。

1.如果order by子句中的所有列都來自關聯的第一個表,mysql在關聯處理第一個表時就進行文件排序。如果是這樣,在EXPLAIN結果中的Extra字段會有Using filesort.

2.除此之外的所有情況,mysql都會先將關聯的結果存放到一個臨時表中,然后在所有的關聯結束后再進行文件排序。如果是這樣,在EXPLAIN結果中的Extra字段會有Using temporary;Using filesort.如果查詢中有LIMIT的話,LIMIT也會在排序之后應用。所以即使需要返回較少的行數,臨時表和需要排序的數據量仍然會非常大。

mysql5.6在這里做了很多重要的改進。當只需要返回部分排序結果的時候,例如,使用LIMIT子句,mysql不再所有結果排序,而是根據實際情況,選擇拋棄不滿足條件的結果,然后再排序。

關聯子查詢

mysql的子查詢實現非常糟糕,最糟糕的一類查詢是where條件中包含in的子查詢語句。

mysql對in()列表中的選項有專門的優化策略,一般會認為,mysql會先執行子查詢。但是,很不幸,mysql會先將相關的外層表押到子查詢中。例如

mysql會將查詢改成這樣

可以看到,mysql會先對film進行全表掃描,然后根據返回的film_id逐個執行子查詢。如果外層表是個非常大的表,那這個查詢的性能會非常糟糕。當然很容易重寫這個查詢,直接用關聯就可以了。

另一個優化方法是使用函數GROUP_CONCAT()在IN()中構造一個由逗號分隔的列表。

另外,通常建議用EXISTS()等效的改寫IN()子查詢。

如何用好關聯子查詢

并不是所有的關聯子查詢性能都會很差。寫好之后,先測試,然后做出自己的判斷。有時候,子查詢也會快些,例如當返回結果中只有一個表的某些列時,假設要返回所有包含同一個演員參演的電影,因為一個電影會有很多演員參演,所以可能會返回些重復記錄。

使用DISTINCT和GROUP BY移除重復的記錄

如果用EXISTS的話,就不需要使用DISTINCT和GROUP BY,也不會產生重復的結果集。我們知道一旦使用DISTINCT和GROUP BY,那么在執行過程中,通常會參數臨時中間表。

測試,看哪種寫法快點

可以看到在這個案例中,子查詢速度要快些。

最值優化

對于MIN(),MAX(),mysql的優化做的并不好,例如

mysql不能夠進行主鍵掃描,只有全表掃描了。這時可以用LIMIT重寫查詢。

這樣可以讓mysql掃描盡可能少的表

優化group by和distinct

它們都可以使用索引優化,這也是最有效的辦法。當無法使用索引時,group by使用兩種策略完成:使用臨時表或文件排序來做分組。

對關聯查詢分組,通常用查找表的標識符分組的效率比其他列更高。例如

下面的效率更高

這個查詢利用了演員姓名和id直接相關的特點,所以改寫后的結果不受影響。

如果不相關的話,可以用MIN(),MAX().繞過這種限制。但一定要清楚,select后面出現的非分組列一定是直接依賴分組列的,并且在每個組內的值是唯一的。

實在較真的話,寫成這樣

不過這樣成本有點高。因為子查詢需要創建和填充臨時表,而創建的臨時表是沒有任何索引的。

優化LIMIT分頁

最簡單的辦法是盡可能使用索引覆蓋掃描,而不是查詢所有的列。然后根據需要做一次關聯操作,再返回所需的列。例如

如果這個表非常大,最好改寫成這樣

這里的”延遲關聯“將大大提升效率,讓mysql掃描盡可能少的頁面,獲取需要訪問的記錄后再根據關聯列回原表查詢需要的所有列。這個也可以用來優化關聯查詢里面的limit.

有時候也可以將limit查詢轉換為已知位置的查詢,讓mysql通過范圍掃描獲得結果。例如

在一個位置列上有索引,并且預先計算出了邊界值。

另外,limit和offset的問題,會導致mysql掃描了大量不需要的行然后在拋棄掉,比如select .... limit 1000,20.

這時可以有變通方法,例如圖書館按照租借記錄翻頁,獲取第一頁。

因為rental_id是遞增的,而查看記錄的時候都是從離當前時間最近的地方開始的。后面的頁就可以用類似于下面的查詢實現

標簽: MySQL 數據庫
相關文章:
主站蜘蛛池模板: 美的商用净水器_美的直饮机_一级代理经销商_Midea租赁价格-厂家反渗透滤芯-直饮水批发品牌售后 | 全自动在线分板机_铣刀式在线分板机_曲线分板机_PCB分板机-东莞市亿协自动化设备有限公司 | 北京模型公司-军事模型-工业模型制作-北京百艺模型沙盘公司 | 高通量组织研磨仪-多样品组织研磨仪-全自动组织研磨仪-研磨者科技(广州)有限公司 | 高尔夫球杆_高尔夫果岭_高尔夫用品-深圳市新高品体育用品有限公司 | 薪动-人力资源公司-灵活用工薪资代发-费用结算-残保金优化-北京秒付科技有限公司 | 时代北利离心机,实验室离心机,医用离心机,低速离心机DT5-2,美国SKC采样泵-上海京工实业有限公司 工业电炉,台车式电炉_厂家-淄博申华工业电炉有限公司 | 临海涌泉蜜桔官网|涌泉蜜桔微商批发代理|涌泉蜜桔供应链|涌泉蜜桔一件代发 | 厌氧反应器,IC厌氧反应器,厌氧三相分离器-山东创博环保科技有限公司 | 欧盟ce检测认证_reach检测报告_第三方检测中心-深圳市威腾检验技术有限公司 | 屏蔽服(500kv-超高压-特高压-电磁)-徐吉电气 | 钛板_钛管_钛棒_钛盘管-无锡市盛钛科技有限公司 | 石家庄救护车出租_重症转院_跨省跨境医疗转送_活动赛事医疗保障_康复出院_放弃治疗_腾康26年医疗护送转诊团队 | 高压油管,液压接头,液压附件-烟台市正诚液压附件 | 仿古瓦,仿古金属瓦,铝瓦,铜瓦,铝合金瓦-西安东申景观艺术工程有限公司 | 铣刨料沥青破碎机-沥青再生料设备-RAP热再生混合料破碎筛分设备 -江苏锡宝重工 | 无锡装修装潢公司,口碑好的装饰装修公司-无锡索美装饰设计工程有限公司 | 集装袋吨袋生产厂家-噸袋廠傢-塑料编织袋-纸塑复合袋-二手吨袋-太空袋-曹县建烨包装 | 震动筛选机|震动分筛机|筛粉机|振筛机|振荡筛-振动筛分设备专业生产厂家高服机械 | 温控器生产厂家-提供温度开关/热保护器定制与批发-惠州市华恺威电子科技有限公司 | 头条搜索极速版下载安装免费新版,头条搜索极速版邀请码怎么填写? - 欧远全 | 大数据营销公司_舆情监测软件_上海SEO公司-文军营销官网 | 全自动过滤器_反冲洗过滤器_自清洗过滤器_量子除垢环_量子环除垢_量子除垢 - 安士睿(北京)过滤设备有限公司 | 专业深孔加工_东莞深孔钻加工_东莞深孔钻_东莞深孔加工_模具深孔钻加工厂-东莞市超耀实业有限公司 | 广州中央空调回收,二手中央空调回收,旧空调回收,制冷设备回收,冷气机组回收公司-广州益夫制冷设备回收公司 | 吊篮式|移动式冷热冲击试验箱-二槽冷热冲击试验箱-广东科宝 | 智能门锁电机_智能门锁离合器_智能门锁电机厂家-温州劲力智能科技有限公司 | 翰墨AI智能写作助手官网_人工智能问答在线AI写作免费一键生成 | 电缆隧道在线监测-智慧配电站房-升压站在线监测-江苏久创电气科技有限公司 | 金刚网,金刚网窗纱,不锈钢网,金刚网厂家- 河北萨邦丝网制品有限公司 | 烘箱-工业烘箱-工业电炉-实验室干燥箱 - 苏州华洁烘箱制造有限公司 | 法兰螺母 - 不锈钢螺母制造厂家 - 万千紧固件--螺母街 | 北京成考网-北京成人高考网| 国产频谱分析仪-国产网络分析仪-上海坚融实业有限公司 | 化妆品加工厂-化妆品加工-化妆品代加工-面膜加工-广东欧泉生化科技有限公司 | 中式装修设计_室内中式装修_【云臻轩】中式设计机构 | nalgene洗瓶,nalgene量筒,nalgene窄口瓶,nalgene放水口大瓶,浙江省nalgene代理-杭州雷琪实验器材有限公司 | 全自动烧卖机厂家_饺子机_烧麦机价格_小笼汤包机_宁波江北阜欣食品机械有限公司 | 报警器_家用防盗报警器_烟雾报警器_燃气报警器_防盗报警系统厂家-深圳市刻锐智能科技有限公司 | 聚丙烯酰胺PAM-聚合氯化铝PAC-絮凝剂-河南博旭环保科技有限公司 巨野电机维修-水泵维修-巨野县飞宇机电维修有限公司 | [官网]叛逆孩子管教_戒网瘾学校_全封闭问题青少年素质教育_新起点青少年特训学校 |