Re: Optimising LIMITs

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Richard!

Step 1
---------------

Is it right?
1. `threadid` value is unique.
2. `threadid` value is auto_increment.
3. if `threadid`(2) > `threadid`(1)  =>  `created`(2) > `created`(1).

You can do the following:

1. Create the index on two fields: (boardid, status)
2. ALTER TABLE `board` ORDER BY `threadid` DESC;

Here is new query to fetch a block of records:

SELECT * FROM `board` WHERE `boardid` = 1 AND `status` = "L" LIMIT
100,50


Step 2
----------------

The average size of row in your table is 128,000,000 / 190,000 ~= 675
bytes.

Split your table in two tables, like:

CREATE TABLE `boardinfo` 
	( `threadid` INT(4) UNSIGNED AUTO_INCREMENT,
	  PRIMARY KEY( `threadid` ),
	  `boardid` INT(4) UNSIGNED,
	  `status` ENUM( 'L', '....' ),
	  `created` TIMESTAMP
	  ... (all fixed fields )
	)

ALTER TABLE `boardinfo` CREATE INDEX `main` (`boardid,`status`)
ALTER TABLE `boardinfo` ORDER BY `threadid` DESC

CREATE TABLE `boarddata` (
	`threadid_ref` INT(4) UNSIGNED,
	PRIMARY KEY ( `threadid_ref` ),
	`threaddata` LONGTEXT
	)

Here is your query after:

SELECT * FROM `boardinfo` LEFT JOIN `boarddata` ON `threadid` =
`threadid_ref` WHERE `boardid` = 1 AND `status` = "L" LIMIT 100,50



Sorry for my englist.

Best regards, Pavel




> Hi all,
> 
> I have what is probably a quite standard question and would love to
> know how you would all approach this scenario:
> 
> I have a table in a database that has approx. 190,000 records in it.
> The table is currently 128MB in size and I'm happy that it is well
> constructed with no data duplication and sensible indexes.
> 
> I'm using MySQL 3.28.58. and my question is about querying this volume
> of data efficiently.
> 
> The table holds forum threads (several years worth) so a common query
> running on the table is to bring back the top 50 or 100 threads from a
> board within the forum.
> 
> To do this I'm using a LIMIT on my query and for the paging through
> the data (i.e. the first 100 threads, the next 100, etc) I use the
> LIMIT n,x syntax. Threads are sorted by date (most recent to the top).
> 
> This is fine and it works well but I'm concerned it's not the most
> efficient way to do this because the use of LIMIT is causing the
> whole table to be scanned each time.
> 
> Here is a typical (simplified) query:
> 
> SELECT *
> FROM thread
> WHERE
> thread.status='L' AND
> thread.boardid=1
> ORDER BY created DESC
> LIMIT 100,50
> 
> This takes over 1.02 seconds to process.
> 
> Running an EXPLAIN on my query shows that it's using one key
> (boardid), but in the Extra field it shows it is having to use a
> filesort on the data. 5701 rows were used in order to bring back the
> final 50 - that's every single thread for this board.
> 
> What I'm trying to figure out is a more efficient way of selecting a
> block of 50 or 100 records from any point in my table without MySQL
> needing to sort/check them all first.
> 
> One thought I did have was that the Primary Key on my table is called
> threadid - and I thought that instead of bring back the data in my
> original query, I could collect nothing but the thread IDs and then
> use a separate query that does something like: "SELECT * FROM thread
> WHERE threadid IN (...)" (where ... = all of the IDs previously
> selected). Would the fact that threadid is my primary key make the
> original LIMIT/sort faster?
> 
> Any thoughts appreciated.
> 
> -- 
> Best regards,
>  Richard Davey
>  http://www.phpcommunity.org/wiki/296.html

-- 
PHP Database Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php


[Index of Archives]     [PHP Home]     [PHP Users]     [Postgresql Discussion]     [Kernel Newbies]     [Postgresql]     [Yosemite News]

  Powered by Linux