Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/61.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 SQLite与其他数据库中的交叉连接_Mysql_Algorithm_Sqlite_Join - Fatal编程技术网

Mysql SQLite与其他数据库中的交叉连接

Mysql SQLite与其他数据库中的交叉连接,mysql,algorithm,sqlite,join,Mysql,Algorithm,Sqlite,Join,我在使用SQLite时遇到了一个奇怪的性能问题,在非常小的数据集上使用了交叉连接。例如,我在SQLite中所做的任何交叉连接都要比mysql中相同的交叉连接花费大约3倍或更长的时间。例如,以下是mysql中3000行的示例: select COUNT(*) from ( select * from main_s limit 3000 ) x cross join ( select * from main_s limit 3000 ) x2 group by x.territory

我在使用SQLite时遇到了一个奇怪的性能问题,在非常小的数据集上使用了
交叉连接。例如,我在SQLite中所做的任何交叉连接都要比mysql中相同的交叉连接花费大约3倍或更长的时间。例如,以下是mysql中3000行的示例:

select COUNT(*) from (
    select * from main_s limit 3000
) x cross join (
    select * from main_s limit 3000
) x2 group by x.territory

SQLite是否使用与其他客户机服务器数据库不同的算法或其他方法来进行交叉联接或其他类型的联接?我很幸运在一个表/数据库上使用SQLite,但每当连接表时,问题似乎就更大了

肖恩已经评论说,这个问题需要更多的细节才能得到真正准确的答案

但是,作为一般回答,请注意,用于执行交叉连接的算法可能是次优的(根据设计!),通常不鼓励使用它们:

旁注:交叉连接的特殊处理。“内部联接”、“联接”和“联接”运算符之间没有区别。它们在SQLite中完全可以互换。“交叉联接”联接运算符产生与“内部联接”、“联接”和“联接”运算符相同的结果,但查询优化器的处理方式不同,因为它阻止查询优化器在联接中对表重新排序。应用程序程序员可以使用交叉连接操作符直接影响为实现SELECT语句而选择的算法。避免使用交叉连接,除非在需要手动控制查询优化器的特定情况下。避免在应用程序开发的早期使用交叉连接,因为这样做是过早的优化。交叉连接的特殊处理是SQLite特有的特性,不是标准SQL的一部分

这清楚地表明SQLite查询计划器处理交叉连接的方式与其他RDBMS不同


注意:尽管如此,我不确定这是否真的适用于您的用例,因为两个被联接的派生表具有相同数量的记录。

Shawn已经评论过,这个问题需要更多的细节才能得到真正准确的答案

但是,作为一般回答,请注意,用于执行交叉连接的算法可能是次优的(根据设计!),通常不鼓励使用它们:

旁注:交叉连接的特殊处理。“内部联接”、“联接”和“联接”运算符之间没有区别。它们在SQLite中完全可以互换。“交叉联接”联接运算符产生与“内部联接”、“联接”和“联接”运算符相同的结果,但查询优化器的处理方式不同,因为它阻止查询优化器在联接中对表重新排序。应用程序程序员可以使用交叉连接操作符直接影响为实现SELECT语句而选择的算法。避免使用交叉连接,除非在需要手动控制查询优化器的特定情况下。避免在应用程序开发的早期使用交叉连接,因为这样做是过早的优化。交叉连接的特殊处理是SQLite特有的特性,不是标准SQL的一部分

这清楚地表明SQLite查询计划器处理交叉连接的方式与其他RDBMS不同


注意:尽管如此,我不确定这是否真的适用于您的用例,因为两个被联接的派生表具有相同数量的记录。

为什么MySQL可能更快:它使用了它称为“使用联接缓冲区(块嵌套循环)”的优化

但是。。。这个查询有很多地方是“错误的”。我不希望您根据您的发现对DB引擎进行比较得出结论

  • 一个数据库可能会创建一个索引来帮助连接,即使没有索引
  • SELECT*
    可能会拖拉所有的列,除非优化器足够聪明,可以抛掷除
    territory
    之外的所有列
  • 没有排序依据的
    限制
    为您提供随机值。您可能认为resultset中的每一行都必须有3000行值“3000”,但产生其他结果是完全有效的。(根据您的订购方式,它可能仍然不确定。)
  • 拥有一个
    COUNT(*)
    而没有一列说明它正在计算什么(
    territory
    )似乎是不现实的
  • 您有两次相同的子查询。某些引擎可能足够聪明,只需对其进行一次评估。或者你可以用
    重新格式化它,以便(可能)给优化器一个这样的提示。(我认为下面的例子展示了如何在MySQL 8.0或MariaDB 10.2中重新格式化它;我不知道SQLite)
  • 如果要将一个数据库与另一个数据库进行比较,请使用与应用程序相关的多个查询
  • 这不一定是一个“小”数据集,因为中间表(除非经过优化)有9000000行
  • 我怀疑我是否在一百个,也许一千个查询中写了不止一个交叉连接。它的表现几乎不值得担心

    WITH w AS ( SELECT territory FROM main_s LIMIT 3000 )
        SELECT COUNT(*)
            FROM w AS x1
            JOIN w AS x2
            GROUP BY x1.territory;
    

为什么MySQL可能更快:它使用了称为“使用连接缓冲区(块嵌套循环)”的优化

但是。。。这个查询有很多地方是“错误的”。我不希望您根据您的发现对DB引擎进行比较得出结论

  • 一个数据库可能会创建一个索引来帮助连接,即使没有索引
  • SELECT*
    可能会拖拉所有的列,除非优化器足够聪明,可以抛掷除
    territory
    之外的所有列
  • 没有排序依据的
    限制
    为您提供随机值。你
    select COUNT(*) from (
        select * from main_s limit 3000
    ) x cross join (
        select * from main_s limit 3000
    ) x2 group by x.territory
    
    select COUNT(*) from (
        select territory from main_s limit 3000
    ) x cross join (
        select * from main_s limit 3000
    ) x2 group by x.territory
    
    select COUNT(*) * 3000 from (
        select territory from main_s limit 3000
    ) group by territory
    
    select COUNT(*) * 3000 from (
        select territory from main_s limit 3000 order by territory
    ) group by territory