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

Как да повторя произволни редове от базата данни?

Две решения, представени тук. И двете предложени решения са само за mysql и могат да се използват от всеки език за програмиране като потребител. PHP би бил твърде бавен за това, но може да е потребител на него.

По-бързо решение :Мога да изведа 1000 произволни реда от таблица от 19 милиона реда за около 2 десети от секундата с по-модерни техники за програмиране.

По-бавно решение :Отнема около 15 секунди с техники за програмиране без захранване.

Между другото и двете използват генерирането на данни, видяно ТУК което написах. Така че това е моята малка схема. Използвам това, продължете с ДВЕ повече самовмъквания се виждат там, докато имам 19 милиона реда. Така че няма да го показвам отново. Но за да получите тези 19 милиона реда, отидете да видите това и направете още 2 от тези вмъквания и ще имате 19 милиона реда.

Първо по-бавна версия

Първо, по-бавният метод.

select id,thing from ratings order by rand() limit 1000;

Това връща 1000 реда за 15 секунди.

По-бързо решение

Това е малко по-сложно за описание. Същността му е, че предварително изчислявате вашите произволни числа и генерирате in clause край на произволни числа, разделени със запетаи и обвити с чифт скоби.

Ще изглежда като (1,2,3,4) но в него ще има 1000 числа.

И вие ги съхранявате и ги използвайте веднъж. Като еднократна подложка за криптография. Добре, не е добра аналогия, но се надявам, че разбирате смисъла.

Мислете за това като за край на in клауза и се съхранява в колона TEXT (като петно).

Защо, за Бога, човек би искал да направи това? Тъй като RNG (генератори на произволни числа) са изключително бавни. Но генерирането им с няколко машини може да бъде в състояние да изкара хиляди относително бързо. Между другото (и ще видите това в структурата на моите т.нар. приложения, аз улавям колко време отнема генерирането на един ред. Около 1 секунда с mysql. Но C#, PHP, Java, всичко може да събере това заедно. Въпросът не е как го сглобяваш, а че го имаш, когато го поискаш.

Тази стратегия, дългата и късата е, когато това се комбинира с извличане на ред, който не е бил използван като случаен списък, маркирането му като използван и издаване на повикване като

select id,thing from ratings where id in (a,b,c,d,e, ... )

и клаузата in има 1000 числа, резултатите са налични за по-малко от половин секунда. Ефективно използва mysql CBO (оптимизатор, базиран на разходите), отколкото го третира като присъединяване към PK индекс.

Оставям това в обобщен вид, защото е малко сложно на практика, но включва следните частици потенциално

  • таблица, съдържаща предварително изчислените произволни числа (Приложение А)
  • стратегия за създаване на събитие на mysql (Приложение Б)
  • съхранена процедура, която използва подготвена декларация (Приложение В)
  • съхранена само в mysql процедура за демонстриране на RNG in клауза за ритници (Приложение Г)

Допълнение A

Таблица, съдържаща предварително изчислените произволни числа

create table randomsToUse
(   -- create a table of 1000 random numbers to use
    -- format will be like a long "(a,b,c,d,e, ...)" string

    -- pre-computed random numbers, fetched upon needed for use

    id int auto_increment primary key,
    used int not null,  -- 0 = not used yet, 1= used
    dtStartCreate datetime not null, -- next two lines to eyeball time spent generating this row
    dtEndCreate datetime not null,
    dtUsed datetime null, -- when was it used
    txtInString text not null -- here is your in clause ending like (a,b,c,d,e, ... )
    -- this may only have about 5000 rows and garbage cleaned
    -- so maybe choose one or two more indexes, such as composites
);

Приложение Б

В интерес да не превръщате това в книга, вижте моя отговор ТУК за механизъм за стартиране на повтарящо се mysql събитие. Той ще управлява поддръжката на таблицата, видяна в Приложение А, като използва техники, показани в Приложение D и други мисли, които искате да измислите. Като повторно използване на редове, архивиране, изтриване, каквото и да е.

Приложение В

съхранена процедура, за да ми даде просто 1000 произволни реда.

DROP PROCEDURE if exists showARandomChunk;
DELIMITER $$
CREATE PROCEDURE showARandomChunk
(
)
BEGIN
  DECLARE i int;
  DECLARE txtInClause text;

  -- select now() into dtBegin;

  select id,txtInString into i,txtInClause from randomsToUse where used=0 order by id limit 1;
  -- select txtInClause as sOut; -- used for debugging

  -- if I run this following statement, it is 19.9 seconds on my Dell laptop
  -- with 19M rows
  -- select * from ratings order by rand() limit 1000; -- 19 seconds

  -- however, if I run the following "Prepared Statement", if takes 2 tenths of a second
  -- for 1000 rows

  set @s1=concat("select * from ratings where id in ",txtInClause);

  PREPARE stmt1 FROM @s1;
  EXECUTE stmt1; -- execute the puppy and give me 1000 rows
  DEALLOCATE PREPARE stmt1;
END
$$
DELIMITER ;

Допълнение Г

Може да се преплита с концепцията на Приложение Б. Въпреки това искате да го направите. Но това ви оставя с нещо, за да видите как mysql може да направи всичко сам от страна на RNG на нещата. Между другото, за параметри 1 и 2, които са съответно 1000 и 19M, това отнема 800 ms на моята машина.

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

drop procedure if exists createARandomInString;
DELIMITER $$
create procedure createARandomInString
(   nHowMany int, -- how many numbers to you want
    nMaxNum int -- max of any one number
)
BEGIN
    DECLARE dtBegin datetime;
    DECLARE dtEnd datetime;
    DECLARE i int;
    DECLARE txtInClause text;
    select now() into dtBegin;

    set i=1;
    set txtInClause="(";
    WHILE i<nHowMany DO
        set txtInClause=concat(txtInClause,floor(rand()*nMaxNum)+1,", "); -- extra space good due to viewing in text editor
        set i=i+1;
    END WHILE;
    set txtInClause=concat(txtInClause,floor(rand()*nMaxNum)+1,")");
    -- select txtInClause as myOutput; -- used for debugging
    select now() into dtEnd;

    -- insert a row, that has not been used yet
    insert randomsToUse(used,dtStartCreate,dtEndCreate,dtUsed,txtInString) values 
       (0,dtBegin,dtEnd,null,txtInClause);
END
$$
DELIMITER ;

Как да извикате горепосочената съхранена процедура:

call createARandomInString(1000,18000000);

Това генерира и записва 1 ред от 1000 числа, увити, както е описано по-горе. Големи числа, от 1 до 18 млн.

Като бърза илюстрация, ако някой трябва да промени съхранената процедура, премахнете отново реда близо до дъното, който казва „използва се за отстраняване на грешки“ и го задайте като последен ред в съхранения процес, който се изпълнява, и изпълнете това:

call createARandomInString(4,18000000);

... за генериране на 4 произволни числа до 18M, резултатите може да изглеждат така

+-------------------------------------+
| myOutput                            |
+-------------------------------------+
| (2857561,5076608,16810360,14821977) |
+-------------------------------------+

Приложение Е

Проверка на реалността. Това са малко напреднали техники и не мога да обучавам никого по тях. Но все пак исках да ги споделя. Но не мога да го науча. Отново и навън.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Как да настроите отдалечена MySQL връзка

  2. Няма подготвени оператори от страна на сървъра, използващи MySQL Connector/J

  3. Премахване на HTML тагове от записа

  4. PHP - Импортиране на CSV файл в mysql база данни с помощта на LOAD DATA INFILE

  5. MySQL ранг в случай на връзки