Wykorzystuje koncepcję cross join
aka produkt kartezjański (wszystkie permutacje). Tak więc twoje tablice tworzą tabelę pochodną (w pamięci) z liczbą wierszy x*y*z
, gdzie te x,y,z są rozmiarami tablic. Jeśli dostarczysz tablice o rozmiarze 3, 4 i 5, tabela pochodna będzie miała liczbę wierszy 3*4*5=60.
Dostarczona przez Ciebie kombinacja tablicy, która tworzy wiersz, wynosiła tylko 4*1*1=4
thing7
poniżej znajduje się Twoja główna tabela, której szukasz. covering index
powinien sprawić, że ta rzecz będzie latać nawet z mnóstwem danych. Indeks pokrywający to taki, w którym dostarczona informacja jest podawana za pośrednictwem skanowania b-drzewa indeksu, a odczytywanie strony danych nie jest wymagane. Czemu? Ponieważ potrzebne dane znajdują się w indeksie. A w twoim przypadku bardzo cienki.
Tabele A B C służą jako tablice.
Jedyną rzeczą do powiedzenia jest to, że każda tabela pochodna wymaga nazwy. Dlatego nadaliśmy mu nazwę xDerived
w zapytaniu. Pomyśl o tabeli pochodnej jako o czymś zwróconym i używanym w pamięci. To nie jest fizyczny stół.
Schemat
create table thing7
( id int auto_increment primary key,
A int not null,
B int not null,
C int not null,
index(A,B,C) -- covering index (uber-thin, uber-fast)
);
insert thing7(A,B,C) values
(1,2,7),
(1,2,8),
(2,2,1),
(1,3,1);
create table A
( id int auto_increment primary key,
value int
);
create table B
( id int auto_increment primary key,
value int
);
create table C
( id int auto_increment primary key,
value int
);
Test 1
truncate table A;
truncate table B;
truncate table C;
insert A (value) values (1),(2),(3),(4);
insert B (value) values (2);
insert C (value) values (7);
select t7.*
from thing7 t7
join
( select A.value as Avalue, B.value as Bvalue, C.value as Cvalue
from A
cross join B
cross join C
order by a.value,b.value,c.value
) xDerived
on xDerived.Avalue=t7.A and xDerived.Bvalue=t7.B and xDerived.Cvalue=t7.C;
+----+---+---+---+
| id | A | B | C |
+----+---+---+---+
| 1 | 1 | 2 | 7 |
+----+---+---+---+
..
Test 2
truncate table A;
truncate table B;
truncate table C;
insert A (value) values (1);
insert B (value) values (2);
insert C (value) values (0);
select t7.*
from thing7 t7
join
( select A.value as Avalue, B.value as Bvalue, C.value as Cvalue
from A
cross join B
cross join C
order by a.value,b.value,c.value
) xDerived
on xDerived.Avalue=t7.A and xDerived.Bvalue=t7.B and xDerived.Cvalue=t7.C;
-- no rows returned
Bardzo łatwo byłoby przekształcić to w wyszukiwanie oparte na sesji. Istnieje koncepcja, w której tablice do przeszukania (tabele A B C) mają kolumnę sesji. Ułatwiłoby to jednoczesne korzystanie przez wielu użytkowników. Ale to jest przesadna odpowiedź, ale zapytaj, czy chcesz uzyskać więcej informacji na ten temat.