Mysql
 sql >> база данни >  >> RDS >> Mysql

Може ли MySQL FIND_IN_SET или еквивалент да се използва за използване на индекси?

Във връзка с вашия коментар:

@MarcB базата данни е нормализирана, CSV низът идва от потребителския интерфейс."Вземете ми данни за следните хора:101,202,303"

Този отговор има тесен фокус само върху тези числа, разделени със запетая. Защото, както се оказа, вие дори не сте говорили за FIND_IN_SET все пак.

Да, можете да постигнете това, което искате. Вие създавате подготвено изявление, което приема низ като параметър, както е в този скорошен отговор от моите. В този отговор погледнете втория блок, който показва CREATE PROCEDURE и неговия 2-ри параметър, който приема низ като (1,2,3) . Ще се върна към този момент след малко.

Не че трябва да го видите @spraff, но други биха могли. Мисията е да получите type !=ВСИЧКИ и възможни_ключове и ключове на Explain да не се показва null, както показахте във втория си блок. За общ прочит по темата вижте статията Разбиране Изход на EXPLAIN и страницата с ръководство на MySQL, озаглавена ОБЯСНЯВАНЕ Допълнителна информация .

Сега, обратно към (1,2,3) справка по-горе. От коментара ви и втория ви изход Explain във вашия въпрос знаем, че отговаря на следните желани условия:

  1. тип =диапазон (и по-специално не ВСИЧКИ) . Вижте документите по-горе за това.
  2. ключът не е нулев

Това са точно условията, които имате във втория си изход Explain и изходът, който може да се види със следната заявка:

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);

където имам 999 стойности в този in списък с клаузи. Това е извадка от този отговор от моето в Приложение D, отколкото генерира такъв произволен низ от csv, заобиколен от отворени и затворени скоби.

И обърнете внимание на следния изход Explain за този елемент 999 в клауза по-долу:

Целта е постигната. Постигате това със съхранена процедура, подобна на тази, която споменах преди в тази връзка с помощта на ПОДГОТОВЕН ДОКЛАД (и тези неща използват concat() последвано от EXECUTE ).

Индексът се използва, Tablescan (което означава лошо) не се изживява. Допълнителни показания са Тип на присъединяване на диапазон , всяка справка, която можете да намерите в оптимизатора на базата на разходите (CBO) на MySQL, този отговор от vladr макар и с дата, с поглед върху ТАБЛИЦА ЗА АНАЛИЗ част, по-специално след значителни промени в данните. Имайте предвид, че ANALYZE може да отнеме значително време, за да работи върху свръх огромни набори от данни. Понякога много и много часове.

Атаки с инжектиране на SQL:

Използването на низове, предавани на Съхранените процедури, е вектор на атака за атаки с инжектиране на SQL. Трябва да се вземат предпазни мерки за предотвратяването им при използване на предоставени от потребителя данни. Ако вашата рутина е приложена срещу вашия собствен идентификатор, генериран от вашата система, тогава сте в безопасност. Обърнете внимание обаче, че атаките с SQL инжектиране от 2-ро ниво възникват, когато данните са въведени на място от рутинни процедури, които не са дезинфекцирали тези данни при предишно вмъкване или актуализиране. Атаките се извършват преди чрез данни и се използват по-късно (вид бомба със закъснител).

Така че този отговор е Готово в по-голямата си част.

По-долу е изглед на същата таблица с незначителна модификация, за да покаже какво е страховито сканиране на таблици ще изглежда като в предишната заявка (но срещу неиндексирана колона, наречена thing ).

Разгледайте текущата ни дефиниция на таблицата:

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 |
+---------+---------+----------+

Имайте предвид, че колоната нещо преди беше колона 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;

И тогава Explain това е Tablescan (срещу колона 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. Как да конвертирате времето в часовата зона на iPhone устройството?

  2. Как работи функцията LCASE() в MySQL

  3. Използване на MySQL релационни бази данни на Gentoo

  4. Как да разбера кога моят docker mysql контейнер е готов и mysql е готов за приемане на заявки?

  5. Формули за изчисляване на географска близост