范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文
国学影视

8种最坑SQL语法,工作中踩过吗?

  sql语句的执行顺序:  FROM   ON     JOIN   WHERE   GROUP BY   HAVING   SELECT  DISTINCT   ORDER BY   LIMIT   1、LIMIT 语句
  分页查询是最常用的场景之一,但也通常也是最容易出问题的地方。比如对于下面简单的语句,一般 DBA 想到的办法是在 type, name, create_time 字段上加组合索引。这样条件排序都能有效的利用到索引,性能迅速提升。SELECT * FROM   operation WHERE  type = "SQLStats"        AND name = "SlowLog" ORDER  BY create_time LIMIT  1000, 10;
  好吧,可能90%以上的 DBA 解决该问题就到此为止。但当 LIMIT 子句变成 "LIMIT 1000000,10" 时,程序员仍然会抱怨:我只取10条记录为什么还是慢?
  要知道数据库也并不知道第1000000条记录从什么地方开始,即使有索引也需要从头计算一次。出现这种性能问题,多数情形下是程序员偷懒了。
  在前端数据浏览翻页,或者大数据分批导出等场景下,是可以将上一页的最大值当成参数作为查询条件的。SQL 重新设计如下:SELECT   * FROM     operation WHERE    type = "SQLStats" AND      name = "SlowLog" AND      create_time > "2017-03-16 14:00:00" ORDER BY create_time limit 10;
  在新设计下查询时间基本固定,不会随着数据量的增长而发生变化。2、隐式转换
  SQL语句中查询变量和字段定义类型不匹配是另一个常见的错误。比如下面的语句:mysql> explain extended SELECT *      > FROM   my_balance b      > WHERE  b.bpn = 14000000123      >       AND b.isverified IS NULL ; mysql> show warnings; | Warning | 1739 | Cannot use ref access on index "bpn" due to type or collation conversion on field "bpn"
  其中字段 bpn 的定义为 varchar(20),MySQL 的策略是将字符串转换为数字之后再比较。函数作用于表字段,索引失效。
  上述情况可能是应用程序框架自动填入的参数,而不是程序员的原意。现在应用框架很多很繁杂,使用方便的同时也小心它可能给自己挖坑。3、关联更新、删除
  虽然 MySQL5.6 引入了物化特性,但需要特别注意它目前仅仅针对查询语句的优化。对于更新或删除需要手工重写成 JOIN。
  比如下面 UPDATE 语句,MySQL 实际执行的是循环/嵌套子查询(DEPENDENT SUBQUERY),其执行时间可想而知。UPDATE operation o SET    status = "applying" WHERE  o.id IN (SELECT id                 FROM   (SELECT o.id,                                o.status                         FROM   operation o                         WHERE  o.group = 123                                AND o.status NOT IN ( "done" )                         ORDER  BY o.parent,                                   o.id                         LIMIT  1) t);
  执行计划:+----+--------------------+-------+-------+---------------+---------+---------+-------+------+-----------------------------------------------------+ | id | select_type        | table | type  | possible_keys | key     | key_len | ref   | rows | Extra                                               | +----+--------------------+-------+-------+---------------+---------+---------+-------+------+-----------------------------------------------------+ | 1  | PRIMARY            | o     | index |               | PRIMARY | 8       |       | 24   | Using where; Using temporary                        | | 2  | DEPENDENT SUBQUERY |       |       |               |         |         |       |      | Impossible WHERE noticed after reading const tables | | 3  | DERIVED            | o     | ref   | idx_2,idx_5   | idx_5   | 8       | const | 1    | Using where; Using filesort                         | +----+--------------------+-------+-------+---------------+---------+---------+-------+------+-----------------------------------------------------+
  重写为 JOIN 之后,子查询的选择模式从 DEPENDENT SUBQUERY 变成 DERIVED,执行速度大大加快,从7秒降低到2毫秒。UPDATE operation o        JOIN  (SELECT o.id,                             o.status                      FROM   operation o                      WHERE  o.group = 123                             AND o.status NOT IN ( "done" )                      ORDER  BY o.parent,                                o.id                      LIMIT  1) t          ON o.id = t.id SET    status = "applying"
  执行计划简化为:+----+-------------+-------+------+---------------+-------+---------+-------+------+-----------------------------------------------------+ | id | select_type | table | type | possible_keys | key   | key_len | ref   | rows | Extra                                               | +----+-------------+-------+------+---------------+-------+---------+-------+------+-----------------------------------------------------+ | 1  | PRIMARY     |       |      |               |       |         |       |      | Impossible WHERE noticed after reading const tables | | 2  | DERIVED     | o     | ref  | idx_2,idx_5   | idx_5 | 8       | const | 1    | Using where; Using filesort                         | +----+-------------+-------+------+---------------+-------+---------+-------+------+-----------------------------------------------------+  4、混合排序
  MySQL 不能利用索引进行混合排序。但在某些场景,还是有机会使用特殊方法提升性能的。SELECT * FROM   my_order o        INNER JOIN my_appraise a ON a.orderid = o.id ORDER  BY a.is_reply ASC,           a.appraise_time DESC LIMIT  0, 20
  执行计划显示为全表扫描:+----+-------------+-------+--------+-------------+---------+---------+---------------+---------+-+ | id | select_type | table | type   | possible_keys     | key     | key_len | ref      | rows    | Extra +----+-------------+-------+--------+-------------+---------+---------+---------------+---------+-+ |  1 | SIMPLE      | a     | ALL    | idx_orderid | NULL    | NULL    | NULL    | 1967647 | Using filesort | |  1 | SIMPLE      | o     | eq_ref | PRIMARY     | PRIMARY | 122     | a.orderid |       1 | NULL           | +----+-------------+-------+--------+---------+---------+---------+-----------------+---------+-+
  由于 is_reply 只有0和1两种状态,我们按照下面的方法重写后,执行时间从1.58秒降低到2毫秒。SELECT * FROM   ((SELECT *          FROM   my_order o                 INNER JOIN my_appraise a                         ON a.orderid = o.id                            AND is_reply = 0          ORDER  BY appraise_time DESC          LIMIT  0, 20)         UNION ALL         (SELECT *          FROM   my_order o                 INNER JOIN my_appraise a                         ON a.orderid = o.id                            AND is_reply = 1          ORDER  BY appraise_time DESC          LIMIT  0, 20)) t ORDER  BY  is_reply ASC,           appraisetime DESC LIMIT  20;  5、EXISTS语句
  MySQL 对待 EXISTS 子句时,仍然采用嵌套子查询的执行方式。如下面的 SQL 语句:SELECT * FROM   my_neighbor n        LEFT JOIN my_neighbor_apply sra               ON n.id = sra.neighbor_id                  AND sra.user_id = "xxx" WHERE  n.topic_status < 4        AND EXISTS(SELECT 1                   FROM   message_info m                   WHERE  n.id = m.neighbor_id                          AND m.inuser = "xxx")        AND n.topic_type <> 5
  执行计划为:+----+--------------------+-------+------+-----+------------------------------------------+---------+-------+---------+ -----+ | id | select_type        | table | type | possible_keys     | key   | key_len | ref   | rows    | Extra   | +----+--------------------+-------+------+ -----+------------------------------------------+---------+-------+---------+ -----+ |  1 | PRIMARY            | n     | ALL  |  | NULL     | NULL    | NULL  | 1086041 | Using where                   | |  1 | PRIMARY            | sra   | ref  |  | idx_user_id | 123     | const |       1 | Using where          | |  2 | DEPENDENT SUBQUERY | m     | ref  |  | idx_message_info   | 122     | const |       1 | Using index condition; Using where | +----+--------------------+-------+------+ -----+------------------------------------------+---------+-------+---------+ -----+
  去掉 exists 更改为 join,能够避免嵌套子查询,将执行时间从1.93秒降低为1毫秒。SELECT * FROM   my_neighbor n        INNER JOIN message_info m                ON n.id = m.neighbor_id                   AND m.inuser = "xxx"        LEFT JOIN my_neighbor_apply sra               ON n.id = sra.neighbor_id                  AND sra.user_id = "xxx" WHERE  n.topic_status < 4        AND n.topic_type <> 5
  新的执行计划:+----+-------------+-------+--------+ -----+------------------------------------------+---------+ -----+------+ -----+ | id | select_type | table | type   | possible_keys     | key       | key_len | ref   | rows | Extra                 | +----+-------------+-------+--------+ -----+------------------------------------------+---------+ -----+------+ -----+ |  1 | SIMPLE      | m     | ref    | | idx_message_info   | 122     | const    |    1 | Using index condition | |  1 | SIMPLE      | n     | eq_ref | | PRIMARY   | 122     | ighbor_id |    1 | Using where      | |  1 | SIMPLE      | sra   | ref    | | idx_user_id | 123     | const     |    1 | Using where           | +----+-------------+-------+--------+ -----+------------------------------------------+---------+ -----+------+ -----+  6、条件下推
  外部查询条件不能够下推到复杂的视图或子查询的情况有:
  1、聚合子查询;2、含有 LIMIT 的子查询;3、UNION 或 UNION ALL 子查询;4、输出字段中的子查询;
  如下面的语句,从执行计划可以看出其条件作用于聚合子查询之后:SELECT * FROM   (SELECT target,                Count(*)         FROM   operation         GROUP  BY target) t WHERE  target = "rm-xxxx" +----+-------------+------------+-------+---------------+-------------+---------+-------+------+-------------+ | id | select_type | table      | type  | possible_keys | key         | key_len | ref   | rows | Extra       | +----+-------------+------------+-------+---------------+-------------+---------+-------+------+-------------+ |  1 | PRIMARY     |  | ref   |    |  | 514     | const |    2 | Using where | |  2 | DERIVED     | operation  | index | idx_4         | idx_4       | 519     | NULL  |   20 | Using index | +----+-------------+------------+-------+---------------+-------------+---------+-------+------+-------------+
  确定从语义上查询条件可以直接下推后,重写如下:SELECT target,        Count(*) FROM   operation WHERE  target = "rm-xxxx" GROUP  BY target
  执行计划变为:+----+-------------+-----------+------+---------------+-------+---------+-------+------+--------------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+-----------+------+---------------+-------+---------+-------+------+--------------------+ | 1 | SIMPLE | operation | ref | idx_4 | idx_4 | 514 | const | 1 | Using where; Using index | +----+-------------+-----------+------+---------------+-------+---------+-------+------+--------------------+
  关于 MySQL 外部条件不能下推的详细解释说明请参考以前文章:MySQL · 性能优化 · 条件下推到物化表 http://mysql.taobao.org/monthly/2016/07/087、提前缩小范围
  先上初始 SQL 语句:SELECT * FROM   my_order o        LEFT JOIN my_userinfo u               ON o.uid = u.uid        LEFT JOIN my_productinfo p               ON o.pid = p.pid WHERE  ( o.display = 0 )        AND ( o.ostaus = 1 ) ORDER  BY o.selltime DESC LIMIT  0, 15
  该SQL语句原意是:先做一系列的左连接,然后排序取前15条记录。从执行计划也可以看出,最后一步估算排序记录数为90万,时间消耗为12秒。+----+-------------+-------+--------+---------------+---------+---------+-----------------+--------+----------------------------------------------------+ | id | select_type | table | type   | possible_keys | key     | key_len | ref             | rows   | Extra                                              | +----+-------------+-------+--------+---------------+---------+---------+-----------------+--------+----------------------------------------------------+ |  1 | SIMPLE      | o     | ALL    | NULL          | NULL    | NULL    | NULL            | 909119 | Using where; Using temporary; Using filesort       | |  1 | SIMPLE      | u     | eq_ref | PRIMARY       | PRIMARY | 4       | o.uid |      1 | NULL                                               | |  1 | SIMPLE      | p     | ALL    | PRIMARY       | NULL    | NULL    | NULL            |      6 | Using where; Using join buffer (Block Nested Loop) | +----+-------------+-------+--------+---------------+---------+---------+-----------------+--------+----------------------------------------------------+
  由于最后 WHERE 条件以及排序均针对最左主表,因此可以先对 my_order 排序提前缩小数据量再做左连接。SQL 重写后如下,执行时间缩小为1毫秒左右。SELECT * FROM ( SELECT * FROM   my_order o WHERE  ( o.display = 0 )        AND ( o.ostaus = 1 ) ORDER  BY o.selltime DESC LIMIT  0, 15 ) o      LEFT JOIN my_userinfo u               ON o.uid = u.uid      LEFT JOIN my_productinfo p               ON o.pid = p.pid ORDER BY  o.selltime DESC limit 0, 15
  再检查执行计划:子查询物化后(select_type=DERIVED)参与 JOIN。虽然估算行扫描仍然为90万,但是利用了索引以及 LIMIT 子句后,实际执行时间变得很小。+----+-------------+------------+--------+---------------+---------+---------+-------+--------+----------------------------------------------------+ | id | select_type | table      | type   | possible_keys | key     | key_len | ref   | rows   | Extra                                              | +----+-------------+------------+--------+---------------+---------+---------+-------+--------+----------------------------------------------------+ |  1 | PRIMARY     |  | ALL    | NULL          | NULL    | NULL    | NULL  |     15 | Using temporary; Using filesort                    | |  1 | PRIMARY     | u          | eq_ref | PRIMARY       | PRIMARY | 4       | o.uid |      1 | NULL                                               | |  1 | PRIMARY     | p          | ALL    | PRIMARY       | NULL    | NULL    | NULL  |      6 | Using where; Using join buffer (Block Nested Loop) | |  2 | DERIVED     | o          | index  | NULL          | idx_1   | 5       | NULL  | 909112 | Using where                                        | +----+-------------+------------+--------+---------------+---------+---------+-------+--------+----------------------------------------------------+  8、中间结果集下推
  再来看下面这个已经初步优化过的例子(左连接中的主表优先作用查询条件):SELECT    a.*,           c.allocated FROM      (               SELECT   resourceid               FROM     my_distribute d                    WHERE    isdelete = 0                    AND      cusmanagercode = "1234567"                    ORDER BY salecode limit 20) a LEFT JOIN           (               SELECT   resourcesid, sum(ifnull(allocation, 0) * 12345) allocated               FROM     my_resources                    GROUP BY resourcesid) c ON        a.resourceid = c.resourcesid
  那么该语句还存在其它问题吗?不难看出子查询 c 是全表聚合查询,在表数量特别大的情况下会导致整个语句的性能下降。
  其实对于子查询 c,左连接最后结果集只关心能和主表 resourceid 能匹配的数据。因此我们可以重写语句如下,执行时间从原来的2秒下降到2毫秒。SELECT    a.*,           c.allocated FROM      (                    SELECT   resourceid                    FROM     my_distribute d                    WHERE    isdelete = 0                    AND      cusmanagercode = "1234567"                    ORDER BY salecode limit 20) a LEFT JOIN           (                    SELECT   resourcesid, sum(ifnull(allocation, 0) * 12345) allocated                    FROM     my_resources r,                             (                                      SELECT   resourceid                                      FROM     my_distribute d                                      WHERE    isdelete = 0                                      AND      cusmanagercode = "1234567"                                      ORDER BY salecode limit 20) a                    WHERE    r.resourcesid = a.resourcesid                    GROUP BY resourcesid) c ON        a.resourceid = c.resourcesid
  但是子查询 a 在我们的SQL语句中出现了多次。这种写法不仅存在额外的开销,还使得整个语句显的繁杂。使用 WITH 语句再次重写:WITH a AS (          SELECT   resourceid          FROM     my_distribute d          WHERE    isdelete = 0          AND      cusmanagercode = "1234567"          ORDER BY salecode limit 20) SELECT    a.*,           c.allocated FROM      a LEFT JOIN           (                    SELECT   resourcesid, sum(ifnull(allocation, 0) * 12345) allocated                    FROM     my_resources r,                             a                    WHERE    r.resourcesid = a.resourcesid                    GROUP BY resourcesid) c ON        a.resourceid = c.resourcesid  总结
  数据库编译器产生执行计划,决定着SQL的实际执行方式。但是编译器只是尽力服务,所有数据库的编译器都不是尽善尽美的。
  上述提到的多数场景,在其它数据库中也存在性能问题。了解数据库编译器的特性,才能避规其短处,写出高性能的SQL语句。
  程序员在设计数据模型以及编写SQL语句时,要把算法的思想或意识带进来。
  编写复杂SQL语句要养成使用 WITH 语句的习惯。简洁且思路清晰的SQL语句也能减小数据库的负担 。

