Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.php > #18413 > unrolled thread
| Started by | cb <cb@ppt.io.it> |
|---|---|
| First post | 2020-11-19 17:43 +0100 |
| Last post | 2020-11-20 17:42 +0100 |
| Articles | 11 — 4 participants |
Back to article view | Back to comp.lang.php
Php/Mysql paginate results without resubmitting query cb <cb@ppt.io.it> - 2020-11-19 17:43 +0100
Re: Php/Mysql paginate results without resubmitting query Jerry Stuckle <jstucklex@attglobal.net> - 2020-11-19 15:05 -0500
Re: Php/Mysql paginate results without resubmitting query cb <cb@ppt.io.it> - 2020-11-21 18:03 +0100
Re: Php/Mysql paginate results without resubmitting query "J.O. Aho" <user@example.net> - 2020-11-19 22:54 +0100
Re: Php/Mysql paginate results without resubmitting query cb <cb@ppt.io.it> - 2020-11-20 08:36 +0100
Re: Php/Mysql paginate results without resubmitting query cb <cb@ppt.io.it> - 2020-11-20 08:45 +0100
Re: Php/Mysql paginate results without resubmitting query cb <cb@ppt.io.it> - 2020-11-20 08:53 +0100
Re: Php/Mysql paginate results without resubmitting query "J.O. Aho" <user@example.net> - 2020-11-20 10:15 +0100
Re: Php/Mysql paginate results without resubmitting query cb <cb@ppt.io.it> - 2020-11-20 11:30 +0100
Re: Php/Mysql paginate results without resubmitting query Jerry Stuckle <jstucklex@attglobal.net> - 2020-11-20 11:05 -0500
Re: Php/Mysql paginate results without resubmitting query Arno Welzel <usenet@arnowelzel.de> - 2020-11-20 17:42 +0100
| From | cb <cb@ppt.io.it> |
|---|---|
| Date | 2020-11-19 17:43 +0100 |
| Subject | Php/Mysql paginate results without resubmitting query |
| Message-ID | <rp67bt$up2$1@gioia.aioe.org> |
Please be patients !
I'm doing a big (sort of) select:
SELECT column1,column2 FROM table ORDER BY column1 LIMIT $count OFFSET
$offset;
(Without the LIMIT the select fails for exceeding time limit or whatelse.)
The user is then allowed to "page down" for getting next $count rows.
It works, BUT the query is re-submitted scanning again the whole DB.
Is there a way to store the RESULTS of the original query, and then
"paginate" into it (into the stored results) not into the DB?
Googling around I've found (and I'm doing it!)
$rc = mysqli_query($db, $qlib);
while ($row = mysqli_fetch_array($rc)) {
array_push($righe, $row);
}
BUT if $qlib has no LIMIT it abend for exceeding limits.
THANK YOU !
[toc] | [next] | [standalone]
| From | Jerry Stuckle <jstucklex@attglobal.net> |
|---|---|
| Date | 2020-11-19 15:05 -0500 |
| Message-ID | <rp6j6v$nff$1@jstuckle.eternal-september.org> |
| In reply to | #18413 |
On 11/19/2020 11:43 AM, cb wrote:
> Please be patients !
> I'm doing a big (sort of) select:
> SELECT column1,column2 FROM table ORDER BY column1 LIMIT $count OFFSET
> $offset;
> (Without the LIMIT the select fails for exceeding time limit or whatelse.)
> The user is then allowed to "page down" for getting next $count rows.
> It works, BUT the query is re-submitted scanning again the whole DB.
>
> Is there a way to store the RESULTS of the original query, and then
> "paginate" into it (into the stored results) not into the DB?
>
> Googling around I've found (and I'm doing it!)
> $rc = mysqli_query($db, $qlib);
> while ($row = mysqli_fetch_array($rc)) {
> array_push($righe, $row);
> }
> BUT if $qlib has no LIMIT it abend for exceeding limits.
>
> THANK YOU !
How big is your database (and which RDBMS are you using)? What indexes
do you have on it? Exactly what is your query? What is your
max_execution_time?
Rather than resubmitting the result, it would be better if you can
optimize your query so it doesn't time out. But this will only work if
the script doesn't terminate (i.e. end of the web page) because stored
results are discarded unless they are saved in your $_SESSION (not
recommended for big data).
Otherwise your only option is to query the database again, updating your
$offset every time.
--
==================
Remove the "x" from my email address
Jerry Stuckle
jstucklex@attglobal.net
==================
[toc] | [prev] | [next] | [standalone]
| From | cb <cb@ppt.io.it> |
|---|---|
| Date | 2020-11-21 18:03 +0100 |
| Message-ID | <rpbh9j$1282$1@gioia.aioe.org> |
| In reply to | #18415 |
I have to apologize for the disturb/noise caused :-( Setting the right key (*), and removing Strumento* (that I actually didn't need) from the ORDER solved all my troubles. Thanks for all the help you gave me: it has been very helpful and I really appreciate it. (*) but sh## I was sure to have already created it .... I was wrong :-(
[toc] | [prev] | [next] | [standalone]
| From | "J.O. Aho" <user@example.net> |
|---|---|
| Date | 2020-11-19 22:54 +0100 |
| Message-ID | <i1o7snFbhv4U1@mid.individual.net> |
| In reply to | #18413 |
On 19/11/2020 17.43, cb wrote:
> Please be patients !
> I'm doing a big (sort of) select:
> SELECT column1,column2 FROM table ORDER BY column1 LIMIT $count OFFSET
> $offset;
> (Without the LIMIT the select fails for exceeding time limit or whatelse.)
> The user is then allowed to "page down" for getting next $count rows.
> It works, BUT the query is re-submitted scanning again the whole DB.
>
> Is there a way to store the RESULTS of the original query, and then
> "paginate" into it (into the stored results) not into the DB?
You would need memcached or other cache system, you check if your data
structure is stored in the cache system, if not then you fetch the data
and process it to the format you want to use and store it to the cache.
Keep in mind that you will have an execution timeout when you try to
fetch all the data, so it wouldn't help you anything to use a cache system.
> Googling around I've found (and I'm doing it!)
> $rc = mysqli_query($db, $qlib);
> while ($row = mysqli_fetch_array($rc)) {
> array_push($righe, $row);
> }
> BUT if $qlib has no LIMIT it abend for exceeding limits.
For it's faster to work on a subset of the data than the whole data.
As Jerry already pointed out, you should look at using indexes, as it
will improve your sort speed.
--
//Aho
[toc] | [prev] | [next] | [standalone]
| From | cb <cb@ppt.io.it> |
|---|---|
| Date | 2020-11-20 08:36 +0100 |
| Message-ID | <rp7rl7$n54$1@gioia.aioe.org> |
| In reply to | #18416 |
Jerry & J.O. thanks for your attention !
>> How big is your database
400.000 rows
>> table definition:
MYSQL
"CREATE TABLE IF NOT EXISTS `Tablescore` ( \n"
+ " `Progr` INT AUTO_INCREMENT , \n"
+ " `Autore` varchar(512) NOT NULL, \n"
+ " `Lavoro` varchar(512) DEFAULT NULL, \n"
+ " `Link` varchar(512) DEFAULT NULL, \n"
+ " `NumFil` varchar(160) DEFAULT NULL, \n"
+ " `DateSubm` varchar(10) DEFAULT NULL, \n"
+ " `PlaceHolder` varchar(30) DEFAULT NULL,\n"
+ " `StrumentoGenerico` varchar(130) DEFAULT NULL,\n"
+ " `StrumentoSpecifico` varchar(130) DEFAULT NULL\n"
+ " , PRIMARY KEY (Progr)) \n"
+ "ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=0 ";
>> query:
SELECT * from Tablescore ORDER BY Autore , Lavoro, StrumentoGenerico,
StrumentoSpecifico
>> max_execution_time:
N/A I'm running on an hosted system, so time_limit(anything) it's non
honored.
and that's reasonable !
On another (italian) newsgroup I got the suggestion to use a temp table.
I'll try it during the week-end.
[toc] | [prev] | [next] | [standalone]
| From | cb <cb@ppt.io.it> |
|---|---|
| Date | 2020-11-20 08:45 +0100 |
| Message-ID | <rp7s6v$toc$1@gioia.aioe.org> |
| In reply to | #18417 |
addendum
>> indexes:
describe Tablescore;
+--------------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra
|
+--------------------+--------------+------+-----+---------+----------------+
| Progr | int(11) | NO | PRI | NULL |
auto_increment |
| Autore | varchar(512) | NO | MUL | NULL |
|
| Lavoro | varchar(512) | YES | MUL | NULL |
|
| Link | varchar(512) | YES | | NULL |
|
| NumFil | varchar(160) | YES | | NULL |
|
| DateSubm | varchar(10) | YES | | NULL |
|
| PlaceHolder | varchar(30) | YES | | NULL |
|
| StrumentoGenerico | varchar(130) | YES | MUL | NULL |
|
| StrumentoSpecifico | varchar(130) | YES | MUL | NULL |
|
+--------------------+--------------+------+-----+---------+----------------+
9 rows in set (0.00 sec)
On 11/20/20 8:36 AM, cb wrote:
> Jerry & J.O. thanks for your attention !
> >> How big is your database
> 400.000 rows
> >> table definition:
> MYSQL
> "CREATE TABLE IF NOT EXISTS `Tablescore` ( \n"
> + " `Progr` INT AUTO_INCREMENT , \n"
> + " `Autore` varchar(512) NOT NULL, \n"
> + " `Lavoro` varchar(512) DEFAULT NULL, \n"
> + " `Link` varchar(512) DEFAULT NULL, \n"
> + " `NumFil` varchar(160) DEFAULT NULL, \n"
> + " `DateSubm` varchar(10) DEFAULT NULL, \n"
> + " `PlaceHolder` varchar(30) DEFAULT NULL,\n"
> + " `StrumentoGenerico` varchar(130) DEFAULT NULL,\n"
> + " `StrumentoSpecifico` varchar(130) DEFAULT NULL\n"
> + " , PRIMARY KEY (Progr)) \n"
> + "ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=0 ";
> >> query:
> SELECT * from Tablescore ORDER BY Autore , Lavoro, StrumentoGenerico,
> StrumentoSpecifico
> >> max_execution_time:
> N/A I'm running on an hosted system, so time_limit(anything) it's non
> honored.
> and that's reasonable !
>
> On another (italian) newsgroup I got the suggestion to use a temp table.
> I'll try it during the week-end.
[toc] | [prev] | [next] | [standalone]
| From | cb <cb@ppt.io.it> |
|---|---|
| Date | 2020-11-20 08:53 +0100 |
| Message-ID | <rp7sld$13k8$1@gioia.aioe.org> |
| In reply to | #18418 |
another addendum: explain SELECT * from Tablescore ORDER BY Autore , Lavoro, StrumentoGenerico, StrumentoSpecifico ; +------+-------------+------------+------+---------------+------+---------+------+--------+----------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +------+-------------+------------+------+---------------+------+---------+------+--------+----------------+ | 1 | SIMPLE | Tablescore | ALL | NULL | NULL | NULL | NULL | 381853 | Using filesort | +------+-------------+------------+------+---------------+------+---------+------+--------+----------------+ 1 row in set (0.00 sec) it looks like I have to investigate why no KEY is used :-( On 11/20/20 8:45 AM, cb wrote: > addendum > >> indexes: > describe Tablescore; > +--------------------+--------------+------+-----+---------+----------------+ > > | Field | Type | Null | Key | Default | Extra | > +--------------------+--------------+------+-----+---------+----------------+ > > | Progr | int(11) | NO | PRI | NULL | > auto_increment | > | Autore | varchar(512) | NO | MUL | NULL | | > | Lavoro | varchar(512) | YES | MUL | NULL | | > | Link | varchar(512) | YES | | NULL | | > | NumFil | varchar(160) | YES | | NULL | | > | DateSubm | varchar(10) | YES | | NULL | | > | PlaceHolder | varchar(30) | YES | | NULL | | > | StrumentoGenerico | varchar(130) | YES | MUL | NULL | | > | StrumentoSpecifico | varchar(130) | YES | MUL | NULL | | > +--------------------+--------------+------+-----+---------+----------------+ > > 9 rows in set (0.00 sec) > > On 11/20/20 8:36 AM, cb wrote: >> Jerry & J.O. thanks for your attention ! >> >> How big is your database >> 400.000 rows >> >> table definition: >> MYSQL >> "CREATE TABLE IF NOT EXISTS `Tablescore` ( \n" >> + " `Progr` INT AUTO_INCREMENT , \n" >> + " `Autore` varchar(512) NOT NULL, \n" >> + " `Lavoro` varchar(512) DEFAULT NULL, \n" >> + " `Link` varchar(512) DEFAULT NULL, \n" >> + " `NumFil` varchar(160) DEFAULT NULL, \n" >> + " `DateSubm` varchar(10) DEFAULT NULL, \n" >> + " `PlaceHolder` varchar(30) DEFAULT NULL,\n" >> + " `StrumentoGenerico` varchar(130) DEFAULT NULL,\n" >> + " `StrumentoSpecifico` varchar(130) DEFAULT NULL\n" >> + " , PRIMARY KEY (Progr)) \n" >> + "ENGINE=InnoDB DEFAULT CHARSET=latin1 >> AUTO_INCREMENT=0 "; >> >> query: >> SELECT * from Tablescore ORDER BY Autore , Lavoro, >> StrumentoGenerico, StrumentoSpecifico >> >> max_execution_time: >> N/A I'm running on an hosted system, so time_limit(anything) it's >> non honored. >> and that's reasonable ! >> >> On another (italian) newsgroup I got the suggestion to use a temp table. >> I'll try it during the week-end. >
[toc] | [prev] | [next] | [standalone]
| From | "J.O. Aho" <user@example.net> |
|---|---|
| Date | 2020-11-20 10:15 +0100 |
| Message-ID | <i1pfq7Fim54U1@mid.individual.net> |
| In reply to | #18417 |
On 20/11/2020 08.36, cb wrote: > Jerry & J.O. thanks for your attention ! > >> How big is your database > 400.000 rows > >> table definition: > MYSQL > "CREATE TABLE IF NOT EXISTS `Tablescore` ( \n" > + " `Progr` INT AUTO_INCREMENT , \n" > + " `Autore` varchar(512) NOT NULL, \n" > + " `Lavoro` varchar(512) DEFAULT NULL, \n" > + " `Link` varchar(512) DEFAULT NULL, \n" > + " `NumFil` varchar(160) DEFAULT NULL, \n" > + " `DateSubm` varchar(10) DEFAULT NULL, \n" > + " `PlaceHolder` varchar(30) DEFAULT NULL,\n" > + " `StrumentoGenerico` varchar(130) DEFAULT NULL,\n" > + " `StrumentoSpecifico` varchar(130) DEFAULT NULL\n" > + " , PRIMARY KEY (Progr)) \n" > + "ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=0 "; I guess the multi key index is Autore , Lavoro, StrumentoGenerico, StrumentoSpecifico and I think that in InnoDB you have a key limit of 767 bytes, so as I can recall your key size would be 512*2 + 512*2 + 130*1 + 130*1 = 2308 the two first one should automatically be made to double bytes as they are larger than 255 chars. Lets see if Jerry agrees with that conclusion. > On another (italian) newsgroup I got the suggestion to use a temp table. > I'll try it during the week-end. I doubt that would make much difference as you ain't joining things and the temp table will be removed when the mysql session is terminated, so on your second connection you can't use the data. One alternative would be to do a select on the whole table, sort it in php and store the result in a cache, how effective this is depends on how often you write to the table as the cache needs to invalidated when you do insert/update/delete. Another alternative is to use a faster database server, like aws aurora, but sure it comes with an extra cost. -- //Aho
[toc] | [prev] | [next] | [standalone]
| From | cb <cb@ppt.io.it> |
|---|---|
| Date | 2020-11-20 11:30 +0100 |
| Message-ID | <rp85t0$1dv6$1@gioia.aioe.org> |
| In reply to | #18420 |
On 11/20/20 10:15 AM, J.O. Aho wrote: > I guess the multi key index is Autore , Lavoro, StrumentoGenerico, > StrumentoSpecifico and I think that in InnoDB you have a key limit of > 767 bytes, so as I can recall your key size would be thank you for your attention/patience ! actually I've already done the multi-key on the fields you suggested:that changed *nothing* Now I understand why :-( Now I have to do some real (paid) work, the Tablescore is just an hobby, but I love it. In the week-end I'll check the real lengths of (Autore , Lavoro, StrumentoGenerico, StrumentoSpecifico) and maybe remove some fields (Strumento*) from the ORDER BY. Will let you know and again THANKYOU.
[toc] | [prev] | [next] | [standalone]
| From | Jerry Stuckle <jstucklex@attglobal.net> |
|---|---|
| Date | 2020-11-20 11:05 -0500 |
| Message-ID | <rp8pg4$7f3$1@jstuckle.eternal-september.org> |
| In reply to | #18420 |
On 11/20/2020 4:15 AM, J.O. Aho wrote: > On 20/11/2020 08.36, cb wrote: >> Jerry & J.O. thanks for your attention ! >> >> How big is your database >> 400.000 rows >> >> table definition: >> MYSQL >> "CREATE TABLE IF NOT EXISTS `Tablescore` ( \n" >> + " `Progr` INT AUTO_INCREMENT , \n" >> + " `Autore` varchar(512) NOT NULL, \n" >> + " `Lavoro` varchar(512) DEFAULT NULL, \n" >> + " `Link` varchar(512) DEFAULT NULL, \n" >> + " `NumFil` varchar(160) DEFAULT NULL, \n" >> + " `DateSubm` varchar(10) DEFAULT NULL, \n" >> + " `PlaceHolder` varchar(30) DEFAULT NULL,\n" >> + " `StrumentoGenerico` varchar(130) DEFAULT NULL,\n" >> + " `StrumentoSpecifico` varchar(130) DEFAULT NULL\n" >> + " , PRIMARY KEY (Progr)) \n" >> + "ENGINE=InnoDB DEFAULT CHARSET=latin1 >> AUTO_INCREMENT=0 "; > > I guess the multi key index is Autore , Lavoro, StrumentoGenerico, > StrumentoSpecifico and I think that in InnoDB you have a key limit of > 767 bytes, so as I can recall your key size would be > > 512*2 + 512*2 + 130*1 + 130*1 = 2308 > > the two first one should automatically be made to double bytes as they > are larger than 255 chars. Lets see if Jerry agrees with that conclusion. > > >> On another (italian) newsgroup I got the suggestion to use a temp table. >> I'll try it during the week-end. > > I doubt that would make much difference as you ain't joining things and > the temp table will be removed when the mysql session is terminated, so > on your second connection you can't use the data. > > One alternative would be to do a select on the whole table, sort it in > php and store the result in a cache, how effective this is depends on > how often you write to the table as the cache needs to invalidated when > you do insert/update/delete. > > Another alternative is to use a faster database server, like aws aurora, > but sure it comes with an extra cost. > Maximum length for a single field is 767 bytes but for total keys it is 3500 bytes (which MySQL limits to 3072 bytes). But the columns themselves are not double byte. When you go over 255 bytes the length field at the beginning of the record expands from one to two bytes, but the rest of the column size is dependent only on the charset being used. Since this is latin1 the data would be single byte. So the actual length of each field is 512 bytes for data + 2 bytes length field = 514 bytes. Other fields would be 130 bytes for data + 1 byte for length or 131 bytes. So the total length would be 514+514+131+131 or 1290 bytes. An index on the four fields (Autore , Lavoro, StrumentoGenerico, StrumentoSpecifico) should help (I don't see any index listed). The other consideration here is searching and sorting on character fields is much slower then integer fields. If any of these fields contain the same information the database could be improved by normalizing it. -- ================== Remove the "x" from my email address Jerry Stuckle jstucklex@attglobal.net ==================
[toc] | [prev] | [next] | [standalone]
| From | Arno Welzel <usenet@arnowelzel.de> |
|---|---|
| Date | 2020-11-20 17:42 +0100 |
| Message-ID | <i1q9vjFnnnhU1@mid.individual.net> |
| In reply to | #18413 |
cb: > Please be patients ! > I'm doing a big (sort of) select: > SELECT column1,column2 FROM table ORDER BY column1 LIMIT $count OFFSET > $offset; > (Without the LIMIT the select fails for exceeding time limit or whatelse.) Without LIMIT pagination makes no sense. So yes - this is the correct way to do it - set a limit and an offset for the records you want to retrieve. > The user is then allowed to "page down" for getting next $count rows. > It works, BUT the query is re-submitted scanning again the whole DB. Define "whole DB"? What *exactly* is your problem? Doing subsequent queries for pagination is totally fine - that's the reason why LIMIT and OFFSET exist. Is column1 indexed? -- Arno Welzel https://arnowelzel.de
[toc] | [prev] | [standalone]
Back to top | Article view | comp.lang.php
csiph-web