how to make selecting random rows in oracle faster with table with millions of rows

前端 未结 7 1131
后悔当初
后悔当初 2021-02-13 11:25

Is there a way to make selecting random rows faster in oracle with a table that has million of rows. I tried to use sample(x) and dbms_random.value and its taking a long time to

7条回答
  •  孤城傲影
    2021-02-13 12:04

    Version with retries when no rows returned:

    WITH gen AS ((SELECT --+ inline leading(e) use_nl(e t) rowid(t)
                         MAX(t.ROWID) KEEP(DENSE_RANK FIRST ORDER BY dbms_random.value) Row_Id
                    FROM (SELECT o.Data_Object_Id,
                                 e.Relative_Fno,
                                 e.Block_Id + TRUNC(Dbms_Random.Value(0, e.Blocks)) AS Block_Id 
                            FROM Dba_Extents e
                            JOIN Dba_Objects o ON o.Owner = e.Owner AND o.Object_Type = e.Segment_Type AND o.Object_Name = e.Segment_Name
                           WHERE e.Segment_Name = 'MY_TABLE'
                             AND(e.Segment_Type, e.Owner, e.Extent_Id) =
                                (SELECT MAX(e.Segment_Type) AS Segment_Type,
                                        MAX(e.Owner)        AS Owner,
                                        MAX(e.Extent_Id) KEEP(DENSE_RANK FIRST ORDER BY Dbms_Random.Value) AS Extent_Id
                                   FROM Dba_Extents e
                                  WHERE e.Segment_Name = 'MY_TABLE'
                                    AND e.Owner = 'MY_USER'
                                    AND e.Segment_Type = 'TABLE')) e
                    JOIN MY_USER.MY_TABLE t ON t.ROWID BETWEEN Dbms_Rowid.Rowid_Create(1, Data_Object_Id, Relative_Fno, Block_Id, 0)
                                                      AND Dbms_Rowid.Rowid_Create(1, Data_Object_Id, Relative_Fno, Block_Id, 32767))),
      Retries(Cnt, Row_Id) AS (SELECT 1, gen.Row_Id
                                 FROM Dual
                                 LEFT JOIN gen ON 1=1
                                UNION ALL
                               SELECT Cnt + 1, gen.Row_Id
                                 FROM Retries
                                 LEFT JOIN gen ON 1=1
                                WHERE Retries.Row_Id IS NULL AND Retries.Cnt < 10)
    SELECT *
      FROM MY_USER.MY_TABLE
     WHERE ROWID = (SELECT Row_Id
                      FROM Retries
                     WHERE Row_Id IS NOT NULL)
    

提交回复
热议问题