漫步在越南街头,碰到漂亮姑娘问要不要生菜,熟客会直接拒绝如果有机会去国外旅行的话,你肯定会十分开心。不仅可以欣赏国外的风景,还可以看一看当地的美女。越南作为中国的邻国,经常吸引许多游客前来旅游,中国游客对这个国家情有独钟。(此处已添加小实用如何让里程有效期多延一年?今天,来分享一个小技巧。如何让里程有效期多延一年?我们以最抠门的东航为例。假如你里程兑换的上海广州航班取消了。你可能一激动就赶紧拨打95530要求退票。结果待里程返还后一看,有效期原来,俄罗斯人也爱去泰国养老!战斗民族都得说真香此前,泰国旅游局表示因俄乌冲突,导致访泰的旅客大量减少。不少俄国人的夏日梦刚要开始就要破灭了,但要知道,在疫情前,每年主要造访泰国的游客除了中国游客之外,其次就是俄罗斯游客,可谓是经常凌晨醒来,说明这里堵住了,每天敲敲手臂,半个月转好人一旦上了年纪,各种器官逐渐老化,与此同时,睡眠质量也会变差,总是在凌晨三到五点之间醒来,也不是因为要上厕所,就是总感觉身体哪里不舒服。相信很多人都会有这样的症状,到底是什么原因引Ulike推出全新脱毛仪,引领Z时代极萌消费新趋势暖花开之际,爱美人士蠢蠢欲动,已经迫不及待脱下束缚,出门郊游撒欢了。与此同时在以Ulike雅萌一众知名品牌所在的美容美体仪器行业,正在悄然刮起一股极萌风。Ulike是家用脱毛仪行业李纯对肤色很自信,穿全白连衣裙也不显黑,梳大背头也那么抢镜不管任何年龄段的女性,对于好看的裙子都没有抵抗力。各式各样的裙装,可以穿出很多样化的风格气质。随着时尚的不断进步,流行的趋势也在不停地转换。除了很多经典的款式之外,很新颖时尚的裙子中国大量采购美豆,允许从俄全境进口小麦,巴西或望眼欲穿人民币中国是全球最大的大豆买家,每年的大豆需求量为1亿吨左右,不过,中国也正在采取措施以减少对进口大豆的依赖,从海关公布的数据统计,2021年中国的大豆进口量近9700万吨,而国产大豆产美国疯狂加息,中国持续放水,中美政策大对决!谁能取胜?时间来到2022年,中美两国在经济政策上,已经出现了严重的割裂。一方面,美国为了自家的经济发展疯狂加息,而中国为保经济,却多次放水。这意味着,两国未来的经济发展,将走向不同的轨迹。16强决出8席!中国1人晋级,丁俊晖再战苦主,期盼会师颜丙涛北京时间2022年3月3日,斯诺克威尔士公开赛继续进行,8位球员率先晋级16强,包括中国选手张安达。接下来,丁俊晖再战苦主奥沙利文,这场比赛的胜者将在下一轮对阵颜丙涛和里奇沃顿之间十年前与雪结缘,哨位君周晓辉谈冬残奥火炬传递周晓辉,中国人民大学新闻学院2017级博士研究生,2022北京冬残奥会火炬手。曾在2011年12月至2013年12月间服役于武警黑龙江省总队,退役后创办军事类自媒体一号哨位,201珠峰8848米,火星的山高达2。1万米,为何地球上的山不能突破1万米中国最高的山峰珠穆朗玛峰已经是截至目前地球比较高的山峰了,其海拔高度达到了8848。86米,然而火星上却出现了高达2。1万米的山峰。这样的数字差异不禁让人感叹,难道地球上就没有突破
一个人的旅行文章转自最右我们讲讲一个人旅行需要什么。机智当你决定旅行的时候你就要明白自己的立场,在你打算放弃之前,你必须一直保持大脑的清醒。放弃那些不切实际的梦想,你需要明白,诗和远方从不在其绿水青山冰天雪地吉林万亿级新支柱产业蓬勃兴起数说吉林这五年,今天看一看绿水青山冰天雪地,打造万亿级旅游新支柱产业的新篇章新作为。274种。生态环境持续向好的查干湖,候鸟种类达到274种,比两年前增加了37。连年游客接待量超过多喝水好,喝太多也不行来源健康报我们常说要多喝水,尤其是夏天。但是喝水要有度,否则过犹不及。喝水太多,为什么会中毒肾脏在正常状态下每小时排出8001000毫升的水。因此,在这个范围内摄入水分,肾脏表示毫湿疹反复发作,该如何预防?推荐5个方法,或能帮你减轻困扰众所周知,湿疹是一种非常常见的皮肤疾病,主要是因为多种内外因素引起的炎症性皮肤疾病,在现实生活中,很多人都得过湿疹这种疾病,而且湿疹还有很多类型比如慢性湿疹顽固性湿疹等,如果不及时每天都喝水,你真的喝对了吗?避开3大误区,水喝对了才健康早晨起床喝杯水已经逐渐成为很多人的一个日常生活习惯。但是,你喝水真的喝对了吗?你可能要说喝水这么简单,谁不会喝?这还真不一定!今天就给你列了一个喝水提醒清单,快来对照看看,你有没有夏天吃这两花一叶,消暑祛湿健脾胃说到夏天,你会想到什么?闷热的天气,聒噪的蝉鸣,多汁的西瓜,清爽的绿豆汤但到了6月,潮湿闷热的天气,多少会让你心情烦躁,加上湿气重,整个人精神不振,食欲不佳,下面小蓝为大家推荐两花夏季必备男女老少皆宜,专治胃口不佳,食欲不振养生调理方芒种已过,仲夏已至。天气越来越热,是否觉得肠胃不比之前了?出现不想吃饭吃啥都不香,甚至腹泻的情况!入夏之后多数人会有以上情况,中医认为,脾属土,主运化水湿,因为夏季闷热多湿,而湿热勇士打造新三巨头?汤神2特质无可取代水花兄弟仍是五小精髓勇士时隔4年再度赢得总冠军,向人们证明了球队这几个赛季的努力没有白费,而库里维金斯普尔的新组合也备受期待。作为勇士资历最高的球员之一,汤普森如今在球队中的战术地位开始下滑,尤其是相CBA最新消息!超级外援重返首钢,吉林签下梅奥,姚明或正式下课目前CBA正处在休赛期当中,各支球队的主要任务就是夏季恢复性的训练,从而备战新赛季,同时在外援的选择方面也是重中之重,各支球队也已经着手。那么接下来让我们一同来关注一下CBA方面最2022温网资格赛张之臻力克17号种子,科尔施雷柏宣布温网后退役张之臻当地时间6月20日,2022温网资格赛拉开帷幕,男单签表中唯一一位中国球员张之臻以6475击败17号种子埃斯科贝多,晋级次轮,将战德国球员马苏尔。本届温网男单资格赛签表中有七家暴弟媳门自杀命运多舛的威尔士队主帅位置还有好运吗?威尔士足总昨晚官方确认,吉格斯辞去威尔士队主帅职务。2020年11月,吉格斯因涉嫌家暴前女友而遭到传讯,这也是他辞职最大的原因。吉格斯总是因为私生活影响职业生涯,比如弟媳门事件。威