konto usunięte
Temat: Losowanie rekordów w dużej bazie danych
Witam serdecznie,Mam taką tabelkę:
CREATE TABLE IF NOT EXISTS `kategorie` (
`id` BIGINT(20) UNSIGNED NOT NULL,
`tytul` VARCHAR(85) COLLATE utf8_unicode_ci DEFAULT NULL,
`domena_url` VARCHAR(100) COLLATE utf8_unicode_ci DEFAULT NULL,
`enable` INT(11) NOT NULL DEFAULT '0',
`level` INT(11) NOT NULL DEFAULT '0',
`parent_id` INT(11) NOT NULL DEFAULT '0'
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
--
-- Indeksy dla zrzutów tabel
--
--
-- Indexes for table `cms_kategorie`
--
ALTER TABLE `cms_kategorie`
ADD PRIMARY KEY (`bf_id`),
ADD UNIQUE KEY `bf_id` (`bf_id`),
ADD KEY `bf_id_2` (`bf_id`);
--
-- AUTO_INCREMENT for dumped tables
--
--
-- AUTO_INCREMENT dla tabeli `cms_kategorie`
--
ALTER TABLE `cms_kategorie`
MODIFY `bf_id` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT;
Baza zawiera 1.5GB i polecenie ORDER by RAND() bardzo "zamula" (skrypt wykonuje się ponad 60 sekund).
Wyczytałem że jest to problem tych randów i trzeba zastosować procedury.
Kombinuję z czymś takim (nie chce mi to za bardzo działać):
DELIMITER $$
DROP PROCEDURE IF EXISTS getRandomRecords$$
CREATE PROCEDURE getRandomRecords(IN cnt INT)
BEGIN
DROP TEMPORARY TABLE IF EXISTS randomRecords;
CREATE TEMPORARY TABLE randomRecords ( `rand_id` BIGINT, `tytul` VARCHAR(85), `domena_url` VARCHAR(100) );
loop_random: LOOP
IF cnt < 1 THEN
LEAVE loop_random;
END IF;
INSERT INTO randomRecords
SELECT r1.id, r1.tytul, r3.domena_url FROM `kategorie` AS r1 JOIN
(SELECT (RAND() *
(SELECT MAX(id) FROM `kategorie`)) AS id) AS r2
WHERE r1.id >= r2.id ORDER BY r1.id ASC LIMIT 1;
SET cnt = cnt - 1;
END LOOP loop_random;
SELECT * FROM randomRecords;
END$$
DELIMITER ; </code>
Wie ktoś jak to powinno wyglądać?
Mój kod php na stronie internetowej wygląda następująco:
<code>
$miasta = Array();
$stmt = $db->prepare("select tytul, domena_url, id FROM kategorie1 WHERE enable= 1 ORDER by RAND() ASC limit 50;");
$stmt->execute();
foreach ($stmt as $rowX) {
array_push($miasta, $rowX['tytul']);
}
$stmt->closeCursor();
$produkty = Array();
$stmt = $db->prepare("select tytul, domena_url, id FROM kategorie2 WHERE enable= 1 ORDER by RAND() ASC limit 50;");
$stmt->execute();
foreach ($stmt as $rowX) {
array_push($produkty, $rowX['tytul']);
}
$stmt->closeCursor();
$res = array();
foreach($miasta as $val) {
$nazwa_miasta = baza_odczyt($val .' ' . array_shift($produkty));
echo "<a href='".$portal_url."' title='".$nazwa_miasta."'>".$nazwa_miasta."</a>, ";
}
Wie ktoś może jak to powinno wyglądać?