Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/60.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 e> 在第一个查询中,每个查询有8个值的条件又添加了64个谓词_Mysql - Fatal编程技术网

Mysql e> 在第一个查询中,每个查询有8个值的条件又添加了64个谓词

Mysql e> 在第一个查询中,每个查询有8个值的条件又添加了64个谓词,mysql,Mysql,随着谓词数量的增加,优化器会在某个时候决定只扫描整个表会更快 select a.id, a.from, a.to, a.message, a.sent, a.read, a.direction from ( ( SELECT * FROM test WHERE test.to = 244975 ) UNION DISTINCT ( SELECT * FROM test WHERE test.from = 244975 ) ) a w

随着谓词数量的增加,优化器会在某个时候决定只扫描整个表会更快

select  a.id, a.from, a.to, a.message, a.sent,
        a.read, a.direction
    from  ( ( SELECT * FROM test WHERE test.to   = 244975 ) UNION DISTINCT
            ( SELECT * FROM test WHERE test.from = 244975 ) ) a
    where ...  -- but change `test` to `a`
假设子查询的行数远少于
test
,这可能会更快

现在,要使用“惰性评估”来加快速度,请执行以下操作:

select  a.id, a.from, a.to, a.message, a.sent,
        a.read, a.direction
    from  ( ( SELECT id FROM test WHERE test.to   = 244975 ) UNION DISTINCT
            ( SELECT id FROM test WHERE test.from = 244975 ) ) b  -- Note `b`
    JOIN test AS a  USING(id)   -- added
    where ...  -- but change `test` to `a`
这可能会有所帮助,因为它不会拖那么长的时间在所有的列上

最后一个版本只需要

PRIMARY KEY(id)
INDEX(from, id)
INDEX(to,   id)

