Couchbase другой результат предложения вложенного цикла WHERE

#couchbase #n1ql

#couchbase #n1ql

Вопрос:

Я столкнулся с странной проблемой в couchbase: я выполнял следующие два запроса:

 SELECT *
FROM (
SELECT *
FROM (
SELECT *
FROM ssb_lineorder
LIMIT 10000) AS cte0
INNER JOIN ssb_ddate ON cte0.ssb_lineorder.lo_orderdate = ssb_ddate.d_datekey) AS cte1
JOIN ssb_part USE NL ON cte1.cte0.ssb_lineorder.lo_partkey = ssb_part.p_partkey
WHERE ssb_part.p_size > 10
 

и

 SELECT *
FROM (
SELECT *
FROM (
SELECT *
FROM (
SELECT *
FROM ssb_lineorder
LIMIT 10000) AS cte0
INNER JOIN ssb_ddate ON cte0.ssb_lineorder.lo_orderdate = ssb_ddate.d_datekey) AS cte1
JOIN ssb_part USE NL ON cte1.cte0.ssb_lineorder.lo_partkey = ssb_part.p_partkey ) AS cte2
WHERE cte2.ssb_part.p_size > 10
 

Эти два точно такие же, за исключением последнего предложения WHERE . Согласно моим знаниям о реляционных СУБД, результаты должны быть точно такими же. но я получаю другой результат: 1 для первого запроса, 7972 для второго запроса.

Мне интересно, правильно ли я понял механизм n1ql?

Ответ №1:

Не должно быть никаких различий.

ОГРАНИЧЕНИЕ внутри без order by может привести к противоречивым результатам. 1 против 7972, это далеко.

Поскольку это зависит от данных, вам необходимо это отладить. Запустите пользовательский интерфейс и перейдите на вкладку Plan Text и посмотрите ItemsIn #, ItemsOut # каждого оператора и посмотрите, где что-то пошло не так.

Также добавьте предикат и уменьшите данные и посмотрите, что не так.

Поскольку ВНЕШНЕГО СОЕДИНЕНИЯ нет, попробуйте следующее.

 CREATE INDEX ix1 ON ssb_part(p_size, p_partkey);
CREATE INDEX ix2 ON ssb_lineorder(lo_partkey, lo_orderdate);
CREATE INDEX ix3 ON ssb_ddate(d_datekey);

SELECT *
FROM ssb_part AS sp
JOIN ssb_lineorder AS sl ON  sp.p_partkey = sl.lo_partkey
JOIN ssb_ddate AS sd ON sl.lo_orderdate = sd.d_datekey
WHERE sp.p_size > 10

SELECT *
FROM ssb_part AS sp
JOIN ssb_lineorder AS sl USE HASH (PROBE) ON  sp.p_partkey = sl.lo_partkey
JOIN ssb_ddate AS sd USE HASH (PROBE) ON sl.lo_orderdate = sd.d_datekey
WHERE sp.p_size > 10 ;