2012-05-22 18 views
17

Występują pewne dziwne problemy z połączeniami wewnętrznymi MySQL. Zasadniczo, otrzymujemy nieparzysty błąd podczas używania operatora '=', ale użycie 'like' powoduje, że działa. Niestety, dzieje się tak za pośrednictwem ActiveRecord i nie ma prostego sposobu, aby zamiast tego po prostu policzyć "like", a ponadto chcemy zrozumieć, co się tutaj dzieje.MySQL INNER JOIN - '=' vs 'like'

Oto zapytanie, które nie:

mysql> SELECT COUNT(*) FROM `versions` INNER JOIN `site_versions` 
       ON `versions`.id = `site_versions`.version_id; 

Tutaj jest błąd:

ERROR 1296 (HY000): Got error 20008 'Query aborted due to out of query memory' 
from NDBCLUSTER 

Oto zapytanie, które działa:

mysql> SELECT COUNT(*) FROM `versions` INNER JOIN `site_versions` 
       ON `versions`.id like `site_versions`.version_id; 

Oto kilka szczegółów na temat same tabele:

mysql> desc site_versions; 
+----------------------+----------+------+-----+---------+----------------+ 
| Field    | Type  | Null | Key | Default | Extra   | 
+----------------------+----------+------+-----+---------+----------------+ 
| id     | int(11) | NO | PRI | NULL | auto_increment | 
| version_id   | int(11) | YES | MUL | NULL |    | 
[..snip..] 
+----------------------+----------+------+-----+---------+----------------+ 

mysql> desc versions; 
+------------+--------------+------+-----+---------+----------------+ 
| Field  | Type   | Null | Key | Default | Extra   | 
+------------+--------------+------+-----+---------+----------------+ 
| id   | int(11)  | NO | PRI | NULL | auto_increment | 
[..snip..] 
+------------+--------------+------+-----+---------+----------------+ 

Jakieś pomysły, dlaczego "jak" działa, a "=" nie?

+4

to coś, co daje oczekiwane rezultaty? może po prostu nie dołącza do niczego (bo co to znaczy dla intów?), a więc unika problemu z pamięcią, który wyzwala prawidłowe zapytanie. –

+1

@andrewcooke - Hmm, "jak" wydaje się działać, gdy jest używany w ten sposób: http://sqlfiddle.com/#!2/86792/1 –

+3

Może to również pomóc w wyświetleniu "wyjaśnienia" każdego zapytania. –

Odpowiedz

0

Nie jestem pewien, czy to rozwiąże problem, ale jest to możliwe. Nie używaj count(*). Może robi się "zakłopotany", co liczyć. Najlepszą praktyką jest zliczanie określonego pola, np. id. Aby to zrobić, musisz użyć aliasu dla tabel.

SELECT COUNT(v.id) FROM versions as v 
INNER JOIN site_versions as sv ON v.id = sv.version_id; 
+1

Lub po prostu użyj stałej: 'SELECT COUNT (1) FROM ...' – bjnord

+4

W nietypowej sytuacji, takiej jak OP, nie można zbytnio zaskoczyć sugestii takich jak Twoja. I nie będę. Ale to stwierdzenie, * "Najlepszą praktyką jest liczyć konkretne pole" *, wykonane w kontekście drugiego, a mianowicie * Nie używaj 'count (*)' '*, brzmi jak ogólna rada dla przyszłość i jako taka jest dyskusyjna, delikatnie mówiąc. Używanie 'COUNT (*)' do zliczania wierszy w grupie, niezależnie od danych w wierszach lub jakichkolwiek innych warunkach, jest całkowicie poprawne i zgodne ze standardem. Być może są jakieś implikacje w MySQL, ale wtedy być może trzeba wspomnieć, że tak było. –

+0

@Andriy - ja też zawsze zakładałem, że 'count (*)' powinien być unikany, kiedy to możliwe? Mimo, że składnia jest poprawna i może niezwiązana z problemem op, naprawdę jest to [zauważalna różnica w wydajności] (http://www.mysqlperformanceblog.com/2007/04/10/count-vs-countcol/). Nie jestem jednak DBA, ale ponieważ program rozwijający zawsze unikał 'count (*)', gdy to możliwe, z tego powodu. Możliwe, że coś tutaj źle zrozumiałem, proszę, powiedz mi, jeśli tak zrobiłem. – stefgosselin

3

Paradoksalnie wydaje się być związane z optymalizacją; za pomocą LIKE zmuszasz MySQL do zaprzestania używania możliwych indeksów (przynajmniej z kolumnami liczbowymi, ponieważ musi on rzucić je wszystkie do łańcucha w celu porównania).

Wygląda na to, że po MySQL zabraknie miejsca (pamięci/dysku) do użycia indeksu (sprawdź ustawienie key_buffer).

Oczywiście, to tylko przeczucie i nie wiem zbyt wiele na temat NDB, aby ci pomóc, ale mam nadzieję, że to cię posunie we właściwym kierunku.