你的桌子有多大?您是否可以尝试使用
FORCE INDEX(PRIMARY)
查看性能是否有所提高?您是否尝试过使用not_exists()?@mani大约400万records@Alec每次执行查询时,值
204177、214518、231429、242739、243834、244354、244644、244690
是不同的还是常数?如果不同,执行的频率是多少?是的。已经有一段时间了。(这里有一个棘手的问题。真正的解决方案可能涉及重新设计架构。)我知道这很棘手,但我认为OP也知道这一点,他有足够的代表性,我认为他知道自己在做什么。问题是为什么不在中的
会引起问题,我试图解决这个问题。查询/模式可以通过多种方式解决。我几个小时后回来,这是一个小世界。我在ysports,喜欢那里。@Harry是的,意识到这个讨厌的查询:(如前所述,
是一个严重的杀手——它有效地导致了表扫描。
不在(选择…
不在(1,2,3)更糟糕)
因为对子查询的重复调用。很高兴能为您提供帮助。如果您想了解有关如何优化上述内容的更多想法,可以使用更好的索引。您不会获得太多收益,但如果优化器选择它们,它们很可能更优。它们比当前索引小,这可能是最大的收益。
select test.id, test.from, test.to, test.message, test.sent, test.read, test.direction from test 
where (

    (test.to = 244975 and test.direction <> 2 and test.direction <> 3 and 
        (
        (test.from = 204177 and test.id > 5341203) OR 
        (test.from = 214518 and test.id > 5336549) OR
        (test.from = 231429 and test.id > 5338284) OR
        (test.from = 242739 and test.id > 5339541) OR
        (test.from = 243834 and test.id > 5340438) OR
        (test.from = 244354 and test.id > 5337489) OR
        (test.from = 244644 and test.id > 5338572) OR
        (test.from = 244690 and test.id > 5338467) 
        )

    )

    or 

    (test.from = 244975 and test.direction <> 1 and test.direction <> 3 and 
        (
        (test.to = 204177 and test.id > 5341203) OR
        (test.to = 214518 and test.id > 5336549) OR
        (test.to = 231429 and test.id > 5338284) OR
        (test.to = 242739 and test.id > 5339541) OR
        (test.to = 243834 and test.id > 5340438) OR
        (test.to = 244354 and test.id > 5337489) OR
        (test.to = 244644 and test.id > 5338572) OR
        (test.to = 244690 and test.id > 5338467)
        )
    )

    or 

    (test.read <> 1 and test.direction <> 3 and test.direction <> 2 and test.to = 244975 

    )

    or

    (test.read <> 1 and test.direction = 2 and test.from = 244975 

    )


     )



     order by test.id;
1   SIMPLE  test    index_merge PRIMARY,one,two,three,four  one,two 5,5     30  Using sort_union(one,two); Using where; Using filesort
SELECT * FROM (
SELECT
    test.id, test.from, test.to, test.message, test.sent, test.read, test.direction
FROM
    test 
WHERE
    test.to = 244975
    AND test.direction <> 2
    AND test.direction <> 3
    AND (
        (test.from = 204177 AND test.id > 5341203) OR 
        (test.from = 214518 AND test.id > 5336549) OR
        (test.from = 231429 AND test.id > 5338284) OR
        (test.from = 242739 AND test.id > 5339541) OR
        (test.from = 243834 AND test.id > 5340438) OR
        (test.from = 244354 AND test.id > 5337489) OR
        (test.from = 244644 AND test.id > 5338572) OR
        (test.from = 244690 AND test.id > 5338467) 
    )
UNION ALL
SELECT
    test.id, test.from, test.to, test.message, test.sent, test.read, test.direction
FROM
    test 
WHERE
    test.from = 244975
    AND test.direction <> 1
    AND test.direction <> 3
    AND (
        (test.to = 204177 and test.id > 5341203) OR
        (test.to = 214518 and test.id > 5336549) OR
        (test.to = 231429 and test.id > 5338284) OR
        (test.to = 242739 and test.id > 5339541) OR
        (test.to = 243834 and test.id > 5340438) OR
        (test.to = 244354 and test.id > 5337489) OR
        (test.to = 244644 and test.id > 5338572) OR
        (test.to = 244690 and test.id > 5338467)
    )
UNION ALL
SELECT
    test.id, test.from, test.to, test.message, test.sent, test.read, test.direction
FROM
    test 
WHERE
    test.read <> 1
    AND test.direction <> 3
    AND test.direction <> 2
    AND test.to = 244975
    AND test.from NOT IN (204177, 214518, 231429, 242739, 243834, 244354, 244644, 244690)
UNION ALL
SELECT
    test.id, test.from, test.to, test.message, test.sent, test.read, test.direction
FROM
    test 
WHERE
    test.read <> 1
    AND test.direction = 2
    AND test.from = 244975
    AND test.to NOT IN (204177, 214518, 231429, 242739, 243834, 244354, 244644, 244690)
) test ORDER BY test.id
SELECT test.id, test.from, test.to, test.message, test.sent, test.read, test.direction
FROM (
  SELECT *
  FROM test
  WHERE test.to = 244975
    AND test.direction not in (2,3)
    AND (
      (test.from = 204177 AND test.id > 5341203)
      OR (test.from = 214518 AND test.id > 5336549)
      OR (test.from = 231429 AND test.id > 5338284)
      OR (test.from = 242739 AND test.id > 5339541)
      OR (test.from = 243834 AND test.id > 5340438)
      OR (test.from = 244354 AND test.id > 5337489)
      OR (test.from = 244644 AND test.id > 5338572)
      OR (test.from = 244690 AND test.id > 5338467)
    )
  UNION
  SELECT *
  FROM test
  WHERE test.from = 244975
    AND test.direction not in (1,3)
    AND (
      (test.to = 204177 AND test.id > 5341203)
      OR (test.to = 214518 AND test.id > 5336549)
      OR (test.to = 231429 AND test.id > 5338284)
      OR (test.to = 242739 AND test.id > 5339541)
      OR (test.to = 243834 AND test.id > 5340438)
      OR (test.to = 244354 AND test.id > 5337489)
      OR (test.to = 244644 AND test.id > 5338572)
      OR (test.to = 244690 AND test.id > 5338467)
    )
  UNION
  SELECT *
  FROM test
  WHERE test.read != 1
    AND test.direction not in (2,3)
    AND test.to = 244975
    AND test.from not in (204177, 214518, 231429, 242739, 243834, 244354, 244644, 244690)
  UNION
  SELECT *
  FROM test
  WHERE test.read != 1
    AND test.direction = 2
    AND test.from = 244975
    AND test.to not in (204177, 214518, 231429, 242739, 243834, 244354, 244644, 244690)
) test
ORDER BY test.id;
real    0m15.410s
user    0m6.681s
sys 0m2.641s
real    0m17.747s
user    0m6.798s
sys 0m2.812s
(select * from test where test.from_ in (244975, 204177, 214518, 231429, 242739, 243834, 244354, 244644, 244690) or test.to_ in (244975, 204177, 214518, 231429, 242739, 243834, 244354, 244644, 244690)) as test 
select SQL_NO_CACHE test.id, test.from_, test.to_, test.message, test.sent, test.read_, test.direction 
from (select * from test where test.from_ in (244975, 204177, 214518, 231429, 242739, 243834, 244354, 244644, 244690) or test.to_ in (244975, 204177, 214518, 231429, 242739, 243834, 244354, 244644, 244690)) as test 
where (
  (test.to_ = 244975 and test.direction <> 2 and test.direction <> 3 and test.from_ in (204177, 214518, 231429, 242739, 243834, 244354, 244644, 244690) and 
        (   
        (test.from_ = 204177 and test.id > 5341203) OR  
        (test.from_ = 214518 and test.id > 5336549) OR
        (test.from_ = 231429 and test.id > 5338284) OR
        (test.from_ = 242739 and test.id > 5339541) OR
        (test.from_ = 243834 and test.id > 5340438) OR
        (test.from_ = 244354 and test.id > 5337489) OR
        (test.from_ = 244644 and test.id > 5338572) OR
        (test.from_ = 244690 and test.id > 5338467) 
        )   
    )   
    or  
    (test.from_ = 244975 and test.direction <> 1 and test.direction <> 3 and test.to_ in (204177, 214518, 231429, 242739, 243834, 244354, 244644, 244690) and 
        (   
        (test.to_ = 204177 and test.id > 5341203) OR
        (test.to_ = 214518 and test.id > 5336549) OR
        (test.to_ = 231429 and test.id > 5338284) OR
        (test.to_ = 242739 and test.id > 5339541) OR
        (test.to_ = 243834 and test.id > 5340438) OR
        (test.to_ = 244354 and test.id > 5337489) OR
        (test.to_ = 244644 and test.id > 5338572) OR
        (test.to_ = 244690 and test.id > 5338467)
        ))  
    or  
    (test.read_ <> 1 and test.direction <> 2 and test.direction <> 3 and test.to_ = 244975  and test.from_ not in (204177, 214518, 231429, 242739, 243834, 244354, 244644, 244690))
    or  
    (test.read_ <> 1 and test.direction = 2 and test.from_ = 244975 and test.to_ not in (204177, 214518, 231429, 242739, 243834, 244354, 244644, 244690))
     )   
     order by test.id;
mysql> \. sql_fixed.sql
*************************** 1. row ***************************
           id: 1
  select_type: PRIMARY
        table: <derived2>
         type: ALL
possible_keys: NULL
          key: NULL
      key_len: NULL
          ref: NULL
         rows: 226
     filtered: 100.00
        Extra: Using where; Using filesort
*************************** 2. row ***************************
           id: 2
  select_type: DERIVED
        table: test
         type: index_merge
possible_keys: one,two
          key: two,one
      key_len: 4,4
          ref: NULL
         rows: 226
     filtered: 100.00
        Extra: Using sort_union(two,one); Using where
2 rows in set, 1 warning (0.01 sec)
1. I don't want these 10 items from a 1,000,000 records I need the other 999,990, this reads the whole index.
2. I only want these 10 from a 1,000,000 records. This might only require one disk seek.
select  a.id, a.from, a.to, a.message, a.sent,
        a.read, a.direction
    from  ( ( SELECT * FROM test WHERE test.to   = 244975 ) UNION DISTINCT
            ( SELECT * FROM test WHERE test.from = 244975 ) ) a
    where ...  -- but change `test` to `a`
select  a.id, a.from, a.to, a.message, a.sent,
        a.read, a.direction
    from  ( ( SELECT id FROM test WHERE test.to   = 244975 ) UNION DISTINCT
            ( SELECT id FROM test WHERE test.from = 244975 ) ) b  -- Note `b`
    JOIN test AS a  USING(id)   -- added
    where ...  -- but change `test` to `a`
PRIMARY KEY(id)
INDEX(from, id)
INDEX(to,   id)