Mysql
 sql >> Baza danych >  >> RDS >> Mysql

Czy MySQL FIND_IN_SET lub odpowiednik może używać indeksów?

W nawiązaniu do Twojego komentarza:

@MarcB baza danych jest znormalizowana, ciąg CSV pochodzi z interfejsu użytkownika."Pobierz dane dla następujących osób:101,202,303"

Ta odpowiedź skupia się tylko na tych liczbach oddzielonych przecinkiem. Ponieważ, jak się okazuje, nawet nie mówiłeś o ZNAJDŹ_W_ZESTAWIE w końcu.

Tak, możesz osiągnąć to, co chcesz. Tworzysz przygotowane oświadczenie, które akceptuje ciąg znaków jako parametr, jak w tym Ostatnia odpowiedź mój. W tej odpowiedzi spójrz na drugi blok, który pokazuje CREATE PROCEDURE i jego drugi parametr, który akceptuje ciąg znaków, taki jak (1,2,3) . Za chwilę wrócę do tego punktu.

Nie to, że musisz to zobaczyć @spraff, ale inni mogą. Misją jest zdobycie typu !=WSZYSTKIE i possible_keys i klawisze of Wyjaśnij, aby nie pokazywać wartości null, jak pokazałeś w drugim bloku. Ogólne informacje na ten temat można znaleźć w artykule Zrozumienie WYJAŚNIJ Wyjście oraz stronę podręcznika MySQL zatytułowaną WYJAŚNIENIE Dodatkowe informacje .

Teraz wróć do (1,2,3) odniesienie powyżej. Z Twojego komentarza i drugiego wyniku Wyjaśnienia w Twoim pytaniu wiemy, że spełnia on następujące pożądane warunki:

  1. typ =zakres (w szczególności nie WSZYSTKIE) . Zobacz powyższe dokumenty na ten temat.
  2. klucz nie jest pusty

Są to dokładnie warunki, które masz w drugim wyniku wyjaśniania, oraz dane wyjściowe, które można zobaczyć za pomocą następującego zapytania:

explain 
select * from ratings where id in (2331425, 430364, 4557546, 2696638, 4510549, 362832, 2382514, 1424071, 4672814, 291859, 1540849, 2128670, 1320803, 218006, 1827619, 3784075, 4037520, 4135373, ... use your imagination ..., ...,  4369522, 3312835);

gdzie mam 999 wartości w tym in lista klauzul. To jest próbka z tej odpowiedzi z mojego w Dodatku D, który generuje taki losowy ciąg csv, otoczony nawiasami otwartymi i zamkniętymi.

I zwróć uwagę na następujące wyjście Wyjaśnij dla tego elementu 999 w klauzuli poniżej:

Cel osiągnięty. Osiągasz to za pomocą przechowywanego procesu podobnego do tego, o którym wspomniałem wcześniej w tym łączu używając PRZYGOTOWANE OŚWIADCZENIE (a te rzeczy używają concat() po którym następuje EXECUTE ).

Używany jest indeks, a Tablescan (czyli zły) nie jest doświadczany. Dalsze odczyty to Typ łączenia zakresu , wszelkie odniesienia, które można znaleźć w MySQL's Cost-Based Optimizer (CBO), ta odpowiedź z vladr choć przestarzały, mając na uwadze ANALIZA TABELI części, w szczególności po istotnych zmianach danych. Zwróć uwagę, że ANALYZE może zająć dużo czasu na bardzo dużych zbiorach danych. Czasami wiele, wiele godzin.

Ataki wstrzykiwania SQL:

Użycie ciągów przekazywanych do procedur składowanych jest wektorem ataku w przypadku ataków typu SQL Injection. Należy zastosować środki ostrożności, aby zapobiec korzystaniu z danych dostarczonych przez użytkownika. Jeśli twoja procedura jest stosowana przeciwko twojemu własnemu identyfikatorowi generowanemu przez twój system, jesteś bezpieczny. Należy jednak zauważyć, że ataki typu SQL Injection drugiego poziomu występują, gdy dane zostały wprowadzone przez procedury, które nie oczyściły tych danych podczas wcześniejszego wstawiania lub aktualizacji. Ataki wprowadzane wcześniej za pośrednictwem danych i wykorzystywane później (rodzaj bomby zegarowej).

Więc ta odpowiedź jest ukończona w większości.

Poniżej znajduje się widok tej samej tabeli z niewielką modyfikacją, aby pokazać, co przerażający Tablescan wyglądałby jak w poprzednim zapytaniu (ale w stosunku do nieindeksowanej kolumny o nazwie thing ).

Spójrz na naszą obecną definicję tabeli:

CREATE TABLE `ratings` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `thing` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=5046214 DEFAULT CHARSET=utf8;

select min(id), max(id),count(*) as theCount from ratings;
+---------+---------+----------+
| min(id) | max(id) | theCount |
+---------+---------+----------+
|       1 | 5046213 |  4718592 |
+---------+---------+----------+

Zauważ, że kolumna thing była wcześniej dopuszczalną wartością null kolumny int.

update ratings set thing=id where id<1000000;
update ratings set thing=id where id>=1000000 and id<2000000;
update ratings set thing=id where id>=2000000 and id<3000000;
update ratings set thing=id where id>=3000000 and id<4000000;
update ratings set thing=id where id>=4000000 and id<5100000;
select count(*) from ratings where thing!=id;
-- 0 rows

ALTER TABLE ratings MODIFY COLUMN thing int not null;

-- current table definition (after above ALTER):
CREATE TABLE `ratings` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `thing` int(11) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=5046214 DEFAULT CHARSET=utf8;

A potem Wyjaśnij, że jest to Tablescan (w stosunku do kolumny thing ):




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. zapytanie wybierające mysql w szeregowanej tablicy

  2. Jak najlepiej uzyskać czyjąś „ranking” z tabeli wyników za pomocą php i mysql bez zapętlania

  3. CHAR() Przykłady w MySQL

  4. Czy możliwe jest grupowanie według wielu kolumn przy użyciu MySQL?

  5. DAY() Przykłady – MySQL