Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/72.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Mysql 对大型开放式架构表上的左联接结果进行排序_Mysql - Fatal编程技术网

Mysql 对大型开放式架构表上的左联接结果进行排序

Mysql 对大型开放式架构表上的左联接结果进行排序,mysql,Mysql,我正在设计一个具有以下表定义的开放模式数据库 mysql> desc orders; +-------+---------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +-------+---------+------+-----+---------+----------------+ | ID | int(11) | NO

我正在设计一个具有以下表定义的开放模式数据库

mysql> desc orders;
+-------+---------+------+-----+---------+----------------+
| Field | Type    | Null | Key | Default | Extra          |
+-------+---------+------+-----+---------+----------------+
| ID    | int(11) | NO   | PRI | NULL    | auto_increment |
| json  | text    | NO   |     | NULL    |                |
+-------+---------+------+-----+---------+----------------+

mysql> desc ordersnames;
+-------+--------------+------+-----+---------+----------------+
| Field | Type         | Null | Key | Default | Extra          |
+-------+--------------+------+-----+---------+----------------+
| ID    | int(11)      | NO   | PRI | NULL    | auto_increment |
| name  | varchar(330) | NO   | UNI | NULL    |                |
+-------+--------------+------+-----+---------+----------------+
名称上有索引

mysql> desc orderskeys;
+-----------+--------------+------+-----+---------+----------------+
| Field     | Type         | Null | Key | Default | Extra          |
+-----------+--------------+------+-----+---------+----------------+
| ID        | int(11)      | NO   | PRI | NULL    | auto_increment |
| reference | int(11)      | NO   | MUL | NULL    |                |
| nameref   | int(11)      | NO   | MUL | NULL    |                |
| value     | varchar(330) | NO   |     | NULL    |                |
+-----------+--------------+------+-----+---------+----------------+
指数如下:

引用,名称引用,值

nameref,value

参考文献

所有json字段(仅1维)在orderskeys表中每个现有字段都有一个条目,其中nameref是对ordersname中定义的字段名的引用

我通常会这样询问:

SELECT
    orderskeysdeliveryPostcode.value deliveryPostcode,
    orders.ID,
    orderskeysCN.value CN
FROM
    orders
JOIN ordersnames as ordersnamesCN   
    on ordersnamesCN.name = 'CN'
JOIN  orderskeys as orderskeysCN
    on orderskeysCN.nameref = ordersnamesCN.ID
    and orderskeysCN.reference = orders.ID
    and orderskeysCN.value = '10094'
JOIN ordersnames as ordersnamesdeliveryPostcode
    on ordersnamesdeliveryPostcode.name = 'deliveryPostcode'
JOIN orderskeys as orderskeysdeliveryPostcode
    on orderskeysdeliveryPostcode.nameref = ordersnamesdeliveryPostcode.ID
    and orderskeysdeliveryPostcode.reference = orders.ID
order by deliveryPostcode
limit 0,1000
产生这样的结果集

 +------------------+--------+-------+
 | deliveryPostcode | ID     | CN    |
 +------------------+--------+-------+
 | NULL             | 251018 | 10094 |
 | NULL             | 157153 | 10094 |
 | NULL             |  95419 | 10094 |
 | B-5030           | 172944 | 10094 |
 +------------------+--------+-------+
SELECT
    orderskeysdeliveryPostcode.value deliveryPostcode,
    orders.ID,
    orderskeysCN.value CN
FROM
    orders
JOIN ordersnames as ordersnamesCN   
    on ordersnamesCN.name = 'CN'
JOIN  orderskeys as orderskeysCN
    on orderskeysCN.nameref = ordersnamesCN.ID
    and orderskeysCN.reference = orders.ID
    and orderskeysCN.value = '10094'
JOIN ordersnames as ordersnamesdeliveryPostcode
    on ordersnamesdeliveryPostcode.name = 'deliveryPostcode'
LEFT JOIN orderskeys as orderskeysdeliveryPostcode
    on orderskeysdeliveryPostcode.nameref =   ordersnamesdeliveryPostcode.ID
    and orderskeysdeliveryPostcode.reference = orders.ID
limit 0,1000
->闪电般的速度,即使有超过400k的订单记录

但是,并非所有记录都包含所有字段,因此上面的查询不会生成没有“deliveryPostcode字段”的记录,因此我必须这样进行查询

 +------------------+--------+-------+
 | deliveryPostcode | ID     | CN    |
 +------------------+--------+-------+
 | NULL             | 251018 | 10094 |
 | NULL             | 157153 | 10094 |
 | NULL             |  95419 | 10094 |
 | B-5030           | 172944 | 10094 |
 +------------------+--------+-------+
SELECT
    orderskeysdeliveryPostcode.value deliveryPostcode,
    orders.ID,
    orderskeysCN.value CN
FROM
    orders
JOIN ordersnames as ordersnamesCN   
    on ordersnamesCN.name = 'CN'
JOIN  orderskeys as orderskeysCN
    on orderskeysCN.nameref = ordersnamesCN.ID
    and orderskeysCN.reference = orders.ID
    and orderskeysCN.value = '10094'
JOIN ordersnames as ordersnamesdeliveryPostcode
    on ordersnamesdeliveryPostcode.name = 'deliveryPostcode'
LEFT JOIN orderskeys as orderskeysdeliveryPostcode
    on orderskeysdeliveryPostcode.nameref =   ordersnamesdeliveryPostcode.ID
    and orderskeysdeliveryPostcode.reference = orders.ID
limit 0,1000
->同样快,但只要我在左联接表的键值上添加ORDERBY子句,mysql就希望在外部进行排序(临时,filesort),而不是使用现有索引

SELECT
    orderskeysdeliveryPostcode.value deliveryPostcode,
    orders.ID,
    orderskeysCN.value CN
FROM
    orders
JOIN ordersnames as ordersnamesCN   
    on ordersnamesCN.name = 'CN'
JOIN  orderskeys as orderskeysCN
    on orderskeysCN.nameref = ordersnamesCN.ID
    and orderskeysCN.reference = orders.ID
    and orderskeysCN.value = '10094'
JOIN ordersnames as ordersnamesdeliveryPostcode
    on ordersnamesdeliveryPostcode.name = 'deliveryPostcode'
LEFT JOIN orderskeys as orderskeysdeliveryPostcode
    on orderskeysdeliveryPostcode.nameref =   ordersnamesdeliveryPostcode.ID
    and orderskeysdeliveryPostcode.reference = orders.ID
ORDER BY deliveryPostCode
limit 0,1000
->非常慢

事实上,排序操作本身并没有太大不同,因为列deliveryPostcode的所有空值都将位于开始(ASC)或结束(DESC),而数据集的其余部分的顺序将与with JOIN相同,而不是LEFT JOIN

如何高效地查询(和排序)这些表?我需要不同的关系或索引吗


非常感谢……

我不确定您在查询的某些部分有什么逻辑

我认为它仍然可以优化

但为了解决您遇到的问题,请尝试暂时将其切换到
右键连接

 SELECT 
  orderskeysdeliveryPostcode.value deliveryPostcode,
  o.id,
  o.CN
FROM orderskeys as orderskeysdeliveryPostcode
INNER JOIN ordersnames as ord_n
    on ord_n.id = orderskeysdeliveryPostcode.nameref
      AND ord_n.name = 'deliveryPostcode'
RIGHT JOIN (
SELECT
    orders.ID,
    orderskeysCN.CN
FROM
    orders
LEFT JOIN 
  (SELECT 
     orderskeys.value as CN,
     orderskeys.reference
   FROM 
    orderskeys 
   INNER JOIN ordersnames as ordersnamesCN   
   ON ordersnamesCN.id = orderskeys.nameref
      AND ordersnamesCN.name = 'CN'
   WHERE orderskeys.value = '12209'
  ) as orderskeysCN
 ON
  orderskeysCN.reference = orders.ID
limit 0,1000
) as o
on 
  orderskeysdeliveryPostcode.reference = o.ID
ORDER BY deliveryPostCode;

这是我们可以玩的。只需要在那里添加数据插入。

对于内部连接,为了减少查找次数,MySQL将从行数最少的表开始(请参阅解释结果以查看MySQL从哪个表开始)

如果您在第一个表中按除列以外的任何内容排序,或者在第一个表中没有满足order by子句的索引,MySQL将不得不进行文件排序

当涉及到文本列时,更可能使用临时表,而不仅仅是内存中的临时表,而是可怕的磁盘上临时表


使用
stright\u JOIN
强制MySQL执行内部联接的顺序。

那么,您没有发布有问题的查询吗?只有两个好的吗?我在帖子中用e-query加上ORDER BY(虽然很清楚)不,我不清楚。您的第一个查询具有orderby,并且您编写了闪电般的速度,即使有超过400k的订单记录,因此您对这个orderby没有问题。所以我不知道你用的是哪一个?第一个查询的区别是orderskeys上的左连接。请注意,只要在联接表上或在没有orderingtry
order by OrdersKeyDeliveryPostcode.value的左侧联接表上执行order by,查询就会保持非常快的速度。这会产生一个错误,因为第一个order by(在from之后),因为按order by排序的数据集无法联合或进一步联接。即使删除该行也不起作用,因为它根本没有实现查询的逻辑。为了避免误解,我在原始帖子中添加了这些查询的结果集的示例输出?然后它不是左或右连接-它是内部的。尝试更新answer@FreudChicken阅读您在帖子中的数据-我不明白当
CN
字段不为空时,您的记录如何保持
NULL
?我承认,空值令人困惑。我想获取所有记录,如果该记录是否包含deliveryPostcode的数据。我通过orderskeysdeliveryPostcode上的左连接查询很容易做到这一点。但是,结果记录集上的任何order by都拒绝使用orderskeys上的索引进行排序,而是创建了一个临时表,这需要很长时间才能排序。我理解您的问题。这就是我试图将查询从左切换到右的原因。它必须返回相同的结果,只是更改了查询-子查询的顺序。mysql服务器应该使用你的索引这更接近我到目前为止所做的研究;)在这种情况下,我曾尝试过直接连接(但没有多大效果)。然而,问题似乎是我想要排序的集合不完全在索引表中,而是包含不存在对应项的连接行的空值。正如在文章中所说的,这与排序顺序无关,因为al NULL值将位于有序数据集的开头或结尾